Search code examples
messagingunit-of-workrebus

Unexpected behaviour during UnitOfWork


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?


Solution

  • 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();
    }