using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using MSAdminUsuarios.Context; using MSAdminUsuarios.Controllers; using MSAdminUsuarios.Models; using Newtonsoft.Json; using RabbitMQ.Client; using RabbitMQ.Client.Events; using System.Reflection; using System.Text; namespace MSAdminUsuarios.Utils { public readonly struct MQExchanges { public static readonly string AgendaMedica = "MsAgendaMedica"; public static readonly string Usuarios = "MSAdminUsuarios"; } public readonly struct MQueues { public static readonly string medico = "UsuarioMedico"; public static readonly string PerfilesPorUsuario = "PerfilesPorUsuario"; public static readonly string Usuarios = "Usuarios"; public static readonly string FirmaUsuario = $"{Usuarios}.Firma"; } public class MsComunicadoresModel { public string exchange { get; set; } = ""; public List queues { get; set; } = new(); } public static class RabbitMQService { private static string[] _queues = Array.Empty(); private static string _exchange = "MSAdminUsuarios"; private static string Exchange { get { return _exchange; } set { _exchange = value; } } private static readonly MsComunicadoresModel ExchangePrincipal = new() { exchange = Exchange, queues = { MQueues.PerfilesPorUsuario, MQueues.Usuarios } }; private static readonly List ListaExchanges = new() { ExchangePrincipal, new() { exchange = MQExchanges.AgendaMedica, queues = { MQueues.medico } } }; public static IModel GetRabbitMQChannel(IServiceProvider serviceProvider, string projectName) { var connection = serviceProvider.GetService(); if (connection == null) throw new Exception("Connection is null."); var channel = connection.CreateModel(); //Declare exchange if it doesnt already exist var exchangeName = projectName; Exchange = exchangeName; ListaExchanges.ForEach(ex => { channel.ExchangeDeclare( exchange: ex.exchange, type: ExchangeType.Topic, durable: true, autoDelete: false, arguments: null ); ex.queues.ForEach(q => { string queue = $"{ex.exchange}.{q}"; channel.QueueDeclare( queue: queue, durable: true, exclusive: false, autoDelete: false, arguments: null ); channel.QueueBind( queue: queue, exchange: ex.exchange, routingKey: $"{queue}.*" ); }); }); return channel; } public static void ListenForIntegrationEvents(string projectName, WebApplicationBuilder builder) { RabbitMQConfig mqConfig = builder.Configuration.GetSection("RabbitMQConfig").Get(); var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole().AddEventLog()); //var logger = loggerFactory.CreateLogger("Rabbit2"); //logger.LogInformation("Inicia Rabbitmq con"); ConnectionFactory factory = new() { HostName = mqConfig.HostName, UserName = mqConfig.UserName, Password = mqConfig.Password, }; IConnection connection = factory.CreateConnection(); IModel channelReceptor = connection.CreateModel(); EventingBasicConsumer consumer = new(channelReceptor); consumer.Received += RabbitMQService.ConsumeRabbitMQEvent; foreach (var queue in ExchangePrincipal.queues) { channelReceptor.BasicConsume( queue: $"{ExchangePrincipal.exchange}.{queue}", autoAck: false, consumer: consumer ); } } public static async void ConsumeRabbitMQEvent(object? sender, BasicDeliverEventArgs ea) { var body = ea.Body.ToArray(); var message = Encoding.UTF8.GetString(body); var route = ea.RoutingKey; if (message == null || message.Length == 0) { throw new Exception("Datos no recibidos"); } if (route == null || route.Length == 0) { throw new Exception("RouteKey no recibida"); } var controller = route.Split("."); var consumer = (EventingBasicConsumer)sender!; var model = consumer.Model; var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole().AddEventLog()); var logger = loggerFactory.CreateLogger("RMQ.MsAdminUsuarios"); ModelContext context = new(); if (controller[1] == "PerfilesPorUsuario") { try { var data = JsonConvert.DeserializeObject(message); var PPUCtrl = new PerfilesPorUsuarioController(context); var result = await PPUCtrl.GuardarPerfilesPorUsuario(data!); logger.LogWarning(20,result.ToString()); if (result is OkResult) { model.BasicAck(ea.DeliveryTag, false); } else throw new Exception(); } catch (Exception ex) { // Temporalmente solo logeamos el error en lugar de rechazar logger.LogCritical(1, ex.ToString()); logger.LogCritical(2, ex.Message); logger.LogCritical(3, ex.InnerException?.ToString()); logger.LogCritical(ExMessage(ex)); //model.BasicReject(ea.DeliveryTag, true); model.BasicAck(ea.DeliveryTag, false); } return; } if (controller[1] == "Usuarios") { try { var UsuariosCtrl = new UsuariosController(context, model); if (controller[2] == "post") { var data = JsonConvert.DeserializeObject(message); IActionResult result = await UsuariosCtrl.GuardarUsuarios(data!); if (result is OkResult) { model.BasicAck(ea.DeliveryTag, false); } else throw new Exception(((ConflictObjectResult)result).Value?.ToString() ?? "No registra log"); } if (controller[2] == "patch") { if(controller.Length == 3) { var data = JsonConvert.DeserializeObject(message); IActionResult result = await UsuariosCtrl.EditarUsuarios(data!); if (result is OkResult) { model.BasicAck(ea.DeliveryTag, false); } else throw new Exception(((ConflictObjectResult)result).Value?.ToString() ?? "No registra log"); } if (controller[3] == "Firma") { var data = JsonConvert.DeserializeObject(message); IActionResult result = await UsuariosCtrl.EditarFirma(data!); if (result is OkResult) { model.BasicAck(ea.DeliveryTag, false); } else throw new Exception(((ConflictObjectResult)result).Value?.ToString() ?? "No registra log"); } } } catch (Exception ex) { // Temporalmente solo logeamos el error en lugar de rechazar logger.LogCritical(ExMessage(ex)); //model.BasicReject(ea.DeliveryTag, true); model.BasicAck(ea.DeliveryTag, false); } return; } } private static string ExMessage(Exception ex) { var sb = new StringBuilder(); sb.Append(ex.Message) .Append(ex.InnerException); return sb.ToString(); } } }