using System; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using FinlyticCore.Dtos.Trading; using FinlyticCore.Services; using FinlyticBot.Services.Execution; using FinlyticBot.Settings; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace FinlyticBot.Services.Consumers; public class EngineProposalConsumerBackgroundService : BackgroundService { private readonly IServiceScopeFactory _scopeFactory; private readonly ISettingsService _settingsService; private readonly IFinlyticLogger _logger; public static Action? OnProposalReceived; public EngineProposalConsumerBackgroundService( IServiceScopeFactory scopeFactory, ISettingsService settingsService, IFinlyticLogger logger) { _scopeFactory = scopeFactory; _settingsService = settingsService; _logger = logger; } protected override Task ExecuteAsync(CancellationToken stoppingToken) { OnProposalReceived = async (proposal) => { if (stoppingToken.IsCancellationRequested) return; try { var autoExec = await _settingsService.GetSettingAsync(BotSettingKeys.EnableAutoExecution, stoppingToken); if (!autoExec) { await _logger.LogInfoAsync(BotSettingKeys.BotChannel, "[ProposalConsumer] Auto-execution is disabled. Ignoring proposal {Id} for {Isin}.", proposal.ProposalId, proposal.UnderlyingIsin); return; } await _logger.LogInfoAsync(BotSettingKeys.BotChannel, "[ProposalConsumer] Consumed approved proposal {Id} for {Isin}. Executing paper trade...", proposal.ProposalId, proposal.UnderlyingIsin); using var scope = _scopeFactory.CreateScope(); var executor = scope.ServiceProvider.GetRequiredService(); await executor.ExecuteProposalAsync(proposal, cancellationToken: stoppingToken); } catch (Exception ex) { await _logger.LogErrorAsync(BotSettingKeys.BotChannel, ex, "[ProposalConsumer] Error executing trade proposal {Id}", proposal.ProposalId); } }; return Task.CompletedTask; } }