Example #1
0
        void DoTry()
        {
            var transportMessage = receiveMessages.ReceiveMessage(TransactionContext.Current);

            if (transportMessage == null)
            {
                // to back off and relax when there's no messages to process, we do this
                nullMessageReceivedBackoffHelper.Wait();
                return;
            }

            nullMessageReceivedBackoffHelper.Reset();

            var id    = transportMessage.Id;
            var label = transportMessage.Label;

            MessageContext context = null;

            if (id == null)
            {
                HandlePoisonMessage(id, transportMessage);
                return;
            }

            if (errorTracker.MessageHasFailedMaximumNumberOfTimes(id))
            {
                HandlePoisonMessage(id, transportMessage);
                errorTracker.StopTracking(id);
                return;
            }

            Exception transportMessageExceptionOrNull = null;

            try
            {
                BeforeTransportMessage(transportMessage);

                // Populate rebus-msg-id, if not set, from transport-level-id
                if (!transportMessage.Headers.ContainsKey(Headers.MessageId))
                {
                    transportMessage.Headers[Headers.MessageId] = transportMessage.Id;
                }

                using (var scope = BeginTransaction())
                {
                    var message = serializeMessages.Deserialize(transportMessage);
                    // successfully deserialized the transport message, let's enter a message context
                    context = MessageContext.Establish(message.Headers);
                    MessageContextEstablished(context);

                    var unitsOfWork = unitOfWorkManagers.Select(u => u.Create())
                                      .Where(u => !ReferenceEquals(null, u))
                                      .ToArray(); //< remember to invoke the chain here :)

                    try
                    {
                        foreach (var logicalMessage in message.Messages.Select(MutateIncoming))
                        {
                            context.SetLogicalMessage(logicalMessage);

                            Exception logicalMessageExceptionOrNull = null;
                            try
                            {
                                BeforeMessage(logicalMessage);

                                var typeToDispatch = logicalMessage.GetType();

                                messageLogger.LogReceive(id, logicalMessage);

                                try
                                {
                                    var dispatchMethod = GetDispatchMethod(typeToDispatch);
                                    var parameters     = new[] { logicalMessage };
                                    dispatchMethod.Invoke(this, parameters);
                                }
                                catch (TargetInvocationException tie)
                                {
                                    var exception = tie.InnerException;
                                    exception.PreserveStackTrace();
                                    throw exception;
                                }
                            }
                            catch (Exception exception)
                            {
                                logicalMessageExceptionOrNull = exception;
                                throw;
                            }
                            finally
                            {
                                try
                                {
                                    AfterMessage(logicalMessageExceptionOrNull, logicalMessage);
                                }
                                catch (Exception exceptionWhileRaisingEvent)
                                {
                                    if (logicalMessageExceptionOrNull != null)
                                    {
                                        log.Error(
                                            "An exception occurred while raising the AfterMessage event, and an exception occurred some" +
                                            " time before that as well. The first exception was this: {0}. And then, when raising the" +
                                            " AfterMessage event (including the details of the first error), this exception occurred: {1}",
                                            logicalMessageExceptionOrNull, exceptionWhileRaisingEvent);
                                    }
                                    else
                                    {
                                        log.Error("An exception occurred while raising the AfterMessage event: {0}",
                                                  exceptionWhileRaisingEvent);
                                    }
                                }

                                context.ClearLogicalMessage();
                            }
                        }

                        foreach (var unitOfWork in unitsOfWork)
                        {
                            try
                            {
                                unitOfWork.Commit();
                            }
                            catch (Exception exception)
                            {
                                throw new UnitOfWorkCommitException(exception, unitOfWork);
                            }
                        }
                    }
                    catch
                    {
                        foreach (var unitOfWork in unitsOfWork)
                        {
                            try
                            {
                                unitOfWork.Abort();
                            }
                            catch (Exception abortException)
                            {
                                log.Warn("An error occurred while aborting the unit of work {0}: {1}",
                                         unitOfWork, abortException);
                            }
                        }
                        throw;
                    }
                    finally
                    {
                        foreach (var unitOfWork in unitsOfWork)
                        {
                            unitOfWork.Dispose();
                        }
                    }

                    if (scope != null)
                    {
                        scope.Complete();
                    }
                }
            }
            catch (Exception exception)
            {
                transportMessageExceptionOrNull = exception;
                log.Debug("Handling message {0} with ID {1} has failed", label, id);
                errorTracker.TrackDeliveryFail(id, exception);
                throw new MessageHandleException(id, exception);
            }
            finally
            {
                try
                {
                    AfterTransportMessage(transportMessageExceptionOrNull, transportMessage);
                }
                catch (Exception exceptionWhileRaisingEvent)
                {
                    if (transportMessageExceptionOrNull != null)
                    {
                        log.Error(
                            "An exception occurred while raising the AfterTransportMessage event, and an exception occurred some" +
                            " time before that as well. The first exception was this: {0}. And then, when raising the" +
                            " AfterTransportMessage event (including the details of the first error), this exception occurred: {1}",
                            transportMessageExceptionOrNull, exceptionWhileRaisingEvent);
                    }
                    else
                    {
                        log.Error("An exception occurred while raising the AfterTransportMessage event: {0}", exceptionWhileRaisingEvent);
                    }
                }

                if (context != null)
                {
                    context.Dispose();                  //< dispose it if we entered
                }
            }

            errorTracker.StopTracking(id);
        }
