fix: migrate is a separate command

This commit is contained in:
Paul Pan 2024-01-06 19:26:18 +08:00
parent 696804452e
commit 5826b98b95
Signed by: Paul
GPG Key ID: D639BDF5BA578AF4
2 changed files with 41 additions and 46 deletions

View File

@ -8,6 +8,7 @@ import (
"git.0x7f.app/WOJ/woj-server/internal/misc/config"
"git.0x7f.app/WOJ/woj-server/internal/misc/log"
"git.0x7f.app/WOJ/woj-server/internal/model"
"git.0x7f.app/WOJ/woj-server/internal/repo/db"
"git.0x7f.app/WOJ/woj-server/internal/web/router"
"git.0x7f.app/WOJ/woj-server/pkg/utils"
"git.0x7f.app/WOJ/woj-server/pkg/zapasynq"
@ -23,7 +24,7 @@ import (
)
func RunServerMigrate(i *do.Injector) error {
do.MustInvoke[db.Service](i).Migrate()
return nil
}

View File

@ -22,7 +22,7 @@ var _ Service = (*service)(nil)
type Service interface {
Get() *gorm.DB
Close() error
Migrate()
HealthCheck() error
Shutdown() error
}
@ -46,7 +46,44 @@ func (s *service) Get() *gorm.DB {
return s.db
}
func (s *service) Close() error {
func (s *service) Migrate() {
s.log.Info("Auto Migrating database...")
// Running AutoMigrate concurrently on the same model fails with various race conditions
// https://github.com/go-gorm/gorm/pull/6680
// https://github.com/go-gorm/postgres/pull/224
// Obtain a lock to prevent concurrent AutoMigrate
lockID := func(s string) int64 {
h := fnv.New64a()
_, err := h.Write([]byte(s))
return utils.If(err != nil, int64(0x4242AA55), int64(h.Sum64()))
}("gorm:migrator")
s.err = s.db.Exec("SELECT pg_advisory_lock(?)", lockID).Error
if s.err != nil {
s.log.Error("Failed to obtain lock", zap.Error(s.err))
return
}
_ = s.db.AutoMigrate(&model.User{})
_ = s.db.AutoMigrate(&model.Problem{})
_ = s.db.AutoMigrate(&model.ProblemVersion{})
_ = s.db.AutoMigrate(&model.Submission{})
_ = s.db.AutoMigrate(&model.Status{})
s.err = s.db.Exec("SELECT pg_advisory_unlock(?)", lockID).Error
if s.err != nil {
s.log.Error("Failed to release lock", zap.Error(s.err))
}
}
func (s *service) HealthCheck() error {
return s.err
}
func (s *service) Shutdown() error {
var db *sql.DB
db, s.err = s.db.DB()
if s.err != nil {
@ -57,14 +94,6 @@ func (s *service) Close() error {
return s.err
}
func (s *service) HealthCheck() error {
return s.err
}
func (s *service) Shutdown() error {
return s.Close()
}
func (s *service) setup(conf *model.Config) {
s.log.Info("Connecting to database...")
@ -109,41 +138,6 @@ func (s *service) setup(conf *model.Config) {
db.SetMaxOpenConns(conf.Database.MaxOpenConns)
db.SetMaxIdleConns(conf.Database.MaxIdleConns)
db.SetConnMaxLifetime(time.Duration(conf.Database.ConnMaxLifetime) * time.Minute)
s.migrateDatabase()
}
func (s *service) migrateDatabase() {
s.log.Info("Auto Migrating database...")
// Running AutoMigrate concurrently on the same model fails with various race conditions
// https://github.com/go-gorm/gorm/pull/6680
// https://github.com/go-gorm/postgres/pull/224
// Obtain a lock to prevent concurrent AutoMigrate
lockID := func(s string) int64 {
h := fnv.New64a()
_, err := h.Write([]byte(s))
return utils.If(err != nil, int64(0x4242AA55), int64(h.Sum64()))
}("gorm:migrator")
s.err = s.db.Exec("SELECT pg_advisory_lock(?)", lockID).Error
if s.err != nil {
s.log.Error("Failed to obtain lock", zap.Error(s.err))
return
}
_ = s.db.AutoMigrate(&model.User{})
_ = s.db.AutoMigrate(&model.Problem{})
_ = s.db.AutoMigrate(&model.ProblemVersion{})
_ = s.db.AutoMigrate(&model.Submission{})
_ = s.db.AutoMigrate(&model.Status{})
s.err = s.db.Exec("SELECT pg_advisory_unlock(?)", lockID).Error
if s.err != nil {
s.log.Error("Failed to release lock", zap.Error(s.err))
}
}
func (s *service) checkAlive(retry int) (*sql.DB, error) {