Exemplo n.º 1
0
        async Task Process(BasicDeliverEventArgs message, CancellationToken messageProcessingCancellationToken)
        {
            Dictionary <string, string> headers;

            try
            {
                headers = messageConverter.RetrieveHeaders(message);
            }
            catch (Exception ex)
            {
                Logger.Error(
                    $"Failed to retrieve headers from poison message. Moving message to queue '{settings.ErrorQueue}'...",
                    ex);
                await MovePoisonMessage(message, settings.ErrorQueue, messageProcessingCancellationToken).ConfigureAwait(false);

                return;
            }

            string messageId;

            try
            {
                messageId = messageConverter.RetrieveMessageId(message, headers);
            }
            catch (Exception ex)
            {
                Logger.Error(
                    $"Failed to retrieve ID from poison message. Moving message to queue '{settings.ErrorQueue}'...",
                    ex);
                await MovePoisonMessage(message, settings.ErrorQueue, messageProcessingCancellationToken).ConfigureAwait(false);

                return;
            }

            var processed                = false;
            var errorHandled             = false;
            var numberOfDeliveryAttempts = 0;
            var messageBody              = message.Body.ToArray();

            while (!processed && !errorHandled)
            {
                var processingContext = new ContextBag();

                processingContext.Set(message);

                try
                {
                    var messageContext = new MessageContext(messageId, headers, messageBody ?? Array.Empty <byte>(),
                                                            TransportTransaction, processingContext);

                    await onMessage(messageContext, messageProcessingCancellationToken).ConfigureAwait(false);

                    processed = true;
                }
                catch (Exception ex) when(!ex.IsCausedBy(messageProcessingCancellationToken))
                {
                    ++numberOfDeliveryAttempts;
                    headers = messageConverter.RetrieveHeaders(message);

                    var errorContext = new ErrorContext(ex, headers, messageId,
                                                        messageBody ?? Array.Empty <byte>(), TransportTransaction, numberOfDeliveryAttempts,
                                                        processingContext);

                    try
                    {
                        errorHandled =
                            await onError(errorContext, messageProcessingCancellationToken).ConfigureAwait(false) ==
                            ErrorHandleResult.Handled;

                        if (!errorHandled)
                        {
                            headers = messageConverter.RetrieveHeaders(message);
                        }
                    }
                    catch (Exception onErrorEx) when(!onErrorEx.IsCausedBy(messageProcessingCancellationToken))
                    {
                        criticalErrorAction(
                            $"Failed to execute recoverability policy for message with native ID: `{messageId}`", onErrorEx,
                            messageProcessingCancellationToken);
                        consumer.Model.BasicRejectAndRequeueIfOpen(message.DeliveryTag);

                        return;
                    }
                }
            }

            try
            {
                consumer.Model.BasicAckSingle(message.DeliveryTag);
            }
            catch (AlreadyClosedException ex)
            {
                Logger.Warn(
                    $"Failed to acknowledge message '{messageId}' because the channel was closed. The message was returned to the queue.",
                    ex);
            }
        }
Exemplo n.º 2
0
        async Task Process(BasicDeliverEventArgs message)
        {
            Dictionary <string, string> headers;

            try
            {
                headers = messageConverter.RetrieveHeaders(message);
            }
            catch (Exception ex)
            {
                Logger.Error($"Failed to retrieve headers from poison message. Moving message to queue '{settings.ErrorQueue}'...", ex);
                await MovePoisonMessage(message, settings.ErrorQueue).ConfigureAwait(false);

                return;
            }

            string messageId;

            try
            {
                messageId = messageConverter.RetrieveMessageId(message, headers);
            }
            catch (Exception ex)
            {
                Logger.Error($"Failed to retrieve ID from poison message. Moving message to queue '{settings.ErrorQueue}'...", ex);
                await MovePoisonMessage(message, settings.ErrorQueue).ConfigureAwait(false);

                return;
            }

            using (var tokenSource = new CancellationTokenSource())
            {
                var processed                = false;
                var errorHandled             = false;
                var numberOfDeliveryAttempts = 0;

                while (!processed && !errorHandled)
                {
                    try
                    {
                        var messageContext = new MessageContext(messageId, headers, message.Body ?? new byte[0], transportTransaction, tokenSource, contextBag);
                        await onMessage(messageContext).ConfigureAwait(false);

                        processed = true;
                    }
                    catch (Exception ex)
                    {
                        ++numberOfDeliveryAttempts;
                        var errorContext = new ErrorContext(ex, headers, messageId, message.Body ?? new byte[0], transportTransaction, numberOfDeliveryAttempts);
                        errorHandled = await onError(errorContext).ConfigureAwait(false) == ErrorHandleResult.Handled;
                    }
                }

                if (processed && tokenSource.IsCancellationRequested)
                {
                    await consumer.Model.BasicRejectAndRequeueIfOpen(message.DeliveryTag, exclusiveScheduler).ConfigureAwait(false);
                }
                else
                {
                    try
                    {
                        await consumer.Model.BasicAckSingle(message.DeliveryTag, exclusiveScheduler).ConfigureAwait(false);
                    }
                    catch (AlreadyClosedException ex)
                    {
                        Logger.Warn($"Failed to acknowledge message '{messageId}' because the channel was closed. The message was returned to the queue.", ex);
                    }
                }
            }
        }