namespace ZB.MOM.WW.ScadaBridge.CentralUI.Services; /// /// Admin-triggered manual failover of the central pair. Declared here — and in terms of /// plain strings — so CentralUI stays Akka-free; the Akka implementation lives in the Host /// (AkkaManualFailoverService) and is registered only in the Central branch. /// public interface IManualFailoverService { /// /// Gracefully fails over the central cluster: the current active (oldest Up) member /// leaves, restarts via its supervisor, and rejoins as standby. The Leave is graceful, /// never a Down, so cluster singletons hand over instead of being killed. /// /// The caller is usually connected THROUGH the node being failed over (Traefik routes /// the UI to the active node), so the calling Blazor circuit should expect to drop and /// reconnect against the new active node. /// /// /// Authenticated user name, recorded on the audit row. /// The address acted on, or null when there is no peer to fail over to /// (failing over a lone node would be an outage, not a failover). Task FailOverCentralAsync(string actor); /// /// Asks a SITE to gracefully fail over its own two-node pair. Central and each site are /// separate Akka clusters, so this is a request relayed over the command/control channel — /// the site performs the Leave itself and reports the outcome. Unlike central failover, /// this does NOT disturb the caller's own UI session. /// /// The site whose pair should fail over. /// Authenticated user name, recorded on the audit row. /// The site's outcome — accepted with a target, or refused with a reason. Task FailOverSiteAsync(string siteId, string actor); } /// /// Outcome of a site-pair failover request, in UI terms. Deliberately distinct from the wire /// ack so CentralUI stays free of the Akka message contract. /// /// true when the site issued the graceful Leave. /// Address of the leaving site node; null when refused. /// /// Why the request was refused or failed. A refusal (peer guard, misroute) is a definitive /// answer FROM the site; an unreachable site surfaces here as a timeout message. Both are /// reported to the operator rather than being flattened into a generic failure. /// public sealed record SiteFailoverOutcome(bool Accepted, string? TargetAddress, string? ErrorMessage);