Exemple #1
0
        public async Task WithServiceBusRouting_WithMessageHandlerMessageBodySerializerSubType_DeserializesCustomMessage()
        {
            // Arrange
            var services       = new ServiceCollection();
            var collection     = new ServiceBusMessageHandlerCollection(services);
            var ignoredHandler = new StubServiceBusMessageHandler <TestMessage>();
            var spyHandler     = new StubServiceBusMessageHandler <Order>();

            var expectedMessage = new TestMessage {
                TestProperty = "Some value"
            };
            string expectedBody = JsonConvert.SerializeObject(expectedMessage);
            var    serializer   = new TestMessageBodySerializer(expectedBody, new SubOrder());

            collection.WithServiceBusMessageHandler <StubServiceBusMessageHandler <Order>, Order>(messageBodySerializer: serializer, implementationFactory: serviceProvider => spyHandler)
            .WithServiceBusMessageHandler <StubServiceBusMessageHandler <TestMessage>, TestMessage>(implementationFactory: serviceProvider => ignoredHandler);

            // Act
            services.AddServiceBusMessageRouting();

            // Assert
            IServiceProvider provider = services.BuildServiceProvider();
            var router = provider.GetRequiredService <IAzureServiceBusMessageRouter>();
            AzureServiceBusMessageContext context = AzureServiceBusMessageContextFactory.Generate();
            var correlationInfo = new MessageCorrelationInfo("operation-id", "transaction-id");

            ServiceBusReceivedMessage message = expectedMessage.AsServiceBusReceivedMessage();
            await router.RouteMessageAsync(message, context, correlationInfo, CancellationToken.None);

            Assert.True(spyHandler.IsProcessed);
            Assert.False(ignoredHandler.IsProcessed);
        }
Exemple #2
0
        public async Task WithServiceBusRouting_IgnoreMissingMembers_ResultsInDifferentMessageHandler(AdditionalMemberHandling additionalMemberHandling)
        {
            // Arrange
            var services         = new ServiceCollection();
            var collection       = new ServiceBusMessageHandlerCollection(services);
            var messageHandlerV1 = new OrderV1AzureServiceBusMessageHandler();
            var messageHandlerV2 = new OrderV2AzureServiceBusMessageHandler();

            collection.WithServiceBusMessageHandler <OrderV1AzureServiceBusMessageHandler, Order>(provider => messageHandlerV1)
            .WithServiceBusMessageHandler <OrderV2AzureServiceBusMessageHandler, OrderV2>(provider => messageHandlerV2);

            // Act
            services.AddServiceBusMessageRouting(options => options.Deserialization.AdditionalMembers = additionalMemberHandling);

            // Assert
            IServiceProvider serviceProvider = services.BuildServiceProvider();
            var router = serviceProvider.GetRequiredService <IAzureServiceBusMessageRouter>();

            OrderV2 orderV2 = OrderV2Generator.Generate();
            ServiceBusReceivedMessage     message = orderV2.AsServiceBusReceivedMessage();
            AzureServiceBusMessageContext context = AzureServiceBusMessageContextFactory.Generate();
            var correlationInfo = new MessageCorrelationInfo("operation-id", "transaction-id");
            await router.RouteMessageAsync(message, context, correlationInfo, CancellationToken.None);

            Assert.Equal(additionalMemberHandling is AdditionalMemberHandling.Error, messageHandlerV2.IsProcessed);
            Assert.Equal(additionalMemberHandling is AdditionalMemberHandling.Ignore, messageHandlerV1.IsProcessed);
        }
