Exemplo n.º 1
0
        public static MessagingOptions UseServiceBusBroker(
            this MessagingOptions options,
            Action <IMessageBroker> brokerAction = null,
            string topicName        = null,
            string subscriptionName = null,
            string section          = "naos:messaging:serviceBus")
        {
            EnsureArg.IsNotNull(options, nameof(options));
            EnsureArg.IsNotNull(options.Context, nameof(options.Context));

            var configuration = options.Context.Configuration.GetSection(section).Get <ServiceBusConfiguration>();

            configuration.EntityPath = topicName ?? $"{Environment.GetEnvironmentVariable(EnvironmentKeys.Environment) ?? "Production"}-Naos.Messaging";
            options.Context.Services.AddSingleton <IServiceBusProvider>(sp =>
            {
                if (configuration?.Enabled == true)
                {
                    return(new ServiceBusProvider(
                               sp.GetRequiredService <ILogger <ServiceBusProvider> >(),
                               SdkContext.AzureCredentialsFactory.FromServicePrincipal(configuration.ClientId, configuration.ClientSecret, configuration.TenantId, AzureEnvironment.AzureGlobalCloud),
                               configuration));
                }

                throw new NotImplementedException("no messaging servicebus is enabled");
            });

            options.Context.Services.AddSingleton <IMessageBroker>(sp =>
            {
                var broker = new ServiceBusMessageBroker(o => o
                                                         .LoggerFactory(sp.GetRequiredService <ILoggerFactory>())
                                                         .Mediator((IMediator)sp.CreateScope().ServiceProvider.GetService(typeof(IMediator)))
                                                         .Provider(sp.GetRequiredService <IServiceBusProvider>())
                                                         .HandlerFactory(new ServiceProviderMessageHandlerFactory(sp))
                                                         .Map(sp.GetRequiredService <ISubscriptionMap>())
                                                         .SubscriptionName(subscriptionName ?? options.Context.Descriptor.Name) //AppDomain.CurrentDomain.FriendlyName, // PRODUCT.CAPABILITY
                                                         .FilterScope(Environment.GetEnvironmentVariable(EnvironmentKeys.IsLocal).ToBool()
                            ? Environment.MachineName.Humanize().Dehumanize().ToLower()
                            : string.Empty));

                brokerAction?.Invoke(broker);
                return(broker);
            }); // scope the messagebus messages to the local machine, so local events are handled locally

            options.Context.Services.AddHealthChecks()
            .AddAzureServiceBusTopic(configuration.ConnectionString, configuration.EntityPath, "messaging-broker-servicebus");

            options.Context.Messages.Add($"{LogEventKeys.Startup} naos services builder: messaging added (broker={nameof(ServiceBusMessageBroker)})");

            return(options);
        }
