Skip to content

Round-trip Envelope.DeduplicationId, and let a ping reach a FIFO destination (5.x backport, GH-3793) - #3802

Merged
jeremydmiller merged 1 commit into
5.0from
gh-3793/deduplication-id-round-trip-5.0
Aug 3, 2026
Merged

Round-trip Envelope.DeduplicationId, and let a ping reach a FIFO destination (5.x backport, GH-3793)#3802
jeremydmiller merged 1 commit into
5.0from
gh-3793/deduplication-id-round-trip-5.0

Conversation

@jeremydmiller

Copy link
Copy Markdown
Member

5.x backport of #3801, for #3793. The reporter is on .NET 8 LTS and explicitly asked for this — 6.x requires .NET 9.

What it fixes

EnvelopeSerializer wrote GroupId and PartitionKey but never DeduplicationId, so any envelope recovered out of durable storage came back with DeduplicationId == null and was then rejected deterministically by an SNS/SQS FIFO destination without ContentBasedDeduplication:

Invalid parameter: The topic should either have ContentBasedDeduplication enabled or MessageDeduplicationId provided explicitly

Also carried over: the circuit-resume ping could never reach a FIFO destination (it has no DeduplicationId, so a latched sender could never unlatch), and SNS mapped MessageDeduplicationId on standard topics, which AWS rejects outright.

See #3801 for the full write-up.

Differences from the 6.x PR

Otherwise identical.

Verification (net8.0, against LocalStack)

  • CoreTests.Serialization — 47 passed
  • Wolverine.AmazonSns.Tests — 108 passed
  • Wolverine.AmazonSqs.Tests — 188 passed, 1 failed

That one SQS failure is end_to_end_with_conventional_routing_with_prefix.send_from_one_node_to_another_all_with_conventional_routing (BrokerInitializationException: Unable to initialize the Broker sqs in time). It reproduces identically on clean origin/5.0 with none of these changes applied, so it predates this work and is unrelated — nothing here touches broker initialization.

🤖 Generated with Claude Code

https://claude.ai/code/session_0116vfBcKwcjWn8msM4ZjkuA

…ination (GH-3793)

EnvelopeSerializer wrote GroupId and PartitionKey but never DeduplicationId, so
every envelope that went through durable storage -- node recovery after a restart,
or reassignment while a sending agent is latched -- came back with
DeduplicationId == null. Publishing that recovered envelope to an SNS/SQS FIFO
destination without ContentBasedDeduplication is then rejected deterministically
("The topic should either have ContentBasedDeduplication enabled or
MessageDeduplicationId provided explicitly"), so it retries forever or dead-letters.
The exact outage the durable outbox exists to survive was the one case that failed.

The reserved-key guard test already covered the invariant that anything the reader
promotes into a typed property must be filtered out of the loose Headers write, so
the new key joins ReservedHeaderKeys too.

Two related AWS defects, both reproduced against LocalStack:

- Wolverine's own circuit-resume ping carries no DeduplicationId, so it was
  rejected by the same validation -- a latched sender could never probe its way
  back on a FIFO destination no matter how healthy the broker was. Both AWS
  transports now fall back to the envelope id for pings only. That is also the
  semantic we want: every ping body is the same four bytes, so content-based
  deduplication would happily collapse consecutive probes into one.
- SNS mapped MessageDeduplicationId unconditionally, and a *standard* topic
  rejects that parameter outright. It is now gated on the topic type the way
  AmazonSqsQueue already gated it.

Ordinary envelopes with no DeduplicationId are untouched, so FIFO destinations
relying on ContentBasedDeduplication keep working exactly as before.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0116vfBcKwcjWn8msM4ZjkuA
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