///<inheritdoc cref="ServiceBusReceiver.DeadLetterMessageAsync(ServiceBusReceivedMessage, string, string, CancellationToken)"/>
 public virtual async Task DeadLetterMessageAsync(
     ServiceBusReceivedMessage message,
     string deadLetterReason,
     string deadLetterErrorDescription   = default,
     CancellationToken cancellationToken = default)
 {
     if (_receiver != null)
     {
         await _receiver.DeadLetterMessageAsync(
             message,
             deadLetterReason,
             deadLetterErrorDescription,
             cancellationToken)
         .ConfigureAwait(false);
     }
     else if (_eventArgs != null)
     {
         await _eventArgs.DeadLetterMessageAsync(
             message,
             deadLetterReason,
             deadLetterErrorDescription,
             cancellationToken)
         .ConfigureAwait(false);
     }
     else
     {
         await _sessionEventArgs.DeadLetterMessageAsync(
             message,
             deadLetterReason,
             deadLetterErrorDescription,
             cancellationToken)
         .ConfigureAwait(false);
     }
 }
Exemplo n.º 2
0
        public async Task UserSettledPropertySetCorrectly()
        {
            var msg  = new ServiceBusReceivedMessage();
            var args = new ProcessMessageEventArgs(
                msg,
                new Mock <ServiceBusReceiver>().Object,
                CancellationToken.None);

            Assert.IsFalse(msg.IsSettled);

            msg.IsSettled = false;
            await args.AbandonMessageAsync(msg);

            Assert.IsTrue(msg.IsSettled);

            await args.CompleteMessageAsync(msg);

            Assert.IsTrue(msg.IsSettled);

            msg.IsSettled = false;
            await args.DeadLetterMessageAsync(msg);

            Assert.IsTrue(msg.IsSettled);

            msg.IsSettled = false;
            await args.DeadLetterMessageAsync(msg, "reason");

            Assert.IsTrue(msg.IsSettled);

            msg.IsSettled = false;
            await args.DeferMessageAsync(msg);

            Assert.IsTrue(msg.IsSettled);
        }
Exemplo n.º 3
0
        private async Task MessageHandler(ProcessMessageEventArgs args)
        {
            try
            {
                _logger.LogInformation($"client '{_systemInfo.ClientId}' received message '{args.Message.MessageId}'. Processing...");

                var message = await _messageParser.DeserializeAsync <TM>(args.Message.Body);

                await _messageProcessor.ProcessAsync((dynamic)message, args.CancellationToken);

                await args.CompleteMessageAsync(args.Message).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"an error has occurred while processing message '{args.Message.MessageId}': {ex.Message}");
                if (args.Message.DeliveryCount > 3)
                {
                    await args.DeadLetterMessageAsync(args.Message).ConfigureAwait(false);
                }
                else
                {
                    await args.AbandonMessageAsync(args.Message).ConfigureAwait(false);
                }
            }
        }
        private async Task MessageHandlerAsync(ProcessMessageEventArgs arg)
        {
            var message = arg.Message;
            var body    = Encoding.UTF8.GetString(message.Body.ToArray());
            var data    = JsonSerializer.Deserialize <TEntity>(body, new JsonSerializerOptions
            {
                PropertyNameCaseInsensitive = true
            });

            if (ValidateMessage(data))
            {
                if (await ProcessDataAsync(data).ConfigureAwait(false))
                {
                    // Now that we're done with "processing" the message, we tell the broker about that being the
                    // case. The MessageReceiver.CompleteAsync operation will settle the message transfer with
                    // the broker and remove it from the broker.
                    await arg.CompleteMessageAsync(message)
                    .ConfigureAwait(false);
                }
                else
                {
                    // If the message does not meet our processing criteria, we will dead letter it, meaning
                    // it is put into a special queue for handling defective messages. The broker will automatically
                    // dead letter the message, if delivery has been attempted too many times.
                    await arg.DeadLetterMessageAsync(message)
                    .ConfigureAwait(false);
                }
            }
        }
        private async Task OnMessageReceivedAsync <TEvent, TConsumer>(EventRegistration ereg, EventConsumerRegistration creg, ProcessMessageEventArgs args)
            where TEvent : class
            where TConsumer : IEventConsumer <TEvent>
        {
            var message           = args.Message;
            var messageId         = message.MessageId;
            var cancellationToken = args.CancellationToken;

            message.ApplicationProperties.TryGetValue(AttributeNames.ActivityId, out var parentActivityId);

            using var log_scope = Logger.BeginScopeForConsume(id: messageId,
                                                              correlationId: message.CorrelationId,
                                                              sequenceNumber: message.SequenceNumber,
                                                              extras: new Dictionary <string, string>
            {
                ["EnqueuedSequenceNumber"] = message.EnqueuedSequenceNumber.ToString(),
            });

            // Instrumentation
            using var activity = EventBusActivitySource.StartActivity(ActivityNames.Consume, ActivityKind.Consumer, parentActivityId?.ToString());
            activity?.AddTag(ActivityTagNames.EventBusEventType, typeof(TEvent).FullName);
            activity?.AddTag(ActivityTagNames.EventBusConsumerType, typeof(TConsumer).FullName);
            activity?.AddTag(ActivityTagNames.MessagingSystem, Name);
            var destination = TransportOptions.UseBasicTier || ereg.UseQueueInsteadOfTopic() ? ereg.EventName : creg.ConsumerName;

            activity?.AddTag(ActivityTagNames.MessagingDestination, destination); // name of the queue/subscription
            activity?.AddTag(ActivityTagNames.MessagingDestinationKind, "queue"); // the spec does not know subscription so we can only use queue for both

            try
            {
                Logger.LogDebug("Processing '{MessageId}'", messageId);
                using var scope = CreateScope();
                using var ms    = message.Body.ToStream();
                var contentType = new ContentType(message.ContentType);
                var context     = await DeserializeAsync <TEvent>(body : ms,
                                                                  contentType : contentType,
                                                                  registration : ereg,
                                                                  scope : scope,
                                                                  cancellationToken : cancellationToken);

                Logger.LogInformation("Received message: '{MessageId}' containing Event '{Id}'",
                                      messageId,
                                      context.Id);

                await ConsumeAsync <TEvent, TConsumer>(@event : context,
                                                       scope : scope,
                                                       cancellationToken : cancellationToken);

                // Complete the message
                Logger.LogDebug("Completing message: {MessageId}.", messageId);
                await args.CompleteMessageAsync(message : message, cancellationToken : cancellationToken);
            }
            catch (Exception ex)
            {
                Logger.LogError(ex, "Event processing failed. Moving to deadletter.");
                await args.DeadLetterMessageAsync(message : message, cancellationToken : cancellationToken);
            }
        }
        private async Task MessageHandler(ProcessMessageEventArgs args)
        {
            try
            {
                var message = _messageParser.Resolve <TM>(args.Message.Body);

                await _messageProcessor.ProcessAsync((dynamic)message, args.CancellationToken);

                await args.CompleteMessageAsync(args.Message).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"an error has occurred while processing message '{args.Message.MessageId}': {ex.Message}");
                if (args.Message.DeliveryCount > 3)
                {
                    await args.DeadLetterMessageAsync(args.Message).ConfigureAwait(false);
                }
                else
                {
                    await args.AbandonMessageAsync(args.Message).ConfigureAwait(false);
                }
            }
        }
