165 lines
6.9 KiB
C#
165 lines
6.9 KiB
C#
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;
|
|
|
|
/// <summary>
|
|
/// Represents a service that implements the <see cref="IPublisherService"/> contract, providing the concrete implementation of the publishing operations defined by the interface.
|
|
/// </summary>
|
|
public class PublisherService : IPublisherService
|
|
{
|
|
private readonly ILogger<PublisherService> _logger;
|
|
private readonly HashSet<string> _queues = new();
|
|
private readonly IBus? _bus;
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="PublisherService"/> class, a RabbitMQ publisher service, by configuring the message bus from <paramref name="rabbitMqSettings"/> and storing <paramref name="logger"/> for diagnostic logging.
|
|
/// </summary>
|
|
/// <param name="rabbitMqSettings">The RabbitMQ configuration whose <see cref="RabbitMqSettings.ConnectionString"/> is used to initialize the message bus.</param>
|
|
/// <param name="logger">The logger used to record initialization status and errors.</param>
|
|
/// <!-- aidoc:v1 sig=e60da0f body=9c07ebc -->
|
|
public PublisherService(
|
|
IOptions<RabbitMqSettings> rabbitMqSettings,
|
|
ILogger<PublisherService> 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<IBus>();
|
|
|
|
_logger.LogInformation("PublisherService initialized");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error initializing PublisherService");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Registers a queue with the specified <paramref name="queueName"/> for tracking purposes,
|
|
/// while the actual queue creation is delegated to EasyNetQ. Returns false when the name is
|
|
/// null, empty, or whitespace, and returns true when the queue is newly added or already
|
|
/// registered (idempotent behavior).
|
|
/// </summary>
|
|
/// <param name="queueName">The name of the queue to register.</param>
|
|
/// <returns>A <see cref="Task{Boolean}"/> that resolves to true when the queue is successfully
|
|
/// registered (either newly added or already present), or false when <paramref name="queueName"/>
|
|
/// is null, empty, or whitespace.</returns>
|
|
/// <!-- aidoc:v1 sig=980f114 body=a6676db -->
|
|
public Task<bool> 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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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 <c>false</c> is returned.
|
|
/// </summary>
|
|
/// <param name="msg">The message payload to send to the queue.</param>
|
|
/// <param name="queueName">The name of the target queue to which the message will be sent.</param>
|
|
/// <returns><c>true</c> if the message was sent successfully; otherwise, <c>false</c>.</returns>
|
|
public async Task<bool> 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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Serializes the specified object to JSON and asynchronously sends it to the named queue.
|
|
/// </summary>
|
|
/// <param name="obj">The object to serialize and send to the queue.</param>
|
|
/// <param name="queueName">The name of the destination queue.</param>
|
|
/// <returns>A task that resolves to <c>true</c> if the message was sent successfully; otherwise, <c>false</c>.</returns>
|
|
public async Task<bool> SendMessage(object obj, string queueName)
|
|
{
|
|
var json = JsonConvert.SerializeObject(obj);
|
|
return await SendMessage(json, queueName);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sends an error message to the specified queue. Validates that the bus instance is available and that the supplied object is a <c>Message<Error></c>; returns <c>false</c> when either validation fails or when the send operation throws an exception.
|
|
/// </summary>
|
|
/// <param name="obj">The message object expected to be a <c>Message<Error></c>. If it is not, the method returns <c>false</c> without sending anything.</param>
|
|
/// <param name="queueName">The name of the queue to which the error message body will be sent. The queue is created if it does not already exist.</param>
|
|
/// <returns>A <see cref="Task{Boolean}"/> that resolves to <c>true</c> when the error message is successfully sent, and <c>false</c> when the bus is null, the object is not a <c>Message<Error></c>, or an exception is raised while sending.</returns>
|
|
public async Task<bool> 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<Error> errorMessage)
|
|
return false;
|
|
|
|
await CreateQueue(queueName);
|
|
|
|
_logger.LogDebug("Sending error message to {queueName}", queueName);
|
|
|
|
// enviamos solo el Error (no Message<Error>)
|
|
await _bus.SendReceive.SendAsync(queueName, errorMessage.Body);
|
|
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error sending error message");
|
|
return false;
|
|
}
|
|
}
|
|
}
|