Files
vigilcare-clinical/VigilCareClinicalAPI/BackgroundServices/ClinicalSyncBatchConsumer.cs
T

77 lines
2.8 KiB
C#

using System.Text;
using System.Text.Json;
using Microsoft.Extensions.Options;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
public sealed class ClinicalSyncBatchConsumer : BackgroundService
{
private readonly IServiceScopeFactory _scopes;
private readonly RabbitMqOptions _rabbitOpts;
private readonly ILogger<ClinicalSyncBatchConsumer> _logger;
public ClinicalSyncBatchConsumer(
IServiceScopeFactory scopes,
IOptions<RabbitMqOptions> rabbitOpts,
ILogger<ClinicalSyncBatchConsumer> logger)
{
_scopes = scopes;
_rabbitOpts = rabbitOpts.Value;
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
var factory = new ConnectionFactory
{
HostName = _rabbitOpts.Host,
Port = _rabbitOpts.Port,
UserName = _rabbitOpts.Username,
Password = _rabbitOpts.Password,
DispatchConsumersAsync = true
};
using var connection = factory.CreateConnection("clinical-sync-consumer");
using var channel = connection.CreateModel();
channel.BasicQos(0, prefetchCount: 5, global: false);
var consumer = new AsyncEventingBasicConsumer(channel);
consumer.Received += async (_, ea) =>
{
try
{
await HandleMessageAsync(channel, ea, stoppingToken);
}
catch (JsonException ex)
{
_logger.LogError(ex, "Invalid sync batch message — NACK no requeue");
channel.BasicNack(ea.DeliveryTag, false, requeue: false);
}
catch (Exception ex)
{
_logger.LogError(ex, "Sync batch consumer failed — NACK requeue");
channel.BasicNack(ea.DeliveryTag, false, requeue: true);
}
};
channel.BasicConsume(RabbitMqTopologyProvisioner.SyncBatchQueue, autoAck: false, consumer);
_logger.LogInformation("ClinicalSyncBatchConsumer consuming {Queue}", RabbitMqTopologyProvisioner.SyncBatchQueue);
await Task.Delay(Timeout.Infinite, stoppingToken);
}
private async Task HandleMessageAsync(IModel channel, BasicDeliverEventArgs ea, CancellationToken ct)
{
var payload = Encoding.UTF8.GetString(ea.Body.Span);
var doc = JsonDocument.Parse(payload);
var batchId = Guid.Parse(doc.RootElement.GetProperty("batchId").GetString()!);
await using var scope = _scopes.CreateAsyncScope();
var processor = scope.ServiceProvider.GetRequiredService<ClinicalSyncBatchProcessor>();
await processor.ProcessBatchAsync(batchId, ct);
channel.BasicAck(ea.DeliveryTag, false);
}
}