feat(redundancy): wire dbHealth into OpcUaPublishActor + spawn PeerProbeSupervisor per node

This commit is contained in:
Joseph Doherty
2026-06-15 13:33:34 -04:00
parent 393b746d9b
commit 4c78dcd358
2 changed files with 17 additions and 1 deletions
@@ -32,6 +32,7 @@ public static class ServiceCollectionExtensions
public const string HistorianAdapterActorName = "historian-adapter";
public const string DependencyMuxActorName = "dependency-mux";
public const string OpcUaPublishActorName = "opcua-publish";
public const string PeerProbeSupervisorName = "peer-probe-supervisor";
/// <summary>
/// Registers shared runtime services. Currently binds <see cref="IAlarmHistorianSink"/>
@@ -213,10 +214,19 @@ public static class ServiceCollectionExtensions
serviceLevel: serviceLevel,
localNode: roleInfo.LocalNode,
dbFactory: dbFactory,
applier: applier),
applier: applier,
dbHealthProbe: dbHealth),
OpcUaPublishActorName);
registry.Register<OpcUaPublishActorKey>(publishActor);
// Per-node peer-probe supervisor — keeps one OPC UA TCP probe per OTHER non-Detached
// driver node, so every node is continuously probed by all its peers. OpcUaPublishActor
// consumes the resulting probe verdicts to learn this node's own reachability.
var peerProbes = system.ActorOf(
PeerProbeSupervisor.Props(roleInfo.LocalNode),
PeerProbeSupervisorName);
registry.Register<PeerProbeSupervisorKey>(peerProbes);
var driverHost = system.ActorOf(
DriverHostActor.Props(dbFactory, roleInfo.LocalNode, coordinator: null,
driverFactory: driverFactory, localRoles: roleInfo.LocalRoles,
@@ -246,3 +256,6 @@ public sealed class DbHealthProbeActorKey { }
public sealed class HistorianAdapterActorKey { }
public sealed class DependencyMuxActorKey { }
public sealed class OpcUaPublishActorKey { }
/// <summary>Marker key for the per-node PeerProbeSupervisor.</summary>
public sealed class PeerProbeSupervisorKey { }
@@ -50,17 +50,20 @@ public sealed class ServiceCollectionExtensionsTests
var historian = host.Services.GetRequiredService<IRequiredActor<HistorianAdapterActorKey>>();
var mux = host.Services.GetRequiredService<IRequiredActor<DependencyMuxActorKey>>();
var publish = host.Services.GetRequiredService<IRequiredActor<OpcUaPublishActorKey>>();
var peerProbes = host.Services.GetRequiredService<IRequiredActor<PeerProbeSupervisorKey>>();
driverHost.ActorRef.ShouldNotBeNull();
dbHealth.ActorRef.ShouldNotBeNull();
historian.ActorRef.ShouldNotBeNull();
mux.ActorRef.ShouldNotBeNull();
publish.ActorRef.ShouldNotBeNull();
peerProbes.ActorRef.ShouldNotBeNull();
driverHost.ActorRef.Path.Name.ShouldBe(ServiceCollectionExtensions.DriverHostActorName);
dbHealth.ActorRef.Path.Name.ShouldBe(ServiceCollectionExtensions.DbHealthProbeActorName);
historian.ActorRef.Path.Name.ShouldBe(ServiceCollectionExtensions.HistorianAdapterActorName);
mux.ActorRef.Path.Name.ShouldBe(ServiceCollectionExtensions.DependencyMuxActorName);
publish.ActorRef.Path.Name.ShouldBe(ServiceCollectionExtensions.OpcUaPublishActorName);
peerProbes.ActorRef.Path.Name.ShouldBe(ServiceCollectionExtensions.PeerProbeSupervisorName);
}
finally
{