Repository navigation
Keep the inbox id of a durable envelope when a CloudEvent with a Guid id is read from its data - #5396
Merged
Merged
Conversation
… id is read from its data
There was a problem hiding this comment.
🟡 Changes recommended
The private test helper needs to be renamed to guidIdJson, with both callers updated, to match the existing camelCase naming convention.
1 open issue
What changed in this PR
Preserves durable inbox identifiers when Wolverine reads CloudEvents with GUID ids, keeping subsequent inbox updates tied to the stored envelope.
Changes:
- Prevents GUID CloudEvent ids from replacing persisted envelope ids during
ReadFromData. - Adds unit coverage for persisted and non-persisted envelopes.
- Adds a Kafka/PostgreSQL regression test for CloudEvents with a default incoming message type.
| File | Description |
|---|---|
src/Wolverine/Runtime/Interop/CloudEventsMapper.cs |
Preserves persisted inbox ids during CloudEvent deserialization. |
src/Transports/Kafka/Wolverine.Kafka.Tests/cloudevents_with_default_incoming_message_keeps_inbox_id.cs |
Checks that successful handling does not leave the inbox row Incoming. |
src/Testing/CoreTests/Runtime/Interop/CloudEventsMapper_non_guid_id_tests.cs |
Tests GUID id behavior for persisted and non-persisted envelopes. |
Review effort: Balanced
Comment on lines
+56
to
+73
| Id = storedId, WasPersistedInInbox = true, Data = Encoding.UTF8.GetBytes(GuidIdJson(Guid.NewGuid())) | ||
| }; | ||
| _mapper.ReadFromData(typeof(Order), envelope); | ||
|
|
||
| envelope.Id.ShouldBe(storedId); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void reading_an_envelope_not_held_in_the_inbox_takes_a_guid_cloud_event_id() | ||
| { | ||
| var cloudEventId = Guid.NewGuid(); | ||
| var envelope = new Envelope { Id = Guid.NewGuid(), Data = Encoding.UTF8.GetBytes(GuidIdJson(cloudEventId)) }; | ||
| _mapper.ReadFromData(typeof(Order), envelope); | ||
|
|
||
| envelope.Id.ShouldBe(cloudEventId); | ||
| } | ||
|
|
||
| private static string GuidIdJson(Guid id) => |
jeremydmiller
added a commit
that referenced
this pull request
Nov 6, 2026
…reads the messageId (#5398) * MassTransit interop keeps the inbox id of a durable envelope when it reads the messageId MassTransitEnvelope.TransferData always replaced Envelope.Id with the MassTransit messageId when the handler pipeline deserialized the body. On SQS the MassTransit mapper leaves the id to the listener, which derives it from the SQS message, and the durable inbox stores the envelope under that id. Mark-handled, retry and dead-letter then matched no row, so the inbox row stayed Incoming and ran again on recovery. Same shape as the CloudEvents case in #5396. TransferData now leaves the id alone for an envelope that WasPersistedInInbox. Tests: CoreTests unit test, and an SQS (LocalStack) + PostgreSQL inbox test that fails without the fix with the row left Incoming. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Reset WithinCodegenCommand after the codegen-command test so later hosts are not MediatorOnly The GH-5391 test runs `codegen test` / `codegen write` through RunJasperFxCommands, which leaves the process-wide DynamicCodeBuilder.WithinCodegenCommand flag set. applyMetadataOnlyModeIfDetected then starts every later host in that test process in MediatorOnly mode, so whichever CoreTests ran after it in the same worker failed ("This operation is not allowed with Wolverine is bootstrapped in MediatorOnly mode") -- red on main at 6.62.1, green at a89e663, depending only on test order. Reset the flag after the commands and in finally, and run the class in a non-parallel collection so no host starts while the flag is set (the same arrangement Wolverine.Grpc.Tests uses for this flag). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.

Problem
CloudEventsMapper.mapIncomingoverwritesenvelope.Idwith the CloudEvent id whenever that id parses as a Guid. GH-5364 addedkeepExistingIdforReadFromData, but only for the non-Guid branch.Reachable path: a Kafka listener with CloudEvents interop,
DefaultIncomingMessage<T>()and the durable inbox.KafkaListenersetsenvelope.MessageType ??= _messageTypeName(KafkaListener.cs:229), so the message type is already set when the receiver sees the envelope.DurableReceivercallsUnwrapEnvelopeIfNecessaryonly whenMessageTypeis empty, so Unwrap is skipped and the envelope is stored inwolverine_incoming_envelopesunder its transport id.WasPersistedInInboxbecomes true.HandlerPipelinecallsserializer.ReadFromData(...)->mapIncoming(..., keepExistingId: true), and the Guid branch replacesenvelope.Idwith the CloudEvent id.envelope.Idand match no row. The row staysIncomingand is run again on recovery, a retry is not persisted, and a dead-lettered message stays in the inbox.Fix
The Guid branch leaves
envelope.Idalone whenkeepExistingIdis set and the envelopeWasPersistedInInbox. A non-persisted envelope still takes the CloudEvent id, andUnwrap(keepExistingId: false) is unchanged.Tests
DefaultIncomingMessage+ durable inbox. After the handler succeeds, the inbox row is not leftIncoming.Both new tests fail without the fix and pass with it. Without it the Kafka test reports
statuses should not contain "Incoming" but was actually ["Incoming"].