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); } }
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); } } } }