| | | 1 | | using ArturRios.Heimdall.Query.HealthChecks; |
| | | 2 | | using ArturRios.Heimdall.Query.Input; |
| | | 3 | | using ArturRios.Heimdall.Query.Output; |
| | | 4 | | using ArturRios.Mediator.Query.Interfaces; |
| | | 5 | | using ArturRios.Output; |
| | | 6 | | |
| | | 7 | | namespace ArturRios.Heimdall.Query.Handlers; |
| | | 8 | | |
| | | 9 | | /// <summary> |
| | | 10 | | /// Handles <see cref="DetailedHealthQuery" /> (UC-30, FR-HC-02…06): runs every registered |
| | | 11 | | /// <see cref="IServiceHealthCheck" />, reports each service's status, and computes the aggregate |
| | | 12 | | /// general status — <c>Healthy</c> only when all services are up, <c>Unhealthy</c> if any is down |
| | | 13 | | /// (FR-HC-05, AF-30c). The set of checks is injected, so new verifications participate without |
| | | 14 | | /// changing this handler. |
| | | 15 | | /// </summary> |
| | 5 | 16 | | public class GetDetailedHealthQueryHandler(IEnumerable<IServiceHealthCheck> healthChecks) |
| | | 17 | | : IQueryHandlerAsync<DetailedHealthQuery, HealthCheckOutput> |
| | | 18 | | { |
| | | 19 | | public async Task<DataOutput<HealthCheckOutput?>> HandleAsync(DetailedHealthQuery query, CancellationToken cancellat |
| | | 20 | | { |
| | 5 | 21 | | var services = new List<ServiceHealthOutput>(); |
| | | 22 | | |
| | 20 | 23 | | foreach (var check in healthChecks) |
| | | 24 | | { |
| | 5 | 25 | | var healthy = await check.IsHealthyAsync(); |
| | | 26 | | |
| | 5 | 27 | | services.Add(new ServiceHealthOutput |
| | 5 | 28 | | { |
| | 5 | 29 | | Name = check.ServiceName, |
| | 5 | 30 | | Status = healthy ? HealthStatuses.Healthy : HealthStatuses.Unhealthy |
| | 5 | 31 | | }); |
| | 5 | 32 | | } |
| | | 33 | | |
| | | 34 | | // Aggregate: any unhealthy service makes the whole API unhealthy (FR-HC-05). |
| | 10 | 35 | | var aggregate = services.TrueForAll(service => service.Status == HealthStatuses.Healthy) |
| | 5 | 36 | | ? HealthStatuses.Healthy |
| | 5 | 37 | | : HealthStatuses.Unhealthy; |
| | | 38 | | |
| | 5 | 39 | | var result = new HealthCheckOutput |
| | 5 | 40 | | { |
| | 5 | 41 | | Status = aggregate, |
| | 5 | 42 | | Services = services |
| | 5 | 43 | | }; |
| | | 44 | | |
| | 5 | 45 | | return DataOutput<HealthCheckOutput?>.New.WithData(result); |
| | 5 | 46 | | } |
| | | 47 | | } |