/// <summary>
        /// Adds a message to the queue
        /// </summary>
        /// <param name="message">The message to add</param>
        /// <param name="principal">The principal that sent the message or from whom
        ///     the message was received</param>
        /// <param name="cancellationToken">A cancellation token that can be used by the caller
        /// to cancel the enqueueing operation</param>
        /// <returns>Returns a task that completes when the message has been added to the queue</returns>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="message"/> is
        /// <c>null</c></exception>
        /// <exception cref="ObjectDisposedException">Thrown if this SQL message queue instance
        /// has already been disposed</exception>
        public virtual async Task Enqueue(Message message, IPrincipal principal, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }
            CheckDisposed();

            var queuedMessage = new QueuedMessage(message, principal, 0);
            var handler       = MessageEnqueued;

            if (handler != null)
            {
                var args = new MessageQueueEventArgs(QueueName, queuedMessage);
                await MessageEnqueued(this, args);
            }

            await _queuedMessages.SendAsync(queuedMessage, cancellationToken);

            // TODO: handle accepted == false

            await DiagnosticService.EmitAsync(
                new DiagnosticEventBuilder(this, DiagnosticEventType.MessageEnqueued)
            {
                Detail  = "New message enqueued",
                Message = message,
                Queue   = QueueName
            }.Build(), cancellationToken);
        }
Beispiel #2
0
        private async Task HandleMaximumAttemptsExceeded(QueuedMessage queuedMessage, CancellationToken cancellationToken)
        {
            try
            {
                var eventArgs = new MessageQueueEventArgs(QueueName, queuedMessage, null);
                await DiagnosticService.EmitAsync(
                    new DiagnosticEventBuilder(this, DiagnosticEventType.MaxAttemptsExceeded)
                {
                    Detail  = "Maximum attempts exceeded (" + _maxAttempts + ")",
                    Message = queuedMessage.Message,
                    Queue   = QueueName
                }.Build(), cancellationToken);

                var maxAttemptsExceededHandlers = MaximumAttemptsExceeded;
                if (maxAttemptsExceededHandlers != null)
                {
                    await MaximumAttemptsExceeded(this, eventArgs);
                }
            }
            catch (Exception ex)
            {
                DiagnosticService.Emit(new DiagnosticEventBuilder(this, DiagnosticEventType.MaxAttemptsExceededError)
                {
                    Detail    = "Unexpected error handling maximum attempts exceeded",
                    Message   = queuedMessage.Message,
                    Queue     = QueueName,
                    Exception = ex
                }.Build());
            }
        }
Beispiel #3
0
        private async Task HandleMessageAcknowledged(QueuedMessage queuedMessage, CancellationToken cancellationToken)
        {
            try
            {
                var eventArgs = new MessageQueueEventArgs(QueueName, queuedMessage);
                await DiagnosticService.EmitAsync(
                    new DiagnosticEventBuilder(this, DiagnosticEventType.MessageAcknowledged)
                {
                    Message = queuedMessage.Message,
                    Queue   = QueueName
                }.Build(), cancellationToken);

                var messageAcknowledgedHandlers = MessageAcknowledged;
                if (messageAcknowledgedHandlers != null)
                {
                    await messageAcknowledgedHandlers(this, eventArgs);
                }
            }
            catch (Exception ex)
            {
                DiagnosticService.Emit(new DiagnosticEventBuilder(this, DiagnosticEventType.MessageAcknowledgementError)
                {
                    Detail    = "Unexpected error handling message acknowledgement",
                    Message   = queuedMessage.Message,
                    Queue     = QueueName,
                    Exception = ex
                }.Build());
            }
        }
Beispiel #4
0
 private async Task HandleAcknowledgementFailure(QueuedMessage queuedMessage)
 {
     try
     {
         var acknowledgementFailureHandlers = AcknowledgementFailure;
         if (acknowledgementFailureHandlers != null)
         {
             var eventArgs = new MessageQueueEventArgs(QueueName, queuedMessage, null);
             await AcknowledgementFailure(this, eventArgs);
         }
     }
     catch (Exception ex)
     {
         DiagnosticService.Emit(new DiagnosticEventBuilder(this, DiagnosticEventType.MessageAcknowledgementError)
         {
             Detail    = "Unexpected error handling message acknowledgement failure",
             Message   = queuedMessage.Message,
             Queue     = QueueName,
             Exception = ex
         }.Build());
     }
 }
        /// <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);
        }