Skip to content

Simplify rabbitmq explicit binding#9911

Open
PascalSenn wants to merge 8 commits into
mainfrom
pse/rework-rabbitmq-explicit-binding
Open

Simplify rabbitmq explicit binding#9911
PascalSenn wants to merge 8 commits into
mainfrom
pse/rework-rabbitmq-explicit-binding

Conversation

@PascalSenn

Copy link
Copy Markdown
Member
  • rework explicity binding of rabbitmq
  • Add bus interceptor functionality to IMessageBusBuilder and related classes

Copilot AI review requested due to automatic review settings June 14, 2026 09:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors transport routing/binding to better support explicit binding (especially for RabbitMQ), adds transport selection controls for outbound routes (OnTransport, default transport validation), and introduces a bus interceptor registration API intended to hook into topology finalization.

Changes:

  • Added transport-selection metadata to outbound routes (TransportName, HasExplicitDestination) plus build-time validation for default transport and OnTransport invariants.
  • Introduced queue-/type-level auto-bind and explicit bind intents (AutoBind, BindFrom) and materialized these intents during receive topology discovery across RabbitMQ/Postgres/InMemory.
  • Added snapshot-based topology assertions and expanded test coverage across transports (including “unified queue” front door behavior and publish endpoint overrides).

Reviewed changes

