diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/Resources/akka.conf b/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/Resources/akka.conf
index b7e7a8a7..56648f0b 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/Resources/akka.conf
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/Resources/akka.conf
@@ -13,14 +13,12 @@ akka {
# since the Serilog logger can be slow to initialize at startup.
logger-startup-timeout = 30s
+ # DistributedPubSub is PAIR-LOCAL and stays: it carries MeshTransport:Mode = Dps (the
+ # single-mesh default), the node-local alarm-command publishes and the node<->node
+ # redundancy-state probe leg. What is gone is the cross-mesh command transport, which is now
+ # gRPC and needs no Akka extension at all.
extensions = [
"Akka.Cluster.Tools.PublishSubscribe.DistributedPubSubExtensionProvider, Akka.Cluster.Tools"
-
- # Per-cluster mesh Phase 2 — the central<->node command boundary. NOT auto-started: without
- # this entry the receptionist materialises only if some code path happens to call
- # ClusterClientReceptionist.Get(system) first, which makes "is the boundary listening?"
- # depend on startup ordering rather than on configuration.
- "Akka.Cluster.Tools.Client.ClusterClientReceptionistExtensionProvider, Akka.Cluster.Tools"
]
actor {
@@ -94,31 +92,6 @@ akka {
down-removal-margin = 15s
run-coordinated-shutdown-when-down = on
- # CLUSTERCLIENT — the central<->node command boundary (per-cluster mesh Phase 2).
- client {
- # DELIBERATE, and NOT what the sister project runs: they never wrote this section, so
- # they inherit buffer-size = 1000. Zero means "if the receptionist is unknown, drop the
- # message now". Buffering would replay a DispatchDeployment on reconnect and apply a
- # deployment ConfigPublishCoordinator had already sealed as TimedOut — the node would
- # then be running a configuration the database says failed. Fail-fast keeps the DB the
- # single record of truth, and reproduces today's DPS behaviour exactly: a node that is
- # down misses the publish and self-heals from the DB on restart.
- buffer-size = 0
-
- # Retry forever rather than self-stopping the client. Restates Akka's default; stated
- # explicitly because the behaviour is load-bearing — a central node down for an hour
- # must not require a driver-node restart to become reachable again.
- reconnect-timeout = off
-
- receptionist {
- # Empty = every member hosts a receptionist. This is what makes the comm actors
- # "registered per node, not as a singleton" work: contact rotation reaches whichever
- # node answers. Restates Akka's default; do NOT scope this to a role, or the
- # boundary becomes reachable through one node only and rotation silently fails.
- role = ""
- }
- }
-
singleton {
singleton-name = "singleton"
}
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests/MeshTransportHoconTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests/MeshTransportHoconTests.cs
index 1960d0c3..9bdb1b0d 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests/MeshTransportHoconTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests/MeshTransportHoconTests.cs
@@ -1,5 +1,4 @@
using Akka.Actor;
-using Akka.Cluster.Tools.Client;
using Akka.Configuration;
using Shouldly;
using Xunit;
@@ -7,8 +6,8 @@ using Xunit;
namespace ZB.MOM.WW.OtOpcUa.Cluster.Tests;
///
-/// Asserts the ClusterClient / receptionist / frame-size settings that are actually in
-/// force on a real built from the shipped base config.
+/// Asserts the remoting frame-size canary and the DistributedPubSub extension that are actually
+/// in force on a real built from the shipped base config.
///
///
/// Asserting the akka.conf text instead would pass while a competing HOCON fragment
@@ -29,38 +28,6 @@ public class MeshTransportHoconTests : IDisposable
_sys = ActorSystem.Create("mesh-hocon-probe", config);
}
- [Fact]
- public void Cluster_client_buffering_is_disabled()
- {
- // Asserted through ClusterClientSettings — the object the client is actually built from —
- // NOT through Config.GetInt. GetInt returns 0 for a MISSING key, so a config assertion here
- // passes identically whether the setting is explicitly 0 or absent with Akka's default of
- // 1000 in force. It was green before this feature existed; that is the whole defect class.
- //
- // buffer-size = 0 means "drop now if the receptionist is unknown". Buffering would replay a
- // DispatchDeployment on reconnect and apply a deployment the coordinator already sealed as
- // TimedOut, leaving the node running a configuration the database says failed. This is a
- // behaviour decision, not a tuning knob.
- ClusterClientSettings.Create(_sys).BufferSize.ShouldBe(0);
- }
-
- [Fact]
- public void Cluster_client_retries_forever_rather_than_self_stopping()
- {
- // reconnect-timeout = off surfaces as a null TimeSpan on the settings object. A central node
- // down for an hour must not require a driver-node restart to become reachable again.
- ClusterClientSettings.Create(_sys).ReconnectTimeout.ShouldBeNull();
- }
-
- [Fact]
- public void Receptionist_serves_every_member_regardless_of_role()
- {
- // An empty role is what makes "registered per node, not as a singleton" work: every member
- // hosts a receptionist, so ClusterClient contact rotation reaches whichever node answers.
- // Scoping this to a role would make the boundary reachable through one node only.
- ClusterReceptionistSettings.Create(_sys).Role.ShouldBeNull();
- }
-
[Fact]
public void Oversized_frames_are_logged_rather_than_dropped_silently()
{
@@ -73,21 +40,11 @@ public class MeshTransportHoconTests : IDisposable
}
[Fact]
- public void Receptionist_extension_is_registered_at_startup()
+ public void Distributed_pub_sub_extension_is_registered_at_startup()
{
- // Not auto-started. Without this entry the receptionist materialises only if some code path
- // happens to call ClusterClientReceptionist.Get(system) first, which makes "is the boundary
- // listening?" depend on startup ordering rather than on configuration.
- _sys.Settings.Config.GetStringList("akka.extensions")
- .ShouldContain(s => s.Contains("ClusterClientReceptionistExtensionProvider"));
- }
-
- [Fact]
- public void Distributed_pub_sub_extension_survives_alongside_the_receptionist()
- {
- // The dark switch keeps both transports live for one phase, and DPS additionally carries
- // traffic Phase 2 does not touch at all — node-local alarm-command publishes and the
- // node<->node redundancy-state probe leg. Losing it here would break far more than deploys.
+ // DPS is PAIR-LOCAL and survives the cross-mesh transport's deletion: it carries
+ // MeshTransport:Mode = Dps (the single-mesh default), the node-local alarm-command publishes
+ // and the node<->node redundancy-state probe leg. Losing it would break far more than deploys.
_sys.Settings.Config.GetStringList("akka.extensions")
.ShouldContain(s => s.Contains("DistributedPubSubExtensionProvider"));
}