Exemplo n.º 2
0
        public static MessagingOptions UseServiceBusBroker(
            this MessagingOptions options,
            Action <IMessageBroker> brokerAction = null,
            string topicName        = null,
            string subscriptionName = null,
            int?retries             = null,
            TimeSpan?expiration     = null,
            string section          = "naos:messaging:serviceBus")
        {
            EnsureArg.IsNotNull(options, nameof(options));
            EnsureArg.IsNotNull(options.Context, nameof(options.Context));

            subscriptionName ??= options.Context.Descriptor.Name.ToLower();
            var configuration = options.Context.Configuration.GetSection(section).Get <ServiceBusConfiguration>();

            if (configuration?.Enabled == true)
            {
                configuration.EntityPath = topicName ?? $"{Environment.GetEnvironmentVariable(EnvironmentKeys.Environment) ?? "Production"}-Naos.Messaging";
                options.Context.Services.AddSingleton <IServiceBusProvider>(sp =>
                {
                    return(new ServiceBusProvider(
                               sp.GetRequiredService <ILogger <ServiceBusProvider> >(),
                               SdkContext.AzureCredentialsFactory.FromServicePrincipal(configuration.ClientId, configuration.ClientSecret, configuration.TenantId, AzureEnvironment.AzureGlobalCloud),
                               configuration));
                });

                options.Context.Services.AddSingleton <Microsoft.Azure.ServiceBus.ISubscriptionClient>(sp =>
                {
                    var logger   = sp.GetRequiredService <ILogger <ServiceBusMessageBroker> >();
                    var provider = sp.GetRequiredService <IServiceBusProvider>();
                    provider.EnsureTopicSubscription(provider.ConnectionStringBuilder.EntityPath, subscriptionName);

                    var client = new Microsoft.Azure.ServiceBus.SubscriptionClient(provider.ConnectionStringBuilder, subscriptionName);
                    try
                    {
                        client
                        .RemoveRuleAsync(RuleDescription.DefaultRuleName)
                        .GetAwaiter()
                        .GetResult();
                    }
                    catch (MessagingEntityNotFoundException)
                    {
                        // do nothing, default rule not found
                    }

                    client.RegisterMessageHandler(
                        async(m, t) =>
                    {
                        //this.logger.LogInformation("message received (id={MessageId}, name={MessageName})", message.MessageId, message.Label);
                        if (await ServiceBusMessageBroker.ProcessMessage(
                                logger,
                                (ITracer)sp.CreateScope().ServiceProvider.GetService(typeof(ITracer)),
                                sp.GetRequiredService <ISubscriptionMap>(),
                                new ServiceProviderMessageHandlerFactory(sp),
                                DefaultSerializer.Create,
                                subscriptionName,
                                (IMediator)sp.CreateScope().ServiceProvider.GetService(typeof(IMediator)),
                                m).AnyContext())
                        {
                            // complete message so it is not received again
                            await client.CompleteAsync(m.SystemProperties.LockToken).AnyContext();
                        }
                    },
                        new MessageHandlerOptions(args =>
                    {
                        var context = args.ExceptionReceivedContext;
                        logger.LogWarning($"{{LogKey:l}} servicebus handler error: topic={context?.EntityPath}, action={context?.Action}, endpoint={context?.Endpoint}, {args.Exception?.Message}, {args.Exception?.StackTrace}", LogKeys.AppMessaging);
                        return(Task.CompletedTask);
                    })
                    {
                        MaxConcurrentCalls   = 10,
                        AutoComplete         = false,
                        MaxAutoRenewDuration = new TimeSpan(0, 5, 0)
                    });

                    return(client);
                });

                options.Context.Services.AddScoped <IMessageBroker>(sp => // TODO: scoped with ITracer injected
                {
                    var broker = new ServiceBusMessageBroker(o => o
                                                             .LoggerFactory(sp.GetRequiredService <ILoggerFactory>())
                                                             .Tracer(sp.GetService <ITracer>())
                                                             .Mediator(sp.GetService <IMediator>())
                                                             .Provider(sp.GetRequiredService <IServiceBusProvider>())                          // singleton
                                                             .Client(sp.GetRequiredService <Microsoft.Azure.ServiceBus.ISubscriptionClient>()) // singleton
                                                             .HandlerFactory(new ServiceProviderMessageHandlerFactory(sp))
                                                             .Subscriptions(sp.GetRequiredService <ISubscriptionMap>())                        // singleton
                                                             .SubscriptionName(subscriptionName)                                               //AppDomain.CurrentDomain.FriendlyName, // PRODUCT.CAPABILITY
                                                                                                                                               //.MessageScope(options.Context.Descriptor.Name)
                                                             .Retries(retries)
                                                             .Expiration(expiration)
                                                             .FilterScope(Environment.GetEnvironmentVariable(EnvironmentKeys.IsLocal).ToBool()
                                ? Environment.MachineName.Humanize().Dehumanize().ToLower()
                                : string.Empty));

                    brokerAction?.Invoke(broker);
                    return(broker);
                }); // scope the messagebus messages to the local machine, so local events are handled locally

                options.Context.Services.AddHealthChecks()
                .AddAzureServiceBusTopic(configuration.ConnectionString, configuration.EntityPath, "messaging-broker-servicebus");

                options.Context.Messages.Add($"naos services builder: messaging added (broker={nameof(ServiceBusMessageBroker)})");
            }
            else
            {
                throw new NaosException("no messaging servicebus is enabled");
            }

            return(options);
        }