This repository has no description
0

Configure Feed

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

core / spindle / startup_migrations.go
2.4 kB 83 lines
1package spindle 2 3import ( 4 "context" 5 "database/sql" 6 "errors" 7 "fmt" 8 "log/slog" 9 "os" 10 11 _ "github.com/mattn/go-sqlite3" 12 "tangled.org/core/spindle/db" 13) 14 15const forceTapResyncFlag = "force-tap-repo-resync-v1" 16 17func runStartupMigrations(ctx context.Context, d *db.DB, tapEmbed bool, tapDBPath string, logger *slog.Logger) error { 18 if !tapEmbed { 19 logger.Warn("tap not embedded: legacy repos won't auto-resync; trigger external tap resync to migrate secrets/casbin") 20 return nil 21 } 22 if err := nudgeTapForResync(ctx, d, tapDBPath, logger); err != nil { 23 return fmt.Errorf("nudge tap for resync: %w", err) 24 } 25 return nil 26} 27 28func nudgeTapForResync(ctx context.Context, d *db.DB, tapDBPath string, logger *slog.Logger) error { 29 if tapDBPath == "" { 30 return fmt.Errorf("tap db path empty in embed mode") 31 } 32 var exists bool 33 if err := d.QueryRowContext(ctx, 34 `select exists (select 1 from migrations where name = ?)`, 35 forceTapResyncFlag, 36 ).Scan(&exists); err != nil { 37 return fmt.Errorf("check %s flag: %w", forceTapResyncFlag, err) 38 } 39 if exists { 40 logger.Warn("skipped migration, already applied", "migration", forceTapResyncFlag) 41 return nil 42 } 43 44 markDone := func() error { 45 if _, err := d.ExecContext(ctx, 46 `insert or ignore into migrations (name) values (?)`, 47 forceTapResyncFlag, 48 ); err != nil { 49 return fmt.Errorf("mark %s done: %w", forceTapResyncFlag, err) 50 } 51 return nil 52 } 53 54 if _, err := os.Stat(tapDBPath); errors.Is(err, os.ErrNotExist) { 55 logger.Info("tap db not yet created, marking resync nudge done", "migration", forceTapResyncFlag, "path", tapDBPath) 56 return markDone() 57 } else if err != nil { 58 return fmt.Errorf("stat tap db: %w", err) 59 } 60 61 tdb, err := sql.Open("sqlite3", tapDBPath+"?_busy_timeout=5000") 62 if err != nil { 63 return fmt.Errorf("open tap db: %w", err) 64 } 65 defer tdb.Close() 66 67 if _, err := tdb.ExecContext(ctx, `delete from repo_records`); err != nil { 68 return fmt.Errorf("clear tap repo_records: %w", err) 69 } 70 res, err := tdb.ExecContext(ctx, 71 `update repos set state = 'desynchronized', retry_after = 0 where state in ('active','error')`, 72 ) 73 if err != nil { 74 return fmt.Errorf("desync tap repos: %w", err) 75 } 76 n, _ := res.RowsAffected() 77 78 if err := markDone(); err != nil { 79 return err 80 } 81 logger.Info("nudged tap to resync", "migration", forceTapResyncFlag, "repos_desynced", n) 82 return nil 83}