sidecar: wire IAlarmEventWriter into Program.cs (PR C.2) #411

Merged
dohertj2 merged 1 commits from track-c2-program-wires-alarm-writer into master 2026-04-30 16:22:39 -04:00
Owner

Summary

Fifth PR of the alarms-over-gateway epic (docs/plans/alarms-over-gateway.md). Depends on PR C.1 (#410, merged).

Today HistorianFrameHandler is constructed at Program.cs:57 without an alarmWriter, so every WriteAlarmEvents frame replies "Sidecar not configured with an alarm-event writer" and the lmxopcua side keeps the row queued. This PR wires a real writer behind a new OTOPCUA_HISTORIAN_ALARM_WRITE_ENABLED toggle.

  • Program.BuildAlarmWriter — env-gated (default true; fail-open under accidental misconfiguration). Constructs an AahClientManagedAlarmEventWriter wrapping a SdkAlarmHistorianWriteBackend with the same connection config the read path uses.
  • Install-Services.ps1 — appends OTOPCUA_HISTORIAN_ALARM_WRITE_ENABLED=true to the OtOpcUaWonderwareHistorian service env block. Read-only deployments flip it to false at service-config edit time without re-installing.
  • HistorianFrameHandler signature already accepts IAlarmEventWriter? — supplying non-null at line 57 lights up the WriteAlarmEvents reply path that's been dormant since PR 3.3.

Until PR D.1 pins the live aahClientManaged entry point, the SdkAlarmHistorianWriteBackend reports RetryPlease for every event with a structured diagnostic. The lmxopcua-side SqliteStoreAndForwardSink retains queued events — same effective behaviour as today's NullAlarmHistorianSink fallback but with visible diagnostics rather than silent discard.

Test plan

  • Sidecar builds clean (net48, x64)
  • 6 new BuildAlarmWriter env-var tests — unset / true / false / unrecognized / capitalization variants
  • Full sidecar test suite: 56 passed (was 48; 8 new)

Follow-up

  • PR B.4 — lmxopcua-side SidecarAlarmHistorianWriter (the IAlarmHistorianWriter consumer that drives WriteAlarmEvents frames now that the slot replies real outcomes).
  • PR D.1 — pins the live aahClientManaged write API and refreshes C:\publish services.
## Summary Fifth PR of the **alarms-over-gateway** epic (docs/plans/alarms-over-gateway.md). Depends on PR C.1 (#410, merged). Today HistorianFrameHandler is constructed at `Program.cs:57` without an `alarmWriter`, so every WriteAlarmEvents frame replies "Sidecar not configured with an alarm-event writer" and the lmxopcua side keeps the row queued. This PR wires a real writer behind a new `OTOPCUA_HISTORIAN_ALARM_WRITE_ENABLED` toggle. - `Program.BuildAlarmWriter` — env-gated (default true; fail-open under accidental misconfiguration). Constructs an `AahClientManagedAlarmEventWriter` wrapping a `SdkAlarmHistorianWriteBackend` with the same connection config the read path uses. - `Install-Services.ps1` — appends `OTOPCUA_HISTORIAN_ALARM_WRITE_ENABLED=true` to the OtOpcUaWonderwareHistorian service env block. Read-only deployments flip it to false at service-config edit time without re-installing. - `HistorianFrameHandler` signature already accepts `IAlarmEventWriter?` — supplying non-null at line 57 lights up the WriteAlarmEvents reply path that's been dormant since PR 3.3. Until **PR D.1** pins the live aahClientManaged entry point, the `SdkAlarmHistorianWriteBackend` reports RetryPlease for every event with a structured diagnostic. The lmxopcua-side `SqliteStoreAndForwardSink` retains queued events — same effective behaviour as today's NullAlarmHistorianSink fallback but with visible diagnostics rather than silent discard. ## Test plan - [x] Sidecar builds clean (net48, x64) - [x] 6 new `BuildAlarmWriter` env-var tests — unset / true / false / unrecognized / capitalization variants - [x] Full sidecar test suite: 56 passed (was 48; 8 new) ## Follow-up - **PR B.4** — lmxopcua-side `SidecarAlarmHistorianWriter` (the `IAlarmHistorianWriter` consumer that drives WriteAlarmEvents frames now that the slot replies real outcomes). - **PR D.1** — pins the live aahClientManaged write API and refreshes `C:\publish` services.
dohertj2 added 1 commit 2026-04-30 16:22:35 -04:00
Fifth PR of the alarms-over-gateway epic
(docs/plans/alarms-over-gateway.md). Depends on PR C.1
(AahClientManagedAlarmEventWriter), already merged.

Today HistorianFrameHandler is constructed at Program.cs line 57
without an alarmWriter, so every WriteAlarmEvents frame replies
"Sidecar not configured with an alarm-event writer" and the lmxopcua
side keeps the row queued. C.2 wires a real writer behind a new
OTOPCUA_HISTORIAN_ALARM_WRITE_ENABLED toggle.

- Program.BuildAlarmWriter — gated on the env var (default true,
  fail-open under accidental misconfiguration). Constructs an
  AahClientManagedAlarmEventWriter wrapping a
  SdkAlarmHistorianWriteBackend with the same connection config the
  read path uses.
- Install-Services.ps1 — appends OTOPCUA_HISTORIAN_ALARM_WRITE_ENABLED=true
  to the OtOpcUaWonderwareHistorian service env block when the
  sidecar is installed. Read-only deployments flip it to false at
  service-config edit time without re-installing.
- HistorianFrameHandler signature already accepts
  IAlarmEventWriter? — supplying non-null at line 57 lights up
  the WriteAlarmEvents reply path that's been dormant since PR 3.3.

Until PR D.1 pins the live aahClientManaged entry point, the
SdkAlarmHistorianWriteBackend reports RetryPlease for every event
with a structured diagnostic. The lmxopcua-side
SqliteStoreAndForwardSink retains queued events; same effective
behaviour as today's NullAlarmHistorianSink fallback but with
visible diagnostics rather than silent discard.

Tests:
- 6 BuildAlarmWriter env-var cases — unset / true / false /
  unrecognized → default-on / capitalization variants.
- Full sidecar test suite: 56 passed (was 48; 8 new).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
dohertj2 merged commit f67b3b1b30 into master 2026-04-30 16:22:39 -04:00
dohertj2 deleted branch track-c2-program-wires-alarm-writer 2026-04-30 16:22:39 -04:00
Sign in to join this conversation.