Monorepo for Tangled tangled.org
5

Configure Feed

Select the types of activity you want to include in your feed.

1package db 2 3import ( 4 "database/sql" 5) 6 7// GetOrAssignOwnerUID returns the virtual UID for ownerDID, minting a new one 8// from the uid_counter table if this owner has not been seen before. 9// UIDs start at 100000 and increment by one per unique owner. 10// 11// A process-wide mutex serialises concurrent callers so two simultaneous 12// requests for distinct DIDs do not race to claim the same counter value. 13// The mutex is local to this DB instance and SQLite itself only permits one 14// writer at a time, so this does not impede throughput in practice. 15func (d *DB) GetOrAssignOwnerUID(ownerDID string) (uint32, error) { 16 d.uidAssignMu.Lock() 17 defer d.uidAssignMu.Unlock() 18 19 tx, err := d.db.Begin() 20 if err != nil { 21 return 0, err 22 } 23 defer tx.Rollback() 24 25 var uid uint32 26 err = tx.QueryRow( 27 `SELECT uid FROM owner_uid_assignments WHERE owner_did = ?`, 28 ownerDID, 29 ).Scan(&uid) 30 if err == nil { 31 return uid, tx.Commit() 32 } 33 if err != sql.ErrNoRows { 34 return 0, err 35 } 36 37 if err := tx.QueryRow(`SELECT next_uid FROM uid_counter`).Scan(&uid); err != nil { 38 return 0, err 39 } 40 if _, err := tx.Exec(`UPDATE uid_counter SET next_uid = next_uid + 1`); err != nil { 41 return 0, err 42 } 43 if _, err := tx.Exec( 44 `INSERT INTO owner_uid_assignments (owner_did, uid) VALUES (?, ?)`, 45 ownerDID, uid, 46 ); err != nil { 47 return 0, err 48 } 49 50 return uid, tx.Commit() 51} 52 53// AllReposForMigration returns all (repo_did, owner_did) pairs with a 54// non-null owner. Pass force=true to include already-migrated repos. 55func (d *DB) AllReposForMigration(force bool) ([]RepoMigrationRow, error) { 56 query := `SELECT repo_did, owner_did FROM repo_keys WHERE owner_did IS NOT NULL` 57 if !force { 58 query += ` AND isolated_at IS NULL` 59 } 60 rows, err := d.db.Query(query) 61 if err != nil { 62 return nil, err 63 } 64 defer rows.Close() 65 66 var result []RepoMigrationRow 67 for rows.Next() { 68 var r RepoMigrationRow 69 if err := rows.Scan(&r.RepoDID, &r.OwnerDID); err != nil { 70 return nil, err 71 } 72 result = append(result, r) 73 } 74 return result, rows.Err() 75} 76 77// CountUnmigratedRepos returns the number of repos that have not yet been 78// isolation-migrated. 79func (d *DB) CountUnmigratedRepos() (int, error) { 80 var n int 81 err := d.db.QueryRow(` 82 SELECT count(1) FROM repo_keys 83 WHERE owner_did IS NOT NULL 84 AND isolated_at IS NULL 85 `).Scan(&n) 86 return n, err 87} 88 89// MarkRepoIsolated sets isolated_at to the current time for repoDID. 90func (d *DB) MarkRepoIsolated(repoDID string) error { 91 _, err := d.db.Exec( 92 `UPDATE repo_keys SET isolated_at = strftime('%Y-%m-%dT%H:%M:%SZ','now') WHERE repo_did = ?`, 93 repoDID, 94 ) 95 return err 96} 97 98// RepoMigrationRow is a row returned by AllReposForMigration. 99type RepoMigrationRow struct { 100 RepoDID string 101 OwnerDID string 102}