Copilot reviewed 198 out of 198 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/Mocha/src/Mocha/Builder/MessageBusBuilder.cs Builds interceptor list feature; adds transport configuration validation.
src/Mocha/src/Mocha/Builder/MessageBusBuilder.Interceptors.cs Adds AddBusInterceptor registration APIs and interceptor ordering logic.
src/Mocha/src/Mocha/Abstractions/IMessageBusBuilder.cs Exposes bus interceptor registration API on the builder abstraction.
src/Mocha/src/Mocha/Interceptors/BusInterceptor.cs Defines interceptor hooks for topology lifecycle.
src/Mocha/src/Mocha/Interceptors/BusInterceptorFeature.cs Stores resolved interceptor list as a bus feature.
src/Mocha/src/Mocha/Interceptors/BusInterceptorRegistration.cs Internal model for interceptor registrations.
src/Mocha/src/Mocha/Interceptors/IBusInterceptorTopologyContext.cs Context interface for interceptor topology hooks.
src/Mocha/src/Mocha/Middlewares/DefaultMessageBus.cs Adds PublishOptions.Endpoint override routing to dispatch endpoint.
src/Mocha/src/Mocha/Execution/PublishOptions.cs Adds Endpoint property for publish override.
src/Mocha/src/Mocha/MessageTypes/OutboundRoute.cs Adds HasExplicitDestination + TransportName tracking.
src/Mocha/src/Mocha/MessageTypes/IMessageRouter.cs Switches outbound transport selection to MessagingTransportSelection.
src/Mocha/src/Mocha/MessageTypes/Descriptors/IOutboundRouteDescriptor.cs Adds OnTransport(string) API.
src/Mocha/src/Mocha/MessageTypes/Descriptors/OutboundRouteDescriptor.cs Implements OnTransport(string) storing transport override.
src/Mocha/src/Mocha/MessageTypes/Configurations/OutboundRouteConfiguration.cs Stores TransportName on route configuration.
src/Mocha/src/Mocha/MessageTypes/Extensions/OutboundRouteDescriptorExtensions.cs Documents neutral-scheme addressing constraints in multi-transport setups.
src/Mocha/src/Mocha/Transport/MessagingTransportDescriptor.cs Adds transport-scope AutoBind(bool) to descriptor.
src/Mocha/src/Mocha/Transport/MessagingTransportConfiguration.cs Adds tri-state AutoBind and expands default transport documentation.
src/Mocha/src/Mocha/Transport/MessagingTransport.cs Exposes ConsumerBindingMode, AutoBind, IsDefaultTransport on transports.
src/Mocha/src/Mocha/Consumers/ConsumerBindingMode.cs Reorders binding mode enum (now implicit-first).
src/Mocha/src/Mocha/Endpoints/ReceiveEndpoint.cs Adds OnDiscoverTopology hook prior to convention discovery.
src/Mocha/src/Mocha/Endpoints/ReceiveEndpoint~1.cs Plumbs typed OnDiscoverTopology into generic endpoint base.
src/Mocha/src/Mocha/Endpoints/ReceiveTypeBindIntent.cs Adds intent models for per-type and bind-from declarations.
src/Mocha/src/Mocha/Endpoints/Configurations/ReceiveEndpointConfiguration.cs Adds queue-scope AutoBind, per-type binds, and queue-level bind-from intents.
src/Mocha/src/Mocha/Endpoints/Descriptors/IReceiveEndpointDescriptor.cs Adds Receives<T>(configure), AutoBind, and BindFrom APIs.
src/Mocha/src/Mocha/Endpoints/Descriptors/IReceiveTypeBindDescriptor.cs Adds per-type auto-bind and bind-from fluent API.
src/Mocha/src/Mocha/Endpoints/Descriptors/ReceiveEndpointDescriptor.cs Implements per-type configure overload and merges type bind intents.
src/Mocha/src/Mocha/Endpoints/Descriptors/ReceiveTypeBindDescriptor.cs Collects per-type bind intents and resolves implicit vs explicit AutoBind.
src/Mocha/src/Mocha/Sagas/SagaTransition.cs Removes transition AutoProvision state.
src/Mocha/src/Mocha/Sagas/Saga.Initialization.cs Updates saga transition initialization accordingly.
src/Mocha/src/Mocha/Sagas/Saga.cs Removes AutoProvision from saga descriptions.
src/Mocha/src/Mocha/Sagas/Descriptors/ISagaTransitionDescriptor.cs Removes AutoProvision(...) from saga transition descriptor API.
src/Mocha/src/Mocha/Sagas/Descriptors/SagaTransitionDescriptor.cs Removes AutoProvision(...) implementation.
src/Mocha/src/Mocha/Sagas/Definitions/SagaTransitionConfiguration.cs Removes AutoProvision from transition configuration.
src/Mocha/src/Mocha/Descriptions/SagaTransitionDescription.cs Removes AutoProvision from transition description record.
src/Mocha/src/Mocha.Transport.RabbitMQ/RabbitMQReceiveEndpoint.cs Materializes queue and bind-from intents into RabbitMQ topology.
src/Mocha/src/Mocha.Transport.RabbitMQ/Conventions/RabbitMQDefaultReceiveEndpointConvention.cs Builds typed satellite endpoints (verbatim names, disable flags, auto-provision inheritance).
src/Mocha/src/Mocha.Transport.RabbitMQ/Configurations/RabbitMQReceiveEndpointConfiguration.cs Adds typed satellite config and queue-specific durable/args/autoprovision fields.
src/Mocha/src/Mocha.Transport.RabbitMQ/Configurations/RabbitMQSatelliteConfiguration.cs Adds typed satellite configuration model (name/disable/autoprovision).
src/Mocha/src/Mocha.Transport.RabbitMQ/Configurations/RabbitMQDispatchEndpointConfiguration.cs Adds dispatch-queue auto-provision override.
src/Mocha/src/Mocha.Transport.RabbitMQ/Topology/RabbitMQTopologyShapeConflictException.cs Adds explicit exception for conflicting declared vs convention shapes.
src/Mocha/src/Mocha.Transport.RabbitMQ/Topology/RabbitMQTopologyProvenance.cs Adds provenance constants for declared/convention/endpoint topology nodes.
src/Mocha/src/Mocha.Transport.RabbitMQ/Topology/Descriptors/RabbitMQQueueDescriptor.cs Marks declared queue provenance on descriptor-created queues.
src/Mocha/src/Mocha.Transport.RabbitMQ/Topology/Descriptors/RabbitMQExchangeDescriptor.cs Marks declared exchange provenance on descriptor-created exchanges.
src/Mocha/src/Mocha.Transport.RabbitMQ/Topology/Descriptors/RabbitMQBindingDescriptor.cs Marks declared binding provenance on descriptor-created bindings.
src/Mocha/src/Mocha.Transport.RabbitMQ/Topology/Descriptors/IRabbitMQExchangeContributionDescriptor.cs Adds interface for partial exchange contribution (publish/send).
src/Mocha/src/Mocha.Transport.RabbitMQ/Topology/Configurations/RabbitMQQueueConfiguration.cs Adds provenance metadata to queue config.
src/Mocha/src/Mocha.Transport.RabbitMQ/Topology/Configurations/RabbitMQExchangeConfiguration.cs Adds provenance metadata defaulting to convention.
src/Mocha/src/Mocha.Transport.RabbitMQ/Topology/Configurations/RabbitMQBindingConfiguration.cs Adds provenance metadata defaulting to convention.
src/Mocha/src/Mocha.Transport.RabbitMQ/RabbitMQPublishExchangeFeature.cs Stores publish-exchange partial declaration as a feature.
src/Mocha/src/Mocha.Transport.RabbitMQ/RabbitMQSendExchangeFeature.cs Stores send-exchange partial declaration as a feature.
src/Mocha/src/Mocha.Transport.RabbitMQ/RabbitMQMessageTypeExtensions.cs Adds PublishExchange/SendExchange message type extensions.
src/Mocha/src/Mocha.Transport.RabbitMQ/Descriptors/IRabbitMQReceiveEndpointDescriptor.cs Adds typed satellites + bind/auto-bind APIs to RabbitMQ receive descriptors.
src/Mocha/src/Mocha.Transport.RabbitMQ/Descriptors/IRabbitMQMessagingTransportDescriptor.cs Adds AutoBind and unified Queue(...) front door APIs.
src/Mocha/src/Mocha.Transport.Postgres/PostgresMessagingTransport.cs Uses destination resolver for endpoint configuration + neutral scheme claiming rules.
src/Mocha/src/Mocha.Transport.Postgres/PostgresReceiveEndpoint.cs Materializes queue/topic + bind-from intents into Postgres topology.
src/Mocha/src/Mocha.Transport.Postgres/Conventions/PostgresDispatchEndpointTopologyConvention.cs Ensures bridge topics in implicit mode via resolver.
src/Mocha/src/Mocha.Transport.Postgres/Conventions/PostgresDefaultReceiveEndpointConvention.cs Adds typed satellite naming/disable behavior.
src/Mocha/src/Mocha.Transport.Postgres/Configurations/PostgresReceiveEndpointConfiguration.cs Adds typed satellite configuration to receive endpoints.
src/Mocha/src/Mocha.Transport.Postgres/Configurations/PostgresSatelliteConfiguration.cs Adds typed satellite config model (name/disable).
src/Mocha/src/Mocha.Transport.Postgres/Topology/PostgresMessagingTopology.cs Allows merging queue/topic duplicates (strengthening AutoProvision).
src/Mocha/src/Mocha.Transport.Postgres/Topology/PostgresQueue.cs Adds merge behavior for queue provisioning settings.
src/Mocha/src/Mocha.Transport.Postgres/Topology/PostgresTopic.cs Adds merge behavior for topic provisioning settings.
src/Mocha/src/Mocha.Transport.Postgres/Descriptors/IPostgresReceiveEndpointDescriptor.cs Adds typed satellites + bind/auto-bind APIs to Postgres receive descriptors.
src/Mocha/src/Mocha.Transport.Postgres/Descriptors/IPostgresMessagingTransportDescriptor.cs Adds AutoBind and unified Queue(...) front door APIs.
src/Mocha/src/Mocha.Transport.Postgres/Descriptors/IPostgresQueueEndpointDescriptor.cs Adds unified queue endpoint descriptor (pinned identity).
src/Mocha/src/Mocha.Transport.InMemory/InMemoryMessagingTransport.cs Uses destination resolver for endpoint configuration + neutral scheme claiming rules.
src/Mocha/src/Mocha.Transport.InMemory/InMemoryReceiveEndpoint.cs Materializes queue/topic + bind-from intents into in-memory topology.
src/Mocha/src/Mocha.Transport.InMemory/Topology/InMemoryMessagingTopology.cs Returns existing queue/topic on duplicates instead of throwing.
src/Mocha/src/Mocha.Transport.InMemory/Descriptors/InMemoryReceiveEndpointDescriptor.cs Adds queue identity pinning and bind/auto-bind APIs.
src/Mocha/src/Mocha.Transport.InMemory/Descriptors/IInMemoryReceiveEndpointDescriptor.cs Adds bind/auto-bind APIs to in-memory receive descriptor interface.
src/Mocha/src/Mocha.Transport.InMemory/Descriptors/IInMemoryMessagingTransportDescriptor.cs Adds AutoBind and unified Queue(...) front door APIs.
src/Mocha/src/Mocha.Transport.InMemory/Descriptors/IInMemoryQueueEndpointDescriptor.cs Adds unified queue endpoint descriptor (pinned identity).
src/Mocha/test/Mocha.Transport.RabbitMQ.Tests/Mocha.Transport.RabbitMQ.Tests.csproj Adds CookieCrumble snapshot test project references/analyzers.
src/Mocha/test/Mocha.Transport.RabbitMQ.Tests/Helpers/RabbitMQDescribeSnapshot.cs Adds deterministic JSON projection for RabbitMQ topology snapshots.
src/Mocha/test/Mocha.Transport.RabbitMQ.Tests/RabbitMQReceiveEndpointTests.cs Updates tests to typed satellites (ErrorQueue/SkippedQueue).
src/Mocha/test/Mocha.Transport.RabbitMQ.Tests/Descriptors/RabbitMQHandlerBindingTests.cs Adds CookieCrumble snapshot assertions for binding modes and auto-bind behavior.
src/Mocha/test/Mocha.Transport.RabbitMQ.Tests/Descriptors/RabbitMQQueueFrontDoorTests.cs Adds unified Queue(...) endpoint convergence tests.
src/Mocha/test/Mocha.Transport.RabbitMQ.Tests/Routing/RabbitMQTransportResolverWiringTests.cs Adds wiring tests for resolver-based dispatch endpoint configuration.
src/Mocha/test/Mocha.Transport.RabbitMQ.Tests/**/snapshots/*.snap Adds/updates many RabbitMQ topology snapshots reflecting new discovery/merge behavior.
src/Mocha/test/Mocha.Transport.Postgres.Tests/Helpers/PostgresDescribeSnapshot.cs Adds deterministic JSON projection for Postgres topology snapshots.
src/Mocha/test/Mocha.Transport.Postgres.Tests/PostgresSatelliteTests.cs Adds typed satellite behavior snapshots for Postgres.
src/Mocha/test/Mocha.Transport.Postgres.Tests/PostgresReceiveEndpointBindFromTests.cs Adds BindFrom intent materialization + routing key rejection tests.
src/Mocha/test/Mocha.Transport.Postgres.Tests/Routing/PostgresTransportResolverWiringTests.cs Adds wiring tests for resolver-based dispatch endpoint configuration.
src/Mocha/test/Mocha.Transport.Postgres.Tests/Routing/PostgresDestinationResolverTests.cs Adds resolver unit tests for convention vs explicit destinations.
src/Mocha/test/Mocha.Transport.Postgres.Tests/Descriptors/PostgresDescriptorTests.cs Updates descriptor tests for typed satellites and auto-bind defaults.
src/Mocha/test/Mocha.Transport.Postgres.Tests/Topology/PostgresMessageTypeExtensionTests.cs Updates test stub to satisfy new OnTransport route API.
src/Mocha/test/Mocha.Transport.Postgres.Tests/**/snapshots/*.snap Adds Postgres topology snapshots for new behavior.
src/Mocha/test/Mocha.Transport.InMemory.Tests/Topology/InMemoryMessagingTopologyTests.cs Updates topology duplicate behavior tests (return existing).
src/Mocha/test/Mocha.Transport.InMemory.Tests/InMemoryReceiveEndpointBindFromTests.cs Adds routing key rejection tests for BindFrom on in-memory transport.
src/Mocha/test/Mocha.Transport.InMemory.Tests/InMemoryHandlerClaimTests.cs Adds tests for explicit binding mode and claim convergence behavior.
src/Mocha/test/Mocha.Transport.InMemory.Tests/Descriptors/InMemoryUnifiedQueueTests.cs Adds unified queue delivery and entity-only lowering tests.
src/Mocha/test/Mocha.Transport.InMemory.Tests/Descriptors/InMemoryDescriptorTests.cs Adds auto-bind default/override tests.
src/Mocha/test/Mocha.Transport.InMemory.Tests/Behaviors/RequestReplyTests.cs Adds request/reply regression test under explicit binding mode.
src/Mocha/test/Mocha.Transport.InMemory.Tests/Behaviors/PublishOptionsEndpointTests.cs Adds behavior test for PublishOptions.Endpoint override.
src/Mocha/test/Mocha.Transport.InMemory.Tests/Topology/snapshots/*.snap Adds/updates in-memory topology snapshots for auto-bind suppression behavior.
src/Mocha/test/Mocha.Tests/MessageTypes/OutboundRouteTests.cs Adds tests for HasExplicitDestination semantics.
src/Mocha/test/Mocha.Tests/MessageTypes/NeutralSchemeResolutionTests.cs Adds tests for neutral-scheme default transport claim behavior.
src/Mocha/test/Mocha.Tests/MessageTypes/MessageBusBuilderTransportValidationTests.cs Adds build-time transport invariant validation tests + snapshots.
src/Mocha/test/Mocha.Tests/Endpoints/ReceiveTypeBindDescriptorTests.cs Adds tests for per-type bind intent accumulation and auto-bind resolution rules.
src/Mocha/test/Mocha.Tests/Conventions/DefaultNamingConventionsTests.cs Adds kebab-casing test for error-queue-like pascal input.
src/Mocha/test/Mocha.Sagas.Tests/SagaExecutionTests.cs Removes saga transition auto-provision assertion.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/Mocha/src/Mocha/Consumers/ConsumerBindingMode.cs Outdated
Comment on lines +7 to +11
public sealed class ReceiveTypeBindDescriptor : IReceiveTypeBindDescriptor
{
private bool? _explicitAutoBind;
private bool _hasBindFrom;
private List<BindFromIntent>? _bindFroms;
Comment on lines +103 to +108
// Merge: explicit AutoBind from the incoming descriptor wins over an implied value;
// if both are null (neither configured), keep null; BindFroms accumulate.
var mergedAutoBind = incoming.ResolvedAutoBind ?? existing.AutoBind;
var mergedBindFroms = existing.BindFroms.Count == 0 && incoming.BindFroms.Count == 0
? (IReadOnlyList<BindFromIntent>)[]
: [.. existing.BindFroms, .. incoming.BindFroms];
Comment on lines +49 to +56
topology.AddQueue(
new RabbitMQQueueConfiguration
{
Name = configuration.QueueName,
AutoDelete = Kind == ReceiveEndpointKind.Reply,
AutoProvision = configuration.AutoProvision,
Provenance = RabbitMQTopologyProvenance.Endpoint
});
Comment on lines +25 to +29
var declaredQueue = transport.Configuration is RabbitMQTransportConfiguration rabbitMQConfiguration
? rabbitMQConfiguration.Queues.FirstOrDefault(q => q.Name == queueName)
: null;
var inheritedAutoProvision = declaredQueue?.AutoProvision ?? configuration.AutoProvision;

Comment on lines +450 to +453
// Build the ordered, IsEnabled-filtered interceptor list once, before any transport
// initialization, so transports may observe it through the feature collection if needed.
var interceptors = BuildInterceptorList(services);
features.Set(new BusInterceptorFeature { Interceptors = interceptors });

// assert
// The inbound route for ImplicitDestinationEvent is created by the handler
var inboundRoute = runtime.Router.InboundRoutes.Single(r => r.MessageType?.RuntimeType == typeof(ImplicitDestinationEvent));
Comment thread src/Mocha/src/Mocha/Transport/MessagingTransportSelection.cs Fixed

topology!.AddTopic(config1);
var first = topology!.AddTopic(config1);
var countAfterFirst = topology.Topics.Count;

topology!.AddQueue(config1);
var first = topology!.AddQueue(config1);
var countAfterFirst = topology.Queues.Count;
Comment thread src/Mocha/src/Mocha/Transport/MessagingTransport.Lifecyle.cs Fixed
Comment thread src/Mocha/src/Mocha/Transport/MessagingTransportSelection.cs Fixed
Comment thread src/Mocha/src/Mocha/Transport/MessagingTransportSelection.cs Fixed
Comment thread src/Mocha/src/Mocha/Transport/MessagingTransportSelection.cs Fixed
@PascalSenn PascalSenn force-pushed the pse/rework-rabbitmq-explicit-binding branch from c70351e to c2fd5e7 Compare June 14, 2026 10:45
- Removed deprecated RabbitMQQueueFrontDoorTests and consolidated queue handling logic.
- Updated RabbitMQUnifiedQueueTests to reflect changes in queue naming and binding behavior.
- Adjusted RabbitMQReceiveEndpointBindFromTests to utilize the new unified queue approach.
- Modified RabbitMQReceiveEndpointTests to streamline queue declarations and handlers.
- Enhanced RabbitMQSatelliteTests to ensure proper queue provisioning and consumer attachment.
- Updated snapshots to reflect changes in queue source from "endpoint" to "declared" for clarity.
Comment thread src/Mocha/src/Mocha/Transport/MessagingTransportSelection.cs Fixed
Comment thread src/Mocha/src/Mocha/Transport/MessagingTransportSelection.cs Fixed
Comment thread src/Mocha/src/Mocha/Transport/MessagingTransportSelection.cs Fixed
- Removed BindFrom method from IReceiveEndpointDescriptor and its implementations in RabbitMQ and Postgres transport descriptors.
- Updated ReceiveEndpointConfiguration to eliminate QueueBindFroms property.
- Adjusted ReceiveTypeBindDescriptor to remove BindFrom method and related logic.
- Simplified tests to reflect changes in binding behavior, ensuring that AutoBind settings are correctly applied without explicit BindFrom declarations.
- Cleaned up documentation and comments related to binding behavior across various transport implementations.
{
if (transports.IsEmpty)
{
throw ThrowHelper.NoTransportForMessageType(route.MessageType);
Comment thread src/Mocha/src/Mocha/Transport/MessagingTransport.Lifecyle.cs Fixed
Comment on lines +35 to +44
foreach (var transport in transports)
{
if (transport.Schema == scheme)
{
// Multiple transports with the same schema is not expected in a valid configuration,
// but we return the first match here since schemas are unique by convention.
matched = transport;
break;
}
}
Comment on lines +72 to +83
foreach (var transport in transports)
{
if (transport.IsDefaultTransport)
{
if (defaultTransport is not null)
{
multipleDefaults = true;
}

defaultTransport = transport;
}
}
- Changed binding method from BindHandlersExplicitly to BindExplicitly across multiple test files to standardize binding behavior.
- Updated snapshot files to reflect changes in RabbitMQ topology descriptions.
- Removed obsolete snapshots that are no longer relevant due to the refactor.
- Adjusted test assertions to ensure they align with the new binding logic.
Comment on lines +253 to +270
foreach (var route in router.InboundRoutes)
{
if (route.Endpoint is { Transport: { } endpointTransport } endpoint
&& endpointTransport == this
&& route.MessageType is { RuntimeType: { } runtimeType })
{
if (!claimedTypeEndpoints.TryGetValue(runtimeType, out var endpoints))
{
endpoints = [];
claimedTypeEndpoints[runtimeType] = endpoints;
}

if (!endpoints.Contains(endpoint))
{
endpoints.Add(endpoint);
}
}
}
Comment on lines +136 to +143
foreach (var route in context.Router.GetOutboundByMessageType(messageType))
{
if (route is { HasExplicitDestination: true, Kind: OutboundRouteKind.Publish })
{
var resolution = resolver.ResolveDestination(context.Naming, route);
return new ChainEntry(resolution.Kind, resolution.Name, IsExplicit: true);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants