using ZB.MOM.WW.OtOpcUa.Commons.Messages.Redundancy; namespace ZB.MOM.WW.OtOpcUa.Runtime.Drivers; /// /// Single decision point for the Primary data-plane gates (inbound device writes, native alarm acks, /// fleet-wide alerts publishes). A KNOWN role wins outright; an UNKNOWN role (no redundancy snapshot /// yet, or the snapshot never mentioned this node — the 03/S5 identity-mismatch shape) is resolved by /// cluster membership: a single-driver cluster stays default-ALLOW (no peer exists — the /// boot-window / single-node posture), a multi-driver cluster is default-DENY (a real Primary peer /// exists; do not touch the shared field device until the redundancy snapshot proves this node is it). /// Fixes archreview 03/S4 (primary gate defaulted to allow while role unknown → dual-primary window). /// public static class PrimaryGatePolicy { /// Decide whether this node should service a Primary-only data-plane operation. /// This node's last-known redundancy role, or null when unknown /// (no snapshot received yet, or the snapshot omitted this node). /// Count of Up cluster members carrying the driver role. /// true to service as Primary; false to deny. public static bool ShouldServiceAsPrimary(RedundancyRole? localRole, int driverMemberCount) => localRole switch { RedundancyRole.Primary => true, RedundancyRole.Secondary or RedundancyRole.Detached => false, _ => driverMemberCount <= 1, // unknown: allow only when no driver peer exists }; }