Esempio n. 1
0
        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);
        }