Skip to content

Instantly share code, notes, and snippets.

@lukeschafer
Created March 2, 2014 23:14
Show Gist options
  • Save lukeschafer/6bd8551c25b3ce8c2781 to your computer and use it in GitHub Desktop.
Save lukeschafer/6bd8551c25b3ce8c2781 to your computer and use it in GitHub Desktop.
Concept for transaction support for Nimbus.
internal class CommandMessageDispatcher : IMessageDispatcher
{
private readonly ICommandHandlerFactory _commandHandlerFactory;
private readonly Type _commandType;
private readonly ITransactionFactory _transactionFactory;
public CommandMessageDispatcher(ICommandHandlerFactory commandHandlerFactory, Type commandType, ITransactionFactory transactionFactory)
{
_commandHandlerFactory = commandHandlerFactory;
_commandType = commandType;
_transactionFactory = transactionFactory;
}
public async Task Dispatch(BrokeredMessage message)
{
var busCommand = message.GetBody(_commandType);
await Dispatch((dynamic) busCommand, message);
}
private async Task Dispatch<TBusCommand>(TBusCommand busCommand, BrokeredMessage message) where TBusCommand : IBusCommand
{
using (var handler = _commandHandlerFactory.GetHandler<TBusCommand>())
{
if (HasAttribute(() => handler.Component.Handle(busCommand), typeof (TransactionalAttribute)))
{
await Transactionally(handler.Component, busCommand);
}
else
{
await handler.Component.Handle(busCommand);
}
}
}
private async Task Transactionally<TBusCommand>(IHandleCommand<TBusCommand> handler, TBusCommand command) where TBusCommand : IBusCommand
{
var t = Task.Factory.StartNew(() =>
{
using (var transaction = _transactionFactory.CreateScope())
{
var result = handler.Handle(command);
result.Wait();
transaction.Complete();
}
});
await t;
}
private static bool HasAttribute(Expression<Action> expression, Type attrType)
{
var body = (MethodCallExpression)expression.Body;
return body.Method.GetCustomAttributes(attrType, false).Any(); ;
}
}
from
public async Task Handle(SubmitOrder message)
{
Task t;
using (var transaction = new TransactionScope())
{
t = Task.Factory.StartNew(() => { }); //do some work, send a command etc....
transaction.Complete();
}
await t;
}
to
[Transactional]
public async Task Handle(SubmitOrder message)
{
await Task.Factory.StartNew(() => { });
}
@lukeschafer
Copy link
Author

Wraps a call to Handle(message) in a transaction. Uses ITransactionFactory (default to local trans) that can be reconfigured in the container to use DTC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment