70 lines
2.6 KiB
C#
70 lines
2.6 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 = RabbitMqConnectionFactory.Create(_rabbitOpts, 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);
|
|
}
|
|
} |