5d4853a1f0
OldestNodeActiveHealthCheck existed because the shared ActiveNodeHealthCheck
selected by cluster leadership (review 01 [High]): leadership is address-ordered
and diverges from singleton placement after a restart, and during a partition
both sides compute themselves leader so Traefik served both. Health 0.3.0 makes
the shared check age-based — it is now this host's own rule, promoted — so the
private copy is deleted and central registers the shared type.
ActiveNodeEvaluator, the "THE single definition of active node" this repo already
maintained, now delegates to the shared ClusterActiveNode rather than
re-implementing it. That keeps the delivery gate, the heartbeat IsActive stamp,
the inbound-API gate and the /health/active tier on one rule, and it means the
rule is shared with OtOpcUa, which had independently written a third copy.
Communication takes a ZB.MOM.WW.Health.Akka reference for it; the layering
trade-off is recorded at the PackageReference.
SitePairActiveNodeHealthCheck is deliberately KEPT. It is not a duplicate of the
rule — it is a thin adapter over the site's own IClusterNodeProvider, which
scopes to site-{SiteId} and is itself now backed by ClusterActiveNode. Registering
the shared check directly would have to re-derive the site role and would lose the
property that the tier and singleton placement come from the same provider.
Central stays unscoped: every central member competes for one active slot.
No behaviour change on any node — same rule, one implementation instead of two.
Verified: Host.Tests 439/439, Communication ActiveNode 2/2.
74 lines
3.8 KiB
XML
74 lines
3.8 KiB
XML
<Project Sdk="Microsoft.NET.Sdk">
|
|
|
|
<PropertyGroup>
|
|
<TargetFramework>net10.0</TargetFramework>
|
|
<ImplicitUsings>enable</ImplicitUsings>
|
|
<Nullable>enable</Nullable>
|
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
|
</PropertyGroup>
|
|
|
|
<ItemGroup>
|
|
<InternalsVisibleTo Include="ZB.MOM.WW.ScadaBridge.Communication.Tests" />
|
|
<InternalsVisibleTo Include="ZB.MOM.WW.ScadaBridge.IntegrationTests" />
|
|
<!-- GrpcSiteTransport failover/failback TestServer coverage (T1B.3) lives in Host.Tests,
|
|
which owns the ASP.NET TestHost stack; it drives the provider's internal failback seams. -->
|
|
<InternalsVisibleTo Include="ZB.MOM.WW.ScadaBridge.Host.Tests" />
|
|
</ItemGroup>
|
|
|
|
<ItemGroup>
|
|
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
|
</ItemGroup>
|
|
|
|
<ItemGroup>
|
|
<PackageReference Include="Akka" />
|
|
<PackageReference Include="Akka.Remote" />
|
|
<PackageReference Include="Akka.Cluster" />
|
|
<PackageReference Include="Akka.Cluster.Tools" />
|
|
<PackageReference Include="Google.Protobuf" />
|
|
<PackageReference Include="Grpc.Net.Client" />
|
|
<PackageReference Include="Grpc.Tools" PrivateAssets="All" />
|
|
<PackageReference Include="ZB.MOM.WW.Configuration" />
|
|
<!-- For ClusterActiveNode — the shared "oldest Up member" primitive that ActiveNodeEvaluator was
|
|
promoted into. The store-and-forward delivery gate, the heartbeat IsActive stamp and the
|
|
/health/active tier must all name the SAME active node; delegating to one implementation is
|
|
what makes that structural. It lives in Health.Akka because that is the family's Akka-cluster
|
|
utility package (it already hosts AkkaClusterStatusPolicy and an endpoint gate); a dedicated
|
|
cluster package would be a better home if a third such primitive appears. -->
|
|
<PackageReference Include="ZB.MOM.WW.Health.Akka" />
|
|
</ItemGroup>
|
|
|
|
<ItemGroup>
|
|
<ProjectReference Include="../ZB.MOM.WW.ScadaBridge.Commons/ZB.MOM.WW.ScadaBridge.Commons.csproj" />
|
|
<ProjectReference Include="../ZB.MOM.WW.ScadaBridge.HealthMonitoring/ZB.MOM.WW.ScadaBridge.HealthMonitoring.csproj" />
|
|
</ItemGroup>
|
|
|
|
<!-- gRPC proto generation. The compiled C# is checked in — under SiteStreamGrpc/
|
|
(Sitestream.cs + SitestreamGrpc.cs) for Protos/sitestream.proto,
|
|
CentralControlGrpc/ (CentralControl.cs + CentralControlGrpc.cs) for
|
|
Protos/central_control.proto, and SiteCommandGrpc/ (SiteCommand.cs +
|
|
SiteCommandGrpc.cs) for Protos/site_command.proto — because protoc segfaults
|
|
inside our linux_arm64 Docker build image. To regenerate after schema changes
|
|
run `docker/regen-proto.sh [sitestream|centralcontrol|sitecommand|all]`, which
|
|
does all of the following and always leaves this file as it found it:
|
|
1. Temporarily uncomment the Protobuf ItemGroup below (just the line for
|
|
the proto you changed — the other files' checked-in C# is already
|
|
compiled, so enabling several at once duplicates types).
|
|
2. Delete the matching checked-in *.cs.
|
|
3. `dotnet build` (on macOS) — Grpc.Tools writes fresh files to obj/.
|
|
4. Copy obj/Debug/net10.0/Protos/*.cs into the matching folder.
|
|
5. Re-comment the ItemGroup.
|
|
central_control.proto imports sitestream.proto, so protoc resolves it from the
|
|
project-relative path without sitestream.proto needing its own Protobuf item.
|
|
An ACTIVE Protobuf item must never be committed — it breaks the Docker image
|
|
build. Eventually we should switch the Docker build image to one with a working
|
|
protoc on arm64. -->
|
|
<!--
|
|
<ItemGroup>
|
|
<Protobuf Include="Protos\sitestream.proto" GrpcServices="Both" />
|
|
<Protobuf Include="Protos\central_control.proto" GrpcServices="Both" />
|
|
<Protobuf Include="Protos\site_command.proto" GrpcServices="Both" />
|
|
</ItemGroup>
|
|
-->
|
|
|
|
</Project>
|