using Managing.Application.Abstractions.Services; using Microsoft.Extensions.Diagnostics.HealthChecks; using static Managing.Common.Enums; namespace Managing.Api.HealthChecks { public class CandleDataHealthCheck : IHealthCheck { private readonly IExchangeService _exchangeService; private readonly Ticker _tickerToCheck = Ticker.ETH; private readonly TradingExchanges _exchangeToCheck = TradingExchanges.Evm; public CandleDataHealthCheck(IExchangeService exchangeService) { _exchangeService = exchangeService; } public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) { try { var now = DateTime.UtcNow; // Define timeframes to check with their appropriate start dates and expected freshness var timeframeChecks = new[] { (timeframe: Timeframe.FifteenMinutes, startDate: now.AddDays(-1), maxAgeMins: 30.0), (timeframe: Timeframe.OneHour, startDate: now.AddDays(-3), maxAgeMins: 120.0), (timeframe: Timeframe.OneDay, startDate: now.AddDays(-30), maxAgeMins: 1440.0) }; var results = new List>(); var isHealthy = true; foreach (var (timeframe, startDate, maxAgeMins) in timeframeChecks) { // Using configured exchange and ticker var candles = await _exchangeService.GetCandlesInflux( _exchangeToCheck, _tickerToCheck, startDate, timeframe); var checkResult = new Dictionary { ["CheckedTicker"] = _tickerToCheck.ToString(), ["CheckedTimeframe"] = timeframe.ToString(), ["StartDate"] = startDate }; if (candles == null || !candles.Any()) { checkResult["Status"] = "Degraded"; checkResult["Message"] = $"No candle data found for {timeframe}"; isHealthy = false; } else { var latestCandle = candles.OrderByDescending(c => c.Date).FirstOrDefault(); var timeDiff = now - latestCandle.Date; checkResult["LatestCandleDate"] = latestCandle.Date; checkResult["TimeDifference"] = $"{timeDiff.TotalMinutes:F2} minutes"; if (timeDiff.TotalMinutes > maxAgeMins) { checkResult["Status"] = "Degraded"; checkResult["Message"] = $"Data for {timeframe} is outdated. Latest candle is from {latestCandle.Date:yyyy-MM-dd HH:mm:ss} UTC"; isHealthy = false; } else { checkResult["Status"] = "Healthy"; checkResult["Message"] = $"Data for {timeframe} is up-to-date. Latest candle is from {latestCandle.Date:yyyy-MM-dd HH:mm:ss} UTC"; } } results.Add(checkResult); } // Combine all results into a summary var resultsDictionary = new Dictionary(); for (int i = 0; i < results.Count; i++) { resultsDictionary[$"TimeframeCheck_{i+1}"] = results[i]; } if (isHealthy) { return HealthCheckResult.Healthy( "All candle timeframes are up-to-date", data: resultsDictionary); } else { return HealthCheckResult.Degraded( "One or more candle timeframes are outdated or missing", data: resultsDictionary); } } catch (Exception ex) { return HealthCheckResult.Unhealthy( "Error checking candle data health", ex, data: new Dictionary { ["ErrorMessage"] = ex.Message, ["ErrorType"] = ex.GetType().Name }); } } } }