Skip to content

Commit b07312c

Browse files
stephenschoettlersteipete
authored andcommitted
fix(delivery-queue): increment retryCount on deadline-deferred entries
Codex P1: entries deferred by the recovery time budget kept retryCount=0 forever, so they could loop across restarts without ever reaching MAX_RETRIES. After breaking on deadline, call failDelivery() for all remaining entries so retryCount is incremented. Entries stay in queue until MAX_RETRIES is reached and they are pruned normally. Also updates the maxRecoveryMs test to assert retryCount=1 on deferred entries.
1 parent 329e539 commit b07312c

2 files changed

Lines changed: 15 additions & 2 deletions

File tree

src/infra/outbound/delivery-queue.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,10 +341,19 @@ export async function recoverPendingDeliveries(opts: {
341341
let skippedMaxRetries = 0;
342342
let deferredBackoff = 0;
343343

344-
for (const entry of pending) {
344+
for (let i = 0; i < pending.length; i++) {
345+
const entry = pending[i];
345346
const now = Date.now();
346347
if (now >= deadline) {
347348
opts.log.warn(`Recovery time budget exceeded — remaining entries deferred to next startup`);
349+
// Increment retryCount for all remaining entries so that entries which
350+
// are consistently deferred by the time budget eventually reach
351+
// MAX_RETRIES and are pruned rather than looping forever.
352+
await Promise.allSettled(
353+
pending
354+
.slice(i)
355+
.map((e) => failDelivery(e.id, "recovery time budget exceeded", opts.stateDir)),
356+
);
348357
break;
349358
}
350359
if (entry.retryCount >= MAX_RETRIES) {

src/infra/outbound/outbound.test.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,10 +504,14 @@ describe("delivery-queue", () => {
504504
expect(result.skippedMaxRetries).toBe(0);
505505
expect(result.deferredBackoff).toBe(0);
506506

507-
// All entries should still be in the queue.
507+
// All entries should still be in the queue (retryCount < MAX_RETRIES).
508508
const remaining = await loadPendingDeliveries(tmpDir);
509509
expect(remaining).toHaveLength(3);
510510

511+
// retryCount should be incremented on all deferred entries so they
512+
// eventually reach MAX_RETRIES and are pruned rather than looping forever.
513+
expect(remaining.every((e) => e.retryCount === 1)).toBe(true);
514+
511515
// Should have logged a warning about deferred entries.
512516
expect(log.warn).toHaveBeenCalledWith(expect.stringContaining("deferred to next startup"));
513517
});

0 commit comments

Comments
 (0)