feat(historian-sidecar): live aahClientManaged alarm-event write path (C.1)

SdkAlarmHistorianWriteBackend.WriteBatchAsync replaces the RetryPlease
placeholder with the real entry point — HistorianAccess.AddStreamedValue
(HistorianEvent, out HistorianAccessError) in aahClientManaged, pinned by
decompiling the installed SDK.

The write path opens its own ReadOnly=false connection: the query-side
HistorianDataSource opens ReadOnly sessions and AddStreamedValue fails on
those with WriteToReadOnlyFile. IHistorianConnectionFactory gains a readOnly
parameter (default true, query path unchanged); BuildConnectionArgs is
extracted as a pure helper. HistorianClusterEndpointPicker is shared for
node failover; connection-class errors abort the batch as RetryPlease and
reset the connection, malformed-input codes map to PermanentFail.

Tests: connection-unavailable batch deferral, ClassifyOutcome error-code
table, BuildConnectionArgs read-vs-write shaping (80 pass, 2 rig-skipped).
Live_* round-trip tests stay Skip-gated for the D.1 rollout smoke.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Joseph Doherty
2026-05-18 16:08:32 -04:00
parent 419eda256b
commit cd2306db66
6 changed files with 544 additions and 142 deletions

View File

@@ -16,11 +16,14 @@ remains, plus follow-ups surfaced during the run.
## Follow-ups surfaced during the run
- **C.1 live SDK binding.** `SdkAlarmHistorianWriteBackend.WriteBatchAsync`
(`src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Backend/`) is
still a placeholder returning `RetryPlease` for every event, so queued
alarm events are retained rather than written. Pinning the real
`aahClientManaged` alarm-write entry point is rig-gated — pairs with #20.
- **~~C.1 live SDK binding.~~** DONE (code). `SdkAlarmHistorianWriteBackend`
(`src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Backend/`) now
writes via the real entry point `HistorianAccess.AddStreamedValue(HistorianEvent,
out error)` in `aahClientManaged`. Two plan corrections found while pinning it:
(a) `ArchestrAAlarmsAndEvents.SDK` has no writer — it's a WCF query proxy;
(b) writes need their own `ReadOnly=false` connection, not the shared read
pool. Remaining: the live-rig write smoke (the `Live_*` tests are still
`Skip`-gated) — folds into #20 / D.1.
- **~~#24 Shelve-method routing.~~** DONE. Acknowledge / Confirm already
routed; OneShotShelve / TimedShelve / Unshelve now route via the native