Exemple #3
0
        /// <summary>
        /// Tries to process the unhandled <paramref name="message"/> through an potential registered <see cref="IAzureServiceBusFallbackMessageHandler"/> instance.
        /// </summary>
        /// <param name="messageReceiver">
        ///     The instance that can receive Azure Service Bus <see cref="ServiceBusReceivedMessage"/>; used within <see cref="IAzureServiceBusFallbackMessageHandler"/>s with Azure Service Bus specific operations.
        /// </param>
        /// <param name="message">The message that was received by the <paramref name="messageReceiver"/>.</param>
        /// <param name="messageContext">The context in which the <paramref name="message"/> should be processed.</param>
        /// <param name="correlationInfo">The information concerning correlation of telemetry and processes by using a variety of unique identifiers.</param>
        /// <param name="cancellationToken">The token to cancel the message processing.</param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown when the <paramref name="messageReceiver"/>, <paramref name="message"/>, <paramref name="messageContext"/>, or <paramref name="correlationInfo"/> is <c>null</c>.
        /// </exception>
        protected async Task TryServiceBusFallbackMessageAsync(
            ServiceBusReceiver messageReceiver,
            ServiceBusReceivedMessage message,
            AzureServiceBusMessageContext messageContext,
            MessageCorrelationInfo correlationInfo,
            CancellationToken cancellationToken)
        {
            Guard.NotNull(message, nameof(message), "Requires an Azure Service Bus message to be processed by the registered fallback message handler");
            Guard.NotNull(messageContext, nameof(messageContext), "Requires an Azure Service Bus message context in which the incoming message can be processed");
            Guard.NotNull(correlationInfo, nameof(correlationInfo), "Requires an correlation information to correlate between incoming Azure Service Bus messages");

            if (HasAzureServiceBusFallbackHandler)
            {
                if (_fallbackMessageHandler.Value is AzureServiceBusMessageHandlerTemplate template)
                {
                    if (messageReceiver is null)
                    {
                        Logger.LogWarning("Fallback message handler '{MessageHandlerType}' uses specific Azure Service Bus operations, but is unable to be configured during message routing because the message router didn't receive a Azure Service Bus message receiver; use other '{RouteMessageAsync}' method overload",
                                          _fallbackMessageHandler.Value.GetType().Name, nameof(RouteMessageAsync));
                    }
                    else
                    {
                        var args = new ProcessMessageEventArgs(message, messageReceiver, cancellationToken);
                        template.SetProcessMessageEventArgs(args);
                    }
                }

                string fallbackMessageHandlerTypeName = _fallbackMessageHandler.Value.GetType().Name;
                Logger.LogTrace("Fallback on registered '{FallbackMessageHandlerType}' because none of the message handlers w ere able to process the message", fallbackMessageHandlerTypeName);
                await _fallbackMessageHandler.Value.ProcessMessageAsync(message, messageContext, correlationInfo, cancellationToken);

                Logger.LogTrace("Fallback message handler '{FallbackMessageHandlerType}' has processed the message", fallbackMessageHandlerTypeName);
            }
        }
        /// <summary>
        ///     Process a new message that was received
        /// </summary>
        /// <param name="message">Message that was received</param>
        /// <param name="azureMessageContext">Context providing more information concerning the processing</param>
        /// <param name="correlationInfo">
        ///     Information concerning correlation of telemetry and processes by using a variety of unique
        ///     identifiers
        /// </param>
        /// <param name="cancellationToken">Cancellation token</param>
        public override async Task ProcessMessageAsync(
            ServiceBusReceivedMessage message,
            AzureServiceBusMessageContext azureMessageContext,
            MessageCorrelationInfo correlationInfo,
            CancellationToken cancellationToken)
        {
            if (azureMessageContext.SystemProperties.DeliveryCount <= 1)
            {
                Logger.LogTrace("Abandoning message '{MessageId}'...", message.MessageId);
                await AbandonMessageAsync(message);

                Logger.LogTrace("Abandoned message '{MessageId}'", message.MessageId);
            }
            else
            {
                string json  = Encoding.UTF8.GetString(message.Body);
                var    order = JsonConvert.DeserializeObject <Order>(json);

                Logger.LogInformation("Processing order {OrderId} for {OrderAmount} units of {OrderArticle} bought by {CustomerFirstName} {CustomerLastName}",
                                      order.Id, order.Amount, order.ArticleNumber, order.Customer.FirstName, order.Customer.LastName);

                await PublishEventToEventGridAsync(order, correlationInfo.OperationId, correlationInfo);

                Logger.LogInformation("Order {OrderId} processed", order.Id);
            }
        }
Exemple #5
0
        public async Task WithServiceBusMessageRouting_WithMessageHandlerMessageBodyFilter_GoesThroughRegisteredMessageHandlers()
        {
            // Arrange
            var services       = new ServiceCollection();
            var collection     = new ServiceBusMessageHandlerCollection(services);
            var ignoredHandler = new StubServiceBusMessageHandler <Order>();
            var spyHandler     = new StubServiceBusMessageHandler <Order>();

            collection.WithServiceBusMessageHandler <StubServiceBusMessageHandler <Order>, Order>(
                messageBodyFilter: body => true, implementationFactory: serviceProvider => spyHandler)
            .WithServiceBusMessageHandler <StubServiceBusMessageHandler <Order>, Order>(
                messageBodyFilter: body => false, implementationFactory: serviceProvider => ignoredHandler);

            // Act
            services.AddServiceBusMessageRouting();

            // Assert
            IServiceProvider provider = services.BuildServiceProvider();
            var router = provider.GetRequiredService <IAzureServiceBusMessageRouter>();
            AzureServiceBusMessageContext context = AzureServiceBusMessageContextFactory.Generate();
            var correlationInfo = new MessageCorrelationInfo("operation-id", "transaction-id");

            Order order = OrderGenerator.Generate();
            ServiceBusReceivedMessage message = order.AsServiceBusReceivedMessage();
            await router.RouteMessageAsync(message, context, correlationInfo, CancellationToken.None);

            Assert.True(spyHandler.IsProcessed);
            Assert.False(ignoredHandler.IsProcessed);
        }
