Skip to content

fix: skip DB update in failed handler on intermediate BullMQ retry attempts#92

Merged
DaxServer merged 2 commits into
mainfrom
fix/source-cdn-error-retry
Jun 7, 2026
Merged

fix: skip DB update in failed handler on intermediate BullMQ retry attempts#92
DaxServer merged 2 commits into
mainfrom
fix/source-cdn-error-retry

Conversation

@DaxServer

Copy link
Copy Markdown
Owner

BullMQ fires the failed event after every failed attempt, not only the final one. For SourceCdnError and HashLockError (which rely on BullMQ's built-in attempts: 3 retry), the handler was calling clearUploadAccessToken on attempt 1. This left the access token null, so the retry attempt hit the !upload.access_token guard and returned without throwing — silently marking the upload as failed with 'session expired' instead of retrying the actual CDN error.

The fix adds an early return in the failed handler when job.attemptsMade < job.opts.attempts and the error is not a StorageError (which has its own custom requeue path and must always run).

— Claude Sonnet 4.6

…tempts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 5/5

Safe to merge — the change is a targeted guard in the failed event handler with no impact on the happy path, and the new tests confirm the DB is left untouched on intermediate retries.

The guard condition (attemptsMade < opts.attempts ?? 1) is correct for all three cases: intermediate retry (skip DB), final failure (run DB update), and jobs with no retry configured (always run DB update). StorageError is correctly excluded so its custom requeue logic still runs every time. The previous concern about the misleading log on intermediate retries is resolved — the logger.error call now sits below the early return.

No files require special attention.

Important Files Changed

Filename Overview
backend/src/workers/upload.worker.ts Early-return guard added for intermediate BullMQ retries; logic is correct and the ?? 1 fallback handles jobs with no retry config safely.
backend/src/tests/upload.worker.test.ts New test block covers the intermediate-retry case for HashLockError and SourceCdnError; existing tests for permanent failure and StorageError requeue remain intact.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["BullMQ 'failed' event fires"] --> B{job defined?}
    B -- No --> Z[return]
    B -- Yes --> C{err instanceof StorageError?}
    C -- Yes --> F["Run StorageError requeue logic"]
    C -- No --> D{"attemptsMade < opts.attempts?"}
    D -- Yes --> E["logger.warn / return early — DB untouched"]
    D -- No --> G["logger.error / updateUploadStatus / clearUploadAccessToken"]
    F --> H{requeueCount < MAX?}
    H -- Yes --> I["updateStatus queued / removeJob / enqueueUpload"]
    H -- No --> G
Loading

Reviews (2): Last reviewed commit: "fix: emit warn (not error) for intermedi..." | Re-trigger Greptile

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@DaxServer

Copy link
Copy Markdown
Owner Author

Fixed — moved the log call inside the handler so intermediate retries now emit logger.warn ("job attempt failed, will retry") instead of logger.error ("job permanently failed"). The error-level log only fires on the final permanent failure.

— Claude Sonnet 4.6

@DaxServer DaxServer merged commit 6c3d949 into main Jun 7, 2026
5 checks passed
@DaxServer DaxServer deleted the fix/source-cdn-error-retry branch June 7, 2026 12:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant