Fix global partitioning interceptor not intercepting Kafka messages#2362
Merged
jeremydmiller merged 1 commit intomainfrom Mar 27, 2026
Merged
Fix global partitioning interceptor not intercepting Kafka messages#2362jeremydmiller merged 1 commit intomainfrom
jeremydmiller merged 1 commit intomainfrom
Conversation
The interceptor checked envelope.Message != null to decide whether to intercept, but for Kafka (and other transports that defer deserialization), envelope.Message is always null at the receiver level - only raw envelope.Data bytes and envelope.MessageType metadata are set. This meant the interceptor never fired for Kafka messages, so messages bypassed global partitioning and were processed directly on whichever node received them, causing EventStreamUnexpectedMaxEventIdException from concurrent access to the same Marten event stream. The fix: - GlobalPartitionedInterceptor now falls back to checking envelope.MessageType (string from headers) when envelope.Message is null, and deserializes via Pipeline.TryDeserializeEnvelope() before re-publishing - GlobalPartitionedMessageTopology tracks message type name strings for fast string-based matching, populated both eagerly (Message<T>()) and at startup (for MessagesImplementing<T>() and other scope-based subscriptions) - Added multi-node reproducing test that runs 2 Wolverine hosts with a separate publisher, confirming 0 concurrent access violations Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This was referenced Mar 30, 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.
Summary
GlobalPartitionedInterceptorcheckedenvelope.Message != nullto decide whether to intercept, but Kafka envelopes arrive with only rawenvelope.Databytes —Messageis alwaysnullat the receiver level because deserialization happens later in the handler pipeline. This meant the interceptor never fired for Kafka messages.EventStreamUnexpectedMaxEventIdException.envelope.MessageType(the string type name from Kafka headers) whenenvelope.Messageis null, deserializes viaPipeline.TryDeserializeEnvelope()before re-publishing, andGlobalPartitionedMessageTopologymaintains aHashSet<string>of message type names for fast string-based matching.global_partitioned_aggregate_concurrency) that runs 2 Wolverine hosts with a separate publisher, confirming 0 concurrent access violations (was 17 before fix).Test plan
🤖 Generated with Claude Code