using adas_core.Application.Services.Interfaces;
using adas_core.Domain.Models.AppSettings;
using EasyNetQ;
using EasyNetQ.SystemMessages;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
namespace adas_core.Infrastructure.Services;
///
/// Represents a service that implements the contract, providing the concrete implementation of the publishing operations defined by the interface.
///
public class PublisherService : IPublisherService
{
private readonly ILogger _logger;
private readonly HashSet _queues = new();
private readonly IBus? _bus;
public PublisherService(
IOptions rabbitMqSettings,
ILogger logger)
{
_logger = logger;
try
{
var connection = rabbitMqSettings.Value.ConnectionString;
if (string.IsNullOrWhiteSpace(connection))
{
_logger.LogError("Missing RabbitMQ connection string");
return;
}
var services = new ServiceCollection();
services.AddEasyNetQ(connection);
var provider = services.BuildServiceProvider();
_bus = provider.GetRequiredService();
_logger.LogInformation("PublisherService initialized");
}
catch (Exception ex)
{
_logger.LogError(ex, "Error initializing PublisherService");
}
}
public Task CreateQueue(string queueName)
{
if (string.IsNullOrWhiteSpace(queueName))
return Task.FromResult(false);
if (_queues.Contains(queueName))
{
_logger.LogDebug("Queue {queueName} already registered", queueName);
return Task.FromResult(true);
}
_queues.Add(queueName);
_logger.LogInformation("Queue registered: {queueName}", queueName);
// EasyNetQ crea colas automáticamente
return Task.FromResult(true);
}
///
/// Sends a message to the specified queue using the configured bus. If the bus is not initialized or an error occurs, the operation is logged and false is returned.
///
/// The message payload to send to the queue.
/// The name of the target queue to which the message will be sent.
/// true if the message was sent successfully; otherwise, false.
public async Task SendMessage(string msg, string queueName)
{
try
{
if (_bus == null)
{
_logger.LogError("Bus is null");
return false;
}
await CreateQueue(queueName);
_logger.LogDebug("Sending message to {queueName}", queueName);
await _bus.SendReceive.SendAsync(queueName, msg);
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error sending message to {queueName}", queueName);
return false;
}
}
///
/// Serializes the specified object to JSON and asynchronously sends it to the named queue.
///
/// The object to serialize and send to the queue.
/// The name of the destination queue.
/// A task that resolves to true if the message was sent successfully; otherwise, false.
public async Task SendMessage(object obj, string queueName)
{
var json = JsonConvert.SerializeObject(obj);
return await SendMessage(json, queueName);
}
///
/// Sends an error message to the specified queue. Validates that the bus instance is available and that the supplied object is a Message<Error>; returns false when either validation fails or when the send operation throws an exception.
///
/// The message object expected to be a Message<Error>. If it is not, the method returns false without sending anything.
/// The name of the queue to which the error message body will be sent. The queue is created if it does not already exist.
/// A that resolves to true when the error message is successfully sent, and false when the bus is null, the object is not a Message<Error>, or an exception is raised while sending.
public async Task SendMessageError(object obj, string queueName)
{
try
{
if (_bus == null)
{
_logger.LogError("Bus is null - cannot send error message");
return false;
}
if (obj is not Message errorMessage)
return false;
await CreateQueue(queueName);
_logger.LogDebug("Sending error message to {queueName}", queueName);
// enviamos solo el Error (no Message)
await _bus.SendReceive.SendAsync(queueName, errorMessage.Body);
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error sending error message");
return false;
}
}
}