Example #1
0
        async Task _handle(IncomingStepContext context, Func <Task> next, string identifierToTrackMessageBy, ITransactionContext transactionContext, string messageId, string secondLevelMessageId = null)
        {
            try
            {
                await next();

                await transactionContext.Commit();

                _errorTracker.CleanUp(messageId);

                if (secondLevelMessageId != null)
                {
                    _errorTracker.CleanUp(secondLevelMessageId);
                }
            }
            catch (OperationCanceledException) when(_cancellationToken.IsCancellationRequested)
            {
                _logger.Info("Dispatch of message with ID {messageId} was cancelled", messageId);

                transactionContext.Abort();
            }
            catch (Exception exception)
            {
                _errorTracker.RegisterError(identifierToTrackMessageBy, exception);
                _checkFinal(context);

                await _handleError(context, next, identifierToTrackMessageBy);
            }
        }
        /// <summary>
        /// Executes the entire message processing pipeline in an exception handler, tracking the number of failed delivery attempts.
        /// Forwards the message to the error queue when the max number of delivery attempts has been exceeded.
        /// </summary>
        public async Task Process(IncomingStepContext context, Func <Task> next)
        {
            var transportMessage   = context.Load <TransportMessage>();
            var transactionContext = context.Load <ITransactionContext>();
            var messageId          = transportMessage.Headers.GetValueOrNull(Headers.MessageId);

            if (string.IsNullOrWhiteSpace(messageId))
            {
                await MoveMessageToErrorQueue("<no message ID>", transportMessage,
                                              transactionContext, string.Format("Received message with empty or absent '{0}' header! All messages must be" +
                                                                                " supplied with an ID . If no ID is present, the message cannot be tracked" +
                                                                                " between delivery attempts, and other stuff would also be much harder to" +
                                                                                " do - therefore, it is a requirement that messages be supplied with an ID.",
                                                                                Headers.MessageId),
                                              shortErrorDescription : string.Format("Received message with empty or absent '{0}' header", Headers.MessageId));

                return;
            }

            if (_errorTracker.HasFailedTooManyTimes(messageId))
            {
                // if we don't have 2nd level retries, just get the message out of the way
                if (!_simpleRetryStrategySettings.SecondLevelRetriesEnabled)
                {
                    await
                    MoveMessageToErrorQueue(messageId, transportMessage, transactionContext,
                                            GetErrorDescriptionFor(messageId), GetErrorDescriptionFor(messageId, brief : true));

                    _errorTracker.CleanUp(messageId);
                    return;
                }

                // change the identifier to track by to perform this 2nd level of delivery attempts
                var secondLevelMessageId = messageId + "-2nd-level";

                if (_errorTracker.HasFailedTooManyTimes(secondLevelMessageId))
                {
                    await
                    MoveMessageToErrorQueue(messageId, transportMessage, transactionContext,
                                            GetErrorDescriptionFor(messageId), GetErrorDescriptionFor(messageId, brief : true));

                    _errorTracker.CleanUp(messageId);
                    _errorTracker.CleanUp(secondLevelMessageId);
                    return;
                }

                context.Save(DispatchAsFailedMessageKey, true);

                await DispatchWithTrackerIdentifier(next, secondLevelMessageId, transactionContext);

                return;
            }

            await DispatchWithTrackerIdentifier(next, messageId, transactionContext);
        }
Example #3
0
    /// <summary>
    /// Executes the entire message processing pipeline in an exception handler, tracking the number of failed delivery attempts.
    /// Forwards the message to the error queue when the max number of delivery attempts has been exceeded.
    /// </summary>
    public async Task Process(IncomingStepContext context, Func <Task> next)
    {
        var transportMessage   = context.Load <TransportMessage>() ?? throw new RebusApplicationException("Could not find a transport message in the current incoming step context");
        var transactionContext = context.Load <ITransactionContext>() ?? throw new RebusApplicationException("Could not find a transaction context in the current incoming step context");

        var messageId = transportMessage.Headers.GetValueOrNull(Headers.MessageId);

        if (string.IsNullOrWhiteSpace(messageId))
        {
            await MoveMessageToErrorQueue(context, transactionContext,
                                          new RebusApplicationException($"Received message with empty or absent '{Headers.MessageId}' header! All messages must be" +
                                                                        " supplied with an ID . If no ID is present, the message cannot be tracked" +
                                                                        " between delivery attempts, and other stuff would also be much harder to" +
                                                                        " do - therefore, it is a requirement that messages be supplied with an ID."));

            return;
        }

        if (_errorTracker.HasFailedTooManyTimes(messageId))
        {
            // if we don't have 2nd level retries, just get the message out of the way
            if (!_simpleRetryStrategySettings.SecondLevelRetriesEnabled)
            {
                var aggregateException = GetAggregateException(messageId);
                await MoveMessageToErrorQueue(context, transactionContext, aggregateException);

                _errorTracker.CleanUp(messageId);
                return;
            }

            // change the identifier to track by to perform this 2nd level of delivery attempts
            var secondLevelMessageId = GetSecondLevelMessageId(messageId);

            if (_errorTracker.HasFailedTooManyTimes(secondLevelMessageId))
            {
                var aggregateException = GetAggregateException(messageId, secondLevelMessageId);
                await MoveMessageToErrorQueue(context, transactionContext, aggregateException);

                _errorTracker.CleanUp(messageId);
                _errorTracker.CleanUp(secondLevelMessageId);
                return;
            }

            context.Save(DispatchAsFailedMessageKey, true);

            await DispatchWithTrackerIdentifier(next, secondLevelMessageId, transactionContext, messageId, secondLevelMessageId);

            return;
        }

        await DispatchWithTrackerIdentifier(next, messageId, transactionContext, messageId);
    }
 public void CleanUp(string messageId)
 {
     _innerErrorTracker.CleanUp(messageId);
 }