void OnPoisonMessage(IBus bus, ReceivedTransportMessage message, PoisonMessageInfo poisonmessageinfo)
        {
            if (message.Headers.ContainsKey("command.id"))
            {
                Guid commandId   = Guid.Parse(message.Headers["command.id"].ToString());
                var  description = message.Headers["command.description"].ToString();

                var    ex        = poisonmessageinfo.Exceptions.Last();
                string exMessage = description;

                Exception exception = ex.Value;
                while (exception is TargetInvocationException)
                {
                    exception = exception.InnerException;
                }

                if (exception != null)
                {
                    exMessage = exception.Message;
                }

                this.MessagesTracker.Failed(commandId, ex.Time, exception);

                var command = GetCommandFromMessage(message);

                if (command != null)
                {
                    var notifyTo = command.GetContextData(MessagesConstants.ReplyToHeader);

                    if (!string.IsNullOrEmpty(notifyTo))
                    {
                        var commandHandled = new CommandHandled(
                            notifyTo,
                            commandId,
                            CommandHandled.CommandResult.Failed,
                            description,
                            exMessage
                            );

                        commandHandled.CopyHeaders(command);
                        bus.Advanced.Routing.Send(
                            message.Headers["rebus-return-address"].ToString(),
                            commandHandled);
                    }
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Inner function to handle the different type of exceptions
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="command"></param>
        /// <param name="retryCount"></param>
        /// <param name="retry"></param>
        /// <param name="replyCommand"></param>
        /// <param name="shouldContinue">true if the handler can continue execution, false if the execution of the command should stop
        /// because there is no need to continue.</param>
        /// <returns>Return always true because it is the very same routine used for aggregate exception. We always want not to throw in this
        /// method, but allow the caller to throw.</returns>
        private Boolean InnerHandle(Exception ex, ICommand command, Int32 retryCount, out Boolean retry, out CommandHandled replyCommand, out Boolean shouldContinue)
        {
            retry          = false;
            replyCommand   = null;
            shouldContinue = false;
            switch (ex)
            {
            case ConcurrencyException cex:

                SharedMetricsHelper.MarkConcurrencyException();
                // retry
                if (_logger.IsInfoEnabled)
                {
                    _logger.InfoFormat(ex, "Handled {0} {1} [{2}], concurrency exception. Retry count: {3}", command.GetType().FullName, command.MessageId, command.Describe(), retryCount);
                }

                // increment the retries counter and maybe add a delay
                if (retryCount++ > _numberOfConcurrencyExceptionBeforeRandomSleeping)
                {
                    Thread.Sleep(new Random(DateTime.Now.Millisecond).Next(retryCount * 10));
                }
                retry          = retryCount < _maxRetryOnConcurrencyException; //can retry
                shouldContinue = true;                                         //can proceed
                break;

            case DomainException dex:

                SharedMetricsHelper.MarkDomainException(command, dex);
                var notifyTo = command.GetContextData(MessagesConstants.ReplyToHeader);
                if (notifyTo != null)
                {
                    replyCommand = new CommandHandled(
                        notifyTo,
                        command.MessageId,
                        CommandHandled.CommandResult.Failed,
                        command.Describe(),
                        ex.Message,
                        isDomainException: true
                        );
                    replyCommand.CopyHeaders(command);
                }
                _logger.ErrorFormat(ex, "DomainException on command {0} [MessageId: {1}] : {2} : {3}", command.GetType(), command.MessageId, command.Describe(), ex.Message);
                shouldContinue = true;     //exception was handled, can proceed to the execution but retry is false
                break;

            case SecurityException sex:

                SharedMetricsHelper.MarkSecurityException(command);
                var notifySexTo = command.GetContextData(MessagesConstants.ReplyToHeader);
                if (notifySexTo != null)
                {
                    replyCommand = new CommandHandled(
                        notifySexTo,
                        command.MessageId,
                        CommandHandled.CommandResult.Failed,
                        command.Describe(),
                        $"Security exception: {ex.Message}",
                        isDomainException: false
                        );
                    replyCommand.CopyHeaders(command);
                }
                _logger.ErrorFormat(ex, "SecurityException on command {0} [MessageId: {1}] : {2} : {3}", command.GetType(), command.MessageId, command.Describe(), ex.Message);
                shouldContinue = true;     //exception was handled, can proceed to the execution but retry is false because security should not retry
                break;

            case Exception gex:

                _logger.ErrorFormat(ex, "Generic Exception on command {0} [MessageId: {1}] : {2} : {3}", command.GetType(), command.MessageId, command.Describe(), ex.Message);
                shouldContinue = false;     //cannot proceed, this exception cannot be handled
                break;
            }

            return(true);
        }
예제 #3
0
        public async Task Handle(T message)
        {
            LoggerThreadContextManager.MarkCommandExecution(message);

            if (Logger.IsDebugEnabled)
            {
                Logger.DebugFormat("Handling {0} {1}", message.GetType().FullName, message.MessageId);
            }

            int  i        = 0;
            bool retry    = false;
            var  notifyTo = message.GetContextData(MessagesConstants.ReplyToHeader);

            CommandHandled replyCommandHandled = null;
            Boolean        success             = false;
            Exception      lastException       = null;

            do
            {
                try
                {
                    _messagesTracker.ElaborationStarted(message, DateTime.UtcNow);
                    _commandHandler.HandleAsync(message).Wait(); //need to wait, or you will free the worker rebus thread and you will dispatch many concurrent handler.
                    _messagesTracker.Completed(message, DateTime.UtcNow);

                    if (notifyTo != null && message.GetContextData("disable-success-reply", "false") != "true")
                    {
                        replyCommandHandled = new CommandHandled(
                            notifyTo,
                            message.MessageId,
                            CommandHandled.CommandResult.Handled,
                            message.Describe()
                            );
                        replyCommandHandled.CopyHeaders(message);
                        _bus.Reply(replyCommandHandled).Wait();
                    }
                    success = true;
                    retry   = false;
                }
                catch (Exception ex)
                {
                    lastException = ex;
                    if (!_commandExecutionExceptionHelper.Handle(ex, message, i, out retry, out replyCommandHandled))
                    {
                        //Handler is not able to handle the exception, simply retrhow
                        _messagesTracker.Failed(message, DateTime.UtcNow, ex);
                        LoggerThreadContextManager.ClearMarkCommandExecution();
                        throw;
                    }
                }
                i++; //if we reach here we need to increment the counter.
            } while (retry);

            if (!success)
            {
                _messagesTracker.Failed(message, DateTime.UtcNow, lastException);

                if (notifyTo != null && replyCommandHandled != null)
                {
                    await _bus.Reply(replyCommandHandled).ConfigureAwait(false);
                }
            }
            if (Logger.IsDebugEnabled)
            {
                Logger.DebugFormat("Handled {0} {1} {2}", message.GetType().FullName, message.MessageId, message.Describe());
            }
            LoggerThreadContextManager.ClearMarkCommandExecution();
        }
예제 #4
0
            public async Task HandlePoisonMessage(TransportMessage transportMessage, ITransactionContext transactionContext, Exception exception)
            {
                try
                {
                    if (transportMessage.Headers.ContainsKey("rbs2-msg-id"))
                    {
                        Guid   commandId   = Guid.Parse(transportMessage.Headers["rbs2-msg-id"]);
                        var    description = transportMessage.Headers["rbs2-msg-type"];
                        String exMessage   = description;

                        while (exception is TargetInvocationException)
                        {
                            exception = exception.InnerException;
                        }

                        var command = GetCommandFromMessage(transportMessage);
                        _lazyMessageTracker.Value.Failed(command, DateTime.UtcNow, exception);

                        if (exception != null)
                        {
                            exMessage = GetErrorMessage(exception);
                            _logger.ErrorFormat("HandlingPoisionMessage for {0}/{1} - {2}", commandId, description, command?.Describe());
                        }

                        if (command != null)
                        {
                            var notifyTo = command.GetContextData(MessagesConstants.ReplyToHeader);

                            if (!string.IsNullOrEmpty(notifyTo))
                            {
                                var commandHandled = new CommandHandled(
                                    notifyTo,
                                    commandId,
                                    CommandHandled.CommandResult.Failed,
                                    description,
                                    exMessage
                                    );

                                commandHandled.CopyHeaders(command);

                                Dictionary <String, String> headers = new Dictionary <string, string>
                                {
                                    { Headers.MessageId, Guid.NewGuid().ToString() }
                                };

                                //TODO: WIth new rebus I do not know how to resend header back. This will throw some unknown and obscure error in rebus.
                                await _lazyBus.Value.Advanced.Routing.Send(
                                    transportMessage.Headers["rbs2-return-address"],
                                    commandHandled,
                                    headers).ConfigureAwait(false);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger.Error($"Error during HandlePoisonMessage of message: {ex.Message}", ex);
                }
                finally
                {
                    var headers = transportMessage.Headers;
                    headers[Headers.ErrorDetails] = exception?.ToString();
                    headers[Headers.SourceQueue]  = _transport.Address;
                    _logger.Error($"Moving message to error queue {_jarvisRebusConfiguration.ErrorQueue}", exception);
                    if (_transport == null)
                    {
                        _logger.Error("Error handler has no transport...this should be not possible. Problem in rebus initialization");
                    }
                    else
                    {
                        await _transport.Send(_jarvisRebusConfiguration.ErrorQueue, transportMessage, transactionContext).ConfigureAwait(false);
                    }
                }
            }
예제 #5
0
        public void Handle(T message)
        {
            try
            {
                Logger.MarkCommandExecution(message);
                if (Logger.IsDebugEnabled)
                {
                    Logger.DebugFormat("Handling {0} {1}", message.GetType().FullName, message.MessageId);
                }
                int  i        = 0;
                bool done     = false;
                var  notifyTo = message.GetContextData(MessagesConstants.ReplyToHeader);
                while (!done && i < 100)
                {
                    try
                    {
                        _messagesTracker.ElaborationStarted(message.MessageId, DateTime.UtcNow);
                        _commandHandler.Handle(message);
                        _messagesTracker.Completed(message.MessageId, DateTime.UtcNow);
                        done = true;

                        if (notifyTo != null && message.GetContextData("disable-success-reply", "false") != "true")
                        {
                            var replyCommand = new CommandHandled(
                                notifyTo,
                                message.MessageId,
                                CommandHandled.CommandResult.Handled,
                                message.Describe()
                                );
                            replyCommand.CopyHeaders(message);
                            _bus.Reply(replyCommand);
                        }
                    }
                    catch (ConflictingCommandException ex)
                    {
                        MetricsHelper.MarkConcurrencyException();
                        // retry
                        if (Logger.IsInfoEnabled)
                        {
                            Logger.InfoFormat(ex, "Handled {0} {1} [{2}], concurrency exception. Retry count: {3}", message.GetType().FullName, message.MessageId, message.Describe(), i);
                        }
                        if (i++ > 5)
                        {
                            Thread.Sleep(new Random(DateTime.Now.Millisecond).Next(i * 10));
                        }
                    }
                    catch (DomainException ex)
                    {
                        MetricsHelper.MarkDomainException();
                        done = true;
                        _messagesTracker.Failed(message.MessageId, DateTime.UtcNow, ex);

                        if (notifyTo != null)
                        {
                            var replyCommand = new CommandHandled(
                                notifyTo,
                                message.MessageId,
                                CommandHandled.CommandResult.Failed,
                                message.Describe(),
                                ex.Message,
                                true
                                );
                            replyCommand.CopyHeaders(message);
                            _bus.Reply(replyCommand);
                        }
                        _logger.ErrorFormat(ex, "DomainException on command {0} [MessageId: {1}] : {2} : {3}", message.GetType(), message.MessageId, message.Describe(), ex.Message);
                    }
                    catch (Exception ex)
                    {
                        _logger.ErrorFormat(ex, "Generic Exception on command {0} [MessageId: {1}] : {2} : {3}", message.GetType(), message.MessageId, message.Describe(), ex.Message);
                        _messagesTracker.Failed(message.MessageId, DateTime.UtcNow, ex);
                        throw; //rethrow exception.
                    }
                }
                if (done == false)
                {
                    _logger.ErrorFormat("Too many conflict on command {0} [MessageId: {1}] : {2}", message.GetType(), message.MessageId, message.Describe());
                    var exception = new Exception("Command failed. Too many Conflicts");
                    _messagesTracker.Failed(message.MessageId, DateTime.UtcNow, exception);
                }
                if (Logger.IsDebugEnabled)
                {
                    Logger.DebugFormat("Handled {0} {1} {3}", message.GetType().FullName, message.MessageId, message.Describe());
                }
            }
            finally
            {
                Logger.ClearCommandExecution();
            }
        }
예제 #6
0
        public void Handle(T message)
        {
            if (Logger.IsDebugEnabled)
            {
                Logger.DebugFormat("Handling {0} {1}", message.GetType().FullName, message.MessageId);
            }
            int  i        = 0;
            bool done     = false;
            var  notifyTo = message.GetContextData(MessagesConstants.ReplyToHeader);

            while (!done && i < 100)
            {
                i++;
                try
                {
                    _commandHandler.Handle(message);
                    _messagesTracker.Completed(message.MessageId, DateTime.UtcNow);
                    done = true;

                    if (notifyTo != null && message.GetContextData("disable-success-reply", "false") != "true")
                    {
                        var replyCommand = new CommandHandled(
                            notifyTo,
                            message.MessageId,
                            CommandHandled.CommandResult.Handled,
                            message.Describe()
                            );
                        replyCommand.CopyHeaders(message);
                        _bus.Reply(replyCommand);
                    }
                }
                catch (ConflictingCommandException ex)
                {
                    // retry
                    if (Logger.IsDebugEnabled)
                    {
                        Logger.DebugFormat("Handled {0} {1}, concurrency exception. Retry count: {2}", message.GetType().FullName, message.MessageId, i);
                    }
                    if (i++ > 5)
                    {
                        Thread.Sleep(new Random(DateTime.Now.Millisecond).Next(i * 10));
                    }
                }
                catch (DomainException ex)
                {
                    done = true;
                    _messagesTracker.Failed(message.MessageId, DateTime.UtcNow, ex);

                    if (notifyTo != null)
                    {
                        var replyCommand = new CommandHandled(
                            notifyTo,
                            message.MessageId,
                            CommandHandled.CommandResult.Failed,
                            message.Describe(),
                            ex.Message,
                            true
                            );
                        replyCommand.CopyHeaders(message);
                        _bus.Reply(replyCommand);
                    }
                }
            }
            if (done == false)
            {
                var exception = new Exception("Command failed. Too many Conflicts");
                _messagesTracker.Failed(message.MessageId, DateTime.UtcNow, exception);
            }
            if (Logger.IsDebugEnabled)
            {
                Logger.DebugFormat("Handled {0} {1}", message.GetType().FullName, message.MessageId);
            }
        }