// Copyright (c) StellaOps. Licensed under the AGPL-3.0-or-later. using Microsoft.Extensions.Diagnostics.HealthChecks; using StellaOps.Eventing.Storage; namespace StellaOps.Timeline.WebService.Endpoints; /// /// Health check endpoints. /// public static class HealthEndpoints { /// /// Maps health check endpoints. /// public static void MapHealthEndpoints(this IEndpointRouteBuilder app) { app.MapHealthChecks("/health"); app.MapHealthChecks("/health/ready", new Microsoft.AspNetCore.Diagnostics.HealthChecks.HealthCheckOptions { Predicate = check => check.Tags.Contains("ready") }); app.MapHealthChecks("/health/live", new Microsoft.AspNetCore.Diagnostics.HealthChecks.HealthCheckOptions { Predicate = check => check.Tags.Contains("live") }); } } /// /// Health check for timeline service. /// public sealed class TimelineHealthCheck : IHealthCheck { private readonly ITimelineEventStore _eventStore; /// /// Initializes a new instance of the class. /// public TimelineHealthCheck(ITimelineEventStore eventStore) { _eventStore = eventStore; } /// public async Task CheckHealthAsync( HealthCheckContext context, CancellationToken cancellationToken = default) { try { // Simple check - try to count events for a nonexistent correlation // This validates database connectivity await _eventStore.CountByCorrelationIdAsync("__health_check__", cancellationToken); return HealthCheckResult.Healthy("Timeline service is healthy"); } catch (Exception ex) { return HealthCheckResult.Unhealthy("Timeline service is unhealthy", ex); } } }