From 2913514da82d23699a65cac1bebb948c5e9829fc Mon Sep 17 00:00:00 2001 From: TekH Date: Thu, 5 Nov 2026 12:03:26 +0100 Subject: [PATCH] feat(notification): make messaging consumer configurable Replace the hard-coded RabbitMQ setup with NotificationOptions bound from a configurable section. The new ConsumerType switch wires either the HTTP API client or the RabbitMQ client, and startup now fails with a clear error when required settings are missing. Bump DigitalData.MessagingService.Client to 3.0.1 for the abstraction used by both transports. --- .../Configuration/ConsumerType.cs | 7 +++ .../Configuration/NotificationOptions.cs | 16 +++++ .../DependencyInjection.cs | 58 ++++++++++--------- ...nerator.Infrastructure.Notification.csproj | 2 +- 4 files changed, 56 insertions(+), 27 deletions(-) create mode 100644 EnvelopeGenerator.Infrastructure.Notification/Configuration/ConsumerType.cs create mode 100644 EnvelopeGenerator.Infrastructure.Notification/Configuration/NotificationOptions.cs diff --git a/EnvelopeGenerator.Infrastructure.Notification/Configuration/ConsumerType.cs b/EnvelopeGenerator.Infrastructure.Notification/Configuration/ConsumerType.cs new file mode 100644 index 00000000..6eb103d6 --- /dev/null +++ b/EnvelopeGenerator.Infrastructure.Notification/Configuration/ConsumerType.cs @@ -0,0 +1,7 @@ +namespace EnvelopeGenerator.Infrastructure.Notification.Configuration; + +public enum ConsumerType +{ + API, + RabbitMQ +} diff --git a/EnvelopeGenerator.Infrastructure.Notification/Configuration/NotificationOptions.cs b/EnvelopeGenerator.Infrastructure.Notification/Configuration/NotificationOptions.cs new file mode 100644 index 00000000..208cb43f --- /dev/null +++ b/EnvelopeGenerator.Infrastructure.Notification/Configuration/NotificationOptions.cs @@ -0,0 +1,16 @@ +using DigitalData.MessagingService.RabbitMQ; + +namespace EnvelopeGenerator.Infrastructure.Notification.Configuration; + +public class NotificationOptions +{ + public const string SectionName = "Notification"; + + public ConsumerType ConsumerType { get; set; } + + public string? ApiUrl { get; set; } + + public string SenderEmail { get; set; } = null!; + + public RabbitMqConnectionConfiguration? RabbitMQ { get; set; } +} diff --git a/EnvelopeGenerator.Infrastructure.Notification/DependencyInjection.cs b/EnvelopeGenerator.Infrastructure.Notification/DependencyInjection.cs index c84c778e..5eb1ff0b 100644 --- a/EnvelopeGenerator.Infrastructure.Notification/DependencyInjection.cs +++ b/EnvelopeGenerator.Infrastructure.Notification/DependencyInjection.cs @@ -1,41 +1,47 @@ using DigitalData.MessagingService.Client; -using DigitalData.MessagingService.Domain.Entities; -using DigitalData.MessagingService.RabbitMQ; using EnvelopeGenerator.Application.Common.Interfaces.Services.Notification; +using EnvelopeGenerator.Infrastructure.Notification.Configuration; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace EnvelopeGenerator.Infrastructure.Notification; public static class DependencyInjection { - public static IServiceCollection AddNotificationInfrastructure(this IServiceCollection services, IConfiguration configuration) + public static IServiceCollection AddNotificationInfrastructure(this IServiceCollection services, IConfiguration configuration, string sectionName = NotificationOptions.SectionName) { - var rMqConfig = configuration.GetSection("RabbitMQ").Get() - ?? throw new ArgumentNullException(nameof(RabbitMqConfiguration), "RabbitMQ configuration is missing"); + var ntfConfiguration = configuration.GetSection(sectionName); + services.Configure(ntfConfiguration); - EmailSender.ConnectRabbitMq(config => + var options = ntfConfiguration.Get() + ?? throw new InvalidOperationException( + $"Failed to bind configuration section '{sectionName}' to {nameof(NotificationOptions)}. Ensure the section exists and is correctly configured."); + + switch (options.ConsumerType) { - config.HostName = rMqConfig.HostName; - config.Port = rMqConfig.Port; - config.UserName = rMqConfig.UserName; - config.Password = rMqConfig.Password; - - config.VirtualHost = "/"; - config.QueueName = "emailprofiler.email.outbox"; - config.ExchangeName = "emailprofiler.emails"; - config.RoutingKey = "email.outbox"; - config.DlqQueueName = "emailprofiler.email.outbox.dlq"; - config.DlqExchangeName = "emailprofiler.emails.dlq"; - config.DlqRoutingKey = "email.outbox.dlq"; - }); - - services.Configure(configuration.GetSection("NotificationEmailAccount")); + case ConsumerType.API: + if (options.ApiUrl is string apiUrl) + services.AddMessagingServiceHttpClient(opt => + { + opt.BaseAddress = new Uri(apiUrl); + // Additional configuration for the MessagingServiceHttpClient can be added here if needed + }); + else + throw new InvalidOperationException( + $"MessagingServiceApiUrl must be provided when ClientType is set to Api in the '{sectionName}' configuration section."); + break; + case ConsumerType.RabbitMQ: + if(options.RabbitMQ is not null) + services.AddMessagingServiceClient(ntfConfiguration, nameof(options.RabbitMQ)); + else + throw new InvalidOperationException( + $"Missing RabbitMQ connection configuration." + + $"When ClientType is set to RabbitMQ, a valid RabbitMQ configuration must be provided in the '{sectionName}' configuration section."); + break; + default: + throw new InvalidOperationException( + $"Unsupported ConsumerType '{options.ConsumerType}' in the '{sectionName}' configuration section."); + } services.AddScoped(); return services; diff --git a/EnvelopeGenerator.Infrastructure.Notification/EnvelopeGenerator.Infrastructure.Notification.csproj b/EnvelopeGenerator.Infrastructure.Notification/EnvelopeGenerator.Infrastructure.Notification.csproj index 469d3e1b..1bbaa52e 100644 --- a/EnvelopeGenerator.Infrastructure.Notification/EnvelopeGenerator.Infrastructure.Notification.csproj +++ b/EnvelopeGenerator.Infrastructure.Notification/EnvelopeGenerator.Infrastructure.Notification.csproj @@ -8,7 +8,7 @@ - +