using Microsoft.Extensions.Diagnostics.HealthChecks; using ZB.MOM.WW.OtOpcUa.Commons.Interfaces; namespace ZB.MOM.WW.OtOpcUa.Host.Health; /// /// Reports Healthy on the admin-role leader, Degraded on a non-leader admin member. Used by /// the /health/active endpoint so external load balancers can route admin-singleton /// traffic to the current leader (cookie sessions still work on either node — DataProtection /// keys are shared). /// public sealed class AdminRoleLeaderHealthCheck : IHealthCheck { private readonly IClusterRoleInfo _roleInfo; /// Initializes a new instance of the AdminRoleLeaderHealthCheck class. /// The cluster role information provider. public AdminRoleLeaderHealthCheck(IClusterRoleInfo roleInfo) { _roleInfo = roleInfo; } /// Checks the health status of the admin role leader. /// The health check context. /// The cancellation token. /// A task representing the health check operation. public Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) { if (!_roleInfo.HasRole("admin")) return Task.FromResult(HealthCheckResult.Healthy("Node does not carry admin role")); var leader = _roleInfo.RoleLeader("admin"); var isLeader = leader is not null && leader.Value.Equals(_roleInfo.LocalNode); return Task.FromResult(isLeader ? HealthCheckResult.Healthy($"Admin leader ({_roleInfo.LocalNode})") : HealthCheckResult.Degraded($"Admin member but not leader (leader={leader?.Value ?? ""})")); } }