Example #2
0
        void TryProcessIncomingMessage()
        {
            using (var transactionScope = BeginTransaction())
            {
                var transportMessage = receiveMessages.ReceiveMessage();

                if (transportMessage == null)
                {
                    Thread.Sleep(20);
                    return;
                }

                var id    = transportMessage.Id;
                var label = transportMessage.Label;

                MessageContext context = null;

                if (errorTracker.MessageHasFailedMaximumNumberOfTimes(id))
                {
                    log.Error("Handling message {0} has failed the maximum number of times", id);
                    MessageFailedMaxNumberOfTimes(transportMessage, errorTracker.GetErrorText(id));
                    errorTracker.StopTracking(id);

                    try
                    {
                        PoisonMessage(transportMessage);
                    }
                    catch (Exception exceptionWhileRaisingEvent)
                    {
                        log.Error("An exception occurred while raising the PoisonMessage event: {0}",
                                  exceptionWhileRaisingEvent);
                    }
                }
                else
                {
                    try
                    {
                        BeforeTransportMessage(transportMessage);

                        var message = serializeMessages.Deserialize(transportMessage);

                        // successfully deserialized the transport message, let's enter a message context
                        context = MessageContext.Enter(message.Headers);

                        foreach (var logicalMessage in message.Messages)
                        {
                            context.SetLogicalMessage(logicalMessage);

                            try
                            {
                                BeforeMessage(logicalMessage);

                                var typeToDispatch = logicalMessage.GetType();

                                log.Debug("Dispatching message {0}: {1}", id, typeToDispatch);

                                GetDispatchMethod(typeToDispatch).Invoke(this, new[] { logicalMessage });

                                AfterMessage(null, logicalMessage);
                            }
                            catch (Exception exception)
                            {
                                try
                                {
                                    AfterMessage(exception, logicalMessage);
                                }
                                catch (Exception exceptionWhileRaisingEvent)
                                {
                                    log.Error("An exception occurred while raising the AfterMessage event, and an exception occurred some time before that as well. The first exception was this: {0}. And then, when raising the AfterMessage event (including the details of the first error), this exception occurred: {1}",
                                              exception, exceptionWhileRaisingEvent);
                                }
                                throw;
                            }
                            finally
                            {
                                context.ClearLogicalMessage();
                            }
                        }

                        AfterTransportMessage(null, transportMessage);
                    }
                    catch (Exception exception)
                    {
                        log.Debug("Handling message {0} ({1}) has failed", label, id);
                        try
                        {
                            AfterTransportMessage(exception, transportMessage);
                        }
                        catch (Exception exceptionWhileRaisingEvent)
                        {
                            log.Error("An exception occurred while raising the AfterTransportMessage event, and an exception occurred some time before that as well. The first exception was this: {0}. And then, when raising the AfterTransportMessage event (including the details of the first error), this exception occurred: {1}",
                                      exception, exceptionWhileRaisingEvent);
                        }
                        errorTracker.TrackDeliveryFail(id, exception);
                        if (context != null)
                        {
                            context.Dispose();                  //< dispose it if we entered
                        }
                        throw;
                    }
                }

                transactionScope.Complete();
                if (context != null)
                {
                    context.Dispose();                  //< dispose it if we entered
                }
                errorTracker.StopTracking(id);
            }
        }
