From 663da01bda1c77b421e18b8766e1bf9b2950af89 Mon Sep 17 00:00:00 2001 From: ryan Date: Mon, 1 Jun 2026 17:15:17 +0800 Subject: [PATCH] =?UTF-8?q?[=E4=BC=98=E5=8C=96]=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E8=BF=81=E7=A7=BB=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- openflare_server/model/main.go | 8 +++++-- openflare_server/model/migrate/v19.go | 7 +++++- openflare_server/model/migrate/v21.go | 31 +++++++++++++++++++++++---- openflare_server/model/migrations.go | 6 ++++++ openflare_server/model/node.go | 2 +- 5 files changed, 46 insertions(+), 8 deletions(-) diff --git a/openflare_server/model/main.go b/openflare_server/model/main.go index 852796ea..028738c9 100644 --- a/openflare_server/model/main.go +++ b/openflare_server/model/main.go @@ -123,10 +123,14 @@ func openDatabase() (*gorm.DB, string, error) { } func autoMigrateAll(db *gorm.DB) error { - for _, item := range registeredModels() { + models := registeredModels() + for i, item := range models { + name := fmt.Sprintf("%T", item) + slog.Info("autoMigrateAll: migrating model", "index", fmt.Sprintf("%d/%d", i+1, len(models)), "model", name) if err := db.AutoMigrate(item); err != nil { - return err + return fmt.Errorf("AutoMigrate %s failed: %w", name, err) } + slog.Info("autoMigrateAll: migrated model", "model", name) } return nil } diff --git a/openflare_server/model/migrate/v19.go b/openflare_server/model/migrate/v19.go index 917b2860..6875702b 100644 --- a/openflare_server/model/migrate/v19.go +++ b/openflare_server/model/migrate/v19.go @@ -64,7 +64,12 @@ func migrateV19(ctx Context, db *gorm.DB, backend string) error { slog.Info("dropped tunnel_id column from proxy_routes") } - return ctx.ApplyCurrentSchema(db, backend) + slog.Info("v19: starting ApplyCurrentSchema (auto-migrate all tables)") + if err := ctx.ApplyCurrentSchema(db, backend); err != nil { + return err + } + slog.Info("v19: ApplyCurrentSchema completed") + return nil } func validateV19(ctx Context, db *gorm.DB, backend string) error { diff --git a/openflare_server/model/migrate/v21.go b/openflare_server/model/migrate/v21.go index 95e15d81..85aa359f 100644 --- a/openflare_server/model/migrate/v21.go +++ b/openflare_server/model/migrate/v21.go @@ -38,15 +38,38 @@ func migrateV21(ctx Context, db *gorm.DB, backend string) error { } } + // Rename agent_version → version (target may already exist if AutoMigrate ran earlier) if migrator.HasColumn(&nodeV21{}, "agent_version") { - if err := migrator.RenameColumn(&nodeV21{}, "agent_version", "version"); err != nil { - return fmt.Errorf("failed to rename agent_version to version: %w", err) + if migrator.HasColumn(&nodeV21{}, "version") { + // version already created by AutoMigrate with empty default; backfill from agent_version + slog.Info("v21: version column already exists, backfilling from agent_version") + if err := db.Exec(`UPDATE nodes SET version = agent_version WHERE version = ''`).Error; err != nil { + return fmt.Errorf("failed to backfill version from agent_version: %w", err) + } + if err := migrator.DropColumn(&nodeV21{}, "agent_version"); err != nil { + slog.Warn("failed to drop agent_version after backfill", "error", err) + } + } else { + if err := migrator.RenameColumn(&nodeV21{}, "agent_version", "version"); err != nil { + return fmt.Errorf("failed to rename agent_version to version: %w", err) + } } } + // Rename nginx_version → ext_version (target may already exist if AutoMigrate ran earlier) if migrator.HasColumn(&nodeV21{}, "nginx_version") { - if err := migrator.RenameColumn(&nodeV21{}, "nginx_version", "ext_version"); err != nil { - return fmt.Errorf("failed to rename nginx_version to ext_version: %w", err) + if migrator.HasColumn(&nodeV21{}, "ext_version") { + slog.Info("v21: ext_version column already exists, backfilling from nginx_version") + if err := db.Exec(`UPDATE nodes SET ext_version = nginx_version WHERE ext_version IS NULL OR ext_version = ''`).Error; err != nil { + return fmt.Errorf("failed to backfill ext_version from nginx_version: %w", err) + } + if err := migrator.DropColumn(&nodeV21{}, "nginx_version"); err != nil { + slog.Warn("failed to drop nginx_version after backfill", "error", err) + } + } else { + if err := migrator.RenameColumn(&nodeV21{}, "nginx_version", "ext_version"); err != nil { + return fmt.Errorf("failed to rename nginx_version to ext_version: %w", err) + } } } diff --git a/openflare_server/model/migrations.go b/openflare_server/model/migrations.go index 8c737858..4f9b6949 100644 --- a/openflare_server/model/migrations.go +++ b/openflare_server/model/migrations.go @@ -184,21 +184,27 @@ func migrateObservabilityLegacyColumns(db *gorm.DB) error { } func applyCurrentSchema(db *gorm.DB, backend string) error { + slog.Info("applyCurrentSchema: step 1/5 - auto migrate schema metadata") if err := autoMigrateSchemaMetadata(db); err != nil { return err } + slog.Info("applyCurrentSchema: step 2/5 - migrate proxy route https column") if err := migrateProxyRouteEnableHTTPSColumn(db); err != nil { return err } + slog.Info("applyCurrentSchema: step 3/5 - auto migrate all models") if err := autoMigrateAll(db); err != nil { return err } + slog.Info("applyCurrentSchema: step 4/5 - migrate text columns") if err := migrateTextColumns(db, backend); err != nil { return err } + slog.Info("applyCurrentSchema: step 5/5 - migrate observability legacy columns") if err := migrateObservabilityLegacyColumns(db); err != nil { return err } + slog.Info("applyCurrentSchema: completed") return nil } diff --git a/openflare_server/model/node.go b/openflare_server/model/node.go index 84222358..0853f90f 100644 --- a/openflare_server/model/node.go +++ b/openflare_server/model/node.go @@ -18,7 +18,7 @@ type Node struct { UpdateChannel string `json:"update_channel" gorm:"size:16;not null;default:'stable'"` UpdateTag string `json:"update_tag" gorm:"size:64"` RestartOpenrestyRequested bool `json:"restart_openresty_requested" gorm:"not null;default:false"` - Version string `json:"version" gorm:"size:64;not null"` + Version string `json:"version" gorm:"size:64;not null;default:''"` ExtVersion string `json:"ext_version" gorm:"size:64"` OpenrestyStatus string `json:"openresty_status" gorm:"size:16;not null;default:'unknown'"` OpenrestyMessage string `json:"openresty_message" gorm:"type:text"`