80668a07bd
Phase 0 of docs/plans/2026-07-22-overview-dashboard-impl-plan.md: give the
canonical health JSON a structured channel so the family overview dashboard can
read each Akka cluster's current leader.
- ZbHealthWriter: optional `"data": {...}` per entry, sourced from
HealthReportEntry.Data, emitted only when non-empty. Per-property JsonIgnore
(NOT a global DefaultIgnoreCondition) so `"description": null` still renders —
payloads from data-less checks stay byte-identical to 0.1.0.
- AkkaClusterHealthCheck: BuildClusterData publishes this node's own view —
leader (omitted while unknown), selfAddress, selfRoles (sorted), memberCount,
unreachableCount — on every result path. The startup-safety paths (no
ActorSystem / cluster inaccessible) stay description-only.
- Tests: writer data emit/omit (raw-JSON assert on the omit case), and a real
single-node self-joined cluster via Akka.TestKit.Xunit2 for the data values.
70 tests green (25/39/6).
- Version 0.1.0 -> 0.2.0; 3 packages published to the Gitea feed and
restore-verified from a scratch consumer, which serves data.leader live.
99 lines
4.6 KiB
Markdown
99 lines
4.6 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
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)
|