refactor(infrastructure): introduce MessagingServiceInfrastructureConfiguration builder

Replace the IConfiguration parameter on AddInfrastructure() with a builder
that makes RabbitMQ wiring explicit and validated.

- Add MessagingServiceInfrastructureConfiguration exposing
  AddRabbitMqConnectionFactory() with IConfiguration and Action<T> overloads
- EnsureRabbitMqConnectionFactoryAdded() throws at registration time if the
  caller omits the wiring step
- Remove the implicit services.AddRabbitMqConnectionFactory(configuration)
  call from AddInfrastructure(); callers must opt in via the builder
This commit is contained in:
2026-11-02 15:02:17 +01:00
parent 084ddc4b56
commit 5944823155
2 changed files with 47 additions and 12 deletions

View File

@@ -7,9 +7,7 @@ using DigitalData.MessagingService.Infrastructure.Repositories;
using DigitalData.MessagingService.Infrastructure.Services;
using DigitalData.MessagingService.Infrastructure.Services.Background;
using DigitalData.MessagingService.Publisher;
using DigitalData.MessagingService.RabbitMQ;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
@@ -23,10 +21,12 @@ public static class DependencyInjection
/// <summary>
/// Adds Infrastructure layer services to the DI container
/// </summary>
public static IServiceCollection AddInfrastructure(
this IServiceCollection services,
IConfiguration configuration)
public static IServiceCollection AddInfrastructure(this IServiceCollection services, Action<MessagingServiceInfrastructureConfiguration> configure)
{
var configuration = new MessagingServiceInfrastructureConfiguration(services);
configure.Invoke(configuration);
configuration.EnsureRabbitMqConnectionFactoryAdded();
// --- External Services ---
// OAuth2 token services — provider-specific implementations registered separately,
// dispatcher is the single IOAuth2TokenService consumed by all other services.
@@ -55,9 +55,6 @@ public static class DependencyInjection
services.AddSingleton<SendingEmailConsumerPool>();
services.AddMessagingServicePublisher();
// --- RabbitMQ Configuration ---
services.AddRabbitMqConnectionFactory(configuration);
// ConsumerInitHealthCheck, RabbitMqConnectionHealthCheck and EmailSyncWorkerHealthCheck are
// registered as singletons here so background workers can inject and update them.
// Health check pipeline is wired up in the API layer via AddHealthChecks().
@@ -79,8 +76,7 @@ public static class DependencyInjection
services.AddMemoryCache();
// --- Database (InMemory) ---
services.AddDbContext<MessagingServiceDbContext>(options =>
options.UseInMemoryDatabase("MessagingServiceDb"));
services.AddDbContext<MessagingServiceDbContext>(options => options.UseInMemoryDatabase("MessagingServiceDb"));
services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
@@ -91,5 +87,4 @@ public static class DependencyInjection
return services;
}
}
}

View File

@@ -0,0 +1,40 @@
using DigitalData.MessagingService.RabbitMQ;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace DigitalData.MessagingService.Infrastructure;
public class MessagingServiceInfrastructureConfiguration
{
internal IServiceCollection Services { get; }
private bool _rabbitMqConnectionFactoryAdded = false;
internal MessagingServiceInfrastructureConfiguration(IServiceCollection services)
{
Services = services;
}
public void EnsureRabbitMqConnectionFactoryAdded()
{
if (!_rabbitMqConnectionFactoryAdded)
{
throw new InvalidOperationException("RabbitMQ connection factory has not been added. Please call AddRabbitMqConnectionFactory() before using this configuration.");
}
}
public MessagingServiceInfrastructureConfiguration AddRabbitMqConnectionFactory(Action<RabbitMqConfiguration> configure)
{
Services.AddRabbitMqConnectionFactory(configure);
_rabbitMqConnectionFactoryAdded = true;
return this;
}
public MessagingServiceInfrastructureConfiguration AddRabbitMqConnectionFactory(IConfiguration configuration, string sectionName = RabbitMqConfiguration.SectionName)
{
Services.AddRabbitMqConnectionFactory(configuration, sectionName);
_rabbitMqConnectionFactoryAdded = true;
return this;
}
}