From e14d90e37e1f01b3edb0c61a991be3d8d8829936 Mon Sep 17 00:00:00 2001 From: StarFleetCPTN Date: Mon, 7 Apr 2025 00:24:10 -0700 Subject: [PATCH] feat: Add recovery migration for transfer_configs table rename - Introduced a new migration (011a_recover_transfer_configs_rename) to check and recover the transfer_configs table if it was incorrectly renamed to _transfer_configs_old during a previous migration. - Implemented logic to handle various states of the tables, including logging warnings for potential issues. - Ensured that the migration can be safely added to the existing migration sequence. This migration enhances the robustness of the database migration process by addressing potential inconsistencies. --- .../011a_recover_transfer_configs_rename.go | 47 +++++++++++++++++++ internal/db/migrations/migrations.go | 27 ++++++----- 2 files changed, 61 insertions(+), 13 deletions(-) create mode 100644 internal/db/migrations/011a_recover_transfer_configs_rename.go diff --git a/internal/db/migrations/011a_recover_transfer_configs_rename.go b/internal/db/migrations/011a_recover_transfer_configs_rename.go new file mode 100644 index 0000000..cd6dcf3 --- /dev/null +++ b/internal/db/migrations/011a_recover_transfer_configs_rename.go @@ -0,0 +1,47 @@ +package migrations + +import ( + "fmt" + + "github.com/go-gormigrate/gormigrate/v2" + "gorm.io/gorm" +) + +// RecoverTransferConfigsRename checks for and corrects a specific inconsistent state +// left by a potentially failed run of migration 012, where the transfer_configs +// table might have been left renamed as _transfer_configs_old. +func RecoverTransferConfigsRename() *gormigrate.Migration { + return &gormigrate.Migration{ + ID: "011a_recover_transfer_configs_rename", + Migrate: func(tx *gorm.DB) error { + fmt.Println("Running migration 011a: Checking for transfer_configs rename recovery...") + + var oldTableExists int + tx.Raw("SELECT count(*) FROM sqlite_master WHERE type='table' AND name='_transfer_configs_old'").Scan(&oldTableExists) + + var newTableExists int + tx.Raw("SELECT count(*) FROM sqlite_master WHERE type='table' AND name='transfer_configs'").Scan(&newTableExists) + + if oldTableExists > 0 && newTableExists == 0 { + fmt.Println("Found _transfer_configs_old table but not transfer_configs. Attempting recovery rename...") + if err := tx.Exec("ALTER TABLE _transfer_configs_old RENAME TO transfer_configs").Error; err != nil { + return fmt.Errorf("failed to rename _transfer_configs_old back to transfer_configs: %w", err) + } + fmt.Println("Successfully renamed _transfer_configs_old to transfer_configs.") + } else if oldTableExists > 0 && newTableExists > 0 { + // This state shouldn't ideally happen if migration 012 followed its logic, + // but indicates a potential issue. Maybe drop the old one? For now, just log. + fmt.Println("Warning: Both transfer_configs and _transfer_configs_old tables exist. Manual inspection might be needed.") + } else { + fmt.Println("No recovery needed for transfer_configs rename.") + } + + return nil + }, + Rollback: func(tx *gorm.DB) error { + // Rollback doesn't make sense for a recovery step. + fmt.Println("Rollback for migration 011a_recover_transfer_configs_rename is not applicable.") + return nil + }, + } +} diff --git a/internal/db/migrations/migrations.go b/internal/db/migrations/migrations.go index be953b6..956e58b 100644 --- a/internal/db/migrations/migrations.go +++ b/internal/db/migrations/migrations.go @@ -11,19 +11,20 @@ var migrations []*gormigrate.Migration func GetMigrations(db *gorm.DB) *gormigrate.Gormigrate { // Add all migrations in order migrations = append(migrations, - InitialSchema(), // 001 - UpdateGDriveType(), // 002 - Add2FA(), // 003 - AddAuditLogs(), // 004 - AddDefaultRoles(), // 005 - AddTimestampsToJobHistories(), // 006 - AddNotificationServices(), // 007 - AddUserNotifications(), // 008 - AddRcloneTables(), // 009 - AddRcloneCommandToConfig(), // 010 - AddAuthProviders(), // 011 - AlterBooleanDefaults(), // 012 - CleanupInvalidBooleans(), // 013 + InitialSchema(), // 001 + UpdateGDriveType(), // 002 + Add2FA(), // 003 + AddAuditLogs(), // 004 + AddDefaultRoles(), // 005 + AddTimestampsToJobHistories(), // 006 + AddNotificationServices(), // 007 + AddUserNotifications(), // 008 + AddRcloneTables(), // 009 + AddRcloneCommandToConfig(), // 010 + AddAuthProviders(), // 011 + RecoverTransferConfigsRename(), // 011a + AlterBooleanDefaults(), // 012 + CleanupInvalidBooleans(), // 013 ) return gormigrate.New(db, gormigrate.DefaultOptions, migrations)