From 979dc102dd40cd0838602143b9dec6501fba67cb Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Wed, 22 Jul 2026 06:05:34 -0400 Subject: [PATCH] feat(cluster): SelfFormAfter option (bootstrap self-form fallback window) Claude-Session: https://claude.ai/code/session_01GASWkNEi68FSCtvr6rLoEW --- .../AkkaClusterOptions.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/AkkaClusterOptions.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/AkkaClusterOptions.cs index c8c79436..7ad64fe6 100644 --- a/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/AkkaClusterOptions.cs +++ b/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/AkkaClusterOptions.cs @@ -55,4 +55,19 @@ public sealed class AkkaClusterOptions /// /// public string SplitBrainResolverStrategy { get; set; } = "auto-down"; + + /// + /// Bootstrap self-form fallback window (decision 2026-07-22, scadaproj/akka_failover.md ยง6.1). + /// Akka only lets the FIRST listed seed form a new cluster; a non-first seed cold-starting + /// while its peer is down loops on InitJoin forever ("auto-down removes the crash outage, + /// not this one" โ€” docs/Redundancy.md). When this node has waited longer than this window + /// without cluster membership it joins itself โ€” but ONLY if its own address appears in + /// ; a non-seed node (e.g. a site node whose only seed is central-1) + /// stays waiting, because self-forming there creates a permanent island. Default 10s + /// (same-datacenter pair; a live peer answers InitJoin in milliseconds). null or a + /// non-positive value disables the fallback. Accepted trade: both pair nodes cold-starting + /// inside the window while mutually unreachable form two clusters โ€” the same dual-active + /// class the auto-down strategy already accepts, same recovery (restart one side). + /// + public TimeSpan? SelfFormAfter { get; set; } = TimeSpan.FromSeconds(10); }