using Akka.Cluster;
using ZB.MOM.WW.ScadaBridge.Host.Actors;
using ZB.MOM.WW.ScadaBridge.InboundAPI;
namespace ZB.MOM.WW.ScadaBridge.Host.Health;
///
/// InboundAPI-008 / InboundAPI-022: production implementation of
/// backed by the running Akka.NET cluster.
///
/// The inbound API is "Central cluster only (active node)" — a standby central
/// node must not execute method scripts or Route.To() calls. This gate
/// mirrors the leadership check in (the
/// node is the cluster leader, ), so
/// can return HTTP 503 on a standby.
///
/// Registered only in the Central-role branch of Program.cs. The gate
/// is resolved per request from HttpContext.RequestServices; while the
/// AkkaHostedService is still warming up (ActorSystem == null)
/// or the node has not yet reached , this
/// implementation reports IsActiveNode == false — the safe-by-default
/// answer matching the standby case.
///
public sealed class ActiveNodeGate : IActiveNodeGate
{
private readonly AkkaHostedService _akkaService;
/// Initializes a new bound to the given Akka hosted service.
/// The Akka hosted service exposing the cluster's .
public ActiveNodeGate(AkkaHostedService akkaService)
{
_akkaService = akkaService;
}
///
/// true only when this node has joined the cluster ()
/// AND is the current cluster leader; false in every other state
/// (actor system not yet started, node still joining, node is a standby).
///
public bool IsActiveNode
{
get
{
var system = _akkaService.ActorSystem;
if (system == null)
return false;
var cluster = Cluster.Get(system);
var self = cluster.SelfMember;
if (self.Status != MemberStatus.Up)
return false;
var leader = cluster.State.Leader;
return leader != null && leader == self.Address;
}
}
}