using Marathon.Application.Abstractions; using Marathon.Application.Configuration; using Marathon.Infrastructure.Configuration; using Marathon.Infrastructure.Notifications; using Marathon.Infrastructure.Persistence; using Marathon.Infrastructure.Scraping; using Marathon.Infrastructure.Workers; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; namespace Marathon.Infrastructure; /// /// Top-level DI composition entry-point for all Infrastructure sub-modules /// (Persistence, Scraping, Workers). /// /// /// Call once from the host's DI /// setup. This replaces the previous reflection-based wiring in /// App.xaml.cs::TryAddApplicationAndInfrastructure. /// public static class InfrastructureModule { /// /// Registers the complete Infrastructure layer: /// /// EF Core / SQLite persistence (). /// HttpClient + AngleSharp + Polly scraping (). /// bound to the Workers config section. /// Three pollers. /// /// public static IServiceCollection AddMarathonInfrastructure( this IServiceCollection services, IConfiguration config) { ArgumentNullException.ThrowIfNull(services); ArgumentNullException.ThrowIfNull(config); services.AddMarathonPersistence(config); services.AddMarathonScraping(config); services .AddOptions() .Bind(config.GetSection(WorkerOptions.SectionName)); services .AddOptions() .Bind(config.GetSection(AnomalyOptions.SectionName)); services .AddOptions() .Bind(config.GetSection(ScrapingThrottle.SectionName)); services .AddOptions() .Bind(config.GetSection(NotificationOptions.SectionName)); services.AddHostedService(); services.AddHostedService(); services.AddHostedService(); services.AddHostedService(); // Outbound anomaly notifications (Telegram). Sink + dispatcher are always // registered; the dispatcher idles until Notifications:Enabled is true and // the sink no-ops until a bot token + chat id are configured. services.AddHttpClient(TelegramNotificationSink.HttpClientName, client => client.Timeout = TimeSpan.FromSeconds(15)); services.AddSingleton(); services.AddHostedService(); return services; } }