Refactor RabbitMQ email queue into publisher/consumer

Refactored the RabbitMQ-based email queue system by splitting
`OutgoingEmailQueue` into `OutgoingEmailPublisher` and
`OutgoingEmailConsumer` to separate publishing and consuming
responsibilities.

- Introduced `IOutgoingEmailConsumer` and renamed
  `IOutgoingEmailQueue` to `IOutgoingEmailPublisher` for clarity.
- Updated `SendEmailCommandHandler` to use the new publisher
  abstraction.
- Added `RabbitMqConnectionFactory` to centralize RabbitMQ
  connection management.
- Updated dependency injection to register new services.
- Simplified RabbitMQ initialization logic by delegating it to
  `RabbitMqConnectionFactory`.
- Enhanced logging for better observability.
- Improved modularity and maintainability by separating concerns
  between message publishing and consuming.
This commit is contained in:
2026-07-24 19:01:42 +02:00
parent 5e587da957
commit 1617d4ab43
8 changed files with 205 additions and 111 deletions

View File

@@ -10,23 +10,18 @@ namespace DigitalData.MessagingService.Infrastructure.Services.Background;
/// Leverages a push-based, event-driven RabbitMQ consumer to eliminate polling overhead.
/// Email account configuration is resolved exclusively from application settings; no database access is performed.
/// </summary>
public class AsyncInitWorker(IOutgoingEmailQueue EmailQueue, ILogger<AsyncInitWorker> Logger) : BackgroundService
public class AsyncInitWorker(IOutgoingEmailConsumer EmailConsumer, IOutgoingEmailPublisher EmailPublisher, RabbitMqConnectionFactory CnnFactory) : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
Logger.LogInformation("Outgoing email queue worker is starting. Initializing event-driven RabbitMQ consumer.");
// Initialize the RabbitMQ push-based consumer. This call is non-blocking;
// message processing is handled asynchronously via registered event callbacks.
await CnnFactory.InitAsync(stoppingToken);
try
{
// Initialize the RabbitMQ push-based consumer. This call is non-blocking;
// message processing is handled asynchronously via registered event callbacks.
if (EmailQueue is OutgoingEmailQueue outgoingEmailQueue)
await outgoingEmailQueue.InitAsync(stoppingToken);
}
catch (Exception ex)
{
Logger.LogError(ex, "A critical error occurred while initializing the outgoing email queue consumer. The worker cannot proceed.");
throw;
}
if (EmailConsumer is OutgoingEmailConsumer outgoingEmailConsumer)
await outgoingEmailConsumer.InitAsync();
if (EmailPublisher is OutgoingEmailPublisher outgoingEmailPublisher)
await outgoingEmailPublisher.InitAsync();
}
}