Pulsar: transport-default DLQ/retry precedence + resolve DLQ-sender TODOs (#3186)#3194
Merged
Merged
Conversation
…default TODOs (#3186) Resolves the two loose-end TODOs in the Pulsar transport. - Transport-vs-endpoint defaults (PulsarTransport.cs): the transport-level DeadLetterTopic and RetryLetterTopic are now true defaults that each endpoint inherits unless it sets its own, resolved per-endpoint-override-wins via the new PulsarEndpoint.EffectiveDeadLetterTopic / EffectiveRetryLetterTopic (mirrors the Kafka transport-default + per-endpoint override shape). UsePulsar(...) now returns a PulsarConfiguration exposing DeadLetterQueueing(...) / RetryLetterQueueing(...) to set the defaults. The listener now keys native DLQ/retry enablement and topic names off the effective values, so a transport default actually takes effect. - DLQ sender (PulsarEndpoint.cs): the stub is resolved by decision rather than a competing implementation. Pulsar native dead-lettering is owned by PulsarListener (ISupportDeadLetterQueue), which produces to the {topic}-DLQ topic WITH the native reconsume metadata and retry-letter-topic chaining; WolverineStorage mode uses the durable store. Returning an endpoint-level sender here makes BufferedReceiver/DurableReceiver report NativeDeadLetterQueueEnabled, which MessageContext.tryGetDeadLetterQueue prefers over the listener — hijacking the richer native path and dropping the reconsume metadata (caught by PulsarNativeReliabilityTests). So TryBuildDeadLetterSender intentionally defers to the base. - DeadLetterStorage now reports Native when a native DLQ is in effect (for monitoring). Tests: precedence + effective-topic resolution and TryBuildDeadLetterSender-always-false unit tests added; existing PulsarNativeReliabilityTests continue to cover native DLQ end-to-end with exception headers. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jun 23, 2026
Closed
This was referenced Jul 9, 2026
This was referenced Jul 16, 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.
First PR of the Pulsar re-evaluation epic #3176. Fixes #3186.
Resolves the two loose-end TODOs in the Pulsar transport.
Transport-vs-endpoint defaults (
PulsarTransport.cs:31TODO)The transport-level
DeadLetterTopic/RetryLetterTopicare now real defaults that each endpoint inherits unless it sets its own, resolved per-endpoint-override-wins through the newPulsarEndpoint.EffectiveDeadLetterTopic/EffectiveRetryLetterTopic— mirroring the Kafka transport-default + per-endpoint override shape.UsePulsar(...)now returns aPulsarConfigurationexposingDeadLetterQueueing(...)/RetryLetterQueueing(...)to set the defaults.PulsarListenerkeys native DLQ/retry enablement and the resolved topic names off the effective values, so a transport default actually takes effect.DLQ sender (
PulsarEndpoint.cs:118TODO) — resolved by decisionThe stub looked like missing functionality, but native dead-lettering is already fully handled by
PulsarListener(ISupportDeadLetterQueue), which produces to the{topic}-DLQtopic with the native reconsume metadata and retry-letter-topic chaining;WolverineStoragemode uses the durable store.Implementing a competing endpoint-level
TryBuildDeadLetterSenderactively regresses this:BufferedReceiver/DurableReceiverthen reportNativeDeadLetterQueueEnabled, andMessageContext.tryGetDeadLetterQueueprefers the receiver (_channel) over the listener — hijacking the richer native path and dropping the reconsume metadata. This was caught byPulsarNativeReliabilityTests(differential: passes onmain, failed with the naive sender impl). SoTryBuildDeadLetterSenderintentionally defers to the base, documented inline.DeadLetterStoragenow reportsNativewhen a native DLQ is in effect (for monitoring).Tests
TryBuildDeadLetterSenderis always false (native owned by the listener; WolverineStorage by the durable store).PulsarNativeReliabilityTests.🤖 Generated with Claude Code