Exemplo n.º 7
0
        public void UserSettledPropertySetCorrectlyOnException()
        {
            var msg          = new ServiceBusReceivedMessage();
            var mockReceiver = new Mock <ServiceBusReceiver>();

            mockReceiver
            .Setup(receiver => receiver.AbandonMessageAsync(
                       It.IsAny <ServiceBusReceivedMessage>(),
                       It.IsAny <IDictionary <string, object> >(),
                       It.IsAny <CancellationToken>()))
            .Throws(new Exception());

            mockReceiver
            .Setup(receiver => receiver.DeferMessageAsync(
                       It.IsAny <ServiceBusReceivedMessage>(),
                       It.IsAny <IDictionary <string, object> >(),
                       It.IsAny <CancellationToken>()))
            .Throws(new Exception());

            mockReceiver
            .Setup(receiver => receiver.CompleteMessageAsync(
                       It.IsAny <ServiceBusReceivedMessage>(),
                       It.IsAny <CancellationToken>()))
            .Throws(new Exception());

            mockReceiver
            .Setup(receiver => receiver.DeadLetterMessageAsync(
                       It.IsAny <ServiceBusReceivedMessage>(),
                       It.IsAny <IDictionary <string, object> >(),
                       It.IsAny <CancellationToken>()))
            .Throws(new Exception());

            mockReceiver
            .Setup(receiver => receiver.DeadLetterMessageAsync(
                       It.IsAny <ServiceBusReceivedMessage>(),
                       It.IsAny <string>(),
                       It.IsAny <string>(),
                       It.IsAny <CancellationToken>()))
            .Throws(new Exception());

            var args = new ProcessMessageEventArgs(
                msg,
                mockReceiver.Object,
                CancellationToken.None);

            Assert.IsFalse(msg.IsSettled);

            msg.IsSettled = false;
            Assert.That(async() => await args.AbandonMessageAsync(msg),
                        Throws.InstanceOf <Exception>());
            Assert.IsFalse(msg.IsSettled);

            Assert.That(async() => await args.CompleteMessageAsync(msg),
                        Throws.InstanceOf <Exception>());
            Assert.IsFalse(msg.IsSettled);

            msg.IsSettled = false;
            Assert.That(async() => await args.DeadLetterMessageAsync(msg),
                        Throws.InstanceOf <Exception>());
            Assert.IsFalse(msg.IsSettled);

            msg.IsSettled = false;
            Assert.That(async() => await args.DeadLetterMessageAsync(msg, "reason"),
                        Throws.InstanceOf <Exception>());
            Assert.IsFalse(msg.IsSettled);

            msg.IsSettled = false;
            Assert.That(async() => await args.DeferMessageAsync(msg),
                        Throws.InstanceOf <Exception>());
            Assert.IsFalse(msg.IsSettled);
        }
 public static Task DeadLetterByDeliveryLimitAsync(this ServiceBusReceivedMessage message, ProcessMessageEventArgs client, int deliveryLimit)
 {
     return(client.DeadLetterMessageAsync(message, "MaxDeliveryCountExceeded", $"DeliveryCount exceeded limit of {deliveryLimit}"));
 }