feat(media): 作品保存恢复 - 按原任务重试交付并避免重复生成计费
This commit is contained in:
@@ -11,7 +11,7 @@ import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const CurrentSchemaVersion int64 = 33
|
||||
const CurrentSchemaVersion int64 = 34
|
||||
|
||||
const baselineSchemaChecksum = "sha256:open-ai-canvas-schema-v1-20260830"
|
||||
const schemaMigrationAppliedAtIndexChecksum = "sha256:schema-migrations-applied-at-index-v2-20260830"
|
||||
@@ -107,6 +107,16 @@ var schemaMigrations = []migration{
|
||||
}},
|
||||
{version: 32, name: "channel_model_tags", checksum: "sha256:channel-model-tags-v32", apply: migrateChannelModelTags},
|
||||
{version: 33, name: "oauth_state_accepted_terms", checksum: "sha256:oauth-state-accepted-terms-v33", apply: migrateOAuthStateAcceptedTerms},
|
||||
{version: 34, name: "task_media_recovery", checksum: "sha256:task-media-recovery-v34", apply: func(tx *gorm.DB) error {
|
||||
for _, field := range []string{"MediaRecoveryJSON", "MediaStage"} {
|
||||
if !tx.Migrator().HasColumn(&model.Task{}, field) {
|
||||
if err := tx.Migrator().AddColumn(&model.Task{}, field); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}},
|
||||
}
|
||||
|
||||
func migrateChannelModelTags(tx *gorm.DB) error {
|
||||
|
||||
38
backend/internal/database/task_media_recovery_test.go
Normal file
38
backend/internal/database/task_media_recovery_test.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"infinite-canvas/backend/internal/model"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTaskMediaRecoveryMigrationPreservesHistoricalTasks(t *testing.T) {
|
||||
db, err := Open(Config{Driver: "sqlite", DSN: ":memory:"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sqlDB, _ := db.DB()
|
||||
t.Cleanup(func() { _ = sqlDB.Close() })
|
||||
if err := db.Exec(`CREATE TABLE tasks (id TEXT PRIMARY KEY, status TEXT, error TEXT)`).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := db.Exec(`INSERT INTO tasks VALUES ('old-task', 'failed', 'download failed')`).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for i := 0; i < 2; i++ {
|
||||
if err := schemaMigrations[33].apply(db); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
var task model.Task
|
||||
if err := db.First(&task, "id = ?", "old-task").Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if task.Status != model.TaskStatusFailed || task.Error != "download failed" || task.MediaRecoveryJSON != "" || task.MediaStage != "" {
|
||||
t.Fatalf("migration rewrote historical task: %+v", task)
|
||||
}
|
||||
for _, field := range []string{"media_stage", "media_recovery_json"} {
|
||||
if !db.Migrator().HasColumn(&model.Task{}, field) {
|
||||
t.Fatalf("missing %s", field)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user