NejCommon.NET/Utils/PostgresSqlHealthCheck.cs
2026-09-09 22:14:13 +02:00

92 lines
3.1 KiB
C#

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<PostgresSqlHealthCheck> _logger;
private readonly IServiceProvider _serviceProvider;
public PostgresSqlHealthCheck(
IConfiguration configuration,
ILogger<PostgresSqlHealthCheck> logger,
IServiceProvider serviceProvider)
{
_configuration = configuration;
_logger = logger;
_serviceProvider = serviceProvider;
}
public async Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default)
{
try
{
// Try to get DbContext via DI
using var scope = _serviceProvider.CreateScope();
var dbContext = scope.ServiceProvider
.GetRequiredService<AppDbContext>();
// 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<string, object>
{
["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<string, object>
{
["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<string, object>
{
["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<string, object>
{
["error"] = ex.Message,
["timestamp"] = DateTime.UtcNow
});
}
}
}