GithubHelp home page GithubHelp logo

rebus-org / rebus.unitofwork Goto Github PK

View Code? Open in Web Editor NEW
2.0 4.0 1.0 3 MB

:bus: Unit of work helper for Rebus

Home Page: https://mookid.dk/category/rebus

License: Other

C# 91.39% Batchfile 8.61%
rebus unitofwork

rebus.unitofwork's Introduction

Rebus.UnitOfWork

install from nuget

Provides a unit of work helper for Rebus.


The unit of work helper works with C# generics and lets you represent your unit of work as anything that makes sense to you.

You configure it like this:

Configure.With(activator)
    .Transport(t => t.Use(...))
    .Options(o => o.EnableUnitOfWork(...))
    .Start();

for the synchronous version, or

Configure.With(activator)
    .Transport(t => t.Use(...))
    .Options(o => o.EnableAsyncUnitOfWork(...))
    .Start();

if you want a unit of work that supports asynchronous creation, completion, etc.

An example could be an Entity Framework database context, MyDbContext, which you then manage like this:

Configure.With(activator)
    .Transport(t => t.Use(...))
    .Options(o => o.EnableAsyncUnitOfWork(
        create: async context => new MyDbContext(),
        commit: async (context, uow) => await uow.SaveChangesAsync(),
        dispose: async (context, uow) => uow.Dispose()
    ))
    .Start();

By the power of C# generics, uow passed to the commit and dispose functions above will have the same type as the one returned from the create method.

context will be the current IMessageContext, which is also statically accessible via MessageContext.Current, this way enabling injection of your unit of work by using the message context to share it:

Configure.With(activator)
    .Transport(t => t.Use(...))
    .Options(o => o.EnableAsyncUnitOfWork(
        create: async context =>
        {
            var uow = new MyDbContext();
            context.TransactionContext.Items["current-uow"] = uow;
            return uow;
        },
        commit: async (context, uow) => await uow.SaveChangesAsync(),
        dispose: async (context, uow) => uow.Dispose()
    ))
    .Start();

and then you can configure your IoC container to be able to inject MyDbContext - e.g. with Microsoft Extensions Dependency Injection like this:

services.AddScoped(p =>
{
    var context = p.GetService<IMessageContext>() 
                    ?? throw new InvalidOperationException("Cannot resolve db context outside of Rebus handler, sorry");

    return context.TransactionContext.Items.TryGetValue("current-uow", out var result)
        ? (MyDbContext)result
        : throw new ArgumentException("Didn't find db context under 'current-uow' key in current context");

});

rebus.unitofwork's People

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

torangel

rebus.unitofwork's Issues

Missing exception handling in UoW factory

The code in UnitOfWorkStep.Process() goes like this:

        var unitOfWork = await _unitOfWorkFactoryMethod(messageContext);

        try
        {
            await next();
            await _commitAction(messageContext, unitOfWork);
        }
        catch (Exception)
        {
            await _rollbackAction(messageContext, unitOfWork);
            throw;
        }
        finally
        {
            await _cleanupAction(messageContext, unitOfWork);
        }

That means we have some nice exception handling with cleanup around commit and rollback. But why not handle exceptions from the factory method?

The issue is that the factory method, in our case (but is seems rather natural), is responsible for setting up the transation ... and sometimes that fails, possibly because of network errors or other infrastructure issues.

When the factory method fails, cleanup is not called - leading to various wonderful and catastrophic error conditions afterwards.

Out fix is to add our own cleanup handling in the factory method - but it should be handled by the bus infrastructure code calling _cleanupAction().

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.