feat: DLQ support for Azure Storage Queues#53
Merged
Conversation
When AzureConfig.DLQ is set, messages whose DequeueCount exceeds MaxReceives (default 10) are enqueued to the DLQ and deleted from the source queue before processing is attempted, mirroring SQS redrive semantics. Infra failures (DLQ enqueue or source delete) are logged and return nil so transient errors do not exit the consume loop. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers the seven cases from the plan: below/above threshold, enqueue failure with retry, source-delete failure with retry (verifying the at-least-once duplicate), DLQ disabled, and the MaxReceives/DLQTTL defaults. Retry cases swap the failing mock mid-test to confirm the message actually lands in the DLQ on the subsequent attempt. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Avoids the int32→int64 cast in the DequeueCount comparison. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
On JSON decode failure, only delete from source once DequeueCount reaches maxReceiveCountBeforeDelete (15), mirroring the SQS broker. Below that threshold the message is left on the queue so a configured DLQ (threshold 10) can catch it first. Above the threshold it is deleted as a last resort. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Negative values (e.g. from misconfigured callers) now fall through to defaults rather than being used as-is. time.Duration is int64 so it can be negative; int64 MaxReceives could also be set negatively by mistake. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
TestNew_DLQ_Defaults (internal) exercises the zero-value defaulting in New() itself rather than via the test helper. The redundant DefaultTTL test is removed; a TTL assertion is added to the existing above-threshold happy-path test instead. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
DLQ tests now use a valid JSON body (validDLQTaskBody const) instead of invalid JSON. Above-threshold tests pass nil processor since the DLQ path returns before decode. The disabled-DLQ test uses a countingProcessor and a registered task name to assert normal processing ran, replacing the IgnoreWhenTaskNotRegistered workaround. Decode-failure coverage remains in the dedicated InvalidJSON_* tests in the internal file. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…reshold The old name implied the threshold applied generally; the new name makes clear it only governs deletion of messages that failed JSON decoding. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Each DLQ test now wires a countingProcessor and asserts whether the task was processed. Above-threshold cases assert count=0 (DLQ path returns before decode). BelowThreshold and DefaultMaxReceives register the task and assert count=1 to confirm normal processing ran. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ransition Single test exercises count=10 (processes normally) then count=11 (redrives to DLQ) using an explicit maxReceives=10; the zero-default is already covered by TestNew_DLQ_Defaults in the internal file. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
cameron-dunn-sublime
approved these changes
May 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Support configuring a DLQ for our Azure Storage Queue brokers. Config requires a queue client bound to the destination URL, accepts a max receive count (defaults to 10), and accepts a queue TTL (defaults to 30 days). If configured,
consumeOnewill (upon seeing a message with a dequeue count larger than the max receive count) insert the message using the DLQ client, and upon successful insertion delete from the source queue (does not delete on failed insertion). This will insert duplicate messages into the DLQ on successful insertion followed by failed delete, which in practice should be relatively harmless.