fix(host): /health/active = oldest member + DB reachable — partition-safe Traefik routing
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
using Akka.Actor;
|
||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.Host.Health;
|
||||
|
||||
/// <summary>
|
||||
/// /health/active check: Healthy only on the oldest Up member — the node that
|
||||
/// hosts the cluster singletons. Replaces the shared package's leader-based
|
||||
/// ActiveNodeHealthCheck (review 01 [High]): leadership is address-ordered and
|
||||
/// diverges from singleton placement after a restart, and during a partition
|
||||
/// BOTH nodes compute themselves leader, so Traefik served both. Oldest-member
|
||||
/// semantics keep exactly one active node through a partition (the non-oldest
|
||||
/// side still sees the old oldest member until SBR resolves membership).
|
||||
/// </summary>
|
||||
public sealed class OldestNodeActiveHealthCheck : IHealthCheck
|
||||
{
|
||||
private readonly ActorSystem _system;
|
||||
|
||||
/// <summary>Initializes a new <see cref="OldestNodeActiveHealthCheck"/> bound to the running actor system.</summary>
|
||||
/// <param name="system">The live cluster actor system.</param>
|
||||
public OldestNodeActiveHealthCheck(ActorSystem system) => _system = system;
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken ct = default)
|
||||
{
|
||||
var cluster = Akka.Cluster.Cluster.Get(_system);
|
||||
return Task.FromResult(ClusterActivityEvaluator.SelfIsOldest(cluster)
|
||||
? HealthCheckResult.Healthy("oldest Up member (singleton host)")
|
||||
: HealthCheckResult.Unhealthy("not the oldest Up member (standby)"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user