From 20f758d4cb13fe5fecab2e1dfac0499fff9d809f Mon Sep 17 00:00:00 2001 From: Stephen Schoettler Date: Sun, 1 Mar 2026 20:13:40 -0800 Subject: [PATCH] fix(delivery-queue): break immediately on deadline instead of failing all remaining entries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit P1-C: After now >= deadline, the old code would iterate all remaining queue entries and call failDelivery() on each — O(n) work that nullified the maxRecoveryMs wall-clock cap on large queues. Fix: break out of the recovery loop immediately when the deadline is exceeded. Remaining entries are picked up on next startup unchanged (retryCount not incremented). The deadline means 'stop here', not 'fail everything remaining'. --- src/infra/outbound/delivery-queue.ts | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/infra/outbound/delivery-queue.ts b/src/infra/outbound/delivery-queue.ts index 19765e2545b..a893243ec3f 100644 --- a/src/infra/outbound/delivery-queue.ts +++ b/src/infra/outbound/delivery-queue.ts @@ -344,19 +344,7 @@ export async function recoverPendingDeliveries(opts: { for (const entry of pending) { const now = Date.now(); if (now >= deadline) { - // Increment retryCount on remaining entries so they eventually hit MAX_RETRIES - const remaining = pending.slice(pending.indexOf(entry)); - for (const r of remaining) { - try { - await failDelivery(r.id, "Recovery time budget exceeded — deferred", opts.stateDir); - } catch { - /* best-effort */ - } - } - const deferred = remaining.length; - opts.log.warn( - `Recovery time budget exceeded — ${deferred} entries deferred (retryCount incremented)`, - ); + opts.log.warn(`Recovery time budget exceeded — remaining entries deferred to next startup`); break; } if (entry.retryCount >= MAX_RETRIES) {