using OpenHarbor.CQRS.Abstractions; using System.Diagnostics; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; using CH.Dal; namespace CH.CQRS.Query.Health; public class HealthQuery { } public class HealthQueryHandler(CHDbContext dbContext, IMemoryCache memoryCache) : IQueryHandler { private const string HealthCheckCacheKey = "HealthStatus"; private const int CacheDurationInSeconds = 60; public async Task HandleAsync(HealthQuery query, CancellationToken cancellationToken = new CancellationToken()) { if (memoryCache.TryGetValue(HealthCheckCacheKey, out var memory)) { return (HealthQueryResult)memory; } var (databaseStatus, databaseLatency) = await MeasureLatencyAsync(CheckDatabaseHealthAsync); var healthCheckResult = new HealthQueryResult { ApiStatus = true, DatabaseStatus = databaseStatus, DatabaseLatency = $"{databaseLatency}ms", }; memoryCache.Set(HealthCheckCacheKey, healthCheckResult, TimeSpan.FromSeconds(CacheDurationInSeconds)); return healthCheckResult; } public static async Task<(bool isHealthy, long latencyMs)> MeasureLatencyAsync(Func> healthCheckAction) { var stopwatch = Stopwatch.StartNew(); var isHealthy = await healthCheckAction(); stopwatch.Stop(); return (isHealthy, stopwatch.ElapsedMilliseconds); } private async Task CheckDatabaseHealthAsync() { try { await dbContext.Database.ExecuteSqlRawAsync("SELECT 1"); return true; } catch { return false; } } }