Introduce RabbitMQ consumer pool for parallel processing

Enhanced RabbitMQ email processing by introducing a `SendingEmailConsumerPool` to enable the competing consumers pattern. Each consumer operates on its own channel, improving scalability and thread safety.

- Added `SendingEmailConsumerPool` to manage multiple consumers.
- Updated `DependencyInjection` to register the consumer pool.
- Refactored `SendingEmailConsumer` for better logging and error handling.
- Updated `AsyncInitWorker` to initialize the consumer pool.
- Added `ConsumerConcurrency` to RabbitMQ configuration.
- Improved error handling in `LimilabsEmailService` with detailed SMTP error messages.
This commit is contained in:
2026-08-05 15:34:33 +02:00
parent bd31bfe528
commit fa9b4973b9
6 changed files with 114 additions and 28 deletions

View File

@@ -28,7 +28,7 @@ public class LimilabsEmailService(
public async Task SendEmailAsync(EmailContext context, CancellationToken cancellationToken = default)
{
using var smtp = new Smtp();
ISendMessageResult? result = null;
try
{
await ConnectAndAuthenticateSmtpAsync(smtp, context.Sender);
@@ -48,25 +48,24 @@ public class LimilabsEmailService(
var mail = builder.Create();
var result = await smtp.SendMessageAsync(mail, cancellationToken);
result = await smtp.SendMessageAsync(mail, cancellationToken);
if (result.Status != SendMessageStatus.Success)
{
throw new InvalidOperationException($"Failed to send email. Status: {result.Status}");
throw new InvalidOperationException($"Failed to send email. Status: {result.Status}. {ErrorMessageBuilder(result)}");
}
await smtp.CloseAsync(cancellationToken);
await Task.CompletedTask; // For async consistency
}
catch (Limilabs.Client.ServerException ex)
{
await smtp.CloseSafelyAsync();
throw new AuthenticationFailedException("SMTP authentication failed. Check credentials or OAuth2 configuration.", ex);
throw new AuthenticationFailedException($"SMTP authentication failed. Check credentials or OAuth2 configuration. {ErrorMessageBuilder(result)}", ex);
}
catch (Exception ex)
{
await smtp.CloseSafelyAsync();
throw new InvalidOperationException("Failed to send email via SMTP server.", ex);
throw new InvalidOperationException($"Failed to send email via SMTP server. {ErrorMessageBuilder(result)}", ex);
}
}
@@ -92,4 +91,21 @@ public class LimilabsEmailService(
await smtp.LoginAsync(smtpAccount.Username, password);
}
}
}
private static string ErrorMessageBuilder(ISendMessageResult? result = null)
{
if(result is null || result.GeneralErrors.Count == 0)
return string.Empty;
else if(result.GeneralErrors.Count == 1)
return $"Error: {result.GeneralErrors.FirstOrDefault()}";
var message = new StringBuilder("Errors:\n");
foreach (var error in result.GeneralErrors)
{
message.AppendLine($" • {error}");
}
return message.ToString();
}
}