using Akka.Cluster; using Microsoft.Extensions.Diagnostics.HealthChecks; namespace ZB.MOM.WW.Health.Akka; /// /// Pure mapping from an Akka to a . /// /// /// /// Wraps a so the decision logic is a deterministic, /// table-testable function — only supplies the live cluster /// status. Two named presets reconcile the divergence between the existing ScadaBridge and OtOpcUa /// implementations; construct a custom instance for project-specific overrides. /// /// public sealed class AkkaClusterStatusPolicy { private readonly Func _evaluate; /// Initializes a new . /// The pure status-to-health mapping function. public AkkaClusterStatusPolicy(Func evaluate) { _evaluate = evaluate ?? throw new ArgumentNullException(nameof(evaluate)); } /// Applies the policy to the given member status. /// The local node's Akka cluster member status. /// The mapped . public HealthStatus Evaluate(MemberStatus status) => _evaluate(status); /// /// ScadaBridge origin: Up/Joining → Healthy, Leaving/Exiting → /// Degraded, everything else → Unhealthy. The convergence target for all projects. /// public static AkkaClusterStatusPolicy Default { get; } = new(static status => status switch { MemberStatus.Up or MemberStatus.Joining => HealthStatus.Healthy, MemberStatus.Leaving or MemberStatus.Exiting => HealthStatus.Degraded, _ => HealthStatus.Unhealthy, }); /// /// OtOpcUa origin: self-Up-among-reachable-members → Healthy, any non-Up state /// (including Leaving/Exiting/Down) → Degraded. Provided for backward /// compatibility during OtOpcUa's migration. /// /// /// The original OtOpcUa check scanned the reachable member set for self with /// Status == Up; any other state caused the scan to miss self and collapse to Degraded. /// This preset reproduces that behavior: only is Healthy. /// public static AkkaClusterStatusPolicy OtOpcUaCompat { get; } = new(static status => status == MemberStatus.Up ? HealthStatus.Healthy : HealthStatus.Degraded); }