using System.Text.Json;
using FinlyticAssets.Services;
using FinlyticCore.Entities.Assets;
using FinlyticCore.Models.Assets;
using FinlyticCore.Util;
namespace FinlyticAssets.Util;
///
/// Represents a managed MQTT client acting as a server-side RPC provider within the asset microservice.
/// It subscribes to request topics, processes incoming JSON payloads via the database service, and publishes
/// the requested asset entities back to the corresponding response topic.
///
public class AssetsMqttClient : ManagedMqttClient
{
private readonly IServiceScopeFactory _scopeFactory;
private readonly ILogger _logger;
///
/// Initializes a new instance of the class.
///
/// The logger used to record connection, error, and status messages.
/// The database service used for querying and validating assets.
public AssetsMqttClient(ILogger logger, IServiceScopeFactory scopeFactory)
: base(logger)
{
_scopeFactory = scopeFactory;
_logger = logger;
}
///
/// Invoked automatically once the connection to the MQTT broker is successfully established or restored.
/// Registers the required wildcard subscriptions for incoming asset validation and search requests.
///
/// A representing the asynchronous subscription operation.
protected override async Task OnConnectedAsync()
{
await SubscribeAsync("services/request/assets_Get/#");
await SubscribeAsync("services/request/assets_Search/#");
}
///
/// Processes incoming messages on the subscribed topics, executes the corresponding database query,
/// and publishes the result to the response topic while preserving the correlation ID.
///
/// The MQTT topic on which the message was received.
/// The incoming message as a UTF-8 encoded JSON string.
/// A representing the asynchronous message processing operation.
protected override async Task OnMessageReceivedAsync(string topic, string payload)
{
var segments = topic.Split('/');
if (segments.Length < 4) return;
var channel = segments[2];
var correlationId = segments[3];
try
{
List responseData = [];
using var scope = _scopeFactory.CreateScope();
var dbService = scope.ServiceProvider.GetRequiredService();
switch (channel)
{
case "assets_Get":
var validReq = JsonSerializer.Deserialize(payload);
if (validReq != null)
{
responseData = await dbService.GetValidAssetsByIsinAsync(validReq.Isin);
}
break;
case "assets_Search":
var searchReq = JsonSerializer.Deserialize(payload);
if (searchReq != null)
{
responseData = await dbService.FindAffectedActiveAssetsAsync(searchReq.SearchQuery);
}
break;
}
{
string responseTopic = $"services/response/{channel}/{correlationId}";
await PublishAsync(responseTopic, responseData.ToDtoList());
}
}
catch (Exception ex)
{
OnError(ex);
}
}
}