Files
wakapi/migrations/migrations.go

132 lines
3.4 KiB
Go

package migrations
import (
"github.com/muety/wakapi/config"
"github.com/muety/wakapi/models"
"gorm.io/gorm"
"log/slog"
"sort"
"strings"
)
type GormMigrationFunc func(db *gorm.DB) error
type migrationFunc struct {
f func(db *gorm.DB, cfg *config.Config) error
name string
// be careful with background migrations, because they must not lock or have side effects on each other, and they must be safe to fail silently
background bool
}
type migrationFuncs []migrationFunc
var (
preMigrations migrationFuncs
postMigrations migrationFuncs
)
func GetMigrationFunc(cfg *config.Config) GormMigrationFunc {
switch cfg.Db.Dialect {
default:
return func(db *gorm.DB) error {
if err := db.AutoMigrate(&models.User{}); err != nil && !cfg.Db.AutoMigrateFailSilently {
return err
}
if err := db.AutoMigrate(&models.KeyStringValue{}); err != nil && !cfg.Db.AutoMigrateFailSilently {
return err
}
if err := db.AutoMigrate(&models.Alias{}); err != nil && !cfg.Db.AutoMigrateFailSilently {
return err
}
if err := db.AutoMigrate(&models.Heartbeat{}); err != nil && !cfg.Db.AutoMigrateFailSilently {
return err
}
if err := db.AutoMigrate(&models.Summary{}); err != nil && !cfg.Db.AutoMigrateFailSilently {
return err
}
if err := db.AutoMigrate(&models.SummaryItem{}); err != nil && !cfg.Db.AutoMigrateFailSilently {
return err
}
if err := db.AutoMigrate(&models.LanguageMapping{}); err != nil && !cfg.Db.AutoMigrateFailSilently {
return err
}
if err := db.AutoMigrate(&models.ProjectLabel{}); err != nil && !cfg.Db.AutoMigrateFailSilently {
return err
}
if err := db.AutoMigrate(&models.Diagnostics{}); err != nil && !cfg.Db.AutoMigrateFailSilently {
return err
}
if err := db.AutoMigrate(&models.LeaderboardItem{}); err != nil && !cfg.Db.AutoMigrateFailSilently {
return err
}
if err := db.AutoMigrate(&models.Duration{}); err != nil && !cfg.Db.AutoMigrateFailSilently {
return err
}
return nil
}
}
}
func registerPreMigration(f migrationFunc) {
preMigrations = append(preMigrations, f)
}
func registerPostMigration(f migrationFunc) {
postMigrations = append(postMigrations, f)
}
func Run(db *gorm.DB, cfg *config.Config) {
RunPreMigrations(db, cfg)
RunSchemaMigrations(db, cfg)
RunPostMigrations(db, cfg)
}
func RunSchemaMigrations(db *gorm.DB, cfg *config.Config) {
if err := GetMigrationFunc(cfg)(db); err != nil {
config.Log().Fatal("migration failed", "error", err)
}
}
func RunPreMigrations(db *gorm.DB, cfg *config.Config) {
sort.Sort(preMigrations)
for _, m := range preMigrations {
slog.Info("potentially running migration", "name", m.name)
if err := m.f(db, cfg); err != nil {
config.Log().Fatal("migration failed", "name", m.name, "error", err)
}
}
}
func RunPostMigrations(db *gorm.DB, cfg *config.Config) {
sort.Sort(postMigrations)
for _, m := range postMigrations {
slog.Info("potentially running migration", "name", m.name)
run := func(m migrationFunc) {
if err := m.f(db, cfg); err != nil {
config.Log().Fatal("migration failed", "name", m.name, "error", err)
}
}
if m.background {
go run(m)
} else {
run(m)
}
}
}
func (m migrationFuncs) Len() int {
return len(m)
}
func (m migrationFuncs) Less(i, j int) bool {
return strings.Compare(m[i].name, m[j].name) < 0
}
func (m migrationFuncs) Swap(i, j int) {
m[i], m[j] = m[j], m[i]
}