Exemple #6
0
        /// <summary>
        /// Handle a new <paramref name="message"/> that was received by routing them through registered <see cref="IAzureServiceBusMessageHandler{TMessage}"/>s
        /// and optionally through an registered <see cref="IFallbackMessageHandler"/> or <see cref="IAzureServiceBusFallbackMessageHandler"/> if none of the message handlers were able to process the <paramref name="message"/>.
        /// </summary>
        /// <param name="messageReceiver">
        ///     The instance that can receive Azure Service Bus <see cref="ServiceBusReceivedMessage"/>; used within <see cref="IMessageHandler{TMessage,TMessageContext}"/>s with Azure Service Bus specific operations.
        /// </param>
        /// <param name="message">The message that was received by the <paramref name="messageReceiver"/>.</param>
        /// <param name="messageContext">The context in which the <paramref name="message"/> should be processed.</param>
        /// <param name="correlationInfo">The information concerning correlation of telemetry and processes by using a variety of unique identifiers.</param>
        /// <param name="cancellationToken">The token to cancel the message processing.</param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown when the <paramref name="messageReceiver"/>, <paramref name="message"/>, <paramref name="messageContext"/>, or <paramref name="correlationInfo"/> is <c>null</c>.
        /// </exception>
        /// <exception cref="InvalidOperationException">Thrown when no message handlers or none matching message handlers are found to process the message.</exception>
        protected async Task RouteMessageWithPotentialFallbackAsync(
            ServiceBusReceiver messageReceiver,
            ServiceBusReceivedMessage message,
            AzureServiceBusMessageContext messageContext,
            MessageCorrelationInfo correlationInfo,
            CancellationToken cancellationToken)
        {
            Guard.NotNull(message, nameof(message), "Requires an Azure Service Bus message to be processed by the registered message handlers");
            Guard.NotNull(messageContext, nameof(messageContext), "Requires an Azure Service Bus message context in which the incoming message can be processed");
            Guard.NotNull(correlationInfo, nameof(correlationInfo), "Requires an correlation information to correlate between incoming Azure Service Bus messages");

            try
            {
                MessageHandler[] messageHandlers = GetRegisteredMessageHandlers().ToArray();
                if (messageHandlers.Length <= 0 && !HasFallbackMessageHandler && !HasAzureServiceBusFallbackHandler)
                {
                    throw new InvalidOperationException(
                              $"Azure Service Bus message pump cannot correctly process the message in the '{nameof(AzureServiceBusMessageContext)}' "
                              + "because no 'IAzureServiceBusMessageHandler<>' was registered in the dependency injection container. "
                              + $"Make sure you call the correct 'WithServiceBusMessageHandler' extension on the {nameof(IServiceCollection)} "
                              + "during the registration of the Azure Service Bus message pump or message router to register a message handler");
                }

                Encoding encoding    = messageContext.GetMessageEncodingProperty(Logger);
                string   messageBody = encoding.GetString(message.Body.ToArray());

                foreach (MessageHandler messageHandler in messageHandlers)
                {
                    MessageResult result = await DeserializeMessageForHandlerAsync(messageBody, messageContext, messageHandler);

                    if (result.IsSuccess)
                    {
                        var args = new ProcessMessageEventArgs(message, messageReceiver, cancellationToken);
                        SetServiceBusPropertiesForSpecificOperations(messageHandler, args, messageContext);

                        await messageHandler.ProcessMessageAsync(result.DeserializedMessage, messageContext, correlationInfo, cancellationToken);

                        return;
                    }
                }

                if (!HasFallbackMessageHandler && !HasAzureServiceBusFallbackHandler)
                {
                    throw new InvalidOperationException(
                              $"Message pump cannot correctly process the message in the '{nameof(AzureServiceBusMessageContext)}' "
                              + "because none of the registered 'IAzureServiceBusMessageHandler<,>' implementations in the dependency injection container matches the incoming message type and context; "
                              + $"and no '{nameof(IFallbackMessageHandler)}' or '{nameof(IAzureServiceBusFallbackMessageHandler)}' was registered to fall back to."
                              + $"Make sure you call the correct '.WithServiceBusMessageHandler' extension on the {nameof(IServiceCollection)} during the registration of the message pump or message router to register a message handler");
                }

                await TryFallbackProcessMessageAsync(messageBody, messageContext, correlationInfo, cancellationToken);
                await TryServiceBusFallbackMessageAsync(messageReceiver, message, messageContext, correlationInfo, cancellationToken);
            }
            catch (Exception exception)
            {
                Logger.LogCritical(exception, "Unable to process message with ID '{MessageId}'", message.MessageId);
                throw;
            }
        }
 /// <summary>Process a new message that was received</summary>
 /// <param name="message">Message that was received</param>
 /// <param name="messageContext">Context providing more information concerning the processing</param>
 /// <param name="correlationInfo">
 ///     Information concerning correlation of telemetry and processes by using a variety of unique
 ///     identifiers
 /// </param>
 /// <param name="cancellationToken">Cancellation token</param>
 public async Task ProcessMessageAsync(
     Order message,
     AzureServiceBusMessageContext messageContext,
     MessageCorrelationInfo correlationInfo,
     CancellationToken cancellationToken)
 {
     throw new NotImplementedException();
 }