Example #3
0
        void DoTry()
        {
            var transportMessage = receiveMessages.ReceiveMessage(TransactionContext.Current);

            if (transportMessage == null)
            {
                // to back off and relax then there's no messages to process, we do this
                successiveNullMessagesReceived++;
                var sleepTimeIndex = Math.Min(nullMessageSleepTimes.Length - 1, successiveNullMessagesReceived);
                var timeToSleep    = nullMessageSleepTimes[sleepTimeIndex];
                Thread.Sleep(timeToSleep);
                return;
            }

            successiveNullMessagesReceived = 0;

            var id    = transportMessage.Id;
            var label = transportMessage.Label;

            MessageContext context = null;

            if (id == null)
            {
                HandlePoisonMessage(id, transportMessage);
                return;
            }

            if (errorTracker.MessageHasFailedMaximumNumberOfTimes(id))
            {
                HandlePoisonMessage(id, transportMessage);
                errorTracker.StopTracking(id);
                return;
            }

            Exception transportMessageExceptionOrNull = null;

            try
            {
                BeforeTransportMessage(transportMessage);

                using (var scope = BeginTransaction())
                {
                    var message = serializeMessages.Deserialize(transportMessage);
                    // successfully deserialized the transport message, let's enter a message context
                    context = MessageContext.Establish(message.Headers);
                    MessageContextEstablished(context);

                    var unitsOfWork = unitOfWorkManagers.Select(u => u.Create())
                                      .Where(u => !ReferenceEquals(null, u))
                                      .ToArray(); //< remember to invoke the chain here :)

                    try
                    {
                        foreach (var logicalMessage in message.Messages.Select(MutateIncoming))
                        {
                            context.SetLogicalMessage(logicalMessage);

                            Exception logicalMessageExceptionOrNull = null;
                            try
                            {
                                BeforeMessage(logicalMessage);

                                var typeToDispatch = logicalMessage.GetType();

                                log.Debug("Dispatching message {0}: {1}", id, typeToDispatch);

                                GetDispatchMethod(typeToDispatch)
                                .Invoke(this, new[] { logicalMessage });
                            }
                            catch (Exception exception)
                            {
                                logicalMessageExceptionOrNull = exception;
                                throw;
                            }
                            finally
                            {
                                try
                                {
                                    AfterMessage(logicalMessageExceptionOrNull, logicalMessage);
                                }
                                catch (Exception exceptionWhileRaisingEvent)
                                {
                                    if (logicalMessageExceptionOrNull != null)
                                    {
                                        log.Error(
                                            "An exception occurred while raising the AfterMessage event, and an exception occurred some" +
                                            " time before that as well. The first exception was this: {0}. And then, when raising the" +
                                            " AfterMessage event (including the details of the first error), this exception occurred: {1}",
                                            logicalMessageExceptionOrNull, exceptionWhileRaisingEvent);
                                    }
                                    else
                                    {
                                        log.Error("An exception occurred while raising the AfterMessage event: {0}",
                                                  exceptionWhileRaisingEvent);
                                    }
                                }

                                context.ClearLogicalMessage();
                            }
                        }

                        foreach (var unitOfWork in unitsOfWork)
                        {
                            unitOfWork.Commit();
                        }
                    }
                    catch
                    {
                        foreach (var unitOfWork in unitsOfWork)
                        {
                            try
                            {
                                unitOfWork.Abort();
                            }
                            catch (Exception abortException)
                            {
                                log.Warn("An error occurred while aborting the unit of work {0}: {1}",
                                         unitOfWork, abortException);
                            }
                        }
                        throw;
                    }
                    finally
                    {
                        foreach (var unitOfWork in unitsOfWork)
                        {
                            unitOfWork.Dispose();
                        }
                    }

                    if (scope != null)
                    {
                        scope.Complete();
                    }
                }
            }
            catch (Exception exception)
            {
                transportMessageExceptionOrNull = exception;
                log.Debug("Handling message {0} ({1}) has failed", label, id);
                errorTracker.TrackDeliveryFail(id, exception);
                throw;
            }
            finally
            {
                try
                {
                    AfterTransportMessage(transportMessageExceptionOrNull, transportMessage);
                }
                catch (Exception exceptionWhileRaisingEvent)
                {
                    if (transportMessageExceptionOrNull != null)
                    {
                        log.Error(
                            "An exception occurred while raising the AfterTransportMessage event, and an exception occurred some" +
                            " time before that as well. The first exception was this: {0}. And then, when raising the" +
                            " AfterTransportMessage event (including the details of the first error), this exception occurred: {1}",
                            transportMessageExceptionOrNull, exceptionWhileRaisingEvent);
                    }
                    else
                    {
                        log.Error("An exception occurred while raising the AfterTransportMessage event: {0}", exceptionWhileRaisingEvent);
                    }
                }

                if (context != null)
                {
                    context.Dispose();                  //< dispose it if we entered
                }
            }

            errorTracker.StopTracking(id);
        }