public async Task CommandHandlerIsResolvedOnlyInsideExecutionHandler() { var commandHandler = Substitute.For <ICommandHandler <TestCommand> >(); serviceLocator.Get(typeof(ICommandHandler <TestCommand>)).Returns(commandHandler); var command = new TestCommand(); var cancellationToken = new CancellationToken(); var executionOptions = new CommandExecutionOptions(); commandBusPipeline .ProcessAsync(command, Arg.Any <CommandBusMiddlewareDelegate>(), sut, executionOptions, cancellationToken) .Returns(ci => { serviceLocator.DidNotReceive().Get(typeof(ICommandHandler <TestCommand>)); var result = ci.ArgAt <CommandBusMiddlewareDelegate>(1)(command); serviceLocator.Received(1).Get(typeof(ICommandHandler <TestCommand>)); return(result); }); await sut.SendAsync(command, executionOptions, cancellationToken); commandHandler.Received(1).HandleAsync(command, cancellationToken); }
public async Task Handle_RunsInNewTaskScope() { TaskContext middlewareContext = null; var middlewares = new[] { Substitute.For <ICommandBusMiddleware <MyCommand> >() }; var command = new MyCommand(); var cancellationToken = new CancellationToken(); var executionOptions = new CommandExecutionOptions(); var executionHandler = Substitute.For <CommandBusMiddlewareDelegate>(); middlewareFactory.CreateMiddlewares <MyCommand>(commandBus) .Returns(middlewares); middlewares[0] .When(x => x.HandleAsync(command, executionOptions, Arg.Any <CommandBusMiddlewareDelegate>(), cancellationToken)) .Do(ci => middlewareContext = TaskContext.Current); var beforeContext = TaskContext.Current; await sut.ProcessAsync(command, executionHandler, commandBus, executionOptions, cancellationToken); var afterContext = TaskContext.Current; beforeContext.Should().BeSameAs(afterContext); beforeContext.Should().NotBeSameAs(middlewareContext); middlewareContext.Should().NotBeNull(); }
public async Task ProcessAsync_MiddlewaresInvokedInOrder(bool reverseMiddlewares) { var middlewares = new[] { Substitute.For <ICommandBusMiddleware <MyCommand> >(), Substitute.For <ICommandBusMiddleware <MyCommand> >() }; var command = new MyCommand(); var command2 = new MyCommand(); var command3 = new MyCommand(); var cancellationToken = new CancellationToken(); var executionOptions = new CommandExecutionOptions(); var executionHandler = Substitute.For <CommandBusMiddlewareDelegate>(); middlewares[0].Order = 1; middlewares[0] .When(x => x.HandleAsync(command, executionOptions, Arg.Any <CommandBusMiddlewareDelegate>(), cancellationToken)) .Do(ci => { middlewares[1].DidNotReceiveWithAnyArgs().HandleAsync(null, null, null, CancellationToken.None); executionHandler.DidNotReceiveWithAnyArgs().Invoke(null); var next = ci.ArgAt <CommandBusMiddlewareDelegate>(2); next(command2); }); middlewares[1].Order = 2; middlewares[1] .When(x => x.HandleAsync(command2, executionOptions, Arg.Any <CommandBusMiddlewareDelegate>(), cancellationToken)) .Do(ci => { middlewares[0].Received(1).HandleAsync(command, executionOptions, Arg.Any <CommandBusMiddlewareDelegate>(), cancellationToken); executionHandler.DidNotReceiveWithAnyArgs().Invoke(null); var next = ci.ArgAt <CommandBusMiddlewareDelegate>(2); next(command3); }); middlewareFactory.CreateMiddlewares <MyCommand>(commandBus) .Returns(reverseMiddlewares ? middlewares.Reverse().ToArray() : middlewares); await sut.ProcessAsync(command, executionHandler, commandBus, executionOptions, cancellationToken); middlewares[0].Received(1).HandleAsync(command, executionOptions, Arg.Any <CommandBusMiddlewareDelegate>(), cancellationToken); middlewares[1].Received(1).HandleAsync(command2, executionOptions, Arg.Any <CommandBusMiddlewareDelegate>(), cancellationToken); executionHandler.Received(1).Invoke(command3); }
public static async Task Main(string[] args) { var options = new CommandExecutionOptions { Prefix = "t!" }; var message = new Message("t!TestCommand a, https://httpstat.us/404"); var handler = new CommandHandler(options); await handler.RunAsync(message); }
/// <summary> /// Execute database command /// </summary> /// <param name="server">Database server</param> /// <param name="executionOptions">Execution options</param> /// <param name="databaseExecutionCommands">Database execution commands</param> /// <param name="useTransaction">Whether use transaction</param> /// <returns>Return affected data number</returns> async Task <int> ExecuteDatabaseCommandAsync(DatabaseServer server, CommandExecutionOptions executionOptions, IEnumerable <DatabaseExecutionCommand> databaseExecutionCommands, bool useTransaction) { int resultValue = 0; bool success = true; using (var conn = PostgreSqlManager.GetConnection(server)) { IDbTransaction transaction = null; if (useTransaction) { transaction = PostgreSqlManager.GetExecutionTransaction(conn, executionOptions); } try { foreach (var cmd in databaseExecutionCommands) { var cmdDefinition = new CommandDefinition(cmd.CommandText, PostgreSqlManager.ConvertCmdParameters(cmd.Parameters), transaction: transaction, commandType: cmd.CommandType, cancellationToken: executionOptions?.CancellationToken ?? default); var executeResultValue = await conn.ExecuteAsync(cmdDefinition).ConfigureAwait(false); success = success && (cmd.MustAffectedData ? executeResultValue > 0 : true); resultValue += executeResultValue; if (useTransaction && !success) { break; } } if (!useTransaction) { return(resultValue); } if (success) { transaction.Commit(); } else { resultValue = 0; transaction.Rollback(); } return(resultValue); } catch (Exception ex) { resultValue = 0; transaction?.Rollback(); throw ex; } } }
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 ProcessAsync_WhenNoMiddleware() { var middlewares = new ICommandBusMiddleware <MyCommand> [0]; middlewareFactory.CreateMiddlewares <MyCommand>(commandBus) .Returns(middlewares); var command = new MyCommand(); var cancellationToken = new CancellationToken(); var executionOptions = new CommandExecutionOptions(); var executionHandler = Substitute.For <CommandBusMiddlewareDelegate>(); await sut.ProcessAsync(command, executionHandler, commandBus, executionOptions, cancellationToken); executionHandler.Received(1).Invoke(command); }
public async Task SendAsync_SelectsCorrectHandler() { var commandHandler = Substitute.For <ICommandHandler <TestCommand> >(); serviceLocator.Get(typeof(ICommandHandler <TestCommand>)).Returns(commandHandler); var command = new TestCommand(); var cancellationToken = new CancellationToken(); var executionOptions = new CommandExecutionOptions(); commandBusPipeline .ProcessAsync(command, Arg.Any <CommandBusMiddlewareDelegate>(), sut, executionOptions, cancellationToken) .Returns(ci => ci.ArgAt <CommandBusMiddlewareDelegate>(1)(command)); await sut.SendAsync(command, executionOptions, cancellationToken); commandHandler.Received(1).HandleAsync(command, cancellationToken); }
public async Task SendAsync_ReturnsFromQuery() { var commandHandler = Substitute.For <ICommandHandler <TestQuery, int> >(); serviceLocator.Get(typeof(ICommandHandler <TestQuery, int>)).Returns(commandHandler); var command = new TestQuery(); var cancellationToken = new CancellationToken(); var executionOptions = new CommandExecutionOptions(); commandHandler.HandleAsync(command, cancellationToken).Returns(42); commandBusPipeline .ProcessAsync(command, Arg.Any <CommandBusMiddlewareDelegate>(), sut, executionOptions, cancellationToken) .Returns(ci => ci.ArgAt <CommandBusMiddlewareDelegate>(1)(command)); int result = await sut.SendAsync(command, executionOptions, cancellationToken); result.Should().Be(42); }
/// <summary> /// Get execution transaction /// </summary> /// <param name="connection">Database connection</param> /// <param name="executionOptions">Execution options</param> /// <returns></returns> public static IDbTransaction GetExecutionTransaction(IDbConnection connection, CommandExecutionOptions executionOptions) { DataIsolationLevel?dataIsolationLevel = executionOptions?.IsolationLevel; if (!dataIsolationLevel.HasValue) { dataIsolationLevel = DataManager.GetDataIsolationLevel(CurrentDatabaseServerType); } var systemIsolationLevel = DataManager.GetSystemIsolationLevel(dataIsolationLevel); if (connection.State != ConnectionState.Open) { connection.Open(); } return(systemIsolationLevel.HasValue ? connection.BeginTransaction(systemIsolationLevel.Value) : connection.BeginTransaction()); }
/// <summary> /// Execute command /// </summary> /// <param name="server">Database server</param> /// <param name="executionOptions">Execution options</param> /// <param name="commands">Commands</param> /// <returns>Return the affected data numbers</returns> public async Task <int> ExecuteAsync(DatabaseServer server, CommandExecutionOptions executionOptions, IEnumerable <ICommand> commands) { #region group execution commands IQueryTranslator translator = PostgreSqlManager.GetQueryTranslator(DataAccessContext.Create(server)); List <DatabaseExecutionCommand> databaseExecutionCommands = new List <DatabaseExecutionCommand>(); var batchExecutionConfig = DataManager.GetBatchExecutionConfiguration(server.ServerType) ?? BatchExecutionConfiguration.Default; var groupStatementsCount = batchExecutionConfig.GroupStatementsCount; groupStatementsCount = groupStatementsCount < 0 ? 1 : groupStatementsCount; var groupParameterCount = batchExecutionConfig.GroupParametersCount; groupParameterCount = groupParameterCount < 0 ? 1 : groupParameterCount; StringBuilder commandTextBuilder = new StringBuilder(); CommandParameters parameters = null; int statementsCount = 0; bool forceReturnValue = false; int cmdCount = 0; DatabaseExecutionCommand GetGroupExecuteCommand() { var executionCommand = new DatabaseExecutionCommand() { CommandText = commandTextBuilder.ToString(), CommandType = CommandType.Text, MustAffectedData = forceReturnValue, Parameters = parameters }; statementsCount = 0; translator.ParameterSequence = 0; commandTextBuilder.Clear(); parameters = null; forceReturnValue = false; return(executionCommand); } foreach (var cmd in commands) { DatabaseExecutionCommand databaseExecutionCommand = GetDatabaseExecutionCommand(translator, cmd as DefaultCommand); if (databaseExecutionCommand == null) { continue; } //Trace log PostgreSqlManager.LogExecutionCommand(databaseExecutionCommand); cmdCount++; if (databaseExecutionCommand.PerformAlone) { if (statementsCount > 0) { databaseExecutionCommands.Add(GetGroupExecuteCommand()); } databaseExecutionCommands.Add(databaseExecutionCommand); continue; } commandTextBuilder.AppendLine(databaseExecutionCommand.CommandText); parameters = parameters == null ? databaseExecutionCommand.Parameters : parameters.Union(databaseExecutionCommand.Parameters); forceReturnValue |= databaseExecutionCommand.MustAffectedData; statementsCount++; if (translator.ParameterSequence >= groupParameterCount || statementsCount >= groupStatementsCount) { databaseExecutionCommands.Add(GetGroupExecuteCommand()); } } if (statementsCount > 0) { databaseExecutionCommands.Add(GetGroupExecuteCommand()); } #endregion return(await ExecuteDatabaseCommandAsync(server, executionOptions, databaseExecutionCommands, executionOptions?.ExecutionByTransaction ?? cmdCount > 1).ConfigureAwait(false)); }
/// <summary> /// Execute command /// </summary> /// <param name="server">Database server</param> /// <param name="executionOptions">Execution options</param> /// <param name="commands">Commands</param> /// <returns>Return the affected data numbers</returns> public async Task <int> ExecuteAsync(DatabaseServer server, CommandExecutionOptions executionOptions, params ICommand[] commands) { IEnumerable <ICommand> cmdCollection = commands; return(await ExecuteAsync(server, executionOptions, cmdCollection).ConfigureAwait(false)); }
/// <summary> /// Execute command /// </summary> /// <param name="server">Database server</param> /// <param name="executionOptions">Execution options</param> /// <param name="commands">Commands</param> /// <returns>Return the affected data numbers</returns> public int Execute(DatabaseServer server, CommandExecutionOptions executionOptions, params ICommand[] commands) { return(ExecuteAsync(server, executionOptions, commands).Result); }
/// <summary> /// Execute command /// </summary> /// <param name="server">Database server</param> /// <param name="executionOptions">Execution options</param> /// <param name="commands">Commands</param> /// <returns>Return the affected data numbers</returns> public int Execute(DatabaseServer server, CommandExecutionOptions executionOptions, IEnumerable <ICommand> commands) { return(ExecuteAsync(server, executionOptions, commands).Result); }