refactor(mesh): step 2 — delete the node-side ClusterClient and its centralClient parameter
WithOtOpcUaRuntimeActors no longer builds a ClusterClient from MeshTransport:CentralContactPoints, and NodeCommunicationActor.Props takes only the gRPC IApplyAckSender. The ackRouter gate narrows from `useClusterClient || useGrpc` to `useGrpc`, and the CentralClusterClientName constant is gone. NodeCommunicationActor's no-transport warning now names MeshTransport:CentralGrpcEndpoints and MeshTransport:Mode only — the old text pointed an operator at a key that no longer exists. Ripples in this step: the two ClusterClient-shaped facts in NodeCommunicationActorTests (Send-not-SendToAll, and sender-wins-over-a-client) are deleted — the first has no subject left, the second guarded a both-transports-present state that is now unconstructible. The Runtime ServiceCollectionExtensions fact keeps its ackRouter pin and drops its "no ClusterClient actor exists" half for the same reason.
This commit is contained in:
@@ -47,7 +47,6 @@ public static class ServiceCollectionExtensions
|
||||
public const string OpcUaPublishActorName = "opcua-publish";
|
||||
public const string PeerProbeSupervisorName = "peer-probe-supervisor";
|
||||
public const string ContinuousHistorizationRecorderActorName = "continuous-historization-recorder";
|
||||
public const string CentralClusterClientName = "central-cluster-client";
|
||||
|
||||
/// <summary>
|
||||
/// Registers shared runtime services. Currently binds <see cref="IAlarmHistorianSink"/>
|
||||
@@ -101,8 +100,8 @@ public static class ServiceCollectionExtensions
|
||||
// with no gate at all, and both nodes would write every sample twice with nothing to say so.
|
||||
services.TryAddSingleton<IHistorizationRoleView>(sp => sp.GetRequiredService<RedundancyRoleView>());
|
||||
|
||||
// ClusterClient→gRPC migration Task 1B.2: the node→central ack transport under
|
||||
// MeshTransport:Mode = Grpc. Registered unconditionally but resolved only by the Grpc arm of
|
||||
// The node→central ack transport under MeshTransport:Mode = Grpc (mesh gRPC command plane,
|
||||
// Task 1B.2). Registered unconditionally but resolved only by the Grpc arm of
|
||||
// WithOtOpcUaRuntimeActors — the mode is not knowable here (this runs before configuration is
|
||||
// read into options), and a singleton nobody resolves is never constructed, so a Dps node
|
||||
// opens no channel.
|
||||
@@ -404,35 +403,15 @@ public static class ServiceCollectionExtensions
|
||||
registry.Register<DependencyMuxActorKey>(mux);
|
||||
|
||||
// Per-cluster mesh Phase 2: the node end of the central↔node command boundary. Spawned
|
||||
// BEFORE DriverHostActor because it is the host's ackRouter under ClusterClient mode.
|
||||
// It has no dependency of its own on the host — inbound commands travel via the node's
|
||||
// BEFORE DriverHostActor because it is the host's ackRouter under Grpc mode. It has no
|
||||
// dependency of its own on the host — inbound commands travel via the node's
|
||||
// EventStream — so this ordering costs nothing.
|
||||
var meshOptions = resolver.GetService<IOptions<MeshTransportOptions>>().Value;
|
||||
var useClusterClient = string.Equals(
|
||||
meshOptions.Mode, MeshTransportOptions.ModeClusterClient, StringComparison.OrdinalIgnoreCase);
|
||||
var useGrpc = string.Equals(
|
||||
meshOptions.Mode, MeshTransportOptions.ModeGrpc, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
IActorRef? centralClient = null;
|
||||
if (useClusterClient)
|
||||
{
|
||||
// Contacts come from appsettings, not the database — the deliberate asymmetry:
|
||||
// central's node set changes as operators add and retire nodes, but central's own
|
||||
// address is part of the deployment. MeshTransportOptionsValidator has already
|
||||
// rejected an empty or malformed list at boot, so this cannot silently produce a
|
||||
// client with no contacts.
|
||||
var contacts = meshOptions.CentralContactPoints
|
||||
.Select(cp => ActorPath.Parse($"{cp}/system/receptionist"))
|
||||
.ToImmutableHashSet();
|
||||
centralClient = system.ActorOf(
|
||||
ClusterClient.Props(ClusterClientSettings.Create(system).WithInitialContacts(contacts)),
|
||||
CentralClusterClientName);
|
||||
}
|
||||
|
||||
// ClusterClient→gRPC migration Task 1B.2. Deliberately EXCLUSIVE with the branch above —
|
||||
// under Grpc no ClusterClient is created at all, which is half the point of the migration
|
||||
// (it is the cross-WAN Akka association this program removes). The two are never both
|
||||
// handed to the actor, and it prefers the sender if they ever were.
|
||||
// The node→central ack transport. Built ONLY under Grpc: under Dps the ack goes out on
|
||||
// the deployment-acks topic from DriverHostActor and never reaches this actor at all.
|
||||
IApplyAckSender? ackSender = null;
|
||||
if (useGrpc)
|
||||
{
|
||||
@@ -451,7 +430,7 @@ public static class ServiceCollectionExtensions
|
||||
}
|
||||
|
||||
var nodeComm = system.ActorOf(
|
||||
NodeCommunicationActor.Props(centralClient, ackSender),
|
||||
NodeCommunicationActor.Props(ackSender),
|
||||
MeshPaths.NodeCommunicationName);
|
||||
|
||||
// Registered with the receptionist in ALL modes: under Dps and Grpc nothing dials it, and
|
||||
@@ -567,12 +546,11 @@ public static class ServiceCollectionExtensions
|
||||
: null;
|
||||
|
||||
var driverHost = system.ActorOf(
|
||||
// ackRouter: under ClusterClient AND Grpc the node comm actor relays ApplyAcks across
|
||||
// the boundary (which transport it then uses is its own business — the ClusterClient
|
||||
// ref or the gRPC sender it was built with); under Dps it stays null and the host
|
||||
// publishes on the deployment-acks topic exactly as before. Grpc MUST be included
|
||||
// here: routed to DPS instead, a Grpc node's ack would never reach the sender at all
|
||||
// and every deployment to it would time out while it applied perfectly.
|
||||
// ackRouter: under Grpc the node comm actor relays ApplyAcks across the mesh
|
||||
// boundary through the gRPC sender it was built with; under Dps it stays null and
|
||||
// the host publishes on the deployment-acks topic exactly as before. Routed to DPS
|
||||
// instead, a Grpc node's ack would never reach the sender at all and every
|
||||
// deployment to it would time out while it applied perfectly.
|
||||
// dbFactory is nullable (Phase 4): a driver-only node passes null here — ConfigDb is
|
||||
// gated on hasAdmin and driver-only nodes are forced to FetchAndCache. DriverHostActor
|
||||
// guards every ConfigDb-touching path on it (UpsertNodeDeploymentState no-ops; central
|
||||
@@ -580,7 +558,7 @@ public static class ServiceCollectionExtensions
|
||||
// alarmStateStore (there is no ConfigDb-backed EF fallback; the host skips the alarm
|
||||
// host when no store was wired).
|
||||
DriverHostActor.Props(dbFactory, roleInfo.LocalNode,
|
||||
ackRouter: useClusterClient || useGrpc ? nodeComm : null,
|
||||
ackRouter: useGrpc ? nodeComm : null,
|
||||
driverFactory: driverFactory, localRoles: roleInfo.LocalRoles,
|
||||
dependencyMux: mux,
|
||||
opcUaPublishActor: publishActor,
|
||||
|
||||
Reference in New Issue
Block a user