docs(mesh): sweep the remaining doubled-quorum comment sites — the coordinator absorbs duplicates idempotently
This commit is contained in:
@@ -128,8 +128,9 @@ public sealed class NodeCommunicationActor : ReceiveActor
|
||||
}
|
||||
|
||||
// Send, not SendToAll: the deploy coordinator is a single singleton, and the central comm
|
||||
// actor forwards to its proxy. SendToAll would deliver one ack per central node, and the
|
||||
// coordinator would count the same node twice.
|
||||
// actor forwards to its proxy. Its NodeId-keyed upsert absorbs a duplicate idempotently,
|
||||
// so single-target is defence in depth and a bound on wasted sends — mirroring the
|
||||
// corrected Grpc-branch rationale above.
|
||||
_centralClient.Tell(new ClusterClient.Send(MeshPaths.CentralCommunication, ack));
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -22,8 +22,9 @@ namespace ZB.MOM.WW.OtOpcUa.Runtime.Tests.Communication;
|
||||
/// <b>The load-bearing fact is that ONE endpoint is dialled on success.</b> This replaces an
|
||||
/// Akka <c>ClusterClient.Send</c>, which is single-target at-most-once — not a
|
||||
/// <c>SendToAll</c>. Both central nodes route an ack to the same
|
||||
/// <c>ConfigPublishCoordinator</c> singleton proxy, so posting to both would have the
|
||||
/// coordinator count this node twice and could seal a deployment on a doubled quorum.
|
||||
/// <c>ConfigPublishCoordinator</c> singleton proxy, whose NodeId-keyed upsert absorbs a
|
||||
/// duplicate idempotently — so the single-endpoint rule is defence in depth and a bound
|
||||
/// on wasted dials, not what protects the seal.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The failure side matters just as much: the receptionist dropped an undeliverable ack in
|
||||
|
||||
+6
-4
@@ -94,8 +94,9 @@ public class NodeCommunicationActorTests : RuntimeActorTestBase
|
||||
public void ApplyAck_goes_to_central_as_a_Send_not_a_SendToAll()
|
||||
{
|
||||
// Send, not SendToAll: the deploy coordinator is one singleton behind the central comm
|
||||
// actor's proxy. SendToAll would deliver one ack per central node and the coordinator would
|
||||
// count this node twice.
|
||||
// actor's proxy. The coordinator's NodeId-keyed upsert absorbs a duplicate idempotently,
|
||||
// so the single-target rule is defence in depth and a bound on wasted work, not a
|
||||
// correctness requirement.
|
||||
var client = CreateTestProbe();
|
||||
var actor = Sys.ActorOf(NodeCommunicationActor.Props(client.Ref));
|
||||
|
||||
@@ -161,8 +162,9 @@ public class NodeCommunicationActorTests : RuntimeActorTestBase
|
||||
public void A_sender_wins_over_a_cluster_client_and_the_ack_is_not_sent_twice()
|
||||
{
|
||||
// Defence in depth. The registration arm builds exactly one transport — under Grpc no
|
||||
// ClusterClient is created at all — but if both were ever present, posting over both would
|
||||
// deliver two acks for one apply and the coordinator would count this node twice.
|
||||
// ClusterClient is created at all — and if both were ever present, posting over both would
|
||||
// deliver two acks for one apply. The coordinator would absorb the duplicate (NodeId-keyed
|
||||
// upsert), so this pins tidiness and bounded work, not seal correctness.
|
||||
var client = CreateTestProbe();
|
||||
var sender = new RecordingAckSender();
|
||||
var actor = Sys.ActorOf(NodeCommunicationActor.Props(client.Ref, sender));
|
||||
|
||||
Reference in New Issue
Block a user