using Akka.Cluster;
namespace ZB.MOM.WW.ScadaBridge.Host.Health;
///
/// THE single definition of "active node" (review 01 [High]): a node is active
/// when it is the OLDEST Up member (optionally within a role scope) — i.e. the
/// member the ClusterSingletonManager places singletons on. Cluster LEADERSHIP
/// (lowest address) is an Akka-internal concept that diverges from singleton
/// placement permanently once the original first node restarts and rejoins;
/// every product-level active/standby decision must use this evaluator, never
/// cluster.State.Leader.
///
public static class ClusterActivityEvaluator
{
/// True when self is Up and no other Up member (in the role scope) is older.
/// Delegates to the shared —
/// one implementation for the delivery gate, the resync authority checks, and the
/// heartbeat IsActive stamp (review 02 round 2, N1).
/// The Akka cluster to evaluate.
/// Optional role scope; when set, only members with this role are considered.
/// true when self is Up and the oldest Up member in the role scope.
public static bool SelfIsOldest(Cluster cluster, string? role = null) =>
Communication.ClusterState.ActiveNodeEvaluator.SelfIsOldestUp(cluster, role);
/// The oldest Up member in the role scope, or null while none is Up. Used for Primary/Standby labelling.
/// The Akka cluster to evaluate.
/// Optional role scope; when set, only members with this role are considered.
/// The oldest Up member in the role scope, or null when none is Up.
public static Member? OldestUpMember(Cluster cluster, string? role = null)
{
Member? oldest = null;
foreach (var m in cluster.State.Members.Where(m => m.Status == MemberStatus.Up))
{
if (role != null && !m.HasRole(role)) continue;
if (oldest == null || m.IsOlderThan(oldest)) oldest = m;
}
return oldest;
}
}