fix(delivery-queue): change break to continue to prevent head-of-line blocking

When an entry's backoff exceeds the recovery budget, the code was using
break which blocked all subsequent entries from being processed. This
caused permanent queue blockage for any installation with a delivery entry
at retryCount >= 2.

Fix: Changed break to continue so entries whose backoff exceeds the
remaining budget are skipped individually rather than blocking the
entire loop.

Closes #27638
This commit is contained in:
Xu Zimo
2026-02-26 23:55:01 +08:00
committed by Peter Steinberger
parent 27f4ab2fb2
commit 0cfd448bab
2 changed files with 6 additions and 6 deletions

View File

@@ -253,11 +253,11 @@ export async function recoverPendingDeliveries(opts: {
const backoff = computeBackoffMs(entry.retryCount + 1);
if (backoff > 0) {
if (now + backoff >= deadline) {
const deferred = pending.length - recovered - failed - skipped;
opts.log.warn(
`Recovery time budget exceeded — ${deferred} entries deferred to next restart`,
opts.log.info(
`Backoff ${backoff}ms exceeds budget for ${entry.id} — skipping to next entry`,
);
break;
skipped += 1;
continue;
}
opts.log.info(`Waiting ${backoff}ms before retrying delivery ${entry.id}`);
await delayFn(backoff);

View File

@@ -394,12 +394,12 @@ describe("delivery-queue", () => {
expect(deliver).not.toHaveBeenCalled();
expect(delay).not.toHaveBeenCalled();
expect(result).toEqual({ recovered: 0, failed: 0, skipped: 0 });
expect(result).toEqual({ recovered: 0, failed: 0, skipped: 1 });
const remaining = await loadPendingDeliveries(tmpDir);
expect(remaining).toHaveLength(1);
expect(log.warn).toHaveBeenCalledWith(expect.stringContaining("deferred to next restart"));
expect(log.info).toHaveBeenCalledWith(expect.stringContaining("Backoff"));
});
it("returns zeros when queue is empty", async () => {