private async Task <bool> HandleMessageReceived(QueuedMessage queuedMessage, CancellationToken cancellationToken) { Message message = null; var acknowledged = false; IPrincipal originalThreadPrincipal = null; try { originalThreadPrincipal = Thread.CurrentPrincipal; message = queuedMessage.Message; queuedMessage = queuedMessage.NextAttempt(); await DiagnosticService.EmitAsync( new DiagnosticEventBuilder(this, DiagnosticEventType.QueuedMessageAttempt) { Detail = "Processing queued message (attempt " + queuedMessage.Attempts + " of " + _maxAttempts + ")", Message = message, Queue = QueueName }.Build(), cancellationToken); var context = new QueuedMessageContext(message, queuedMessage.Principal); Thread.CurrentPrincipal = context.Principal; cancellationToken.ThrowIfCancellationRequested(); await _listener.MessageReceived(message, context, cancellationToken); if (_autoAcknowledge && !context.Acknowledged) { await context.Acknowledge(); } acknowledged = context.Acknowledged; } catch (Exception ex) { DiagnosticService.Emit(new DiagnosticEventBuilder(this, DiagnosticEventType.UnhandledException) { Detail = "Unhandled exception handling queued message", Message = message, Queue = QueueName, Exception = ex }.Build()); } finally { Thread.CurrentPrincipal = originalThreadPrincipal; } return(acknowledged); }
/// <inheritdoc /> public async Task EnqueueMessage(QueueName queueName, Message message, IPrincipal senderPrincipal, CancellationToken cancellationToken = default(CancellationToken)) { if (!_virtualQueues.TryGetValue(queueName, out var queue)) { throw new QueueNotFoundException(queueName); } var context = new QueuedMessageContext(message, senderPrincipal); await queue.Listener.MessageReceived(message, context, cancellationToken); var acknowledged = context.Acknowledged || queue.AutoAcknowledge; if (!acknowledged) { throw new MessageNotAcknowledgedException(); } }
/// <summary> /// Called by the message processing loop to process an individual message /// </summary> /// <param name="queuedMessage">The queued message to process</param> /// <param name="cancellationToken">A cancellation token that can be used by the caller /// to cancel message processing operation</param> /// <returns>Returns a task that completes when the queued message is processed</returns> protected virtual async Task ProcessQueuedMessage(QueuedMessage queuedMessage, CancellationToken cancellationToken) { Exception exception = null; var message = queuedMessage.Message; var principal = queuedMessage.Principal; // ReSharper disable once ConditionIsAlwaysTrueOrFalse queuedMessage = queuedMessage.NextAttempt(); await DiagnosticService.EmitAsync( new DiagnosticEventBuilder(this, DiagnosticEventType.QueuedMessageAttempt) { Detail = "Processing queued message (attempt " + queuedMessage.Attempts + " of " + _maxAttempts + ")", Message = message, Queue = QueueName }.Build(), cancellationToken); var context = new QueuedMessageContext(message, principal); Thread.CurrentPrincipal = context.Principal; cancellationToken.ThrowIfCancellationRequested(); try { await _listener.MessageReceived(message, context, cancellationToken); if (_autoAcknowledge && !context.Acknowledged) { await context.Acknowledge(); } } catch (Exception ex) { exception = ex; DiagnosticService.Emit(new DiagnosticEventBuilder(this, DiagnosticEventType.UnhandledException) { Detail = "Unhandled exception handling queued message", Message = message, Queue = QueueName, Exception = ex }.Build()); } var eventArgs = new MessageQueueEventArgs(QueueName, queuedMessage, exception); if (context.Acknowledged) { await DiagnosticService.EmitAsync( new DiagnosticEventBuilder(this, DiagnosticEventType.MessageAcknowledged) { Message = message, Queue = QueueName }.Build(), cancellationToken); var messageAcknowledgedHandlers = MessageAcknowledged; if (messageAcknowledgedHandlers != null) { await messageAcknowledgedHandlers(this, eventArgs); } return; } await DiagnosticService.EmitAsync( new DiagnosticEventBuilder(this, DiagnosticEventType.MessageNotAcknowledged) { Message = message, Queue = QueueName }.Build(), cancellationToken); if (queuedMessage.Attempts >= _maxAttempts) { await DiagnosticService.EmitAsync( new DiagnosticEventBuilder(this, DiagnosticEventType.MaxAttemptsExceeded) { Detail = "Maximum attempts exceeded (" + _maxAttempts + ")", Message = message, Queue = QueueName }.Build(), cancellationToken); var maxAttemptsExceededHandlers = MaximumAttemptsExceeded; if (maxAttemptsExceededHandlers != null) { await MaximumAttemptsExceeded(this, eventArgs); } return; } var acknowledgementFailureHandlers = AcknowledgementFailure; if (acknowledgementFailureHandlers != null) { await AcknowledgementFailure(this, eventArgs); } await DiagnosticService.EmitAsync( new DiagnosticEventBuilder(this, DiagnosticEventType.QueuedMessageRetry) { Detail = "Message not acknowledged; retrying in " + _retryDelay, Message = message, Queue = QueueName }.Build(), cancellationToken); ScheduleRetry(queuedMessage, cancellationToken); }