Exemplo n.º 1
0
        public async Task ServiceBusTopicMessagePumpWithNamespaceScopedConnectionString_PublishesServiceBusMessage_MessageSuccessfullyProcessed()
        {
            // Arrange
            var    config = TestConfig.Create();
            string topicConnectionString     = config.GetServiceBusConnectionString(ServiceBusEntityType.Topic);
            var    properties                = ServiceBusConnectionStringProperties.Parse(topicConnectionString);
            string namespaceConnectionString = properties.GetNamespaceConnectionString();

            var options = new WorkerOptions();

            options.AddEventGridPublisher(config)
            .AddServiceBusTopicMessagePump(
                topicName: properties.EntityPath,
                subscriptionName: "Test-Receive-All-Topic-Only",
                getConnectionStringFromConfigurationFunc: configuration => namespaceConnectionString,
                configureMessagePump: opt => opt.AutoComplete = true)
            .WithServiceBusMessageHandler <OrdersAzureServiceBusMessageHandler, Order>();

            // Act
            await using (var worker = await Worker.StartNewAsync(options))
                await using (var service = await TestMessagePumpService.StartNewAsync(config, _logger))
                {
                    // Assert
                    await service.SimulateMessageProcessingAsync(topicConnectionString);
                }
        }
Exemplo n.º 2
0
        public async Task ServiceBusQueueMessagePumpUsingManagedIdentity_PublishServiceBusMessage_MessageSuccessfullyProcessed()
        {
            // Arrange
            var    config           = TestConfig.Create();
            string connectionString = config.GetServiceBusConnectionString(ServiceBusEntityType.Queue);
            ServiceBusConnectionStringProperties properties = ServiceBusConnectionStringProperties.Parse(connectionString);

            ServicePrincipal servicePrincipal = config.GetServiceBusServicePrincipal();
            string           tenantId         = config.GetTenantId();

            using (TemporaryEnvironmentVariable.Create(EnvironmentVariables.AzureTenantId, tenantId))
                using (TemporaryEnvironmentVariable.Create(EnvironmentVariables.AzureServicePrincipalClientId, servicePrincipal.ClientId))
                    using (TemporaryEnvironmentVariable.Create(EnvironmentVariables.AzureServicePrincipalClientSecret, servicePrincipal.ClientSecret))
                    {
                        var options = new WorkerOptions();
                        options.AddEventGridPublisher(config)
                        .AddServiceBusQueueMessagePumpUsingManagedIdentity(
                            queueName: properties.EntityPath,
                            serviceBusNamespace: properties.FullyQualifiedNamespace,
                            clientId: servicePrincipal.ClientId,
                            configureMessagePump: opt => opt.AutoComplete = true)
                        .WithServiceBusMessageHandler <OrdersAzureServiceBusMessageHandler, Order>();

                        // Act
                        await using (var worker = await Worker.StartNewAsync(options))
                            await using (var service = await TestMessagePumpService.StartNewAsync(config, _logger))
                            {
                                // Assert
                                await service.SimulateMessageProcessingAsync(connectionString);
                            }
                    }
        }
Exemplo n.º 3
0
        public async Task ServiceBusQueueMessagePumpWithServiceBusDeadLetterOnFallback_PublishServiceBusMessage_MessageSuccessfullyProcessed()
        {
            // Arrange
            var    config           = TestConfig.Create();
            string connectionString = config.GetServiceBusConnectionString(ServiceBusEntityType.Queue);
            var    options          = new WorkerOptions();

            options.AddServiceBusQueueMessagePump(
                configuration => connectionString,
                opt => opt.AutoComplete = false)
            .WithServiceBusMessageHandler <ShipmentAzureServiceBusMessageHandler, Shipment>((AzureServiceBusMessageContext context) => true)
            .WithServiceBusFallbackMessageHandler <OrdersAzureServiceBusDeadLetterFallbackMessageHandler>();

            Order order = OrderGenerator.Generate();

            await using (var worker = await Worker.StartNewAsync(options))
                await using (var service = await TestMessagePumpService.StartNewAsync(config, _logger))
                {
                    // Act
                    await service.SendMessageToServiceBusAsync(connectionString, order.AsServiceBusMessage());

                    // Assert
                    await service.AssertDeadLetterMessageAsync(connectionString);
                }
        }
