refactor: make migration process more intelligent, add test coverage

This commit is contained in:
2026-09-19 21:36:31 -07:00
parent ff7f0a57c8
commit 40bc0db036
6 changed files with 361 additions and 32 deletions

View File

@@ -1,5 +1,14 @@
package db
import (
"fmt"
"github.com/jmoiron/sqlx"
"git.offline-twitter.com/offline-labs/gas-stack/pkg/must"
"git.offline-twitter.com/offline-labs/gas-stack/pkg/textutils"
)
type Migration struct {
// ID is the version number that the schema will be at, after applying the migration.
ID int
@@ -10,3 +19,32 @@ type Migration struct {
// SQL is the body of the migration that will be executed.
SQL string
}
// Apply runs the migration in a transaction. Foreign key checking is delayed until right before committing the transaction.
func (m Migration) Apply(db *sqlx.DB) error {
fmt.Print(textutils.ColorCyan)
fmt.Println(m.SQL)
fmt.Print(textutils.ColorReset)
// Temporarily suspend foreign keys until the migration is finished
db.MustExec("pragma foreign_keys = off")
defer db.MustExec("pragma foreign_keys = on")
tx := db.MustBegin()
defer func() { _ = tx.Rollback() }()
// Sanity: should initially be on the previous version
var prevVersion int
must.Do(tx.Get(&prevVersion, `select version from db_version`))
if prevVersion != m.ID-1 {
return fmt.Errorf("%w: tried to apply migration %d on DB version %d", ErrMigrationOrder, m.ID, prevVersion)
}
// Execute the migration
tx.MustExec(m.SQL)
tx.MustExec("update db_version set version = ?", m.ID)
must.Do(PragmaForeignKeyCheck(tx))
must.Do(tx.Commit())
return nil
}