Exemple #8
0
        protected override async Task ProcessMessageAsync(Order orderMessage, AzureServiceBusMessageContext messageContext, MessageCorrelationInfo correlationInfo, CancellationToken cancellationToken)
        {
            Logger.LogInformation("Processing order {OrderId} for {OrderAmount} units of {OrderArticle} bought by {CustomerFirstName} {CustomerLastName}", orderMessage.Id, orderMessage.Amount, orderMessage.ArticleNumber, orderMessage.Customer.FirstName, orderMessage.Customer.LastName);

            await PublishEventToEventGridAsync(orderMessage, correlationInfo.OperationId, correlationInfo);

            Logger.LogInformation("Order {OrderId} processed", orderMessage.Id);
        }
 /// <summary>
 ///     Process a new message that was received
 /// </summary>
 /// <param name="message">Message that was received</param>
 /// <param name="messageContext">Context providing more information concerning the processing</param>
 /// <param name="correlationInfo">
 ///     Information concerning correlation of telemetry and processes by using a variety of unique
 ///     identifiers
 /// </param>
 /// <param name="cancellationToken">Cancellation token</param>
 public Task ProcessMessageAsync(
     ServiceBusReceivedMessage message,
     AzureServiceBusMessageContext messageContext,
     MessageCorrelationInfo correlationInfo,
     CancellationToken cancellationToken)
 {
     return(Task.CompletedTask);
 }
 /// <summary>
 ///     Process a new message that was received
 /// </summary>
 /// <param name="message">Message that was received</param>
 /// <param name="messageContext">Context providing more information concerning the processing</param>
 /// <param name="correlationInfo">
 ///     Information concerning correlation of telemetry and processes by using a variety of unique
 ///     identifiers
 /// </param>
 /// <param name="cancellationToken">Cancellation token</param>
 public Task ProcessMessageAsync(
     OrderV2 message,
     AzureServiceBusMessageContext messageContext,
     MessageCorrelationInfo correlationInfo,
     CancellationToken cancellationToken)
 {
     IsProcessed = true;
     return(Task.CompletedTask);
 }
