sidecar: AahClientManagedAlarmEventWriter implements IAlarmEventWriter (PR C.1) #410

Merged
dohertj2 merged 1 commits from track-c1-aah-alarm-writer into master 2026-04-30 16:19:38 -04:00
Owner

Summary

Fourth PR of the alarms-over-gateway epic (docs/plans/alarms-over-gateway.md). Independent of Tracks A and B — the sidecar slot defined in HistorianFrameHandler.cs:242 (IAlarmEventWriter) is unwired today; PR C.2 (next) flips it on in Program.cs.

  • AlarmHistorianWriteOutcome (sidecar-local, net48 — twin of Core.AlarmHistorian.HistorianWriteOutcome which is net10): Ack / RetryPlease / PermanentFail.
  • IAlarmHistorianWriteBackend abstraction so the SDK call can be faked in unit tests.
  • AahClientManagedAlarmEventWriter implements IAlarmEventWriter, delegates to the backend, maps Ack→true / Retry|Permanent→false for the IPC bool[] reply contract. Backend exception → whole batch RetryPlease (preserves the sender's queue across transients rather than dropping). Wrong-count return defends against a backend bug desyncing queue accounting.
  • SdkAlarmHistorianWriteBackend — production binding skeleton. Reports RetryPlease for every event and logs a structured diagnostic until PR D.1 pins the live aahClientManaged entry point against the dev rig. The sender's SqliteStoreAndForwardSink retains queued events, mirroring today's NullAlarmHistorianSink behaviour but with visible diagnostics instead of silent discard.
  • MapOutcome shared helper — pinned via theory tests so the D.1 swap can change the SDK call site without reshuffling the HRESULT → outcome mapping.

Test plan

  • Sidecar builds clean (net48, x64)
  • 6 new writer tests — empty batch / single Ack / mixed Ack-Retry-Permanent-Ack ordering / backend-throw → RetryPlease batch / cancellation propagates / wrong-count defensive degrade
  • 5 new MapOutcome theory cases pin the HRESULT → outcome table
  • Full sidecar test suite: 48 passed (was 42; 11 new)

Follow-up

  • PR C.2 wires IAlarmEventWriter into Program.cs behind the OTOPCUA_HISTORIAN_ALARM_WRITE_ENABLED toggle.
  • PR D.1 pins the live aahClientManaged SDK entry point against the dev rig — only changes the body of SdkAlarmHistorianWriteBackend.WriteBatchAsync.
## Summary Fourth PR of the **alarms-over-gateway** epic (docs/plans/alarms-over-gateway.md). Independent of Tracks A and B — the sidecar slot defined in `HistorianFrameHandler.cs:242` (IAlarmEventWriter) is unwired today; PR C.2 (next) flips it on in Program.cs. - **AlarmHistorianWriteOutcome** (sidecar-local, net48 — twin of `Core.AlarmHistorian.HistorianWriteOutcome` which is net10): Ack / RetryPlease / PermanentFail. - **IAlarmHistorianWriteBackend** abstraction so the SDK call can be faked in unit tests. - **AahClientManagedAlarmEventWriter** implements `IAlarmEventWriter`, delegates to the backend, maps Ack→true / Retry|Permanent→false for the IPC `bool[]` reply contract. Backend exception → whole batch RetryPlease (preserves the sender's queue across transients rather than dropping). Wrong-count return defends against a backend bug desyncing queue accounting. - **SdkAlarmHistorianWriteBackend** — production binding skeleton. Reports RetryPlease for every event and logs a structured diagnostic until PR D.1 pins the live aahClientManaged entry point against the dev rig. The sender's SqliteStoreAndForwardSink retains queued events, mirroring today's NullAlarmHistorianSink behaviour but with visible diagnostics instead of silent discard. - **MapOutcome** shared helper — pinned via theory tests so the D.1 swap can change the SDK call site without reshuffling the HRESULT → outcome mapping. ## Test plan - [x] Sidecar builds clean (net48, x64) - [x] 6 new writer tests — empty batch / single Ack / mixed Ack-Retry-Permanent-Ack ordering / backend-throw → RetryPlease batch / cancellation propagates / wrong-count defensive degrade - [x] 5 new MapOutcome theory cases pin the HRESULT → outcome table - [x] Full sidecar test suite: 48 passed (was 42; 11 new) ## Follow-up - **PR C.2** wires `IAlarmEventWriter` into `Program.cs` behind the `OTOPCUA_HISTORIAN_ALARM_WRITE_ENABLED` toggle. - **PR D.1** pins the live `aahClientManaged` SDK entry point against the dev rig — only changes the body of `SdkAlarmHistorianWriteBackend.WriteBatchAsync`.
dohertj2 added 1 commit 2026-04-30 16:19:29 -04:00
Fourth PR of the alarms-over-gateway epic
(docs/plans/alarms-over-gateway.md). Independent of Tracks A and B —
the sidecar slot defined in HistorianFrameHandler line 242 is unwired
today; PR C.2 (next) flips it on in Program.cs.

- AlarmHistorianWriteOutcome (sidecar-local, net48 — twin of
  Core.AlarmHistorian.HistorianWriteOutcome which is net10): Ack /
  RetryPlease / PermanentFail.
- IAlarmHistorianWriteBackend abstraction so the SDK call can be
  faked in unit tests.
- AahClientManagedAlarmEventWriter implements IAlarmEventWriter,
  delegates to the backend, maps Ack→true / Retry|Permanent→false
  for the IPC bool[] reply contract. Backend exception → whole
  batch RetryPlease (preserves the sender's queue across transients
  rather than dropping). Wrong-count return defends against a
  backend bug desyncing queue accounting.
- SdkAlarmHistorianWriteBackend — production binding skeleton.
  Reports RetryPlease for every event and logs a structured
  diagnostic until PR D.1 pins the live aahClientManaged entry
  point against the dev rig. The sender's SqliteStoreAndForwardSink
  retains queued events, mirroring today's NullAlarmHistorianSink
  behaviour but with visible diagnostics instead of silent discard.
- MapOutcome shared helper — pinned via theory tests so the D.1
  swap can change the SDK call site without reshuffling the
  HRESULT → outcome mapping.

Tests:
- 6 writer tests — empty batch / single Ack / mixed Ack-Retry-
  Permanent-Ack ordering / backend-throw → RetryPlease batch /
  cancellation propagates / wrong-count defensive degrade.
- 5 outcome theory cases — hresult 0 → Ack, malformed wins over
  hresult 0, comm error → Retry, unknown failure → Retry,
  malformed + comm → Permanent.
- Full sidecar test suite: 48 passed (was 42; 6 new).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
dohertj2 merged commit 8a4526a376 into master 2026-04-30 16:19:38 -04:00
dohertj2 deleted branch track-c1-aah-alarm-writer 2026-04-30 16:19:39 -04:00
Sign in to join this conversation.