From 50ba23fae15133a81a78e9238340000a77cfe2d6 Mon Sep 17 00:00:00 2001 From: Codex Date: Sun, 17 May 2026 15:20:22 +0000 Subject: [PATCH] fix: persist code queue retry claims --- src/components/microservices/code-queue/src/index.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/components/microservices/code-queue/src/index.ts b/src/components/microservices/code-queue/src/index.ts index b1df3600..775b6d3d 100644 --- a/src/components/microservices/code-queue/src/index.ts +++ b/src/components/microservices/code-queue/src/index.ts @@ -3398,10 +3398,12 @@ function queueActiveTasksForRestartRetry(reason: string, method: string, options return recovered; } -async function recoverOrphanedActiveTasks(reason: string, method: string): Promise { +async function recoverOrphanedActiveTasks(reason: string, method: string, options: { taskIds?: Set; staleMs?: number } = {}): Promise { + const staleMs = options.staleMs ?? orphanedActiveTaskRecoveryStaleMs; const staleOrphanTaskIds = new Set( state.tasks - .filter((task) => taskIsRecoverableOrphanedActive(task)) + .filter((task) => options.taskIds === undefined || options.taskIds.has(task.id)) + .filter((task) => taskIsRecoverableOrphanedActive(task, staleMs)) .map((task) => task.id), ); if (staleOrphanTaskIds.size === 0) return 0; @@ -3492,7 +3494,7 @@ async function runTask(task: QueueTask): Promise { } if (!claimed) { releaseRunSlot(); - await recoverOrphanedActiveTasks("Database claim found stale active task without local run", "database/claim-recovery"); + await recoverOrphanedActiveTasks("Database claim found stale active task without local run", "database/claim-recovery", { taskIds: new Set([task.id]), staleMs: 0 }); return; } publishTaskOaEvent(task, "claim"); @@ -3550,6 +3552,7 @@ async function runTask(task: QueueTask): Promise { task.updatedAt = nowIso(); appendOutput(task, "system", `judge=fail treated as retry (${task.judgeFailCount}/${judgeFailRetryLimit}); appending continuation prompt to existing session\n`, "queue"); persistTaskState(task); + await flushDirtyTasksToDatabase(true); logger("warn", "task_judge_fail_treated_as_retry", { taskId: task.id, attempt: task.currentAttempt, @@ -3587,6 +3590,7 @@ async function runTask(task: QueueTask): Promise { setAttemptFeedbackPrompt(latestAttempt, nextPrompt, judge.continuePrompt?.trim() ? "judge-continue-prompt" : "judge-retry-generated", task.attempts.length + 1); task.updatedAt = nowIso(); persistTaskState(task); + await flushDirtyTasksToDatabase(true); const delayMs = retryBackoffMs(task.attempts.length); appendOutput(task, "system", `retry backoff ${Math.round(delayMs / 1000)}s before appending continuation to existing session\n`, "queue"); await sleepForRetryBackoff(task, delayMs);