using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; namespace ScadaLink.HealthMonitoring; public static class ServiceCollectionExtensions { /// /// Register site-side health monitoring services (metric collection + periodic reporting). /// Call this on site nodes only. For central, call AddCentralHealthAggregation() instead. /// public static IServiceCollection AddSiteHealthMonitoring(this IServiceCollection services) { AddOptionsValidation(services); services.AddSingleton(); services.AddHostedService(); return services; } /// /// Register shared health monitoring services (safe for both central and site). /// Does not start the HealthReportSender — call AddSiteHealthMonitoring() on site nodes for that. /// public static IServiceCollection AddHealthMonitoring(this IServiceCollection services) { AddOptionsValidation(services); services.AddSingleton(); return services; } /// /// Register central-side health aggregation services. Includes the /// that generates a self-report /// for the central cluster so it appears on /monitoring/health. /// public static IServiceCollection AddCentralHealthAggregation(this IServiceCollection services) { AddOptionsValidation(services); services.AddSingleton(); services.AddSingleton(sp => sp.GetRequiredService()); services.AddHostedService(sp => sp.GetRequiredService()); services.AddHostedService(); return services; } /// /// HealthMonitoring-014: register the /// so a misconfigured ScadaLink:HealthMonitoring section (zero/negative /// intervals, or a CentralOfflineTimeout shorter than /// OfflineTimeout) is rejected with a clear, key-naming message when the /// hosted services resolve their options at startup — rather than crashing /// later inside a constructor with an opaque /// . Idempotent so it is safe when /// more than one of the registration methods above is called. /// private static void AddOptionsValidation(IServiceCollection services) { services.TryAddEnumerable( ServiceDescriptor.Singleton, HealthMonitoringOptionsValidator>()); } }