38 lines
1.6 KiB
Go
38 lines
1.6 KiB
Go
package repository
|
|
|
|
import (
|
|
"time"
|
|
|
|
"yingce/backend/internal/model"
|
|
)
|
|
|
|
// The existing task lease fences every checkpoint write, including after cancellation.
|
|
func (r *Repository) SaveTaskMediaCheckpoint(task *model.Task, encrypted, stage string) error {
|
|
result := taskLeaseWriter(r.db.Model(&model.Task{}), task.LeaseOwner).
|
|
Where("id = ? AND user_id = ? AND status = ? AND route_run = ?", task.ID, task.UserID, model.TaskStatusRunning, task.RouteRun).
|
|
Updates(map[string]any{"media_recovery_json": encrypted, "media_stage": stage, "stage": "作品已生成,正在保存", "updated_at": time.Now()})
|
|
if result.Error != nil {
|
|
return result.Error
|
|
}
|
|
if result.RowsAffected != 1 {
|
|
return ErrTaskStateConflict
|
|
}
|
|
task.MediaRecoveryJSON, task.MediaStage = encrypted, stage
|
|
return nil
|
|
}
|
|
|
|
// Manual recovery requeues the same task and order, never a new generation.
|
|
func (r *Repository) RequeueTaskMediaRecovery(task *model.Task, encrypted string) error {
|
|
now := time.Now()
|
|
result := r.db.Model(&model.Task{}).
|
|
Where("id = ? AND user_id = ? AND status = ? AND media_recovery_json = ? AND (lease_expires_at IS NULL OR lease_expires_at <= ?)", task.ID, task.UserID, model.TaskStatusFailed, task.MediaRecoveryJSON, now).
|
|
Updates(map[string]any{"status": model.TaskStatusQueued, "stage": "等待恢复作品保存", "error": "", "completed_at": nil, "next_poll_at": nil, "lease_owner": "", "lease_expires_at": nil, "media_recovery_json": encrypted, "updated_at": now})
|
|
if result.Error != nil {
|
|
return result.Error
|
|
}
|
|
if result.RowsAffected != 1 {
|
|
return ErrTaskStateConflict
|
|
}
|
|
return nil
|
|
}
|