-
-
Notifications
You must be signed in to change notification settings - Fork 363
Message dispatch
Since message dispatch is such an important part of Rebus, I think it's fair to dedicate a page to explain how it happens... here goes :)
Message dispatch is what happens when a Rebus endpoint receives a message - and by message, I mean a transport message. A transport message is a serialized thing that has headers and a body, and the body will contain 1 or more logical messages. When you're using the default Rebus operations as exposed directly on IBus
, you will always be shipping one single logical message at a time.
Since Rebus supports batching on the client side, a sender/publisher can optionally send/publish multiple messages at once by using the batch API: bus.Advanced.Batch.Send(IEnumerable ofMessages)
and bus.Advanced.Batch.Publish(IEnumerable ofMessages)
.
When batching messages, the entire batch will be packed into one single transport message which will be handled "at once" by the receiver.
When a transport message has been properly deserialized in the receiving end, Rebus has a sequence of one or more logical messages that must be dispatched.
For each logical message, Rebus will resolve - with multiple calls to the current implementation of IActivateHandlers
- all possible handlers for that logical message. This means that at least two calls will be made for each logical message:
- Resolve
IHandleMessages<YourMessage>
- Resolve
IHandleMessages<object>
which also means that if your message has more base types in its inheritance hierarchy, additional calls will be made.
At this point, no handler has been called yet - Rebus has just resolved all handlers and put them in a sequence.
Now, with this potentially giant pipeline of handlers, Rebus can - if you've configured it to do so - order the pipeline in accordance with the specification made like so:
Configure.With(...)
.(...)
.SpecifyOrderOfHandlers(s => s.First<MustBeFirst>().Then<MustBeSecond>())
.(...)
where you can keep calling .Then<AnotherHandlerType>()
as many times as you want. This is just the built-in mechanism however, you can go and implement IInspectHandlerPipeline
yourself if you want even more control.
Now, finally, we're ready to actually call some handlers! We have a sequence of messages and a sequence of handlers, and the handlers must be called in the right order.
Therefore, we dispatch like this (not actual C# code ;)):
- For each handler
h
** For each logical messagem
*** Ifm
can be dispatched toh
: Do it
AND - this is important - the message queue transaction AND the Rebus unit of work (if you're using that) span this entire process. This means that a single transport message can and should be handled as a single unit of work, either committing or rolling back the whole thing atomically.
Basic stuff
- Home
- Introduction
- Getting started
- Different bus modes
- How does rebus compare to other .net service buses?
- 3rd party extensions
- Rebus versions
Configuration
Scenarios
Areas
- Logging
- Routing
- Serialization
- Pub sub messaging
- Process managers
- Message context
- Data bus
- Correlation ids
- Container adapters
- Automatic retries and error handling
- Message dispatch
- Thread safety and instance policies
- Timeouts
- Timeout manager
- Transactions
- Delivery guarantees
- Idempotence
- Unit of work
- Workers and parallelism
- Wire level format of messages
- Handler pipeline
- Polymorphic message dispatch
- Persistence ignorance
- Saga parallelism
- Transport message forwarding
- Testing
- Outbox
- Startup/shutdown
Transports (not a full list)
Customization
- Extensibility
- Auto flowing user context extensibility example
- Back off strategy
- Message compression and encryption
- Fail fast on certain exception types
Pipelines
- Log message pipelines
- Incoming messages pipeline
- Incoming step context
- Outgoing messages pipeline
- Outgoing step context
Prominent application services