feat(tasks): add coalescing queue and task lifecycle guards
- Coalescing queue: use HasPendingTaskForIssue (queued/dispatched only) instead of HasActiveTaskForIssue so comments during a running task enqueue exactly one follow-up task that picks up all new comments. - Stale task cleanup: runtime sweeper now fails orphaned tasks when their runtime goes offline (daemon crash/network partition). - Cancel-aware daemon: handleTask checks task status after execution and discards results if the task was cancelled mid-run (e.g. reassign). - Terminal issue guard: ClaimTaskForRuntime auto-cancels pending tasks for done/cancelled issues instead of executing them. - Race condition safety net: unique partial index ensures at most one pending task per issue at the DB level.
This commit is contained in:
parent
32f795e1ef
commit
b112d1f1ae
13 changed files with 148 additions and 3 deletions
|
|
@ -325,6 +325,18 @@ func (h *Handler) CompleteTask(w http.ResponseWriter, r *http.Request) {
|
|||
writeJSON(w, http.StatusOK, taskToResponse(*task))
|
||||
}
|
||||
|
||||
// GetTaskStatus returns the current status of a task.
|
||||
// Used by the daemon to check whether a task was cancelled mid-execution.
|
||||
func (h *Handler) GetTaskStatus(w http.ResponseWriter, r *http.Request) {
|
||||
taskID := chi.URLParam(r, "taskId")
|
||||
task, err := h.Queries.GetAgentTask(r.Context(), parseUUID(taskID))
|
||||
if err != nil {
|
||||
writeError(w, http.StatusNotFound, "task not found")
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, map[string]string{"status": task.Status})
|
||||
}
|
||||
|
||||
// FailTask marks a running task as failed.
|
||||
type TaskFailRequest struct {
|
||||
Error string `json:"error"`
|
||||
|
|
|
|||
|
|
@ -389,9 +389,11 @@ func (h *Handler) shouldEnqueueOnComment(ctx context.Context, issue db.Issue) bo
|
|||
if !h.isAgentTriggerEnabled(ctx, issue, "on_comment") {
|
||||
return false
|
||||
}
|
||||
// Don't enqueue if there's already an active task for this issue.
|
||||
hasActive, err := h.Queries.HasActiveTaskForIssue(ctx, issue.ID)
|
||||
if err != nil || hasActive {
|
||||
// Coalescing queue: allow enqueue when a task is running (so the agent
|
||||
// picks up new comments on the next cycle) but skip if a pending task
|
||||
// already exists (natural dedup for rapid-fire comments).
|
||||
hasPending, err := h.Queries.HasPendingTaskForIssue(ctx, issue.ID)
|
||||
if err != nil || hasPending {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue