part #2
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace StellaOps.Worker.Health;
|
||||
|
||||
/// <summary>
|
||||
/// Health check that reports healthy once the host has fully started.
|
||||
/// Before <see cref="IHostApplicationLifetime.ApplicationStarted"/> fires,
|
||||
/// this check returns <see cref="HealthStatus.Degraded"/> so readiness
|
||||
/// probes can distinguish startup from running state.
|
||||
/// </summary>
|
||||
internal sealed class HostStartedHealthCheck : IHealthCheck, IDisposable
|
||||
{
|
||||
private volatile bool _started;
|
||||
private CancellationTokenRegistration _registration;
|
||||
|
||||
public HostStartedHealthCheck(IHostApplicationLifetime lifetime)
|
||||
{
|
||||
_registration = lifetime.ApplicationStarted.Register(() => _started = true);
|
||||
}
|
||||
|
||||
public Task<HealthCheckResult> CheckHealthAsync(
|
||||
HealthCheckContext context,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
return Task.FromResult(_started
|
||||
? HealthCheckResult.Healthy("Host started.")
|
||||
: HealthCheckResult.Degraded("Host is starting."));
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_registration.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<LangVersion>preview</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,49 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
|
||||
namespace StellaOps.Worker.Health;
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods to add lightweight health endpoints to worker services.
|
||||
/// </summary>
|
||||
public static class WorkerHealthExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Registers a health check that tracks whether the host has fully started.
|
||||
/// Call this on <c>builder.Services</c> before building the application.
|
||||
/// </summary>
|
||||
public static IServiceCollection AddWorkerHealthChecks(this IServiceCollection services)
|
||||
{
|
||||
services.AddHealthChecks()
|
||||
.AddCheck<HostStartedHealthCheck>("host_started", tags: ["ready"]);
|
||||
return services;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps <c>/health/liveness</c> (always 200) and <c>/health/readiness</c>
|
||||
/// (checks registered health checks) endpoints.
|
||||
/// </summary>
|
||||
public static WebApplication MapWorkerHealthEndpoints(this WebApplication app)
|
||||
{
|
||||
// Liveness: always returns 200 if the process is running
|
||||
app.MapGet("/health/liveness", () => Results.Ok("Alive"))
|
||||
.ExcludeFromDescription();
|
||||
|
||||
// Readiness: runs all registered health checks tagged "ready"
|
||||
app.MapHealthChecks("/health/readiness", new HealthCheckOptions
|
||||
{
|
||||
Predicate = check => check.Tags.Contains("ready"),
|
||||
ResultStatusCodes =
|
||||
{
|
||||
[HealthStatus.Healthy] = StatusCodes.Status200OK,
|
||||
[HealthStatus.Degraded] = StatusCodes.Status503ServiceUnavailable,
|
||||
[HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable,
|
||||
},
|
||||
});
|
||||
|
||||
return app;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user