コード例 #1
0
        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);
        }
コード例 #2
0
        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();
        }
コード例 #3
0
        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);
        }
コード例 #4
0
        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);
        }
コード例 #5
0
        /// <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;
                }
            }
        }
コード例 #6
0
 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));
     }
 }
コード例 #7
0
        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);
        }
コード例 #8
0
        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);
        }
コード例 #9
0
        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);
        }
コード例 #10
0
        /// <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());
        }
コード例 #11
0
        /// <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));
        }
コード例 #12
0
        /// <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));
        }
コード例 #13
0
 /// <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);
 }
コード例 #14
0
 /// <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);
 }