using System.Collections.Concurrent; using Managing.Application.Abstractions.Services; using Managing.Application.Hubs; using Managing.Domain.Backtests; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using static Managing.Common.Enums; namespace Managing.Application.Workers; public class NotifyBundleBacktestWorker : BaseWorker { private readonly IServiceProvider _serviceProvider; private readonly IHubContext _hubContext; private readonly ConcurrentDictionary> _sentBacktestIds = new(); public NotifyBundleBacktestWorker( IServiceProvider serviceProvider, IHubContext hubContext, ILogger logger) : base(WorkerType.NotifyBundleBacktest, logger, TimeSpan.FromMinutes(1), serviceProvider) { _serviceProvider = serviceProvider; _hubContext = hubContext; } protected override async Task Run(CancellationToken stoppingToken) { try { // Create a new service scope to get fresh instances of services with scoped DbContext using var scope = _serviceProvider.CreateScope(); var backtester = scope.ServiceProvider.GetRequiredService(); // Fetch all running bundle requests var runningBundles = await backtester.GetBundleBacktestRequestsByStatusAsync(BundleBacktestRequestStatus.Running); foreach (var bundle in runningBundles) { var requestId = bundle.RequestId; // Fetch all backtests for this bundle var (backtests, _) = backtester.GetBacktestsByRequestIdPaginated(requestId, 1, 100); if (!_sentBacktestIds.ContainsKey(requestId)) _sentBacktestIds[requestId] = new HashSet(); foreach (var backtest in backtests) { if (_sentBacktestIds[requestId].Contains(backtest.Id)) continue; // If backtest is already LightBacktest, send directly var lightResponse = backtest as LightBacktest; if (lightResponse != null) { await _hubContext.Clients.Group($"bundle-{requestId}") .SendAsync("BundleBacktestUpdate", lightResponse, stoppingToken); _sentBacktestIds[requestId].Add(backtest.Id); } } // If the bundle is now completed, flush the sent IDs for this requestId if (bundle.Status == BundleBacktestRequestStatus.Completed && _sentBacktestIds.ContainsKey(requestId)) { _sentBacktestIds.TryRemove(requestId, out _); } } } catch (Exception ex) { _logger.LogError(ex, "Error in NotifyBundleBacktestWorker"); } } }