Map Wolverine TenantId from incoming MassTransit messages (supersedes #3167)#3192
Merged
Conversation
…essages Add IMassTransitInterop.MapTenantIdFrom<T>(env => ...) so applications consuming MassTransit messages can derive Wolverine's Envelope.TenantId from either the message body or the MassTransit envelope metadata (headers, addresses, ids). The lambda receives a new public read-only view, IMassTransitEnvelope<T>, exposing the deserialized Message alongside the MassTransit metadata. The concrete MassTransitEnvelope<T> stays internal so the mutable serialization DTO is not leaked. Multiple message types compose; each mapper only fires for its own T and a null/empty result never clobbers an existing tenant id. Inbound (read) path only.
…nd SQS listeners UseMassTransitInterop(configure) dropped the configure lambda on the Rabbit MQ and Amazon SQS listeners: Rabbit MQ called InteropWithMassTransit() with no argument, and the SQS MassTransitMapper never received it. As a result any serializer customization (UseSystemTextJsonForSerialization, and now MapTenantIdFrom) silently no-opped on those transports while only Azure Service Bus honored it. Thread the configure action through to the MassTransit serializer on both. Covered by no-broker tests driving the Rabbit MQ deserialization pipeline end to end and the SQS mapper construction.
…elope interface Follow-up on the MassTransit tenant-id mapping work: instead of exposing a new public IMassTransitEnvelope<T> interface as the MapTenantIdFrom hook type, make the concrete MassTransitEnvelope type public and remove the interface abstraction entirely. - MassTransitEnvelope is now a public abstract base carrying the MassTransit transport metadata (ids, addresses, headers, TransferData); MassTransitEnvelope<T> is the public generic subclass adding the deserialized Message body. The non-generic class is now the base of the generic one (previously inverted) so it can serve as the non-generic handle the serializer needs. - Removed both the internal non-generic IMassTransitEnvelope interface and the IMassTransitEnvelope<T> interface introduced alongside the tenant-id feature. - IMassTransitInterop.MapTenantIdFrom<T> now takes Func<MassTransitEnvelope<T>, string?>. - BusHostInfo is made public so the public MassTransitEnvelope.Host property is consistent. - MassTransitEnvelopeTests now uses MassTransitEnvelope<object> for the non-generic case. Co-authored-by: Geoffrey MARC <geoffrey.marc@consulting-for.edenred.com> 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.
Supersedes #3167 by @outofrange-consulting (Geoffrey MARC), whose original commits are retained here with authorship intact. This adds the requested feature and then reworks the public surface per maintainer review.
Feature (from #3167)
IMassTransitInterop.MapTenantIdFrom<T>(...)lets you derive Wolverine'sEnvelope.TenantIdfor incoming MassTransit messages from either the deserialized message body or the surrounding MassTransit metadata (headers, addresses, ids). It affects only the inbound/deserialization path, supports multiple message types (each mapper fires only for its ownT), and works on every MassTransit-interop listener (RabbitMQ, Azure Service Bus, Amazon SQS). TheUseMassTransitInterop(configure)lambda is now threaded through to the serializer on the RabbitMQ and SQS listeners so the mapping actually takes effect.What changed vs #3167 (public API rework)
#3167 exposed a new public interface
IMassTransitEnvelope<T>as theMapTenantIdFromhook type. Per review, this instead exposes the concreteMassTransitEnvelopetype publicly and removes the interface abstraction:MassTransitEnvelopeis now a public abstract base (MassTransit transport metadata +TransferData);MassTransitEnvelope<T>is the public generic subclass adding the typedMessage. (The non-generic type is now the base of the generic one — previously inverted — so it can serve as the non-generic handle the serializer needs.)IMassTransitEnvelopeand theIMassTransitEnvelope<T>interface that Map Wolverine TenantId from incoming MassTransit messages #3167 introduced.MapTenantIdFrom<T>now takesFunc<MassTransitEnvelope<T>, string?>.BusHostInfois made public so the publicMassTransitEnvelope.Hostproperty has consistent accessibility.Breaking-change assessment
IMassTransitInterop.MapTenantIdFrom<T>is a new member on a public interface → technically a source/binary break for any external implementer ofIMassTransitInterop. In practice the only implementer is the internalMassTransitJsonSerializer(it's a config seam, not a user-implemented interface), andmainis on the 6.0 line where deliberate breaks are acceptable. Low real-world impact.MassTransitEnvelope/MassTransitEnvelope<T>/BusHostInfopublic is additive (they wereinternal).IMassTransitEnvelope<T>only ever existed in the unmerged Map Wolverine TenantId from incoming MassTransit messages #3167, so removing it is not a break to any shipped API.Tests
All MassTransit interop tests pass locally: CoreTests (24, incl. the new
MassTransitTenantMappingTestsand the updatedMassTransitEnvelopeTests), the RabbitMQ stubbedmasstransit_interop_map_tenant_id, and the AWS SQSmasstransit_mapper_tenant_mapping.🤖 Generated with Claude Code