Files
scadaproj/ZB.MOM.WW.Health
Joseph Doherty 6a4fa220de docs(health): oldest-Up-member is the active-node rule (0.3.0)
Rewrites the active-node sections of the spec and shared contract, which
described the leader-based design that both consumers rejected.

- SPEC §2.3 replaced: the rule, the ordered RolePreference, why a node holding
  none of the preferred roles is Unhealthy rather than Healthy, and the data
  payload. §4 (IActiveNodeGate) and the tier table follow.
- SPEC §6 marked historical: it still tells adopters to use
  ActiveNodeHealthCheck(role: "admin") and AkkaActiveNodeGate, which is the
  advice that produced the defect. Kept for provenance, annotated so nobody
  follows it again.
- GAPS: gaps L1/L2 recorded as closed the wrong way, reopened, then closed at
  0.3.0 — including the part worth remembering, that both apps adopted the
  shared check as specified, hit it live, and reverted to private copies, so the
  surface reached zero consumers by being avoided rather than unused.
- Index rows updated with the consumer-visible changes and both app branches.
2026-07-24 13:24:30 -04:00
..

ZB.MOM.WW.Health

Health-check libraries for the ZB.MOM.WW SCADA family (OtOpcUa, MxAccessGateway, ScadaBridge). These are libraries, not a service — each package is linked directly into the consuming application at build time. There is no central health process or network hop; probes run in-process alongside the application.

The library normalizes the three-tier health endpoint convention (/health/ready, /health/active, /healthz) and provides reusable probe implementations so the three sister projects share a common surface without duplicating probe logic.


Packages

Package Description Key Dependencies
ZB.MOM.WW.Health Core tiers, MapZbHealth extension, canonical JSON writer (ZbHealthWriter), IActiveNodeGate seam, GrpcDependencyHealthCheck reachability probe, and tier-tag constants (ZbHealthTags). No Akka or EF dependency. Microsoft.AspNetCore.App (framework ref), Grpc.Net.Client
ZB.MOM.WW.Health.Akka AkkaClusterHealthCheck with a configurable AkkaClusterStatusPolicy (presets: Default three-way / OtOpcUaCompat two-way), ActiveNodeHealthCheck with an optional role filter, and AkkaActiveNodeGate that backs IActiveNodeGate from the cluster member state. ZB.MOM.WW.Health, Akka.Cluster
ZB.MOM.WW.Health.EntityFrameworkCore DatabaseHealthCheck<TContext> with CanConnectAsync by default and an optional ProbeQuery delegate for custom connectivity validation. ZB.MOM.WW.Health, Microsoft.EntityFrameworkCore

Consumer Matrix

Consumer ZB.MOM.WW.Health (core) ZB.MOM.WW.Health.Akka ZB.MOM.WW.Health.EntityFrameworkCore
OtOpcUa yes (+ GrpcDependencyHealthCheck for the MxAccessGateway channel) yes yes
MxAccessGateway yes (+ GrpcDependencyHealthCheck for the x86 worker IPC)
ScadaBridge yes yes yes

MxAccessGateway consumes the core package only — it has no Akka cluster and no EF DbContext. OtOpcUa and ScadaBridge consume all three packages.


Versioning

All three packages are versioned lockstep from Directory.Build.props. The current release is 0.2.0. A single version bump in Directory.Build.props bumps all three packages simultaneously — consumers should reference the same version for all ZB.MOM.WW.Health packages.

0.2.0 — per-entry data (additive, non-breaking)

  • ZbHealthWriter emits an optional "data": { … } object per entry, sourced from the check's HealthCheckResult.Data, only when non-empty — a check that publishes no data produces a byte-identical body to 0.1.0, so every existing consumer is unaffected. Data keys are written verbatim (the camelCase policy applies to the envelope, not to dictionary keys).
  • AkkaClusterHealthCheck populates that dictionary with this node's cluster view: leader (omitted while unknown), selfAddress, selfRoles, memberCount, unreachableCount. The startup-safety paths (no ActorSystem, cluster not yet accessible) stay description-only.
  • Consumers gain the leader field on a package bump alone — no application code change, provided the app registers the shared AkkaClusterHealthCheck.

Building and testing

# from ZB.MOM.WW.Health/
dotnet build ZB.MOM.WW.Health.slnx
dotnet test  ZB.MOM.WW.Health.slnx

All three test assemblies run with dotnet test and require no external dependencies — no database and no external cluster (the cluster-data tests form a single-node in-process Akka cluster on a loopback port via Akka.TestKit.Xunit2):

Assembly Tests
ZB.MOM.WW.Health.Tests 25
ZB.MOM.WW.Health.Akka.Tests 39
ZB.MOM.WW.Health.EntityFrameworkCore.Tests 6
Total 70

Packing

dotnet pack ZB.MOM.WW.Health.slnx -c Release -o ./artifacts

Produces three .nupkg files in artifacts/:

ZB.MOM.WW.Health.0.2.0.nupkg
ZB.MOM.WW.Health.Akka.0.2.0.nupkg
ZB.MOM.WW.Health.EntityFrameworkCore.0.2.0.nupkg

GeneratePackageOnBuild is off — pack explicitly as above.


Status

Built at 0.2.0 and published to the Gitea NuGet feed. Adopted by all four apps (OtOpcUa, MxAccessGateway, ScadaBridge, HistorianGateway). Adoption is tracked in the component backlog:

  • ~/Desktop/scadaproj/components/health/GAPS.md

Design documentation lives alongside that backlog:

  • ~/Desktop/scadaproj/components/health/spec/SPEC.md — normalized three-tier target
  • ~/Desktop/scadaproj/components/health/shared-contract/ZB.MOM.WW.Health.md — proposed API
  • ~/Desktop/scadaproj/components/health/current-state/ — per-project current state (code-verified)