From 2b0c692ac5168e262c1e3095a56628719c5eb1e6 Mon Sep 17 00:00:00 2001 From: asepharyana Date: Tue, 15 Sep 2026 14:52:54 +0700 Subject: [PATCH] fix: journaled migrations (schema_migrations), rerun-safe on existing prod DB --- backend/internal/store/db.go | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/backend/internal/store/db.go b/backend/internal/store/db.go index ea41405..b435c1e 100644 --- a/backend/internal/store/db.go +++ b/backend/internal/store/db.go @@ -48,14 +48,36 @@ func (db *DB) migrate() error { } } sort.Strings(names) + if _, err := db.Exec(`CREATE TABLE IF NOT EXISTS schema_migrations(name TEXT PRIMARY KEY)`); err != nil { + return fmt.Errorf("store: schema_migrations: %w", err) + } for _, n := range names { + var applied int + if err := db.QueryRow(`SELECT COUNT(*) FROM schema_migrations WHERE name=?`, n).Scan(&applied); err != nil { + return err + } + if applied > 0 { + continue + } b, err := migrationsFS.ReadFile(n) if err != nil { return err } - if _, err := db.Exec(string(b)); err != nil { + tx, err := db.Begin() + if err != nil { + return err + } + if _, err := tx.Exec(string(b)); err != nil { + _ = tx.Rollback() return fmt.Errorf("store: migration %s: %w", n, err) } + if _, err := tx.Exec(`INSERT INTO schema_migrations(name) VALUES(?)`, n); err != nil { + _ = tx.Rollback() + return err + } + if err := tx.Commit(); err != nil { + return err + } } return nil }