using Akka.Actor;
using Akka.Cluster;
using ZB.MOM.WW.ScadaBridge.Commons.Messages.Health;
using ZB.MOM.WW.ScadaBridge.HealthMonitoring;
using ZB.MOM.WW.ScadaBridge.Host.Actors;
namespace ZB.MOM.WW.ScadaBridge.Host.Health;
///
/// Provides cluster node statuses from Akka.NET cluster membership for health reporting.
///
public class AkkaClusterNodeProvider : IClusterNodeProvider
{
private readonly AkkaHostedService _akkaService;
private readonly string _siteRole;
///
/// Initializes a new .
///
/// The Akka hosted service providing access to the actor system.
/// The Akka cluster role used to filter relevant member nodes.
public AkkaClusterNodeProvider(AkkaHostedService akkaService, string siteRole)
{
_akkaService = akkaService;
_siteRole = siteRole;
}
///
public bool SelfIsPrimary
{
get
{
var system = _akkaService.ActorSystem;
if (system == null) return false;
var cluster = Cluster.Get(system);
return ClusterActivityEvaluator.SelfIsOldest(cluster, _siteRole);
}
}
///
public IReadOnlyList GetClusterNodes()
{
var system = _akkaService.ActorSystem;
if (system == null) return [];
var cluster = Cluster.Get(system);
var oldest = ClusterActivityEvaluator.OldestUpMember(cluster, _siteRole);
var nodes = new List();
foreach (var member in cluster.State.Members)
{
if (!member.HasRole(_siteRole))
continue;
var hostname = member.Address.Host ?? member.Address.ToString();
var isOnline = member.Status == MemberStatus.Up;
var isPrimary = oldest != null && member.UniqueAddress.Equals(oldest.UniqueAddress);
var role = isPrimary ? "Primary" : "Standby";
nodes.Add(new NodeStatus(hostname, isOnline, role));
}
// If we have unreachable members, add them as offline
foreach (var unreachable in cluster.State.Unreachable)
{
if (!unreachable.HasRole(_siteRole))
continue;
// Don't duplicate if already in members list
if (nodes.Any(n => n.Hostname == (unreachable.Address.Host ?? unreachable.Address.ToString())))
continue;
var hostname = unreachable.Address.Host ?? unreachable.Address.ToString();
nodes.Add(new NodeStatus(hostname, false, "Standby"));
}
return nodes;
}
}