private async Task <object> ProcessNextMiddleware <T>(T command, ICommandBusMiddleware <T>[] middlewares, int middlewareIndex, CommandBusMiddlewareDelegate executionHandler, CommandExecutionOptions executionOptions, CancellationToken cancellationToken) where T : class, ICommandBase { CommandBusMiddlewareDelegate next; if (middlewareIndex == middlewares.Length - 1) { next = executionHandler; } else { next = async processedCommand => { var typedCommand = processedCommand as T ?? throw new ArgumentException( $"Command passed to command bus middleware ({processedCommand?.GetType()}) is not of original type {typeof(T)}"); return(await ProcessNextMiddleware <T>(typedCommand, middlewares, middlewareIndex + 1, executionHandler, executionOptions, cancellationToken)); }; } return(await middlewares[middlewareIndex].HandleAsync(command, executionOptions, next, cancellationToken)); }
private async Task <object> HandleNext(ICommandBase command, CommandBusMiddlewareDelegate next, IUnitOfWork unitOfWork) { ICommandContext newContext = new CommandContext(command, unitOfWork); commandContextStack.Push(newContext); newContext.UnitOfWork?.Begin(); try { var result = await next(command); if (newContext.UnitOfWork != null) { await newContext.UnitOfWork.CommitAsync(); } return(result); } finally { Debug.Assert(commandContextStack.PeekOrDefault == newContext); commandContextStack.Pop(); } }
public async Task HandleAsync_ReturnsResult() { var query = new Query1(); CommandBusMiddlewareDelegate next = async paramCommand => 42; var result = await sut.HandleAsync(query, CommandExecutionOptions.Default, next, CancellationToken.None); result.Should().Be(42); }
public async Task HandleAsync_PopsCommandContextOnException() { var command = new Command1(); CommandBusMiddlewareDelegate next = async paramCommand => { throw new Exception(); }; await sut.Awaiting(x => x.HandleAsync(command, CommandExecutionOptions.Default, next, CancellationToken.None)).Should().ThrowExactlyAsync <Exception>(); commandContextStack.PeekOrDefault.Should().BeNull(); }
public Task <object> ProcessAsync(ICommandBase command, CommandBusMiddlewareDelegate executionHandler, ICommandBus commandBus, CommandExecutionOptions executionOptions, CancellationToken cancellationToken) { var processMethod = GetType().GetRuntimeMethods().Single(x => x.Name == "ProcessInternalAsync"); var boundProcessMethod = processMethod.MakeGenericMethod(command.GetType()); return((Task <object>)boundProcessMethod.Invoke(this, new object[] { command, executionHandler, commandBus, executionOptions, cancellationToken })); }
public async Task HandleAsync_DoesNotCommitWhenConfigured() { var command = new Command1(); CommandBusMiddlewareDelegate next = async paramCommand => { commandContextStack.UnitOfWork.Should().BeNull(); return(null); }; await sut.HandleAsync(command, new CommandExecutionOptions(false, null), next, CancellationToken.None); unitOfWorkFactory.DidNotReceive().CreateUnitOfWork(); }
public async Task HandleAsync_DoesNotCommitForQueries() { var query = new Query1(); CommandBusMiddlewareDelegate next = async paramCommand => { commandContextStack.UnitOfWork.Should().BeNull(); return(null); }; await sut.HandleAsync(query, CommandExecutionOptions.Default, next, CancellationToken.None); unitOfWorkFactory.DidNotReceive().CreateUnitOfWork(); }
public async Task <object> HandleAsync(ICommandBase command, CommandExecutionOptions executionOptions, CommandBusMiddlewareDelegate next, CancellationToken cancellationToken) { if (executionOptions.TenantContext != null) { using (TenantContextOverride.Push(executionOptions.TenantContext.Tenant)) { return(await next(command)); } } else { return(await next(command)); } }
public async Task HandleAsync_CommitsWhenConfigured() { var query = new Query1(); CommandBusMiddlewareDelegate next = async paramCommand => { commandContextStack.UnitOfWork.Should().Be(unitOfWork); return(null); }; await sut.HandleAsync(query, new CommandExecutionOptions(true, null), next, CancellationToken.None); unitOfWorkFactory.Received(1).CreateUnitOfWork(); unitOfWork.Received(1).CommitAsync(); }
public async Task HandleAsync_CommitsForCommands() { var command = new Command1(); CommandBusMiddlewareDelegate next = async paramCommand => { commandContextStack.UnitOfWork.Should().Be(unitOfWork); return(null); }; await sut.HandleAsync(command, CommandExecutionOptions.Default, next, CancellationToken.None); unitOfWorkFactory.Received(1).CreateUnitOfWork(); unitOfWork.Received(1).CommitAsync(); }
public Task <object> HandleAsync(ICommandBase command, CommandExecutionOptions executionOptions, CommandBusMiddlewareDelegate next, CancellationToken cancellationToken) { if (executionOptions.AutoCommitUnitOfWork == true || (executionOptions.AutoCommitUnitOfWork == null && !IsQuery(command))) { using (var uow = unitOfWorkFactory.CreateUnitOfWork()) { return(HandleNext(command, next, uow)); } } else { return(HandleNext(command, next, null)); } }
public async Task <object> HandleAsync(T command, CommandExecutionOptions executionOptions, CommandBusMiddlewareDelegate next, CancellationToken cancellationToken) { await PreFilterAsync(command); try { var result = await next(command); await PostFilterAsync(command); return(result); } catch (Exception e) { await FilterExceptionAsync(command, e); throw; } }
private async Task <object> ProcessInternalAsync <T>(T command, CommandBusMiddlewareDelegate executionHandler, ICommandBus commandBus, CommandExecutionOptions executionOptions, CancellationToken cancellationToken) where T : class, ICommandBase { using (TaskContext.Enter()) { var middlewares = middlewareFactory.CreateMiddlewares <T>(commandBus); if (middlewares.Length == 0) { return(executionHandler(command)); } middlewares = middlewares.OrderBy(x => x.Order).ToArray(); return(await ProcessNextMiddleware(command, middlewares, 0, executionHandler, executionOptions, cancellationToken)); } }
private async Task <TResult> InvokeHandleAsync <TResult>(Type handlerType, ICommandBase command, CommandExecutionOptions executionOptions, CancellationToken cancellationToken) { CommandBusMiddlewareDelegate executionHandler = async processedCommand => { if (processedCommand == null) { throw new ArgumentNullException(nameof(processedCommand)); } if (!command.GetType().IsInstanceOfType(processedCommand)) { throw new ArgumentException( $"Command passed back to command bus from a middleware is not of its original type {command.GetType()}"); } Type commandType = command.GetType(); object listener = serviceLocator.Get(handlerType); var handleMethod = listener.GetType() .GetRuntimeMethod(nameof(ICommandHandler <ICommand> .HandleAsync), new[] { commandType, typeof(CancellationToken) }); var resultTask = (Task)handleMethod.Invoke(listener, new object[] { command, cancellationToken }); if (resultTask is Task <TResult> resultObjectTask) { return(await resultObjectTask); } else { await resultTask; return(null); } }; object result = await pipeline.ProcessAsync(command, executionHandler, this, executionOptions, cancellationToken); return((TResult)result); // TODO test with contravariant handlers }
public async Task HandleAsync_PushesAndPopsCommandContext() { var command = new Command1(); var expectedResult = new object(); int invokedNext = 0; CommandBusMiddlewareDelegate next = async paramCommand => { paramCommand.Should().Be(command); commandContextStack.CurrentCommand.Should().Be(command); unitOfWorkFactory.Received(1).CreateUnitOfWork(); commandContextStack.UnitOfWork.Should().Be(unitOfWork); invokedNext++; return(expectedResult); }; var result = await sut.HandleAsync(command, CommandExecutionOptions.Default, next, CancellationToken.None); invokedNext.Should().Be(1); result.Should().Be(expectedResult); commandContextStack.PeekOrDefault.Should().BeNull(); }