docs(health): GrpcDependencyHealthCheck has no consumers - keep it, correct SPEC/README (scadaproj#28)
SPEC 2.4 named OtOpcUa and MxGateway as users; neither is (verified against every app's default branch; MxGateway worker IPC is named pipes, OtOpcUa deliberately does not gate readiness on gateway channels). Keep the check (removal is a breaking API change; small, tested building block), mark it as no-current-consumers in SPEC 2.4/6/7, both READMEs, the shared-contract doc and GAPS. Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
This commit is contained in:
@@ -84,10 +84,11 @@ Checks that can only return **Degraded** (so never cause a 503): OtOpcUa `akka`
|
||||
failures and reset only on a factory success, which needs an RPC, which a 503-ed pod never receives;
|
||||
caller cancellation also counted. Fixed on main `5de3dd9`: caller cancellation no longer counts and each keepalive tick probes one session while the count is non-zero; still present on deployed builds until historiangw#78 redeploys. Detail:
|
||||
[current-state/historiangateway](current-state/historiangateway/CURRENT-STATE.md).
|
||||
- **SPEC text is stale on §2.4.** It names OtOpcUa and MxGateway as `GrpcDependencyHealthCheck` users;
|
||||
- **SPEC text was stale on §2.4 - corrected (scadaproj#28).** It named OtOpcUa and MxGateway as `GrpcDependencyHealthCheck` users;
|
||||
**no app uses it** (HistorianGateway, once cited as a user, now probes the Historian through its
|
||||
connection pool). The check stays in the library but has zero consumers; the SPEC/README wording should
|
||||
be corrected when the spec is next revised.
|
||||
connection pool). Decision: **keep** the check (a breaking public-API removal for no gain; small, unit-tested,
|
||||
a ready building block if a gRPC dependency ever needs a readiness probe) but document it as having no current
|
||||
consumers. SPEC §2.4/§6/§7, both READMEs and the shared-contract doc now say so.
|
||||
|
||||
## Deferred items — status from code (2026-11-09)
|
||||
|
||||
|
||||
@@ -40,8 +40,8 @@ below describe the original 2026-06 design rationale.
|
||||
writer wiring needed).
|
||||
- `IActiveNodeGate` seam — generalized from ScadaBridge's `ActiveNodeGate`; wired into `MapZbHealth`
|
||||
for automatic active-tier response.
|
||||
- `GrpcDependencyHealthCheck` — reachability probe for a downstream gRPC dependency (covers
|
||||
OtOpcUa → MxAccessGateway channel and MxAccessGateway → worker IPC).
|
||||
- `GrpcDependencyHealthCheck` — reachability probe for a downstream gRPC dependency. Shipped but
|
||||
**currently has no consumers** (neither OtOpcUa nor MxAccessGateway adopted it; scadaproj#28).
|
||||
- `AkkaClusterHealthCheck` (in `ZB.MOM.WW.Health.Akka`) with a configurable status policy.
|
||||
Default = ScadaBridge's three-way policy; `OtOpcUaCompat` preset preserves OtOpcUa's two-way
|
||||
self-Up-among-members scan.
|
||||
@@ -62,7 +62,7 @@ below describe the original 2026-06 design rationale.
|
||||
- MxAccessGateway's `GatewayHealthReply` metadata (`DefaultBackend`, `WorkerProtocolVersion`) —
|
||||
keep as a bespoke `/info` endpoint.
|
||||
- The x86 worker process — out of process and out of scope; the gateway-side
|
||||
`GrpcDependencyHealthCheck` observes it indirectly.
|
||||
no probe observes it directly (worker IPC is named pipes, not gRPC).
|
||||
|
||||
## Package structure
|
||||
|
||||
@@ -70,7 +70,7 @@ below describe the original 2026-06 design rationale.
|
||||
|
||||
| Package | Contents | Consumers |
|
||||
|---|---|---|
|
||||
| `ZB.MOM.WW.Health` | Core tiers, `MapZbHealth`, canonical writer, `IActiveNodeGate`, `GrpcDependencyHealthCheck` | All three |
|
||||
| `ZB.MOM.WW.Health` | Core tiers, `MapZbHealth`, canonical writer, `IActiveNodeGate`, `GrpcDependencyHealthCheck` (no consumers) | All three |
|
||||
| `ZB.MOM.WW.Health.Akka` | `AkkaClusterHealthCheck` + status presets, `ActiveNodeHealthCheck` + role filter | OtOpcUa, ScadaBridge |
|
||||
| `ZB.MOM.WW.Health.EntityFrameworkCore` | `DatabaseHealthCheck<TContext>` + optional probe delegate | OtOpcUa, ScadaBridge |
|
||||
|
||||
|
||||
@@ -31,8 +31,8 @@ into each app — there is no central health service. Consumers reference only w
|
||||
| `…Health.EntityFrameworkCore` | EF Core | — | ✅ | ✅ |
|
||||
|
||||
**Why MxGateway takes only core:** it is not Akka-based and does not use EF Core. The
|
||||
`GrpcDependencyHealthCheck` in the core package covers its only probe need (worker channel
|
||||
reachability), so it avoids the Akka and EF transitive trees entirely.
|
||||
Core is all it needs, so it avoids the Akka and EF transitive trees entirely. (An earlier draft said
|
||||
`GrpcDependencyHealthCheck` would cover a worker-channel probe; the worker IPC is named pipes, so no app uses it - scadaproj#28.)
|
||||
|
||||
## `ZB.MOM.WW.Health`
|
||||
|
||||
@@ -277,7 +277,7 @@ public sealed class DatabaseHealthCheckOptions<TContext>
|
||||
|
||||
| Consumer | Packages | Notes |
|
||||
|---|---|---|
|
||||
| **MxGateway** | `ZB.MOM.WW.Health` (core only) | `GrpcDependencyHealthCheck` on the worker channel; all three tiers via `MapZbHealth()`; `IActiveNodeGate` not needed (not Akka-based) |
|
||||
| **MxGateway** | `ZB.MOM.WW.Health` (core only) | no gRPC-dependency probe (worker IPC is named pipes); all three tiers via `MapZbHealth()`; `IActiveNodeGate` not needed (not Akka-based) |
|
||||
| **OtOpcUa** | All three | `AkkaClusterHealthCheck` + `OtOpcUaCompat` preset → `Default` on convergence; `ActiveNodeHealthCheck(role: "admin")`; `DatabaseHealthCheck<T>` with `ProbeQuery` delegate |
|
||||
| **ScadaBridge** | All three | `AkkaClusterHealthCheck` + `Default` policy; `ActiveNodeHealthCheck` (role-less); `DatabaseHealthCheck<T>` default probe; `AkkaActiveNodeGate` replaces inline `ActiveNodeGate` |
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ OtOpcUa and ScadaBridge; the `ClusterActiveNode` oldest-`Up`-member rule and the
|
||||
`OldestNodeActiveHealthCheck` — the two private replacements each app wrote after the original
|
||||
leader-based check proved wrong on a live rig; a generic
|
||||
`DatabaseHealthCheck<TContext>` that covers both apps' EF Core probe patterns; a
|
||||
`GrpcDependencyHealthCheck` for downstream gRPC reachability.
|
||||
`GrpcDependencyHealthCheck` for downstream gRPC reachability (shipped, currently no consumers - see §2.4).
|
||||
|
||||
**Explicitly NOT normalized** (domain-specific — keep per project): which probes each app
|
||||
registers and how it wires them to tags; orchestrator / Traefik routing rules and routing priorities;
|
||||
@@ -123,12 +123,17 @@ payload alone.
|
||||
|
||||
Checks that a downstream gRPC channel is reachable by invoking a caller-supplied probe
|
||||
delegate (`Func<GrpcChannel, CancellationToken, Task<bool>>`). The default probe calls
|
||||
`GrpcChannel.ConnectAsync`. Used by:
|
||||
`GrpcChannel.ConnectAsync`.
|
||||
|
||||
- OtOpcUa — checks the MxAccessGateway gRPC channel.
|
||||
- MxGateway — checks the x86 worker gRPC channel.
|
||||
**Current consumers: none** (verified 2026-11-09 against every app's default branch). Earlier drafts
|
||||
named OtOpcUa (MxAccessGateway channel) and MxGateway (x86 worker channel) as users, but neither adopted it:
|
||||
MxGateway's worker IPC is named pipes, not gRPC, and workers exist only per session; OtOpcUa creates its
|
||||
gateway channels per driver from DB config and deliberately keeps serving last-known-good when a source is
|
||||
down, so it does not gate readiness on them (see `GAPS.md`, "Downstream dependency probes"). The check is
|
||||
retained in the library as an available, unit-tested building block for a future gRPC dependency; it is not
|
||||
part of any app's convergence target.
|
||||
|
||||
Registered to the `ready` tag.
|
||||
If used, register it on the `ready` tag.
|
||||
|
||||
## 3. Response-writer contract
|
||||
|
||||
@@ -219,14 +224,14 @@ predicates and response writer.
|
||||
|---|---|---|---|
|
||||
| **OtOpcUa** | All three tiers present (`/health/ready`, `/health/active`, `/healthz`); `DatabaseHealthCheck`, `AkkaClusterHealthCheck`, `AdminRoleLeaderHealthCheck` inline. | Inline probes diverge from the shared policy model; no `IActiveNodeGate`. | Replace inline `AkkaClusterHealthCheck` with shared + `OtOpcUaCompat` preset; replace `AdminRoleLeaderHealthCheck` with shared `ActiveNodeHealthCheck(role: "admin")`; replace inline `DatabaseHealthCheck` with shared generic; call `app.MapZbHealth()`. |
|
||||
| **ScadaBridge** | `/health/ready` + `/health/active` present; no `/healthz`; `DatabaseHealthCheck`, `AkkaClusterHealthCheck`, `ActiveNodeHealthCheck`, `ActiveNodeGate` inline. | Missing `/healthz` live tier; inline implementations. | Add `/healthz` via `MapZbHealth()`; replace inline probes with shared equivalents (Default policy); replace inline `ActiveNodeGate` with `AkkaActiveNodeGate`. |
|
||||
| **MxGateway** | Only `/health/live` (custom `GatewayHealthReply`); `AddHealthChecks()` called but zero probes registered. | Missing `ready` and `active` tiers; no probes; not using standard health middleware. | Replace custom endpoint with `app.MapZbHealth()`; register `GrpcDependencyHealthCheck` for the x86 worker channel on the `ready` tag. |
|
||||
| **MxGateway** | Only `/health/live` (custom `GatewayHealthReply`); `AddHealthChecks()` called but zero probes registered. | Missing `ready` and `active` tiers; no probes; not using standard health middleware. | Replace custom endpoint with `app.MapZbHealth()`; no gRPC-dependency probe (the worker IPC is named pipes - see §2.4 / GAPS). |
|
||||
|
||||
## 7. Acceptance (what "converged" means)
|
||||
|
||||
A project is converged when: (a) it calls `app.MapZbHealth()` and exposes all three canonical
|
||||
endpoints; (b) its Akka probes (if applicable) use the `AkkaClusterHealthCheck` + `ActiveNodeHealthCheck`
|
||||
from `ZB.MOM.WW.Health.Akka` with the Default policy; (c) its DB probe uses `DatabaseHealthCheck<TContext>`
|
||||
from `ZB.MOM.WW.Health.EntityFrameworkCore`; (d) its gRPC-dependency probe (if applicable) uses
|
||||
from `ZB.MOM.WW.Health.EntityFrameworkCore`; (d) its gRPC-dependency probe (if it has one; none currently do) uses
|
||||
`GrpcDependencyHealthCheck`; (e) its `IActiveNodeGate` implementation is `AkkaActiveNodeGate`
|
||||
(or a project-specific implementation of the shared interface); (f) all health endpoints return the
|
||||
canonical JSON shape defined in §3.
|
||||
|
||||
Reference in New Issue
Block a user