Merge hw3-alarms (#656 atomic ActiveAcknowledged + re-statement flag for native alarms)

Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
This commit is contained in:
Joseph Doherty
2026-10-09 00:14:47 -04:00
20 changed files with 1006 additions and 84 deletions
+2
View File
@@ -94,6 +94,8 @@ Full per-field descriptions live in `Config/GalaxyDriverOptions.cs`. The full JS
The session-less alarm feed (`GatewayGalaxyAlarmFeed`) and alarm acknowledger (`GatewayGalaxyAlarmAcknowledger`) run on a separate always-on `_ownedMxClient` that is intentionally **not** recreated when `ReconnectSupervisor` rebuilds the worker session. The feed has its own re-invoke loop (~5 s backoff) that reopens `StreamAlarms` after any stream fault, and gRPC.NET's channel auto-reconnect recovers the underlying HTTP/2 connection after a gateway restart — so both the alarm stream and individual ack calls recover without client replacement. The acknowledger is completely stateless between calls: each `AcknowledgeAsync` issues a single unary RPC and returns; no dead-client state is latched on failure. Channel-level keepalive hardening (TCP keep-alive intervals, gRPC ping frames) would require exposing additional knobs on `MxGatewayClientOptions` in the sibling `mxaccessgw` repo — a future option if flaky long-lived connections are observed in production.
Every (re)open of `StreamAlarms` replays the gateway's active-alarm snapshot. `GatewayGalaxyAlarmFeed` maps each entry to a transition flagged `IsRestatement` (#656): `Active` → `Retrigger` (upstream's unack is authoritative), `ActiveAcked` → `ActiveAcknowledged` (one atomic active+acked projection — the old `Acknowledge` mapping projected an acked alarm **inactive** on a cold host), `Inactive` → `Clear`. The host writes no `/alerts` row for a replayed entry that changes nothing the condition shows, so a gateway reconnect no longer duplicates history; live `Transition` messages are never flagged. The gateway folds UnackRtn and AckRtn into `Inactive`, so an inactive-unacked alarm cannot be distinguished at reconnect (gateway contract limit).
## Testing
- **Unit tests**: `tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Tests/` — fakes the gateway gRPC surface; covers Browse, Runtime, Health, and Config in isolation.