using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using FinlyticBackend.Database;
using FinlyticBackend.Hubs;
using FinlyticBackend.Services;
using FinlyticBackend.Settings;
using FinlyticCore.Dtos.Bot;
using FinlyticCore.Dtos.Logging;
using FinlyticCore.Dtos.News;
using FinlyticCore.Dtos.Trading;
using FinlyticCore.Models;
using FinlyticCore.Services;
using FinlyticCore.Util;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace FinlyticBackend.Util;
///
/// Central Managed MQTT Bridge & RPC Gateway for FinlyticBackend.
/// Subscribes to general broadcast MQTT topics and forwards them to SignalR clients and FCM push services.
///
public class BackendMqttBridge : ManagedMqttClient, IHostedService
{
public static readonly ConcurrentDictionary> ServiceLogsRingBuffer = new(StringComparer.OrdinalIgnoreCase);
private readonly IConfiguration _configuration;
private readonly IServiceScopeFactory _scopeFactory;
private readonly IHubContext _tradeStreamHubContext;
private readonly IHubContext _newsHubContext;
private readonly IHubContext _logHubContext;
private readonly IFirebaseNotificationService _firebaseService;
private readonly ILogger _logger;
private readonly IFinlyticLogger _finlyticLogger;
public BackendMqttBridge(
IConfiguration configuration,
IServiceScopeFactory scopeFactory,
IHubContext tradeStreamHubContext,
IHubContext newsHubContext,
IHubContext logHubContext,
IFirebaseNotificationService firebaseService,
ILogger logger,
IFinlyticLogger finlyticLogger) : base(logger)
{
_configuration = configuration;
_scopeFactory = scopeFactory;
_tradeStreamHubContext = tradeStreamHubContext;
_newsHubContext = newsHubContext;
_logHubContext = logHubContext;
_firebaseService = firebaseService;
_logger = logger;
_finlyticLogger = finlyticLogger;
}
///
public async Task StartAsync(CancellationToken cancellationToken)
{
var config = MqttConfiguration.FromConfiguration(_configuration, "finlytic_backend_gateway");
_logger.LogInformation("Starting Backend MQTT Gateway Bridge. Host: {Host}, ClientId: {ClientId}", config.Host, config.ClientId);
await ConnectAsync(config);
}
///
public async Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Stopping Backend MQTT Gateway Bridge.");
await DisconnectAsync();
}
///
protected override async Task OnConnectedAsync()
{
await _finlyticLogger.LogInfoAsync(BackendSettingKeys.MqttChannel,
"[BackendMqttBridge] Backend MQTT Gateway Bridge connected. Subscribing to broadcast topics...");
// RPC response stream
await SubscribeAsync(MqttTopics.ResponseWildcard);
// Engine & Bot streams
await SubscribeAsync(MqttTopics.EngineWildcard);
await SubscribeAsync(MqttTopics.BotWildcard);
// News & Sentiment streams
await SubscribeAsync(MqttTopics.NewsCompleted);
await SubscribeAsync(MqttTopics.NewsStreamWildcard);
await SubscribeAsync(MqttTopics.SentimentWildcard);
// Real-time Logs
await SubscribeAsync(MqttTopics.LogsWildcard);
// Universe RPC Endpoint for FinlyticTechnicals
await SubscribeRpcAsync