diff options
Diffstat (limited to 'internal/storage')
| -rw-r--r-- | internal/storage/db.go | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/internal/storage/db.go b/internal/storage/db.go index 31d38ed..01ce902 100644 --- a/internal/storage/db.go +++ b/internal/storage/db.go @@ -210,6 +210,44 @@ func (s *DB) UpdateTaskState(id string, newState task.State) error { return tx.Commit() } +// ResetTaskForRetry sets a task to QUEUED and clears its agent type/model +// so it can be re-classified. +func (s *DB) ResetTaskForRetry(id string) (*task.Task, error) { + tx, err := s.db.Begin() + if err != nil { + return nil, err + } + defer tx.Rollback() //nolint:errcheck + + t, err := scanTask(tx.QueryRow(`SELECT id, name, description, config_json, priority, timeout_ns, retry_json, tags_json, depends_on_json, parent_task_id, state, created_at, updated_at, rejection_comment, question_json FROM tasks WHERE id = ?`, id)) + if err != nil { + if err == sql.ErrNoRows { + return nil, fmt.Errorf("task %q not found", id) + } + return nil, err + } + + if !task.ValidTransition(t.State, task.StateQueued) { + return nil, fmt.Errorf("invalid state transition %s → %s for task %q", t.State, task.StateQueued, id) + } + + t.Agent.Type = "" + t.Agent.Model = "" + configJSON, _ := json.Marshal(t.Agent) + + now := time.Now().UTC() + if _, err := tx.Exec(`UPDATE tasks SET state = ?, config_json = ?, updated_at = ? WHERE id = ?`, + string(task.StateQueued), string(configJSON), now, id); err != nil { + return nil, err + } + + if err := tx.Commit(); err != nil { + return nil, err + } + t.State = task.StateQueued + return t, nil +} + // RejectTask sets a task's state to PENDING and stores the rejection comment. func (s *DB) RejectTask(id, comment string) error { now := time.Now().UTC() |
