Files
lmxopcua/docs/plans
Joseph Doherty 124de57e6f docs(localdb): phase-2 recon findings
Answers Task 0 with file:line citations against master 2e46d054.

The STOP condition does not fire: PayloadJson is TEXT, no BLOB column, so
alarm_sf_events can be registered for replication as-is.

Two findings reshape the plan's assumptions:

- The drain worker is not a hosted service or an actor. It is a
  self-rescheduling Timer owned by the sink and started from the DI
  factory, so the Primary gate has to live inside DrainOnceAsync as an
  injected delegate -- Core.AlarmHistorian cannot reference
  PrimaryGatePolicy, which lives in Runtime.

- A Primary gate already exists on the enqueue side
  (HistorianAdapterActor.ShouldHistorize), using a different policy than
  the one the plan specifies for the drain. That gate is why today's
  ungated drain is safe: the Secondary never enqueues, so its queue is
  empty. Replicating the table breaks that invariant, which makes the
  drain gate mandatory in the same commit rather than a refinement.

Records deviations D-1 (deterministic content-hash ids so a boot-window
double-enqueue converges instead of duplicating), D-2 (gate denial must be
observable or a snapshot identity mismatch silently stops alarm history),
D-3 (Tasks 2+3 land as one commit) and D-4 (the rig will dead-letter in
~5 minutes at MaxAttempts 10 with no gateway).

Claude-Session: https://claude.ai/code/session_01GASWkNEi68FSCtvr6rLoEW
2026-07-21 03:56:06 -04:00
..