mirror of
https://github.com/bitwarden/server
synced 2026-01-07 19:13:50 +00:00
[PM-17562] Add Azure Service Bus support for event integration retries (#5880)
* [PM-17562] Add Azure Service Bus support for event integration retries * Cleanup AzureServiceBusIntegrationListenerService.cs; add nullable * Removed IntegrationHandlerBase* since it is no longer used (We removed the subclasses previously) * Changed strategy to assume ApplyRetry always gives us a non-null DelayUntilDate; Added test to confirm as well
This commit is contained in:
@@ -20,7 +20,7 @@ public class AzureServiceBusEventListenerService : EventLoggingListenerService
|
||||
string subscriptionName) : base(handler)
|
||||
{
|
||||
_client = new ServiceBusClient(globalSettings.EventLogging.AzureServiceBus.ConnectionString);
|
||||
_processor = _client.CreateProcessor(globalSettings.EventLogging.AzureServiceBus.TopicName, subscriptionName, new ServiceBusProcessorOptions());
|
||||
_processor = _client.CreateProcessor(globalSettings.EventLogging.AzureServiceBus.EventTopicName, subscriptionName, new ServiceBusProcessorOptions());
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ public class AzureServiceBusEventWriteService : IEventWriteService, IAsyncDispos
|
||||
public AzureServiceBusEventWriteService(GlobalSettings globalSettings)
|
||||
{
|
||||
_client = new ServiceBusClient(globalSettings.EventLogging.AzureServiceBus.ConnectionString);
|
||||
_sender = _client.CreateSender(globalSettings.EventLogging.AzureServiceBus.TopicName);
|
||||
_sender = _client.CreateSender(globalSettings.EventLogging.AzureServiceBus.EventTopicName);
|
||||
}
|
||||
|
||||
public async Task CreateAsync(IEvent e)
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
#nullable enable
|
||||
|
||||
using Azure.Messaging.ServiceBus;
|
||||
using Bit.Core.Settings;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Bit.Core.Services;
|
||||
|
||||
public class AzureServiceBusIntegrationListenerService : BackgroundService
|
||||
{
|
||||
private readonly int _maxRetries;
|
||||
private readonly string _subscriptionName;
|
||||
private readonly string _topicName;
|
||||
private readonly IIntegrationHandler _handler;
|
||||
private readonly ServiceBusClient _client;
|
||||
private readonly ServiceBusProcessor _processor;
|
||||
private readonly ServiceBusSender _sender;
|
||||
private readonly ILogger<AzureServiceBusIntegrationListenerService> _logger;
|
||||
|
||||
public AzureServiceBusIntegrationListenerService(
|
||||
IIntegrationHandler handler,
|
||||
string subscriptionName,
|
||||
GlobalSettings globalSettings,
|
||||
ILogger<AzureServiceBusIntegrationListenerService> logger)
|
||||
{
|
||||
_handler = handler;
|
||||
_logger = logger;
|
||||
_maxRetries = globalSettings.EventLogging.AzureServiceBus.MaxRetries;
|
||||
_topicName = globalSettings.EventLogging.AzureServiceBus.IntegrationTopicName;
|
||||
_subscriptionName = subscriptionName;
|
||||
|
||||
_client = new ServiceBusClient(globalSettings.EventLogging.AzureServiceBus.ConnectionString);
|
||||
_processor = _client.CreateProcessor(_topicName, _subscriptionName, new ServiceBusProcessorOptions());
|
||||
_sender = _client.CreateSender(_topicName);
|
||||
}
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_processor.ProcessMessageAsync += HandleMessageAsync;
|
||||
_processor.ProcessErrorAsync += args =>
|
||||
{
|
||||
_logger.LogError(args.Exception, "Azure Service Bus error");
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
await _processor.StartProcessingAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public override async Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await _processor.StopProcessingAsync(cancellationToken);
|
||||
await _processor.DisposeAsync();
|
||||
await _sender.DisposeAsync();
|
||||
await _client.DisposeAsync();
|
||||
await base.StopAsync(cancellationToken);
|
||||
}
|
||||
|
||||
private async Task HandleMessageAsync(ProcessMessageEventArgs args)
|
||||
{
|
||||
var json = args.Message.Body.ToString();
|
||||
|
||||
try
|
||||
{
|
||||
var result = await _handler.HandleAsync(json);
|
||||
var message = result.Message;
|
||||
|
||||
if (result.Success)
|
||||
{
|
||||
await args.CompleteMessageAsync(args.Message);
|
||||
return;
|
||||
}
|
||||
|
||||
message.ApplyRetry(result.DelayUntilDate);
|
||||
|
||||
if (result.Retryable && message.RetryCount < _maxRetries)
|
||||
{
|
||||
var scheduledTime = (DateTime)message.DelayUntilDate!;
|
||||
var retryMsg = new ServiceBusMessage(message.ToJson())
|
||||
{
|
||||
Subject = args.Message.Subject,
|
||||
ScheduledEnqueueTime = scheduledTime
|
||||
};
|
||||
|
||||
await _sender.SendMessageAsync(retryMsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
await args.DeadLetterMessageAsync(args.Message, "Retry limit exceeded or non-retryable");
|
||||
return;
|
||||
}
|
||||
|
||||
await args.CompleteMessageAsync(args.Message);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Unhandled error processing ASB message");
|
||||
await args.CompleteMessageAsync(args.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using Azure.Messaging.ServiceBus;
|
||||
using Bit.Core.AdminConsole.Models.Data.Integrations;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Settings;
|
||||
|
||||
namespace Bit.Core.Services;
|
||||
|
||||
public class AzureServiceBusIntegrationPublisher : IIntegrationPublisher, IAsyncDisposable
|
||||
{
|
||||
private readonly ServiceBusClient _client;
|
||||
private readonly ServiceBusSender _sender;
|
||||
|
||||
public AzureServiceBusIntegrationPublisher(GlobalSettings globalSettings)
|
||||
{
|
||||
_client = new ServiceBusClient(globalSettings.EventLogging.AzureServiceBus.ConnectionString);
|
||||
_sender = _client.CreateSender(globalSettings.EventLogging.AzureServiceBus.IntegrationTopicName);
|
||||
}
|
||||
|
||||
public async Task PublishAsync(IIntegrationMessage message)
|
||||
{
|
||||
var json = message.ToJson();
|
||||
|
||||
var serviceBusMessage = new ServiceBusMessage(json)
|
||||
{
|
||||
Subject = message.IntegrationType.ToRoutingKey(),
|
||||
};
|
||||
|
||||
await _sender.SendMessageAsync(serviceBusMessage);
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
await _sender.DisposeAsync();
|
||||
await _client.DisposeAsync();
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using Bit.Core.AdminConsole.Models.Data.Integrations;
|
||||
using Bit.Core.AdminConsole.Utilities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Repositories;
|
||||
|
||||
namespace Bit.Core.Services;
|
||||
|
||||
public abstract class IntegrationEventHandlerBase(
|
||||
IUserRepository userRepository,
|
||||
IOrganizationRepository organizationRepository,
|
||||
IOrganizationIntegrationConfigurationRepository configurationRepository)
|
||||
: IEventMessageHandler
|
||||
{
|
||||
public async Task HandleEventAsync(EventMessage eventMessage)
|
||||
{
|
||||
var organizationId = eventMessage.OrganizationId ?? Guid.Empty;
|
||||
var configurations = await configurationRepository.GetConfigurationDetailsAsync(
|
||||
organizationId,
|
||||
GetIntegrationType(),
|
||||
eventMessage.Type);
|
||||
|
||||
foreach (var configuration in configurations)
|
||||
{
|
||||
var context = await BuildContextAsync(eventMessage, configuration.Template);
|
||||
var renderedTemplate = IntegrationTemplateProcessor.ReplaceTokens(configuration.Template, context);
|
||||
|
||||
await ProcessEventIntegrationAsync(configuration.MergedConfiguration, renderedTemplate);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task HandleManyEventsAsync(IEnumerable<EventMessage> eventMessages)
|
||||
{
|
||||
foreach (var eventMessage in eventMessages)
|
||||
{
|
||||
await HandleEventAsync(eventMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<IntegrationTemplateContext> BuildContextAsync(EventMessage eventMessage, string template)
|
||||
{
|
||||
var context = new IntegrationTemplateContext(eventMessage);
|
||||
|
||||
if (IntegrationTemplateProcessor.TemplateRequiresUser(template) && eventMessage.UserId.HasValue)
|
||||
{
|
||||
context.User = await userRepository.GetByIdAsync(eventMessage.UserId.Value);
|
||||
}
|
||||
|
||||
if (IntegrationTemplateProcessor.TemplateRequiresActingUser(template) && eventMessage.ActingUserId.HasValue)
|
||||
{
|
||||
context.ActingUser = await userRepository.GetByIdAsync(eventMessage.ActingUserId.Value);
|
||||
}
|
||||
|
||||
if (IntegrationTemplateProcessor.TemplateRequiresOrganization(template) && eventMessage.OrganizationId.HasValue)
|
||||
{
|
||||
context.Organization = await organizationRepository.GetByIdAsync(eventMessage.OrganizationId.Value);
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
protected abstract IntegrationType GetIntegrationType();
|
||||
|
||||
protected abstract Task ProcessEventIntegrationAsync(JsonObject mergedConfiguration, string renderedTemplate);
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Bit.Core.AdminConsole.Models.Data.Integrations;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Repositories;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace Bit.Core.Services;
|
||||
|
||||
public class SlackEventHandler(
|
||||
IUserRepository userRepository,
|
||||
IOrganizationRepository organizationRepository,
|
||||
IOrganizationIntegrationConfigurationRepository configurationRepository,
|
||||
ISlackService slackService)
|
||||
: IntegrationEventHandlerBase(userRepository, organizationRepository, configurationRepository)
|
||||
{
|
||||
protected override IntegrationType GetIntegrationType() => IntegrationType.Slack;
|
||||
|
||||
protected override async Task ProcessEventIntegrationAsync(JsonObject mergedConfiguration,
|
||||
string renderedTemplate)
|
||||
{
|
||||
var config = mergedConfiguration.Deserialize<SlackIntegrationConfigurationDetails>();
|
||||
if (config is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await slackService.SendSlackMessageByChannelIdAsync(
|
||||
config.token,
|
||||
renderedTemplate,
|
||||
config.channelId
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Bit.Core.AdminConsole.Models.Data.Integrations;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Repositories;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace Bit.Core.Services;
|
||||
|
||||
public class WebhookEventHandler(
|
||||
IHttpClientFactory httpClientFactory,
|
||||
IUserRepository userRepository,
|
||||
IOrganizationRepository organizationRepository,
|
||||
IOrganizationIntegrationConfigurationRepository configurationRepository)
|
||||
: IntegrationEventHandlerBase(userRepository, organizationRepository, configurationRepository)
|
||||
{
|
||||
private readonly HttpClient _httpClient = httpClientFactory.CreateClient(HttpClientName);
|
||||
|
||||
public const string HttpClientName = "WebhookEventHandlerHttpClient";
|
||||
|
||||
protected override IntegrationType GetIntegrationType() => IntegrationType.Webhook;
|
||||
|
||||
protected override async Task ProcessEventIntegrationAsync(JsonObject mergedConfiguration,
|
||||
string renderedTemplate)
|
||||
{
|
||||
var config = mergedConfiguration.Deserialize<WebhookIntegrationConfigurationDetails>();
|
||||
if (config is null || string.IsNullOrEmpty(config.url))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var content = new StringContent(renderedTemplate, Encoding.UTF8, "application/json");
|
||||
var response = await _httpClient.PostAsync(config.url, content);
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
}
|
||||
@@ -288,11 +288,15 @@ public class GlobalSettings : IGlobalSettings
|
||||
public class AzureServiceBusSettings
|
||||
{
|
||||
private string _connectionString;
|
||||
private string _topicName;
|
||||
private string _eventTopicName;
|
||||
private string _integrationTopicName;
|
||||
|
||||
public int MaxRetries { get; set; } = 3;
|
||||
public virtual string EventRepositorySubscriptionName { get; set; } = "events-write-subscription";
|
||||
public virtual string SlackSubscriptionName { get; set; } = "events-slack-subscription";
|
||||
public virtual string WebhookSubscriptionName { get; set; } = "events-webhook-subscription";
|
||||
public virtual string SlackEventSubscriptionName { get; set; } = "events-slack-subscription";
|
||||
public virtual string SlackIntegrationSubscriptionName { get; set; } = "integration-slack-subscription";
|
||||
public virtual string WebhookEventSubscriptionName { get; set; } = "events-webhook-subscription";
|
||||
public virtual string WebhookIntegrationSubscriptionName { get; set; } = "integration-webhook-subscription";
|
||||
|
||||
public string ConnectionString
|
||||
{
|
||||
@@ -300,10 +304,16 @@ public class GlobalSettings : IGlobalSettings
|
||||
set => _connectionString = value.Trim('"');
|
||||
}
|
||||
|
||||
public string TopicName
|
||||
public string EventTopicName
|
||||
{
|
||||
get => _topicName;
|
||||
set => _topicName = value.Trim('"');
|
||||
get => _eventTopicName;
|
||||
set => _eventTopicName = value.Trim('"');
|
||||
}
|
||||
|
||||
public string IntegrationTopicName
|
||||
{
|
||||
get => _integrationTopicName;
|
||||
set => _integrationTopicName = value.Trim('"');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -557,7 +557,7 @@ public static class ServiceCollectionExtensions
|
||||
services.AddKeyedSingleton<IEventWriteService, AzureQueueEventWriteService>("storage");
|
||||
|
||||
if (CoreHelpers.SettingHasValue(globalSettings.EventLogging.AzureServiceBus.ConnectionString) &&
|
||||
CoreHelpers.SettingHasValue(globalSettings.EventLogging.AzureServiceBus.TopicName))
|
||||
CoreHelpers.SettingHasValue(globalSettings.EventLogging.AzureServiceBus.EventTopicName))
|
||||
{
|
||||
services.AddKeyedSingleton<IEventWriteService, AzureServiceBusEventWriteService>("broadcast");
|
||||
}
|
||||
@@ -589,86 +589,83 @@ public static class ServiceCollectionExtensions
|
||||
return services;
|
||||
}
|
||||
|
||||
private static IServiceCollection AddAzureServiceBusEventRepositoryListener(this IServiceCollection services, GlobalSettings globalSettings)
|
||||
{
|
||||
services.AddSingleton<IEventRepository, TableStorageRepos.EventRepository>();
|
||||
services.AddSingleton<AzureTableStorageEventHandler>();
|
||||
services.AddKeyedSingleton<IEventWriteService, RepositoryEventWriteService>("persistent");
|
||||
|
||||
services.AddSingleton<IHostedService>(provider =>
|
||||
new AzureServiceBusEventListenerService(
|
||||
handler: provider.GetRequiredService<AzureTableStorageEventHandler>(),
|
||||
logger: provider.GetRequiredService<ILogger<AzureServiceBusEventListenerService>>(),
|
||||
globalSettings: globalSettings,
|
||||
subscriptionName: globalSettings.EventLogging.AzureServiceBus.EventRepositorySubscriptionName));
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
private static IServiceCollection AddAzureServiceBusIntegration<TConfig, THandler>(
|
||||
this IServiceCollection services,
|
||||
string eventSubscriptionName,
|
||||
string integrationSubscriptionName,
|
||||
IntegrationType integrationType,
|
||||
GlobalSettings globalSettings)
|
||||
where TConfig : class
|
||||
where THandler : class, IIntegrationHandler<TConfig>
|
||||
{
|
||||
var routingKey = integrationType.ToRoutingKey();
|
||||
|
||||
services.AddSingleton<IIntegrationPublisher, AzureServiceBusIntegrationPublisher>();
|
||||
|
||||
services.AddKeyedSingleton<IEventMessageHandler>(routingKey, (provider, _) =>
|
||||
new EventIntegrationHandler<TConfig>(
|
||||
integrationType,
|
||||
provider.GetRequiredService<IIntegrationPublisher>(),
|
||||
provider.GetRequiredService<IOrganizationIntegrationConfigurationRepository>(),
|
||||
provider.GetRequiredService<IUserRepository>(),
|
||||
provider.GetRequiredService<IOrganizationRepository>()));
|
||||
|
||||
services.AddSingleton<IHostedService>(provider =>
|
||||
new AzureServiceBusEventListenerService(
|
||||
handler: provider.GetRequiredKeyedService<IEventMessageHandler>(routingKey),
|
||||
logger: provider.GetRequiredService<ILogger<AzureServiceBusEventListenerService>>(),
|
||||
globalSettings: globalSettings,
|
||||
subscriptionName: eventSubscriptionName));
|
||||
|
||||
services.AddSingleton<IIntegrationHandler<TConfig>, THandler>();
|
||||
|
||||
services.AddSingleton<IHostedService>(provider =>
|
||||
new AzureServiceBusIntegrationListenerService(
|
||||
handler: provider.GetRequiredService<IIntegrationHandler<TConfig>>(),
|
||||
subscriptionName: integrationSubscriptionName,
|
||||
logger: provider.GetRequiredService<ILogger<AzureServiceBusIntegrationListenerService>>(),
|
||||
globalSettings: globalSettings));
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddAzureServiceBusListeners(this IServiceCollection services, GlobalSettings globalSettings)
|
||||
{
|
||||
if (CoreHelpers.SettingHasValue(globalSettings.EventLogging.AzureServiceBus.ConnectionString) &&
|
||||
CoreHelpers.SettingHasValue(globalSettings.EventLogging.AzureServiceBus.TopicName))
|
||||
{
|
||||
services.AddSingleton<IEventRepository, TableStorageRepos.EventRepository>();
|
||||
services.AddSingleton<AzureTableStorageEventHandler>();
|
||||
services.AddKeyedSingleton<IEventWriteService, RepositoryEventWriteService>("persistent");
|
||||
services.AddSingleton<IHostedService>(provider =>
|
||||
new AzureServiceBusEventListenerService(
|
||||
provider.GetRequiredService<AzureTableStorageEventHandler>(),
|
||||
provider.GetRequiredService<ILogger<AzureServiceBusEventListenerService>>(),
|
||||
globalSettings,
|
||||
globalSettings.EventLogging.AzureServiceBus.EventRepositorySubscriptionName));
|
||||
if (!CoreHelpers.SettingHasValue(globalSettings.EventLogging.AzureServiceBus.ConnectionString) ||
|
||||
!CoreHelpers.SettingHasValue(globalSettings.EventLogging.AzureServiceBus.EventTopicName))
|
||||
return services;
|
||||
|
||||
services.AddAzureServiceBusEventRepositoryListener(globalSettings);
|
||||
|
||||
services.AddSlackService(globalSettings);
|
||||
services.AddSingleton<SlackEventHandler>();
|
||||
services.AddSingleton<IHostedService>(provider =>
|
||||
new AzureServiceBusEventListenerService(
|
||||
provider.GetRequiredService<SlackEventHandler>(),
|
||||
provider.GetRequiredService<ILogger<AzureServiceBusEventListenerService>>(),
|
||||
globalSettings,
|
||||
globalSettings.EventLogging.AzureServiceBus.SlackSubscriptionName));
|
||||
|
||||
services.AddSingleton<WebhookEventHandler>();
|
||||
services.AddHttpClient(WebhookEventHandler.HttpClientName);
|
||||
services.AddSingleton<IHostedService>(provider =>
|
||||
new AzureServiceBusEventListenerService(
|
||||
provider.GetRequiredService<WebhookEventHandler>(),
|
||||
provider.GetRequiredService<ILogger<AzureServiceBusEventListenerService>>(),
|
||||
globalSettings,
|
||||
globalSettings.EventLogging.AzureServiceBus.WebhookSubscriptionName));
|
||||
}
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddRabbitMqListeners(this IServiceCollection services, GlobalSettings globalSettings)
|
||||
{
|
||||
if (IsRabbitMqEnabled(globalSettings))
|
||||
{
|
||||
services.AddRabbitMqEventRepositoryListener(globalSettings);
|
||||
|
||||
services.AddSlackService(globalSettings);
|
||||
services.AddRabbitMqIntegration<SlackIntegrationConfigurationDetails, SlackIntegrationHandler>(
|
||||
globalSettings.EventLogging.RabbitMq.SlackEventsQueueName,
|
||||
globalSettings.EventLogging.RabbitMq.SlackIntegrationQueueName,
|
||||
globalSettings.EventLogging.RabbitMq.SlackIntegrationRetryQueueName,
|
||||
globalSettings.EventLogging.RabbitMq.IntegrationDeadLetterQueueName,
|
||||
IntegrationType.Slack,
|
||||
globalSettings);
|
||||
|
||||
services.AddHttpClient(WebhookIntegrationHandler.HttpClientName);
|
||||
services.AddRabbitMqIntegration<WebhookIntegrationConfigurationDetails, WebhookIntegrationHandler>(
|
||||
globalSettings.EventLogging.RabbitMq.WebhookEventsQueueName,
|
||||
globalSettings.EventLogging.RabbitMq.WebhookIntegrationQueueName,
|
||||
globalSettings.EventLogging.RabbitMq.WebhookIntegrationRetryQueueName,
|
||||
globalSettings.EventLogging.RabbitMq.IntegrationDeadLetterQueueName,
|
||||
IntegrationType.Webhook,
|
||||
globalSettings);
|
||||
}
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddSlackService(this IServiceCollection services, GlobalSettings globalSettings)
|
||||
{
|
||||
if (CoreHelpers.SettingHasValue(globalSettings.Slack.ClientId) &&
|
||||
CoreHelpers.SettingHasValue(globalSettings.Slack.ClientSecret) &&
|
||||
CoreHelpers.SettingHasValue(globalSettings.Slack.Scopes))
|
||||
{
|
||||
services.AddHttpClient(SlackService.HttpClientName);
|
||||
services.AddSingleton<ISlackService, SlackService>();
|
||||
}
|
||||
else
|
||||
{
|
||||
services.AddSingleton<ISlackService, NoopSlackService>();
|
||||
}
|
||||
services.AddSlackService(globalSettings);
|
||||
services.AddAzureServiceBusIntegration<SlackIntegrationConfigurationDetails, SlackIntegrationHandler>(
|
||||
eventSubscriptionName: globalSettings.EventLogging.AzureServiceBus.SlackEventSubscriptionName,
|
||||
integrationSubscriptionName: globalSettings.EventLogging.AzureServiceBus.SlackIntegrationSubscriptionName,
|
||||
integrationType: IntegrationType.Slack,
|
||||
globalSettings: globalSettings);
|
||||
|
||||
services.AddHttpClient(WebhookIntegrationHandler.HttpClientName);
|
||||
services.AddAzureServiceBusIntegration<WebhookIntegrationConfigurationDetails, WebhookIntegrationHandler>(
|
||||
eventSubscriptionName: globalSettings.EventLogging.AzureServiceBus.WebhookEventSubscriptionName,
|
||||
integrationSubscriptionName: globalSettings.EventLogging.AzureServiceBus.WebhookIntegrationSubscriptionName,
|
||||
integrationType: IntegrationType.Webhook,
|
||||
globalSettings: globalSettings);
|
||||
return services;
|
||||
}
|
||||
|
||||
@@ -729,6 +726,36 @@ public static class ServiceCollectionExtensions
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddRabbitMqListeners(this IServiceCollection services, GlobalSettings globalSettings)
|
||||
{
|
||||
if (!IsRabbitMqEnabled(globalSettings))
|
||||
{
|
||||
return services;
|
||||
}
|
||||
|
||||
services.AddRabbitMqEventRepositoryListener(globalSettings);
|
||||
|
||||
services.AddSlackService(globalSettings);
|
||||
services.AddRabbitMqIntegration<SlackIntegrationConfigurationDetails, SlackIntegrationHandler>(
|
||||
globalSettings.EventLogging.RabbitMq.SlackEventsQueueName,
|
||||
globalSettings.EventLogging.RabbitMq.SlackIntegrationQueueName,
|
||||
globalSettings.EventLogging.RabbitMq.SlackIntegrationRetryQueueName,
|
||||
globalSettings.EventLogging.RabbitMq.IntegrationDeadLetterQueueName,
|
||||
IntegrationType.Slack,
|
||||
globalSettings);
|
||||
|
||||
services.AddHttpClient(WebhookIntegrationHandler.HttpClientName);
|
||||
services.AddRabbitMqIntegration<WebhookIntegrationConfigurationDetails, WebhookIntegrationHandler>(
|
||||
globalSettings.EventLogging.RabbitMq.WebhookEventsQueueName,
|
||||
globalSettings.EventLogging.RabbitMq.WebhookIntegrationQueueName,
|
||||
globalSettings.EventLogging.RabbitMq.WebhookIntegrationRetryQueueName,
|
||||
globalSettings.EventLogging.RabbitMq.IntegrationDeadLetterQueueName,
|
||||
IntegrationType.Webhook,
|
||||
globalSettings);
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
private static bool IsRabbitMqEnabled(GlobalSettings settings)
|
||||
{
|
||||
return CoreHelpers.SettingHasValue(settings.EventLogging.RabbitMq.HostName) &&
|
||||
@@ -737,6 +764,23 @@ public static class ServiceCollectionExtensions
|
||||
CoreHelpers.SettingHasValue(settings.EventLogging.RabbitMq.EventExchangeName);
|
||||
}
|
||||
|
||||
public static IServiceCollection AddSlackService(this IServiceCollection services, GlobalSettings globalSettings)
|
||||
{
|
||||
if (CoreHelpers.SettingHasValue(globalSettings.Slack.ClientId) &&
|
||||
CoreHelpers.SettingHasValue(globalSettings.Slack.ClientSecret) &&
|
||||
CoreHelpers.SettingHasValue(globalSettings.Slack.Scopes))
|
||||
{
|
||||
services.AddHttpClient(SlackService.HttpClientName);
|
||||
services.AddSingleton<ISlackService, SlackService>();
|
||||
}
|
||||
else
|
||||
{
|
||||
services.AddSingleton<ISlackService, NoopSlackService>();
|
||||
}
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
public static void UseDefaultMiddleware(this IApplicationBuilder app,
|
||||
IWebHostEnvironment env, GlobalSettings globalSettings)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user