using Microsoft.AspNetCore.Routing; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Diagnostics.HealthChecks; using Microsoft.Extensions.Options; using ZB.MOM.WW.Health; using ZB.MOM.WW.Health.Akka; using ZB.MOM.WW.Health.EntityFrameworkCore; using ZB.MOM.WW.LocalDb.Replication; using ZB.MOM.WW.OtOpcUa.Configuration; using ZB.MOM.WW.OtOpcUa.Host.Configuration; namespace ZB.MOM.WW.OtOpcUa.Host.Health; public static class HealthEndpoints { /// /// Registers the shared ZB.MOM.WW health probes. Tier semantics preserved: configdb + akka on /// ready+active; admin-leader on active only. /// /// The service collection to register the health checks on. /// The same service collection, for chaining. public static IServiceCollection AddOtOpcUaHealth(this IServiceCollection services) { services.AddHealthChecks() .AddTypeActivatedCheck>( "configdb", failureStatus: null, tags: new[] { ZbHealthTags.Ready, ZbHealthTags.Active }, args: new DatabaseHealthCheckOptions { ProbeQuery = static (db, ct) => db.Deployments.AsNoTracking().Take(1).ToListAsync(ct), }) .AddTypeActivatedCheck( "akka", failureStatus: null, tags: new[] { ZbHealthTags.Ready, ZbHealthTags.Active }, args: AkkaClusterStatusPolicy.OtOpcUaCompat) .AddTypeActivatedCheck( "admin-leader", failureStatus: null, tags: new[] { ZbHealthTags.Active }, args: "admin") // Registered unconditionally, not driver-gated. AddOtOpcUaHealth takes no role argument // and runs on every node; the check itself resolves ISyncStatus optionally and reports // Healthy when LocalDb is absent (admin-only graphs) or replication is default-OFF, so a // plain node is never degraded by it. A factory registration keeps this no-arg signature // while still reading ISyncStatus + options + the sync port from the container. .Add(new HealthCheckRegistration( "localdb-replication", sp => new LocalDbReplicationHealthCheck( sp.GetService(), sp.GetRequiredService>(), LocalDbRegistration.SyncListenPort(sp.GetRequiredService())), failureStatus: null, tags: new[] { ZbHealthTags.Active })); return services; } /// Maps the OtOpcUa health check endpoints to the route builder. /// The endpoint route builder. /// The same endpoint route builder, for chaining. public static IEndpointRouteBuilder MapOtOpcUaHealth(this IEndpointRouteBuilder app) { app.MapZbHealth(); return app; } }