Apigateway/Microservicios/MsUsuarios/Utils/RabbitMQService.cs
2024-05-16 16:37:29 -05:00

273 lines
9.1 KiB
C#

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
{
//AdminUsuarios
public static readonly string PerfilesPorUsuario = "PerfilesPorUsuario";
public static readonly string Usuarios = "Usuarios";
// Agenda
public static readonly string FirmaUsuario = $"{Usuarios}.Firma";
public static readonly string medico = "UsuarioMedico";
}
public class MsComunicadoresModel
{
public string exchange { get; set; } = "";
public List<string> queues { get; set; } = new();
}
public static class RabbitMQService
{
private static string[] _queues = Array.Empty<string>();
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<MsComunicadoresModel> ListaExchanges = new() {
ExchangePrincipal,
new() {
exchange = MQExchanges.AgendaMedica,
queues = { MQueues.medico }
}
};
public static IModel GetRabbitMQChannel(IServiceProvider serviceProvider, string projectName)
{
var connection = serviceProvider.GetService<IConnection>();
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<RabbitMQConfig>();
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,
Port = mqConfig.Port
};
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<PERFILPORUSUARIO[]>(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<USUARIO>(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<USUARIO>(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<USUARIO>(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();
}
}
}