-
-
Notifications
You must be signed in to change notification settings - Fork 361
Transactions
Out of the box, Rebus will NOT use DTC. This is a deliberate design choice, because my opinion is that data consistency and resiliency against failures are are much better handled by being conscious about how those things work and what the consequences are.
Another thing is that distributed transactions are usually quite expensive, performance-wise, because of the communication overhead involved. Also, since DTC (as everyone else) is subject to the CAP theorem, it will have to give up availability (the 'A' in CAP) when a network partition occurs.
To put it shortly: By committing transactions in the right order.
Nothing to worry about here - just bus.Send
the message, and all is good.
Since publishing a message with Rebus consists of sending the message directly to possibly many subscribers, these two operations are equivalent (unless you're using the RabbitMQ transport in its multicast incarnation - then a bus.Publish
translates into one single publish in RabbitMQ).
So, if it's important to you that either ALL or NONE of the recipients/subscribers get the message, you must perform the operation in a transaction. You can do that by letting Rebus enlist in an ordinary ambient transaction like so:
using(var tx = new TransactionScope())
{
// perform several calls to the queueing system in here
bus.Send(something);
bus.Send(somethingElse);
bus.Publish(whatever);
tx.Complete();
}
This will work, because Rebus' transports are nice enough to enlist a lightweight queue transaction in the ambient transaction, thus allowing all queue interactions to be performed withing that transaction, and thus committed/rolled back atomically.
In this special case, Rebus will create a queue transaction which will surround the entire processing of the message. This means that Rebus will
- receive the incoming message
- send/publish all outgoing messages
as a part of the same queue transaction.
This also means that if your work fails, the queue transaction is rolled back, and nothing is lost.
THE ONLY THING TO LOOK OUT FOR: is if your work SUCCEEDS, but committing the queue transaction fails, then the incoming message will be received again. But this time, you will already have performed your work - but none of your outgoing messages will have been sent.
In this case - and you may already have figured this out - you must keep adhering to the rules of how to implement idempotency, which state that you must perform the same externally visible actions, even when your internal state reveals that you have already processed the incoming message.
If you want to use DTC, you'll have to do some work yourself. At the moment, no transport implementation exists for Rebus that can enlist in a distributed transaction.
It shouldn't be that hard to create one though, e.g. by grabbing the existing MsmqMessageQueue
, copy the source code to a new class, e.g. DtcMsmqMessageQueue
, and then use MSMQ in a way that enlists the queue transaction in a way that allows for DTC escalation.
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