As you have correctly observed, Rebus collects outbound messages sent from within a message handler, ensuring that they're sent AFTER your handler has finished executing.
The reason is, that this is almost always what you want – because otherwise events could be published and thus handled by other services, even before your own unit of work was properly committed(*).
However, if you really want to, you can "escape" Rebus' collection of outgoing messages by temporarily removing the current transaction context like this:
var transactionContext = AmbientTransactionContext.Current;
AmbientTransactionContext.Current = null;
try
{
// current transaction will never know....
await bus.Publish(whee);
}
finally
{
AmbientTransactionContext.Current = transactionContext;
}
If you decide to use this method of escaping the transaction context, I suggest you wrap it in something that implements IDisposable
, so your code could look like this:
using(new RebusTransactionContextDismantler())
{
// current transaction will never know....
await bus.Publish(whee);
}
(*) You could imagine a situation where an event postulates FinalPaymentReceived
, but when a subscriber handles it, the order has not been updated accordingly in the database, because the SQL transaction has not been fully committed yet.
You could also imagine that the SQL transaction could not be committed due to a unique key constraint violation, which may be caused by parallel work being made on some particular object, in which case the SQL transaction is rolled back. It would be pretty disastrous, if events had already been published (and possibly handled!) at that point in time.