feat(cluster): embed Akka HOCON config matching ScadaLink tuning

This commit is contained in:
Joseph Doherty
2026-05-26 04:31:03 -04:00
parent fdb4ac7051
commit 3d0f4dc168
3 changed files with 92 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
namespace ZB.MOM.WW.OtOpcUa.Cluster;
public static class HoconLoader
{
private const string ResourceName = "ZB.MOM.WW.OtOpcUa.Cluster.Resources.akka.conf";
public static string LoadBaseConfig()
{
using var stream = typeof(HoconLoader).Assembly.GetManifestResourceStream(ResourceName)
?? throw new InvalidOperationException(
$"Embedded resource '{ResourceName}' not found. Verify EmbeddedResource glob in csproj.");
using var reader = new StreamReader(stream);
return reader.ReadToEnd();
}
}

View File

@@ -0,0 +1,73 @@
# Base Akka.NET cluster configuration for OtOpcUa fused-host nodes.
#
# Roles, seed nodes, public hostname/port, and the actor system name are overlaid
# at runtime by AkkaHostedService — see ZB.MOM.WW.OtOpcUa.Cluster/AkkaHostedService.cs.
# Everything else here is the cluster-wide tuning that should match across nodes.
#
# Tuning sourced from ScadaLink (ScadaLink.Host/Actors/AkkaHostedService.BuildHocon);
# any divergence must be deliberate and recorded in docs/v2/Architecture.md.
akka {
extensions = [
"Akka.Cluster.Tools.PublishSubscribe.DistributedPubSubExtensionProvider, Akka.Cluster.Tools"
]
actor {
provider = cluster
}
remote {
dot-netty.tcp {
hostname = "0.0.0.0"
port = 4053
}
transport-failure-detector {
heartbeat-interval = 2s
acceptable-heartbeat-pause = 10s
}
}
cluster {
seed-nodes = []
roles = []
min-nr-of-members = 1
split-brain-resolver {
active-strategy = "keep-oldest"
stable-after = 15s
keep-oldest {
down-if-alone = on
}
}
failure-detector {
heartbeat-interval = 2s
threshold = 10.0
acceptable-heartbeat-pause = 10s
}
down-removal-margin = 15s
run-coordinated-shutdown-when-down = on
singleton {
singleton-name = "singleton"
}
singleton-proxy {
singleton-identification-interval = 1s
}
}
coordinated-shutdown {
run-by-clr-shutdown-hook = on
default-phase-timeout = 30s
}
}
# Pinned dispatcher used by OpcUaPublishActor (Task 44) so the OPC UA SDK sees
# only one thread per actor instance — its session/subscription locks expect
# strict single-threaded access.
opcua-synchronized-dispatcher {
type = "PinnedDispatcher"
executor = "thread-pool-executor"
throughput = 1
}

View File

@@ -19,6 +19,10 @@
<ProjectReference Include="..\ZB.MOM.WW.OtOpcUa.Commons\ZB.MOM.WW.OtOpcUa.Commons.csproj"/>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources\akka.conf"/>
</ItemGroup>
<ItemGroup>
<!-- OpenTelemetry.Api 1.9.0 reaches this project transitively from Akka.Cluster.Hosting.
Bump arrives when Akka updates its OTel dependency; tracked separately. -->