feat(backend): generic settings RPC bridge, LogStreamHub SignalR, and log ringbuffer
This commit is contained in:
@@ -7,6 +7,7 @@ using System.Threading.Tasks;
|
||||
using FinlyticBackend.Database;
|
||||
using FinlyticBackend.Hubs;
|
||||
using FinlyticBackend.Services;
|
||||
using FinlyticCore.Dtos.Logging;
|
||||
using FinlyticCore.Dtos.News;
|
||||
using FinlyticCore.Models;
|
||||
using FinlyticCore.Models.Auth;
|
||||
@@ -28,12 +29,14 @@ public class BackendMqttBridge : ManagedMqttClient, IHostedService
|
||||
{
|
||||
public static readonly ConcurrentDictionary<string, JsonElement> FundamentalsCache = new(StringComparer.OrdinalIgnoreCase);
|
||||
public static readonly ConcurrentDictionary<string, JsonElement> TechnicalsCache = new(StringComparer.OrdinalIgnoreCase);
|
||||
public static readonly ConcurrentDictionary<string, ConcurrentQueue<LogMessageDto>> ServiceLogsRingBuffer = new(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly IServiceScopeFactory _scopeFactory;
|
||||
private readonly IHubContext<TradeRealtimeHub, ITradeClient> _hubContext;
|
||||
private readonly IHubContext<TradeHub> _tradeHubContext;
|
||||
private readonly IHubContext<NewsHub> _newsHubContext;
|
||||
private readonly IHubContext<LogStreamHub> _logHubContext;
|
||||
private readonly IFirebaseNotificationService _firebaseService;
|
||||
private readonly ILogger<BackendMqttBridge> _logger;
|
||||
|
||||
@@ -43,6 +46,7 @@ public class BackendMqttBridge : ManagedMqttClient, IHostedService
|
||||
IHubContext<TradeRealtimeHub, ITradeClient> hubContext,
|
||||
IHubContext<TradeHub> tradeHubContext,
|
||||
IHubContext<NewsHub> newsHubContext,
|
||||
IHubContext<LogStreamHub> logHubContext,
|
||||
IFirebaseNotificationService firebaseService,
|
||||
ILogger<BackendMqttBridge> logger) : base(logger)
|
||||
{
|
||||
@@ -51,6 +55,7 @@ public class BackendMqttBridge : ManagedMqttClient, IHostedService
|
||||
_hubContext = hubContext;
|
||||
_tradeHubContext = tradeHubContext;
|
||||
_newsHubContext = newsHubContext;
|
||||
_logHubContext = logHubContext;
|
||||
_firebaseService = firebaseService;
|
||||
_logger = logger;
|
||||
}
|
||||
@@ -95,6 +100,8 @@ public class BackendMqttBridge : ManagedMqttClient, IHostedService
|
||||
await SubscribeAsync("finlytic/technicalanalysis/#");
|
||||
await SubscribeAsync("finlytic/ta/#");
|
||||
|
||||
// Real-time Logs
|
||||
await SubscribeAsync("finlytic/logs/#");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -104,7 +111,11 @@ public class BackendMqttBridge : ManagedMqttClient, IHostedService
|
||||
|
||||
try
|
||||
{
|
||||
if (topic.StartsWith("finlytic/trades/proposed/", StringComparison.OrdinalIgnoreCase) ||
|
||||
if (topic.StartsWith("finlytic/logs/", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
await HandleLogMessageAsync(payloadStr);
|
||||
}
|
||||
else if (topic.StartsWith("finlytic/trades/proposed/", StringComparison.OrdinalIgnoreCase) ||
|
||||
topic.StartsWith("finlytic/trades/update", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
await HandleTradeProposalAsync(payloadStr);
|
||||
@@ -136,6 +147,23 @@ public class BackendMqttBridge : ManagedMqttClient, IHostedService
|
||||
}
|
||||
}
|
||||
|
||||
private async Task HandleLogMessageAsync(string payloadStr)
|
||||
{
|
||||
var logDto = JsonSerializer.Deserialize<LogMessageDto>(payloadStr, FinlyticJsonSerializerContext.Default.LogMessageDto);
|
||||
if (logDto == null) return;
|
||||
|
||||
string serviceKey = logDto.ServiceName;
|
||||
var queue = ServiceLogsRingBuffer.GetOrAdd(serviceKey, _ => new ConcurrentQueue<LogMessageDto>());
|
||||
queue.Enqueue(logDto);
|
||||
|
||||
// Keep buffer capped at 250 entries
|
||||
while (queue.Count > 250 && queue.TryDequeue(out _)) { }
|
||||
|
||||
// Broadcast to SignalR clients
|
||||
await _logHubContext.Clients.Group(serviceKey).SendAsync("ReceiveLogMessage", logDto);
|
||||
await _logHubContext.Clients.All.SendAsync("ReceiveLogMessage", logDto);
|
||||
}
|
||||
|
||||
private async Task HandleTradeProposalAsync(string payloadStr)
|
||||
{
|
||||
var proposal = JsonSerializer.Deserialize<TradeProposalDto>(payloadStr);
|
||||
|
||||
Reference in New Issue
Block a user