this repo has no description
1package db 2 3import ( 4 "context" 5 "database/sql" 6 "strings" 7 8 "github.com/bluesky-social/indigo/atproto/syntax" 9 _ "github.com/mattn/go-sqlite3" 10 "tangled.org/core/log" 11 "tangled.org/core/orm" 12) 13 14type DB struct { 15 *sql.DB 16} 17 18func Make(ctx context.Context, dbPath string) (*DB, error) { 19 // https://github.com/mattn/go-sqlite3#connection-string 20 opts := []string{ 21 "_foreign_keys=1", 22 "_journal_mode=WAL", 23 "_synchronous=NORMAL", 24 "_auto_vacuum=incremental", 25 } 26 27 logger := log.FromContext(ctx) 28 logger = log.SubLogger(logger, "db") 29 30 db, err := sql.Open("sqlite3", dbPath+"?"+strings.Join(opts, "&")) 31 if err != nil { 32 return nil, err 33 } 34 35 conn, err := db.Conn(ctx) 36 if err != nil { 37 return nil, err 38 } 39 defer conn.Close() 40 41 _, err = db.Exec(` 42 create table if not exists _jetstream ( 43 id integer primary key autoincrement, 44 last_time_us integer not null 45 ); 46 47 create table if not exists known_dids ( 48 did text primary key 49 ); 50 51 create table if not exists repos ( 52 id integer primary key autoincrement, 53 knot text not null, 54 owner text not null, 55 name text not null, 56 addedAt text not null default (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')), 57 58 unique(owner, name) 59 ); 60 61 create table if not exists repo_collaborators ( 62 -- identifiers 63 id integer primary key autoincrement, 64 did text not null, 65 rkey text not null, 66 at_uri text generated always as ('at://' || did || '/' || 'sh.tangled.repo.collaborator' || '/' || rkey) stored, 67 68 repo text not null, 69 subject text not null, 70 71 addedAt text not null default (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')), 72 unique(did, rkey) 73 ); 74 75 create table if not exists spindle_members ( 76 -- identifiers for the record 77 id integer primary key autoincrement, 78 did text not null, 79 rkey text not null, 80 81 -- data 82 instance text not null, 83 subject text not null, 84 created text not null default (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')), 85 86 -- constraints 87 unique (did, instance, subject) 88 ); 89 90 -- status event for a single workflow 91 create table if not exists events ( 92 rkey text not null, 93 nsid text not null, 94 event text not null, -- json 95 created integer not null -- unix nanos 96 ); 97 `) 98 if err != nil { 99 return nil, err 100 } 101 102 // run migrations 103 104 // NOTE: this won't migrate existing records 105 // they will be fetched again with tap instead 106 orm.RunMigration(conn, logger, "add-rkey-to-repos", func(tx *sql.Tx) error { 107 // archive legacy repos (just in case) 108 _, err = tx.Exec(`alter table repos rename to repos_old`) 109 if err != nil { 110 return err 111 } 112 113 _, err := tx.Exec(` 114 create table repos ( 115 -- identifiers 116 id integer primary key autoincrement, 117 did text not null, 118 rkey text not null, 119 at_uri text generated always as ('at://' || did || '/' || 'sh.tangled.repo' || '/' || rkey) stored, 120 121 name text not null, 122 knot text not null, 123 124 addedAt text not null default (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')), 125 unique(did, rkey) 126 ); 127 `) 128 if err != nil { 129 return err 130 } 131 132 return nil 133 }) 134 135 return &DB{db}, nil 136} 137 138func (d *DB) IsKnownDid(did syntax.DID) (bool, error) { 139 // is spindle member / repo collaborator 140 var exists bool 141 err := d.QueryRow( 142 `select exists ( 143 select 1 from repo_collaborators where subject = ? 144 union all 145 select 1 from spindle_members where did = ? 146 )`, 147 did, 148 did, 149 ).Scan(&exists) 150 return exists, err 151}