9cbe65c844
Audited the registration and mapping code of each app at its origin default branch: OtOpcUa c904472a, MxAccessGateway de86f8b8, ScadaBridge c7d868c5, HistorianGateway 4d6a9ad (all on Health 0.3.0, all MapZbHealth with default paths: /healthz runs nothing, /health/ready and /health/active by tag). GAPS.md now carries the verified per-endpoint coverage matrix and a SPEC-by-app table; each current-state doc lists exactly what each endpoint runs, and HistorianGateway gets its first current-state doc. Recorded: mxaccessgw#206 (worker-executable + galaxy-sql readiness checks, on /health/ready) is merged; historiangw#87 (session-pool check latches 503 until restart) is still open at 4d6a9ad. Deferred P2 downstream probes are now per-app; ScadaBridge IActiveNodeGate unification stays deferred (shared rule already used, only the interface is local). Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
69 lines
4.4 KiB
Markdown
69 lines
4.4 KiB
Markdown
# Health — current state: MxAccessGateway
|
|
|
|
**Verified 2026-11-09 at `mxaccessgw@de86f8b8` (`origin/main`)** for scadaproj#11. Read-only `git grep` /
|
|
`git show` against the origin default branch; all paths relative to the repo root
|
|
(`~/Desktop/MxAccessGateway`). The pre-adoption state (verified 2026-06-01: a hardcoded `/health/live`
|
|
`MapGet`, a dead `AddHealthChecks()`, no probes) is gone; see git history of this file.
|
|
|
|
- **Package:** `ZB.MOM.WW.Health` **0.3.0**, core only (`src/ZB.MOM.WW.MxGateway.Server/ZB.MOM.WW.MxGateway.Server.csproj:20`).
|
|
No `.Akka`, no `.EntityFrameworkCore` — the gateway has no Akka cluster and no EF context.
|
|
- **Registration:** `builder.Services.AddGatewayHealthChecks()` (`GatewayApplication.cs:118`) →
|
|
`src/ZB.MOM.WW.MxGateway.Server/Diagnostics/GatewayHealthCheckExtensions.cs:19-41`.
|
|
- **Mapping:** `endpoints.MapZbHealth()` with default paths/writer (`GatewayApplication.cs:346`),
|
|
anonymous unconditionally (the Overview dashboard polls `/health/active` without credentials).
|
|
|
|
## Per-endpoint contents
|
|
|
|
| Endpoint | Checks run | Can return 503 when |
|
|
|---|---|---|
|
|
| `/healthz` (live) | none (`_ => false`) | never (process up) |
|
|
| `/health/ready` | `auth-store`, `worker-executable`, `galaxy-sql` | auth SQLite unreachable; worker exe missing; Galaxy SQL unreachable or > 5 s |
|
|
| `/health/active` | `mxaccess-sessions` | every open session is `Faulted` (zero sessions = Healthy) |
|
|
|
|
No check is tagged `live` (asserted by `GatewayHealthCheckRegistrationTests`).
|
|
|
|
## Checks
|
|
|
|
All registered with `AddTypeActivatedCheck`, `failureStatus: null` (the check's own status is used).
|
|
Files under `src/ZB.MOM.WW.MxGateway.Server/Diagnostics/`.
|
|
|
|
| Name | Class | Tag | Probes | Failure |
|
|
|---|---|---|---|---|
|
|
| `auth-store` | `AuthStoreHealthCheck` | ready | Opens the API-key SQLite store via `AuthSqliteConnectionFactory`, runs `SELECT 1` | Unhealthy |
|
|
| `worker-executable` | `WorkerExecutableHealthCheck` | ready | `File.Exists(Path.GetFullPath(MxGateway:Worker:ExecutablePath))` — same resolution as `WorkerProcessLauncher.ResolveExecutablePath` | Unhealthy (missing or invalid path) |
|
|
| `galaxy-sql` | `GalaxySqlHealthCheck` | ready | `IGalaxyRepository.TestConnectionAsync` bounded by a 5 s `TimeProvider` timeout | Unhealthy (false, throw, or timeout) |
|
|
| `mxaccess-sessions` | `SessionHealthCheck` | active | Buckets `ISessionRegistry.Snapshot()` by state; `data` = total/ready/faulted/starting/closing | Healthy if 0 faulted (incl. 0 sessions); Degraded if some faulted; Unhealthy if all usable sessions faulted |
|
|
|
|
`worker-executable` and `galaxy-sql` are new on `main` `8c21678c` (mxaccessgw#206, closed 2026-11-09).
|
|
They check that the worker **binary exists** and that **Galaxy SQL answers**; neither checks a running
|
|
worker or the named-pipe IPC (workers are per-session and only exist while a client holds a session).
|
|
No LDAP check was added (#206 comment: deliberately out of scope).
|
|
|
|
`galaxy-sql` is unconditional: `AddZbGalaxyRepository` is always registered (`GatewayApplication.cs:167`),
|
|
so a gateway whose Galaxy SQL is down drops out of readiness even though its MXAccess data path does not
|
|
use SQL. That is the #206 design ("must take the gateway out of rotation"), not an accident.
|
|
|
|
## Active-node gating
|
|
|
|
None. The gateway is a singleton per host (no cluster), registers no `IActiveNodeGate`, and uses no
|
|
`RequireActiveNode()`. The `active` tier is used for a **session-health** signal instead of an
|
|
active/standby signal, so every gateway answers 200 on `/health/active` unless all its sessions are
|
|
faulted.
|
|
|
|
## Other endpoints
|
|
|
|
`MapZbMetrics()` (`:347`, anonymous by default, see `MetricsOptions`), `MapZbGalaxyRepository()` (`:359`),
|
|
dashboard routes. No bespoke health endpoint remains.
|
|
|
|
## vs SPEC
|
|
|
|
| SPEC | Status | Note |
|
|
|---|---|---|
|
|
| §1 three tiers via `MapZbHealth`, canonical tags | ✅ | default paths |
|
|
| §1 nothing on `live` | ✅ | test-asserted |
|
|
| §2.1 `DatabaseHealthCheck<T>` | n/a | no EF; custom SQLite + Galaxy SQL checks |
|
|
| §2.3 active tier = oldest `Up` member | 🟡 deviation | no cluster; active tier carries `mxaccess-sessions` (deliberate, documented in `SessionHealthCheck`) |
|
|
| §2.4 `GrpcDependencyHealthCheck` for the worker | ⛔ not used | worker IPC is named pipes, not gRPC; `worker-executable` is a presence proxy (see GAPS P2) |
|
|
| §3 canonical JSON writer | ✅ | `MapZbHealth` default |
|
|
| §4 `IActiveNodeGate` | n/a | no active/standby |
|