Repository navigation
Implement message type binding for receive endpoints and enhance error handling - #9870
Merged
Merged
Conversation
…r handling - Added `Receives<TMessage>()` and `Receives(Type messageType)` methods to endpoint descriptors for binding handlers by message type. - Updated `MessagingTransport` to utilize the new binding methods and throw exceptions when no handler is registered for a message type. - Introduced tests to validate the new binding behavior and error handling. - Updated documentation to reflect the new binding approach for message types.
Address devil's-advocate review of Receives<T> binding: - BindRouteToEndpoint now copies the source route's Condition onto the fan-out clone, so custom filters and saga typed-reply guards are no longer widened to a default condition. - Add an idempotency guard so declaring the same message type or consumer across three or more endpoints does not over-clone routes. Add regression tests: condition preservation on fan-out, no duplicate routes across three endpoints, and behavioral delivery to both queues. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ve test coverage for receives
Contributor
There was a problem hiding this comment.
Pull request overview
This PR adds a new way to explicitly bind receive endpoints by message type (in addition to binding by handler/consumer type), updates transport initialization to apply those bindings (and fail fast when a declared message type has no handlers), and documents/tests the behavior across transports.
Changes:
- Added
Receives<TMessage>()/Receives(Type)to receive endpoint descriptors and configuration (ReceivedMessageTypes). - Updated
MessagingTransportinitialization to bind inbound routes to endpoints based on declared received message types, and to throw when no matching handler/consumer exists. - Added/updated transport tests and docs/examples demonstrating message-type binding.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| website-next/content/docs/mocha/routing-and-endpoints.md | Documents binding endpoints by message type via .Receives<T>(). |
| src/Mocha/test/Mocha.Transport.RabbitMQ.Tests/Behaviors/ExplicitTopologyTests.cs | Adds RabbitMQ explicit-topology test coverage for .Receives<T>(). |
| src/Mocha/test/Mocha.Transport.Postgres.Tests/Behaviors/ExplicitTopologyTests.cs | Adds Postgres explicit-topology test coverage for .Receives<T>(). |
| src/Mocha/test/Mocha.Transport.InMemory.Tests/ReceivesTests.cs | New InMemory-focused tests for binding/fan-out/idempotency/error behavior of .Receives<T>(). |
| src/Mocha/src/Mocha/Transport/MessagingTransport.Lifecyle.cs | Implements binding routes to endpoints by declared message types; introduces shared binding helper. |
| src/Mocha/src/Mocha/ThrowHelper.cs | Adds a dedicated exception helper for “no handler for message type declared on endpoint”. |
| src/Mocha/src/Mocha/Endpoints/Descriptors/ReceiveEndpointDescriptor.cs | Implements .Receives<TMessage>() / .Receives(Type) on the base descriptor. |
| src/Mocha/src/Mocha/Endpoints/Descriptors/IReceiveEndpointDescriptor.cs | Extends the public descriptor interface with the new .Receives APIs. |
| src/Mocha/src/Mocha/Endpoints/Configurations/ReceiveEndpointConfiguration.cs | Adds ReceivedMessageTypes to persist declared message-type bindings. |
| src/Mocha/src/Mocha.Transport.RabbitMQ/Descriptors/RabbitMQReceiveEndpointDescriptor.cs | Adds fluent .Receives methods returning the RabbitMQ-specific descriptor type. |
| src/Mocha/src/Mocha.Transport.RabbitMQ/Descriptors/IRabbitMQReceiveEndpointDescriptor.cs | Extends RabbitMQ receive endpoint interface with .Receives methods. |
| src/Mocha/src/Mocha.Transport.Postgres/Descriptors/PostgresReceiveEndpointDescriptor.cs | Adds fluent .Receives methods returning the Postgres-specific descriptor type. |
| src/Mocha/src/Mocha.Transport.Postgres/Descriptors/IPostgresReceiveEndpointDescriptor.cs | Extends Postgres receive endpoint interface with .Receives methods. |
| src/Mocha/src/Mocha.Transport.InMemory/Descriptors/InMemoryReceiveEndpointDescriptor.cs | Adds fluent .Receives methods returning the InMemory-specific descriptor type. |
| src/Mocha/src/Mocha.Transport.InMemory/Descriptors/IInMemoryReceiveEndpointDescriptor.cs | Extends InMemory receive endpoint interface with .Receives methods. |
| src/Mocha/examples/PostgresTransport/PostgresTransport.OrderService/Program.cs | Updates example to demonstrate using .Receives<T>() for explicit topology. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
47
to
52
| foreach (var handlerType in endpointConfiguration.ConsumerIdentities) | ||
| { | ||
| var consumer = context.Consumers.FirstOrDefault(h => h.Identity == handlerType); | ||
| var consumer = context.Consumers.FirstOrDefault(h => h.Identity == handlerType) | ||
| ?? throw new InvalidOperationException( | ||
| $"Handler type {handlerType.FullName} not found for endpoint {Configuration.Name}"); | ||
|
|
Comment on lines
+141
to
+154
| // The route is bound to another endpoint, so fan it out by adding an equivalent route to | ||
| // this endpoint. Skip when an equivalent route is already present so binding the same | ||
| // message type or consumer across three or more endpoints stays idempotent. | ||
| // Conditions are not part of the equivalence check, so two routes for the same consumer | ||
| // and message type that differ only by condition will not both be fanned out. | ||
| foreach (var existing in context.Router.GetInboundByEndpoint(endpoint)) | ||
| { | ||
| if (existing.Consumer == route.Consumer | ||
| && existing.Kind == route.Kind | ||
| && existing.MessageType == route.MessageType) | ||
| { | ||
| return; | ||
| } | ||
| } |
This was referenced Jun 16, 2026
This was referenced Jun 24, 2026
This was referenced Jul 20, 2026
chore(deps): Bump HotChocolate.Subscriptions.InMemory from 15.1.14 to 16.5.1
Kuestenlogik/Bowire#506
Merged
This was referenced Aug 31, 2026
This was referenced Sep 8, 2026
This was referenced Sep 17, 2026
This was referenced Sep 28, 2026
This was referenced Oct 5, 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.
Receives<TMessage>()andReceives(Type messageType)methods to endpoint descriptors for binding handlers by message type.MessagingTransportto utilize the new binding methods and throw exceptions when no handler is registered for a message type.