private void DistributeExecution(object payload, object context, Envelope envelope, ICommand commandWithKey, HandlerDescriptor handler) { object key = distributor.Distribute(payload); queue.Enqueue(key, async() => { Action <Exception> additionalExceptionDecorator = e => { AggregateRootException aggregateException = e as AggregateRootException; if (aggregateException != null) { // If envelope is created and contains source command key, use it. IKey sourceCommandKey; if (aggregateException.SourceCommandKey == null && envelope != null && envelope.TryGetSourceCommandKey(out sourceCommandKey)) { aggregateException.SourceCommandKey = sourceCommandKey; } // If command is command with key, use it. if (aggregateException.CommandKey == null && commandWithKey != null) { aggregateException.CommandKey = commandWithKey.Key; } } }; try { if (handler.IsContext) { await handler.Execute(context, additionalExceptionDecorator); } else if (handler.IsEnvelope) { await handler.Execute(envelope, additionalExceptionDecorator); } else if (handler.IsPlain) { await handler.Execute(payload, additionalExceptionDecorator); } else { throw Ensure.Exception.UndefinedHandlerType(handler); } // If we have command with the key, notify about successful execution. if (store != null && commandWithKey != null) { await store.PublishedAsync(commandWithKey.Key); } } catch (Exception e) { DispatcherExceptionHandlers.Handle(e); } }); }