Any messages send/publish inside a message handler will be dispatched when the transaction is committed. (This is a really nice OOTB behaviour)
I have implemented UnitOfWork per your example. Discovered that if a exception occurred inside the action of OnCommitted(action)
the enqueued messages might get sent, it just depends if the deliver task is executed before the uow.commit()
action.
I have found a work around by adding a process step that at the end of the receive pipeline. It checks if a uow exists in the current context and then commits the uow. If a exception like a database schema change occurs during the commit it happens before OnCommitted is called and non of the enqueued messages is dispatched.
What is the correct way to implement a UnitOfWork with Rebus?
Could you try the Rebus.UnitOfWork package and see if you can use it?
It provides a redesigned unit of work API for Rebus that allows you to go:
Configure.With(...)
.(...)
.Options(o => {
o.EnableUnitOfWork(Create, Commit);
})
where Create
and Commit
could be like this:
public YourOwnUnitOfWork Create(IMessageContext context)
{
return new YourOwnUnitOfWork(...);
}
public void Commit(IMessageContext context, YourOwnUnitOfWork uow)
{
uow.Commit();
}