using System.Text.RegularExpressions; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Diagnostics.HealthChecks; using NejAccountingAPI.Models; namespace NejCommon.Utils; public class PostgresSqlHealthCheck : IHealthCheck { private readonly IConfiguration _configuration; private readonly ILogger _logger; private readonly IServiceProvider _serviceProvider; public PostgresSqlHealthCheck( IConfiguration configuration, ILogger logger, IServiceProvider serviceProvider) { _configuration = configuration; _logger = logger; _serviceProvider = serviceProvider; } public async Task CheckHealthAsync( HealthCheckContext context, CancellationToken cancellationToken = default) { try { // Try to get DbContext via DI using var scope = _serviceProvider.CreateScope(); var dbContext = scope.ServiceProvider .GetRequiredService(); // Execute simple query to check connectivity var canConnect = await dbContext.Database .CanConnectAsync(cancellationToken); if (!canConnect) { return HealthCheckResult.Unhealthy( "Cannot connect to PostgreSQL database", data: new Dictionary { ["timestamp"] = DateTime.UtcNow, ["database"] = "PostgreSQL" }); } // Check for pending migrations var pendingMigrations = await dbContext.Database .GetPendingMigrationsAsync(cancellationToken); if (pendingMigrations.Any()) { return HealthCheckResult.Degraded( "Database has pending migrations", data: new Dictionary { ["pendingMigrations"] = pendingMigrations.Count(), ["migrations"] = string.Join(", ", pendingMigrations) }); } // Test real query to validate permissions var recordCount = await dbContext.ApiKeys .CountAsync(cancellationToken); return HealthCheckResult.Healthy( "PostgreSQL connection is healthy", data: new Dictionary { ["responseTime"] = DateTime.UtcNow }); } catch (Exception ex) { _logger.LogError(ex, "PostgreSQL health check failed: {Message}", ex.Message); return HealthCheckResult.Unhealthy( "PostgreSQL health check failed", exception: ex, data: new Dictionary { ["error"] = ex.Message, ["timestamp"] = DateTime.UtcNow }); } } }