using System.Text; using System.Text.Json; using Microsoft.Extensions.Options; using RabbitMQ.Client; public interface IReconciliationPublisher { Task PublishAsync(ReconciliationAlert alert, CancellationToken ct); } public sealed class ReconciliationPublisher : IReconciliationPublisher { private readonly RabbitMqOptions _opts; private readonly ILogger _logger; public ReconciliationPublisher( IOptions opts, ILogger logger) { _opts = opts.Value; _logger = logger; } public Task PublishAsync(ReconciliationAlert alert, CancellationToken ct) { var factory = new ConnectionFactory { HostName = _opts.Host, Port = _opts.Port, UserName = _opts.Username, Password = _opts.Password, }; using var connection = factory.CreateConnection("reconciliation-publisher"); using var channel = connection.CreateModel(); var props = channel.CreateBasicProperties(); props.Persistent = true; var payload = JsonSerializer.Serialize(new { reconciliationAlertId = alert.Id, checkType = alert.CheckType.ToDbString(), encounterId = alert.EncounterId, patientId = alert.PatientId, details = alert.Details, createdAt = alert.CreatedAt, }); channel.BasicPublish( exchange: RabbitMqTopologyProvisioner.Exchange, routingKey: RabbitMqTopologyProvisioner.ReconciliationKey, basicProperties: props, body: Encoding.UTF8.GetBytes(payload)); _logger.LogInformation( "[RECONCILIATION-PUBLISHED] CheckType={CheckType} EncounterId={EncounterId}", alert.CheckType.ToDbString(), alert.EncounterId); return Task.CompletedTask; } }