Exemple #11
0
 /// <summary>
 ///     Process a new message that was received
 /// </summary>
 /// <param name="message">Message that was received</param>
 /// <param name="messageContext">Context providing more information concerning the processing</param>
 /// <param name="correlationInfo">
 ///     Information concerning correlation of telemetry and processes by using a variety of unique
 ///     identifiers
 /// </param>
 /// <param name="cancellationToken">Cancellation token</param>
 public Task ProcessMessageAsync(
     Order message,
     AzureServiceBusMessageContext messageContext,
     MessageCorrelationInfo correlationInfo,
     CancellationToken cancellationToken)
 {
     throw new InvalidOperationException(
               "Sabotage the message processing with an unhandled exception");
 }
        /// <summary>
        ///     Process a new message that was received
        /// </summary>
        /// <param name="message">Message that was received</param>
        /// <param name="messageContext">Context providing more information concerning the processing</param>
        /// <param name="correlationInfo">
        ///     Information concerning correlation of telemetry and processes by using a variety of unique
        ///     identifiers
        /// </param>
        /// <param name="cancellationToken">Cancellation token</param>
        public override async Task ProcessMessageAsync(
            Order message,
            AzureServiceBusMessageContext messageContext,
            MessageCorrelationInfo correlationInfo,
            CancellationToken cancellationToken)
        {
            await _orderMessageHandler.ProcessMessageAsync(message, messageContext, correlationInfo, cancellationToken);

            await CompleteMessageAsync();
        }
        /// <summary>
        ///     Process a new message that was received
        /// </summary>
        /// <param name="message">The Azure Service Bus Message message that was received</param>
        /// <param name="messageContext">The context providing more information concerning the processing</param>
        /// <param name="correlationInfo">
        ///     The information concerning correlation of telemetry and processes by using a variety of unique
        ///     identifiers.
        /// </param>
        /// <param name="cancellationToken">The cancellation token to cancel the processing.</param>
        public override async Task ProcessMessageAsync(
            ServiceBusReceivedMessage message,
            AzureServiceBusMessageContext messageContext,
            MessageCorrelationInfo correlationInfo,
            CancellationToken cancellationToken)
        {
            await _fallbackMessageHandler.ProcessMessageAsync(message, messageContext, correlationInfo, cancellationToken);

            await CompleteAsync(message);
        }
        /// <summary>
        ///     Process a new message that was received
        /// </summary>
        /// <param name="message">Message that was received</param>
        /// <param name="messageContext">Context providing more information concerning the processing</param>
        /// <param name="correlationInfo">
        ///     Information concerning correlation of telemetry and processes by using a variety of unique
        ///     identifiers
        /// </param>
        /// <param name="cancellationToken">Cancellation token</param>
        public override async Task ProcessMessageAsync(
            Order message,
            AzureServiceBusMessageContext messageContext,
            MessageCorrelationInfo correlationInfo,
            CancellationToken cancellationToken)
        {
            Logger.LogTrace("Dead letter message '{OrderId}'...", message.Id);
            await DeadLetterMessageAsync();

            Logger.LogInformation("Message '{OrderId}' is dead lettered", message.Id);
        }
 protected virtual async Task PreProcessingAsync(
     MessageHandler handler,
     AzureServiceBusMessageContext messageContext,
     MessageReceiver messageReceiver)
 {
     if (handler.Service is AzureServiceBusMessageHandlerTemplate template)
     {
         template.GetType().GetMethod("SetMessageReceiver", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(template, new [] { messageReceiver });
         template.GetType().GetMethod("SetLockToken", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(template, new [] { messageContext.SystemProperties.LockToken });
     }
 }
Exemple #16
0
 /// <summary>
 ///     Process a new message that was received
 /// </summary>
 /// <param name="batch">Message that was received</param>
 /// <param name="messageContext">Context providing more information concerning the processing</param>
 /// <param name="correlationInfo">
 ///     Information concerning correlation of telemetry and processes by using a variety of unique
 ///     identifiers
 /// </param>
 /// <param name="cancellationToken">Cancellation token</param>
 public async Task ProcessMessageAsync(
     OrderBatch batch,
     AzureServiceBusMessageContext messageContext,
     MessageCorrelationInfo correlationInfo,
     CancellationToken cancellationToken)
 {
     foreach (Order order in batch.Orders)
     {
         await _messageHandler.ProcessMessageAsync(order, messageContext, correlationInfo, cancellationToken);
     }
 }
        /// <summary>Process a new message that was received</summary>
        /// <param name="message">Message that was received</param>
        /// <param name="messageContext">Context providing more information concerning the processing</param>
        /// <param name="correlationInfo">
        ///     Information concerning correlation of telemetry and processes by using a variety of unique
        ///     identifiers
        /// </param>
        /// <param name="cancellationToken">Cancellation token</param>
        public async Task ProcessMessageAsync(
            EmptyMessage message,
            AzureServiceBusMessageContext messageContext,
            MessageCorrelationInfo correlationInfo,
            CancellationToken cancellationToken)
        {
            _logger.LogTrace("Processing message {message}...", message);

            // Process message.

            _logger.LogInformation("Message {message} processed!", message);
        }
Exemple #18
0
        public async Task Run(
            [ServiceBusTrigger("myqueue", Connection = "")] string myQueueItem,
            Microsoft.Azure.ServiceBus.Message message,
            MessageReceiver messageReceiver,
            ILogger log)
        {
            log.LogInformation($"C# ServiceBus queue trigger function processed message: {myQueueItem}");

            var context = new AzureServiceBusMessageContext(message.MessageId, message.SystemProperties, message.UserProperties);
            MessageCorrelationInfo correlation = message.GetCorrelationInfo();

            await _router.ProcessMessageAsync(messageReceiver, message, context, correlation, CancellationToken.None);
        }
        public async Task WithServiceBusRouting_WithMessageHandlerCanHandleAllFiltersAtOnce_AndStillFindsTheRightMessageHandler()
        {
            // Arrange
            var services        = new ServiceCollection();
            var collection      = new ServiceBusMessageHandlerCollection(services);
            var ignoredHandler1 = new StubServiceBusMessageHandler <TestMessage>();
            var ignoredHandler2 = new StubServiceBusMessageHandler <TestMessage>();
            var ignoredHandler3 = new StubServiceBusMessageHandler <Order>();
            var spyHandler      = new StubServiceBusMessageHandler <Order>();

            AzureServiceBusMessageContext context = AzureServiceBusMessageContextFactory.Generate();
            var expectedMessage = new TestMessage {
                TestProperty = "Some value"
            };
            string expectedBody = JsonConvert.SerializeObject(expectedMessage);
            var    serializer   = new TestMessageBodySerializer(expectedBody, OrderGenerator.Generate());

            collection
            .WithServiceBusMessageHandler <StubServiceBusMessageHandler <Order>, Order>(
                messageContextFilter: ctx => ctx != null,
                messageBodyFilter: body => body != null,
                messageBodySerializer: new TestMessageBodySerializer(expectedBody, new Customer()),
                implementationFactory: serviceProvider => ignoredHandler3)
            .WithServiceBusMessageHandler <StubServiceBusMessageHandler <TestMessage>, TestMessage>(
                messageBodyFilter: body => body is null,
                implementationFactory: serviceProvider => ignoredHandler2)
            .WithServiceBusMessageHandler <StubServiceBusMessageHandler <Order>, Order>(
                messageBodySerializer: serializer,
                messageBodyFilter: body => body.Customer != null,
                messageContextFilter: ctx => ctx.MessageId.StartsWith("message-id"),
                implementationFactory: serviceProvider => spyHandler)
            .WithServiceBusMessageHandler <StubServiceBusMessageHandler <TestMessage>, TestMessage>()
            .WithServiceBusMessageHandler <StubServiceBusMessageHandler <TestMessage>, TestMessage>(
                implementationFactory: serviceProvider => ignoredHandler1);

            // Act
            services.AddServiceBusMessageRouting();

            // Assert
            IServiceProvider provider = services.BuildServiceProvider();
            var router = provider.GetRequiredService <IAzureServiceBusMessageRouter>();

            var correlationInfo = new MessageCorrelationInfo("operation-id", "transaction-id");
            ServiceBusReceivedMessage message = expectedMessage.AsServiceBusReceivedMessage();
            await router.RouteMessageAsync(message, context, correlationInfo, CancellationToken.None);

            Assert.True(spyHandler.IsProcessed);
            Assert.False(ignoredHandler1.IsProcessed);
            Assert.False(ignoredHandler2.IsProcessed);
            Assert.False(ignoredHandler3.IsProcessed);
        }
Exemple #20
0
        /// <summary>Process a new message that was received</summary>
        /// <param name="message">Message that was received</param>
        /// <param name="messageContext">Context providing more information concerning the processing</param>
        /// <param name="correlationInfo">
        ///     Information concerning correlation of telemetry and processes by using a variety of unique
        ///     identifiers
        /// </param>
        /// <param name="cancellationToken">Cancellation token</param>
        public async Task ProcessMessageAsync(
            Order message,
            AzureServiceBusMessageContext messageContext,
            MessageCorrelationInfo correlationInfo,
            CancellationToken cancellationToken)
        {
            _logger.LogInformation(
                "Processing order {OrderId} for {OrderAmount} units of {OrderArticle}",
                message.Id, message.Amount, message.ArticleNumber);

            await PublishEventToEventGridAsync(message, correlationInfo.OperationId, correlationInfo);

            _logger.LogInformation("Order {OrderId} processed", message.Id);
        }
Exemple #21
0
        /// <summary>
        /// Handle a new <paramref name="message"/> that was received by routing them through registered <see cref="IAzureServiceBusMessageHandler{TMessage}"/>s
        /// and optionally through an registered <see cref="IFallbackMessageHandler"/> or <see cref="IAzureServiceBusFallbackMessageHandler"/> if none of the message handlers were able to process the <paramref name="message"/>.
        /// </summary>
        /// <param name="messageReceiver">
        ///     The instance that can receive Azure Service Bus <see cref="ServiceBusReceivedMessage"/>; used within <see cref="IMessageHandler{TMessage,TMessageContext}"/>s with Azure Service Bus specific operations.
        /// </param>
        /// <param name="message">The message that was received by the <paramref name="messageReceiver"/>.</param>
        /// <param name="messageContext">The context in which the <paramref name="message"/> should be processed.</param>
        /// <param name="correlationInfo">The information concerning correlation of telemetry and processes by using a variety of unique identifiers.</param>
        /// <param name="cancellationToken">The token to cancel the message processing.</param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown when the <paramref name="messageReceiver"/>, <paramref name="message"/>, <paramref name="messageContext"/>, or <paramref name="correlationInfo"/> is <c>null</c>.
        /// </exception>
        /// <exception cref="InvalidOperationException">Thrown when no message handlers or none matching message handlers are found to process the message.</exception>
        public async Task RouteMessageAsync(
            ServiceBusReceiver messageReceiver,
            ServiceBusReceivedMessage message,
            AzureServiceBusMessageContext messageContext,
            MessageCorrelationInfo correlationInfo,
            CancellationToken cancellationToken)
        {
            Guard.NotNull(messageReceiver, nameof(messageReceiver), "Requires an Azure Service Bus message receiver while processing the message, so message handlers can call Azure Service Bus specific operations");
            Guard.NotNull(message, nameof(message), "Requires an Azure Service Bus message to be processed by the registered message handlers");
            Guard.NotNull(messageContext, nameof(messageContext), "Requires an Azure Service Bus message context in which the incoming message can be processed");
            Guard.NotNull(correlationInfo, nameof(correlationInfo), "Requires an correlation information to correlate between incoming Azure Service Bus messages");

            await RouteMessageWithPotentialFallbackAsync(messageReceiver, message, messageContext, correlationInfo, cancellationToken);
        }
        /// <summary>
        ///     Process a new message that was received
        /// </summary>
        /// <param name="message">Message that was received</param>
        /// <param name="azureMessageContext">Context providing more information concerning the processing</param>
        /// <param name="correlationInfo">
        ///     Information concerning correlation of telemetry and processes by using a variety of unique
        ///     identifiers
        /// </param>
        /// <param name="cancellationToken">Cancellation token</param>
        public async Task ProcessMessageAsync(
            ServiceBusReceivedMessage message,
            AzureServiceBusMessageContext azureMessageContext,
            MessageCorrelationInfo correlationInfo,
            CancellationToken cancellationToken)
        {
            string messageBody = Encoding.UTF8.GetString(message.Body);
            var    order       = JsonConvert.DeserializeObject <Order>(messageBody);

            _logger.LogInformation("Processing order {OrderId} for {OrderAmount} units of {OrderArticle} bought by {CustomerFirstName} {CustomerLastName}",
                                   order.Id, order.Amount, order.ArticleNumber, order.Customer.FirstName, order.Customer.LastName);

            await PublishEventToEventGridAsync(order, correlationInfo.OperationId, correlationInfo);

            _logger.LogInformation("Order {OrderId} processed", order.Id);
        }
Exemple #23
0
        /// <summary>
        /// Process a new message that was received
        /// </summary>
        /// <param name="message">Message that was received</param>
        /// <param name="messageContext">Context providing more information concerning the processing</param>
        /// <param name="correlationInfo">
        ///     Information concerning correlation of telemetry and processes by using a variety of unique
        ///     identifiers
        /// </param>
        /// <param name="cancellationToken">Cancellation token</param>
        public async Task ProcessMessageAsync(
            CloudEvent message,
            AzureServiceBusMessageContext messageContext,
            MessageCorrelationInfo correlationInfo,
            CancellationToken cancellationToken)
        {
            Guard.NotNull(message, nameof(message), "Cannot invalidate Azure KeyVault secret from a 'null' CloudEvent");

            var secretNewVersionCreated = message.GetPayload <SecretNewVersionCreated>();

            if (secretNewVersionCreated is null)
            {
                throw new CloudException(
                          "Azure Key Vault job cannot map Event Grid event to CloudEvent because the event data isn't recognized as a 'SecretNewVersionCreated' schema");
            }

            await _cachedSecretProvider.InvalidateSecretAsync(secretNewVersionCreated.ObjectName);

            _logger.LogInformation("Invalidated Azure Key Vault '{SecretName}' secret in vault '{VaultName}'", secretNewVersionCreated.ObjectName, secretNewVersionCreated.VaultName);
        }
Exemple #24
0
        /// <summary>
        /// Generates a valid <see cref="AzureServiceBusMessageContext"/> instance.
        /// </summary>
        public static AzureServiceBusMessageContext Generate()
        {
            var amqp = new AmqpAnnotatedMessage(new AmqpMessageBody(new ReadOnlyMemory <byte> [0]));

            amqp.Header.DeliveryCount = BogusGenerator.Random.UInt();

            var message = (ServiceBusReceivedMessage)Activator.CreateInstance(typeof(ServiceBusReceivedMessage),
                                                                              BindingFlags.NonPublic | BindingFlags.Instance,
                                                                              args: new object[] { amqp },
                                                                              binder: null,
                                                                              culture: null,
                                                                              activationAttributes: null);

            AzureServiceBusSystemProperties systemProperties = message.GetSystemProperties();

            var context = new AzureServiceBusMessageContext(
                $"message-id-{Guid.NewGuid()}",
                $"job-id-{Guid.NewGuid()}",
                systemProperties,
                new Dictionary <string, object>());

            return(context);
        }
        /// <summary>
        ///     Process a new message that was received
        /// </summary>
        /// <param name="order">Message that was received</param>
        /// <param name="azureMessageContext">Context providing more information concerning the processing</param>
        /// <param name="correlationInfo">
        ///     Information concerning correlation of telemetry and processes by using a variety of unique
        ///     identifiers
        /// </param>
        /// <param name="cancellationToken">Cancellation token</param>
        public override async Task ProcessMessageAsync(
            Order order,
            AzureServiceBusMessageContext azureMessageContext,
            MessageCorrelationInfo correlationInfo,
            CancellationToken cancellationToken)
        {
            if (++_deliveryCount <= 1)
            {
                Logger.LogTrace("Abandoning message '{OrderId}'...", order.Id);
                await AbandonMessageAsync();

                Logger.LogTrace("Abandoned message '{OrderId}'", order.Id);
            }
            else
            {
                Logger.LogInformation("Processing order {OrderId} for {OrderAmount} units of {OrderArticle} bought by {CustomerFirstName} {CustomerLastName}",
                                      order.Id, order.Amount, order.ArticleNumber, order.Customer.FirstName, order.Customer.LastName);

                await PublishEventToEventGridAsync(order, correlationInfo.OperationId, correlationInfo);

                Logger.LogInformation("Order {OrderId} processed", order.Id);
            }
        }
        /// <summary>
        ///     Process a new message that was received
        /// </summary>
        /// <param name="message">Message that was received</param>
        /// <param name="messageContext">Context providing more information concerning the processing</param>
        /// <param name="correlationInfo">
        ///     Information concerning correlation of telemetry and processes by using a variety of unique
        ///     identifiers
        /// </param>
        /// <param name="cancellationToken">Cancellation token</param>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="message"/> is <c>null</c>.</exception>
        /// <exception cref="CloudException">Thrown when the <paramref name="message"/> doesn't represent an <see cref="SecretNewVersionCreated"/> event.</exception>
        public async Task ProcessMessageAsync(
            CloudEvent message,
            AzureServiceBusMessageContext messageContext,
            MessageCorrelationInfo correlationInfo,
            CancellationToken cancellationToken)
        {
            Guard.NotNull(message, nameof(message), "Cannot invalidate Azure KeyVault secret from a 'null' CloudEvent");

            _logger.LogTrace("Receiving new Azure Key Vault notification...");

            var secretNewVersionCreated = message.GetPayload <SecretNewVersionCreated>();

            if (secretNewVersionCreated is null)
            {
                _logger.LogWarning("Azure Key Vault job cannot map Event Grid event to CloudEvent because the event data isn't recognized as a 'SecretNewVersionCreated' schema");
            }
            else
            {
                if (_targetConnectionStringKey == secretNewVersionCreated.ObjectName)
                {
                    _logger.LogTrace("Received Azure Key vault 'Secret New Version Created' event, restarting target message pump '{JobId}' on entity path '{EntityPath}' in '{Namespace}'", _messagePump.JobId, _messagePump.EntityPath, _messagePump.Namespace);
                    await _messagePump.RestartAsync();

                    _logger.LogEvent("Message pump restarted", new Dictionary <string, object>
                    {
                        ["JobId"]      = _messagePump.JobId,
                        ["EntityPath"] = _messagePump.EntityPath,
                        ["Namespace"]  = _messagePump.Namespace
                    });
                }
                else
                {
                    _logger.LogTrace("Received Azure Key Vault 'Secret New Version Created' event for another secret, ignoring.");
                }
            }
        }
Exemple #27
0
        /// <summary>
        /// Sets the Azure Service Bus properties on registered <see cref="IAzureServiceBusMessageHandler{TMessage}"/>s
        /// that implements the <see cref="AzureServiceBusMessageHandler{TMessage}"/> for calling specific Service Bus operations during the message processing.
        /// </summary>
        /// <param name="messageHandler">The message handler on which the Service Bus properties should be set.</param>
        /// <param name="eventArgs">The event args of the incoming Service Bus message.</param>
        /// <param name="messageContext">The context in which the received Service Bus message is processed.</param>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="messageHandler"/> or <paramref name="messageContext"/> is <c>null</c>.</exception>
        protected void SetServiceBusPropertiesForSpecificOperations(
            MessageHandler messageHandler,
            ProcessMessageEventArgs eventArgs,
            AzureServiceBusMessageContext messageContext)
        {
            Guard.NotNull(messageHandler, nameof(messageHandler), "Requires an Azure Service Bus message handler to set the specific Service Bus properties");
            Guard.NotNull(messageContext, nameof(messageContext), "Requires an Azure Service Bus message context in which the incoming message can be processed");

            object messageHandlerInstance = messageHandler.GetMessageHandlerInstance();
            Type   messageHandlerType     = messageHandlerInstance.GetType();

            if (messageHandlerInstance is AzureServiceBusMessageHandlerTemplate template)
            {
                if (eventArgs is null)
                {
                    Logger.LogWarning("Message handler '{MessageHandlerType}' uses specific Azure Service Bus operations, but is not able to be configured during message routing because the message router didn't receive a Azure Service Bus message receiver; use other '{RouteMessageOverload}' method overload",
                                      messageHandlerType.Name, nameof(RouteMessageAsync));
                }
                else
                {
                    template.SetProcessMessageEventArgs(eventArgs);
                }
            }
        }
 /// <summary>
 /// Process a new Azure Service Bus message that was received.
 /// </summary>
 /// <param name="message">The Azure Service Bus Message message that was received.</param>
 /// <param name="messageContext">The context providing more information concerning the processing.</param>
 /// <param name="correlationInfo">The information concerning correlation of telemetry and processes by using a variety of unique identifiers.</param>
 /// <param name="cancellationToken">The token to cancel the processing.</param>
 /// <exception cref="ArgumentNullException">
 ///     Thrown when the <paramref name="message"/>, the <paramref name="messageContext"/>, or the <paramref name="correlationInfo"/> is <c>null</c>.
 /// </exception>
 public abstract Task ProcessMessageAsync(
     TMessage message,
     AzureServiceBusMessageContext messageContext,
     MessageCorrelationInfo correlationInfo,
     CancellationToken cancellationToken);