From d8876ec76ba56565a5a2f627888d26be4525a489 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 9b09aef4550..897963f264b 100644 --- a/src/infra/outbound/delivery-queue.ts +++ b/src/infra/outbound/delivery-queue.ts @@ -303,19 +303,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) {