Exemplo n.º 4
0
        public async Task ServiceBusQueueMessagePumpWithContextAndBodyFilteringWithSerializer_RoutesServiceBusMessage_MessageSuccessfullyProcessed()
        {
            // Arrange
            var    config           = TestConfig.Create();
            string connectionString = config.GetServiceBusConnectionString(ServiceBusEntityType.Queue);
            var    options          = new WorkerOptions();

            options.AddEventGridPublisher(config)
            .AddServiceBusQueueMessagePump(configuration => connectionString, opt => opt.AutoComplete = true)
            .WithServiceBusMessageHandler <PassThruOrderMessageHandler, Order>(messageContextFilter: context => false)
            .WithServiceBusMessageHandler <CustomerMessageHandler, Customer>(messageBodyFilter: message => true)
            .WithServiceBusMessageHandler <OrderBatchMessageHandler, OrderBatch>(
                messageContextFilter: context => context != null,
                messageBodySerializerImplementationFactory: serviceProvider =>
            {
                var logger = serviceProvider.GetService <ILogger <OrderBatchMessageBodySerializer> >();
                return(new OrderBatchMessageBodySerializer(logger));
            },
                messageBodyFilter: message => message.Orders.Length == 1);

            // Act
            await using (var worker = await Worker.StartNewAsync(options))
                await using (var service = await TestMessagePumpService.StartNewAsync(config, _logger))
                {
                    // Assert
                    await service.SimulateMessageProcessingAsync(connectionString);
                }
        }
        /// <summary>
        /// Starts a new instance of the <see cref="TestMessagePumpService"/> type to simulate messages.
        /// </summary>
        public static async Task <TestMessagePumpService> StartNewAsync(
            ServiceBusEntity entity,
            TestConfig config,
            ITestOutputHelper outputWriter)
        {
            var service = new TestMessagePumpService(entity, config, outputWriter);
            await service.StartAsync();

            return(service);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Starts a new instance of the <see cref="TestMessagePumpService"/> type to simulate messages.
        /// </summary>
        /// <param name="config">The configuration instance to retrieve the Azure Service Bus test infrastructure authentication information.</param>
        /// <param name="logger">The instance to log diagnostic messages during the interaction with teh Azure Service Bus test infrastructure.</param>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="config"/> or the <paramref name="logger"/> is <c>null</c>.</exception>
        public static async Task <TestMessagePumpService> StartNewAsync(
            TestConfig config,
            ILogger logger)
        {
            Guard.NotNull(config, nameof(config));
            Guard.NotNull(logger, nameof(logger));

            var service = new TestMessagePumpService(config, logger);
            await service.StartAsync();

            return(service);
        }
Exemplo n.º 7
0
        public async Task ServiceBusMessagePump_FailureDuringMessageHandling_TracksCorrelationInApplicationInsights()
        {
            // Arrange
            var    config           = TestConfig.Create();
            string connectionString = config.GetServiceBusConnectionString(ServiceBusEntityType.Queue);

            var spySink = new InMemoryLogSink();
            var options = new WorkerOptions();

            options.Configure(host => host.UseSerilog((context, currentConfig) =>
            {
                currentConfig
                .MinimumLevel.Debug()
                .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
                .Enrich.FromLogContext()
                .Enrich.WithVersion()
                .Enrich.WithComponentName("Service Bus Queue Worker")
                .WriteTo.Sink(spySink);
            }));
            options.AddServiceBusQueueMessagePump(configuration => connectionString, opt => opt.AutoComplete = true)
            .WithServiceBusMessageHandler <OrdersSabotageAzureServiceBusMessageHandler, Order>();

            string            operationId = $"operation-{Guid.NewGuid()}", transactionId = $"transaction-{Guid.NewGuid()}";
            ServiceBusMessage orderMessage = OrderGenerator.Generate().AsServiceBusMessage(operationId, transactionId);

            await using (var worker = await Worker.StartNewAsync(options))
            {
                await using (var service = await TestMessagePumpService.StartNewAsync(config, _logger))
                {
                    // Act
                    await service.SendMessageToServiceBusAsync(connectionString, orderMessage);
                }

                // Assert
                RetryAssertUntilTelemetryShouldBeAvailable(() =>
                {
                    Assert.Contains(spySink.CurrentLogEmits,
                                    log => log.Exception?.InnerException?.Message.Contains("Sabotage") == true &&
                                    log.ContainsProperty(ContextProperties.Correlation.OperationId, operationId) &&
                                    log.ContainsProperty(ContextProperties.Correlation.TransactionId, transactionId));
                },
                                                           timeout: TimeSpan.FromMinutes(1));
            }
        }
Exemplo n.º 8
0
        public async Task ServiceBusMessagePump_RotateServiceBusConnectionKeys_MessagePumpRestartsThenMessageSuccessfullyProcessed()
        {
            // Arrange
            var config = TestConfig.Create();
            KeyRotationConfig keyRotationConfig = config.GetKeyRotationConfig();

            _logger.LogInformation("Using Service Principal [ClientID: '{ClientId}']", keyRotationConfig.ServicePrincipal.ClientId);

            var    client = new ServiceBusConfiguration(keyRotationConfig, _logger);
            string freshConnectionString = await client.RotateConnectionStringKeysForQueueAsync(KeyType.PrimaryKey);

            ServicePrincipalAuthentication authentication = keyRotationConfig.ServicePrincipal.CreateAuthentication();
            IKeyVaultClient keyVaultClient = await authentication.AuthenticateAsync();

            await SetConnectionStringInKeyVaultAsync(keyVaultClient, keyRotationConfig, freshConnectionString);

            var options = new WorkerOptions();

            options.AddEventGridPublisher(config)
            .AddSingleton <ISecretProvider>(serviceProvider =>
            {
                return(new KeyVaultSecretProvider(
                           new ServicePrincipalAuthentication(keyRotationConfig.ServicePrincipal.ClientId,
                                                              keyRotationConfig.ServicePrincipal.ClientSecret),
                           new KeyVaultConfiguration(keyRotationConfig.KeyVault.VaultUri)));
            })
            .AddServiceBusQueueMessagePump(keyRotationConfig.KeyVault.SecretName, opt => opt.AutoComplete = true)
            .WithServiceBusMessageHandler <OrdersAzureServiceBusMessageHandler, Order>();

            await using (var worker = await Worker.StartNewAsync(options))
            {
                string newSecondaryConnectionString = await client.RotateConnectionStringKeysForQueueAsync(KeyType.SecondaryKey);
                await SetConnectionStringInKeyVaultAsync(keyVaultClient, keyRotationConfig, newSecondaryConnectionString);

                await using (var service = await TestMessagePumpService.StartNewAsync(config, _logger))
                {
                    // Act
                    string newPrimaryConnectionString = await client.RotateConnectionStringKeysForQueueAsync(KeyType.PrimaryKey);

                    // Assert
                    await service.SimulateMessageProcessingAsync(newPrimaryConnectionString);
                }
            }
        }
Exemplo n.º 9
0
        public async Task ServiceBusMessagePumpWithServiceBusFallback_PublishServiceBusMessage_MessageSuccessfullyProcessed()
        {
            // Arrange
            var    config           = TestConfig.Create();
            string connectionString = config.GetServiceBusConnectionString(ServiceBusEntityType.Queue);
            var    options          = new WorkerOptions();

            options.AddEventGridPublisher(config)
            .AddServiceBusQueueMessagePump(configuration => connectionString, opt => opt.AutoComplete = true)
            .WithServiceBusMessageHandler <PassThruOrderMessageHandler, Order>((AzureServiceBusMessageContext context) => false)
            .WithServiceBusFallbackMessageHandler <OrdersServiceBusFallbackMessageHandler>();

            await using (var worker = await Worker.StartNewAsync(options))
                await using (var service = await TestMessagePumpService.StartNewAsync(config, _logger))
                {
                    // Act / Assert
                    await service.SimulateMessageProcessingAsync(connectionString);
                }
        }
Exemplo n.º 10
0
        public async Task ServiceBusTopicMessagePumpWithServiceBusAbandon_PublishServiceBusMessage_MessageSuccessfullyProcessed()
        {
            // Arrange
            var    config           = TestConfig.Create();
            string connectionString = config.GetServiceBusConnectionString(ServiceBusEntityType.Topic);
            var    options          = new WorkerOptions();

            options.AddEventGridPublisher(config)
            .AddServiceBusTopicMessagePump("Test-Receive-All-Topic-Only",
                                           configuration => connectionString,
                                           opt => opt.AutoComplete = false)
            .WithServiceBusMessageHandler <OrdersAzureServiceBusAbandonMessageHandler, Order>();

            await using (var worker = await Worker.StartNewAsync(options))
                await using (var service = await TestMessagePumpService.StartNewAsync(config, _logger))
                {
                    // Act
                    await service.SimulateMessageProcessingAsync(connectionString);
                }
        }
Exemplo n.º 11
0
        public async Task ServiceBusQueueMessagePumpWithIgnoringMissingMembersDeserialization_PublishesServiceBusMessage_MessageGetsProcessedByDifferentMessageHandler()
        {
            // Arrange
            var    config           = TestConfig.Create();
            string connectionString = config.GetServiceBusConnectionString(ServiceBusEntityType.Queue);

            var options = new WorkerOptions();

            options.AddEventGridPublisher(config)
            .AddServiceBusQueueMessagePump(configuration => connectionString, opt => opt.Deserialization.AdditionalMembers = AdditionalMemberHandling.Ignore)
            .WithServiceBusMessageHandler <OrderV2AzureServiceBusMessageHandler, OrderV2>();

            // Act
            await using (var worker = await Worker.StartNewAsync(options))
                await using (var service = await TestMessagePumpService.StartNewAsync(config, _logger))
                {
                    // Assert
                    await service.SimulateMessageProcessingAsync(connectionString);
                }
        }
Exemplo n.º 12
0
        public async Task ServiceBusTopicMessagePumpWithBodyFiltering_RoutesServiceBusMessage_MessageSuccessfullyProcessed()
        {
            // Arrange
            var    config           = TestConfig.Create();
            string connectionString = config.GetServiceBusConnectionString(ServiceBusEntityType.Topic);
            var    options          = new WorkerOptions();

            options.AddEventGridPublisher(config)
            .AddServiceBusTopicMessagePump("Test-Receive-All-Topic-Only", configuration => connectionString, opt => opt.AutoComplete = true)
            .WithServiceBusMessageHandler <CustomerMessageHandler, Customer>((Customer body) => body is null)
            .WithServiceBusMessageHandler <OrdersAzureServiceBusMessageHandler, Order>((Order body) => body.Id != null)
            .WithMessageHandler <PassThruOrderMessageHandler, Order, AzureServiceBusMessageContext>((Order body) => false);

            // Act
            await using (var worker = await Worker.StartNewAsync(options))
                await using (var service = await TestMessagePumpService.StartNewAsync(config, _logger))
                {
                    // Assert
                    await service.SimulateMessageProcessingAsync(connectionString);
                }
        }
        public async Task ServiceBusMessagePump_PublishServiceBusMessage_MessageSuccessfullyProcessed()
        {
            // Arrange
            var config = TestConfig.Create();
            const ServiceBusEntity entity = ServiceBusEntity.Queue;

            var commandArguments = new[]
            {
                CommandArgument.CreateSecret("EVENTGRID_TOPIC_URI", config.GetTestInfraEventGridTopicUri()),
                CommandArgument.CreateSecret("EVENTGRID_AUTH_KEY", config.GetTestInfraEventGridAuthKey()),
                CommandArgument.CreateSecret("ARCUS_SERVICEBUS_CONNECTIONSTRING", config.GetServiceBusConnectionString(entity)),
            };

            using (var project = await ServiceBusWorkerProject.StartNewWithAsync <ServiceBusQueueProgram>(config, _outputWriter, commandArguments))
            {
                await using (var service = await TestMessagePumpService.StartNewAsync(entity, config, _outputWriter))
                {
                    // Act / Assert
                    await service.SimulateMessageProcessingAsync();
                }
            }
        }
Exemplo n.º 14
0
        public async Task ServiceBusQueueMessagePumpWithNamespaceScopedConnectionString_PublishesServiceBusMessage_MessageSuccessfullyProcessed()
        {
            // Arrange
            var    config = TestConfig.Create();
            string entityConnectionString    = config.GetServiceBusConnectionString(ServiceBusEntityType.Queue);
            var    properties                = ServiceBusConnectionStringProperties.Parse(entityConnectionString);
            string namespaceConnectionString = properties.GetNamespaceConnectionString();

            var options = new WorkerOptions();

            options.AddEventGridPublisher(config)
            .AddServiceBusQueueMessagePump(properties.EntityPath, configuration => namespaceConnectionString, opt => opt.AutoComplete = true)
            .WithServiceBusMessageHandler <OrdersAzureServiceBusMessageHandler, Order>();

            // Act
            await using (var worker = await Worker.StartNewAsync(options))
                await using (var service = await TestMessagePumpService.StartNewAsync(config, _logger))
                {
                    // Assert
                    await service.SimulateMessageProcessingAsync(entityConnectionString);
                }
        }
Exemplo n.º 15
0
        public async Task ServiceBusTopicMessagePumpWithSubscriptionNameOver50_PublishServiceBusMessage_MessageSuccessfullyProcessed()
        {
            // Arrange
            var    config           = TestConfig.Create();
            string connectionString = config.GetServiceBusConnectionString(ServiceBusEntityType.Topic);
            var    options          = new WorkerOptions();

            options.AddEventGridPublisher(config)
            .AddServiceBusTopicMessagePump(
                "Test-Receive-All-Topic-Only-with-an-azure-servicebus-topic-subscription-name-over-50-characters",
                configuration => connectionString,
                opt => opt.AutoComplete = true)
            .WithServiceBusMessageHandler <OrdersAzureServiceBusMessageHandler, Order>();

            // Act
            await using (var worker = await Worker.StartNewAsync(options))
                await using (var service = await TestMessagePumpService.StartNewAsync(config, _logger))
                {
                    // Assert
                    await service.SimulateMessageProcessingAsync(connectionString);
                }
        }
Exemplo n.º 16
0
        public async Task ServiceBusQueueMessagePumpWithContextAndBodyFiltering_RoutesServiceBusMessage_MessageSuccessfullyProcessed()
        {
            // Arrange
            var    config           = TestConfig.Create();
            string connectionString = config.GetServiceBusConnectionString(ServiceBusEntityType.Queue);
            var    options          = new WorkerOptions();

            options.AddEventGridPublisher(config)
            .AddServiceBusQueueMessagePump(configuration => connectionString, opt => opt.AutoComplete = true)
            .WithServiceBusMessageHandler <CustomerMessageHandler, Customer>(context => context.Properties.ContainsKey("NotExisting"), body => false)
            .WithServiceBusMessageHandler <OrdersAzureServiceBusMessageHandler, Order>(
                context => context.Properties["Topic"].ToString() == "Orders",
                body => body.Id != null);

            // Act
            await using (var worker = await Worker.StartNewAsync(options))
                await using (var service = await TestMessagePumpService.StartNewAsync(config, _logger))
                {
                    // Assert
                    await service.SimulateMessageProcessingAsync(connectionString);
                }
        }
Exemplo n.º 17
0
        public async Task ServiceBusQueueMessagePumpWithBatchedMessages_PublishServiceBusMessage_MessageSuccessfullyProcessed()
        {
            // Arrange
            var    config           = TestConfig.Create();
            string connectionString = config.GetServiceBusConnectionString(ServiceBusEntityType.Queue);
            var    options          = new WorkerOptions();

            options.AddEventGridPublisher(config)
            .AddServiceBusQueueMessagePump(configuration => connectionString, opt => opt.AutoComplete = true)
            .WithServiceBusMessageHandler <OrderBatchMessageHandler, OrderBatch>(messageBodySerializerImplementationFactory: serviceProvider =>
            {
                var logger = serviceProvider.GetService <ILogger <OrderBatchMessageBodySerializer> >();
                return(new OrderBatchMessageBodySerializer(logger));
            });

            // Act
            await using (var worker = await Worker.StartNewAsync(options))
                await using (var service = await TestMessagePumpService.StartNewAsync(config, _logger))
                {
                    // Assert
                    await service.SimulateMessageProcessingAsync(connectionString);
                }
        }
Exemplo n.º 18
0
        public async Task ServiceBusQueueMessagePumpWithServiceBusDeadLetterAfterContextPredicate_PublishServiceBusMessage_MessageSuccessfullyProcessed()
        {
            // Arrange
            var    config           = TestConfig.Create();
            string connectionString = config.GetServiceBusConnectionString(ServiceBusEntityType.Queue);
            var    options          = new WorkerOptions();

            options.AddServiceBusQueueMessagePump(configuration => connectionString, opt => opt.AutoComplete = false)
            .WithServiceBusMessageHandler <CustomerMessageHandler, Customer>(context => context.Properties["Topic"].ToString() == "Customers")
            .WithServiceBusMessageHandler <OrdersAzureServiceBusDeadLetterMessageHandler, Order>(context => context.Properties["Topic"].ToString() == "Orders")
            .WithMessageHandler <PassThruOrderMessageHandler, Order, AzureServiceBusMessageContext>((AzureServiceBusMessageContext context) => false);

            Order order = OrderGenerator.Generate();

            await using (var worker = await Worker.StartNewAsync(options))
                await using (var service = await TestMessagePumpService.StartNewAsync(config, _logger))
                {
                    // Act
                    await service.SendMessageToServiceBusAsync(connectionString, order.AsServiceBusMessage());

                    // Assert
                    await service.AssertDeadLetterMessageAsync(connectionString);
                }
        }