Review remediation: Lane H2 — Historian remainder (opus; review opus) #746

Open
opened 2026-10-22 06:05:20 -04:00 by dohertj2 · 0 comments
Owner

From the 2026-10-21 Fable system review. Findings R0x:ID refer to docs/reviews/2026-10-21/0x-*.md (location, evidence, failure scenario, fix recipe). Plan: docs/superpowers/plans/2026-10-22-review-remediation.md.

Lane H2 — Historian remainder (opus; review opus)

Owns: src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.*/** (minus H1's files), Runtime/Historian/** (recorder + adapter), docs/Historian.md, the AdminUI historian backend picker.

  • Gateway events: drain to completion with a budget, cancellation arms (R08:1.2, 2.5).
  • Drop native TimeAverage/Total behind ServerHistorian:Gateway:EnableNativeTimeWeighted=false until historiangw#27 (2.1).
  • Capability matrix in docs + picker + a startup warning for continuous historization on Gateway (2.2).
  • ProbeAsync health timer (2.4).
  • Writers:
    • OCE rethrow in all three (4.1).
    • Gateway via LiveWritePreparer (4.2).
    • IHistorianValueWriter.FlushAsync pass-end hook, QuestDB WAL wait once per pass with exponential poll (3.1).
  • Batched alarm-history writers: SqlServer TVP + OUTPUT; QuestDb multi-row; Gateway bounded pipelining until a batch RPC (3.2).
  • Retention pre-filter (3.3).
  • QuestDB symbol indexes + migration (3.4).
  • Presence cache exact lookup (3.5).
  • Paged DeleteRaw (4.3).
  • QuestDB trail applied marker + DEDUP key (4.4).
  • Recorder: CommitMode=Periodic(100 ms) default + off-mailbox append with an in-flight cap + mailbox-depth metric (R02:P3); timeouts on GetStatus (R02:H3).
  • HistorianAdapterActor bounded channel + delete the senderless receive (R02:H4, U3).
  • Outbox scan outside the lock (R08:1.3).

Lane gate: Historian.Conformance green on all backends. The Wave 4 AVEVA live gate (userGate, existing recipe in .claude/rules/historian.md) checks events paging and that TimeAverage is refused.

Lane B2 — HistoryReadEvents full projection — folded into Lane H2 as its LAST task (opus; review fable)

This runs inside H2 because it shares the backends' event read paths with H2's Gateway events-drain fix. It runs after H2's other tasks, and OtOpcUaNodeManager.cs is free by then because B merged in Wave 1.
Adds to H2's ownership: the HistoricalEvent contract in Core.Abstractions and the HistoryReadEvents projection in OtOpcUaNodeManager.cs.

  • Carry EventType/ConditionName, map SourceNode when resolvable, and honour an OfType where-clause (R01:U1).
  • Test over the wire: a Client.CLI historyread --events with a select clause including EventType returns non-null values.
From the 2026-10-21 Fable system review. Findings `R0x:ID` refer to `docs/reviews/2026-10-21/0x-*.md` (location, evidence, failure scenario, fix recipe). Plan: `docs/superpowers/plans/2026-10-22-review-remediation.md`. ### Lane H2 — Historian remainder (opus; review opus) **Owns:** `src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.*/**` (minus H1's files), `Runtime/Historian/**` (recorder + adapter), `docs/Historian.md`, the AdminUI historian backend picker. - Gateway events: drain to completion with a budget, cancellation arms (`R08:1.2`, `2.5`). - Drop native `TimeAverage`/`Total` behind `ServerHistorian:Gateway:EnableNativeTimeWeighted=false` until historiangw#27 (`2.1`). - Capability matrix in docs + picker + a startup warning for continuous historization on Gateway (`2.2`). - `ProbeAsync` health timer (`2.4`). - Writers: - OCE rethrow in all three (`4.1`). - Gateway via `LiveWritePreparer` (`4.2`). - `IHistorianValueWriter.FlushAsync` pass-end hook, QuestDB WAL wait once per pass with exponential poll (`3.1`). - Batched alarm-history writers: SqlServer TVP + `OUTPUT`; QuestDb multi-row; Gateway bounded pipelining until a batch RPC (`3.2`). - Retention pre-filter (`3.3`). - QuestDB symbol indexes + migration (`3.4`). - Presence cache exact lookup (`3.5`). - Paged `DeleteRaw` (`4.3`). - QuestDB trail `applied` marker + DEDUP key (`4.4`). - Recorder: `CommitMode=Periodic(100 ms)` default + off-mailbox append with an in-flight cap + mailbox-depth metric (`R02:P3`); timeouts on `GetStatus` (`R02:H3`). - `HistorianAdapterActor` bounded channel + delete the senderless receive (`R02:H4`, `U3`). - Outbox scan outside the lock (`R08:1.3`). **Lane gate:** `Historian.Conformance` green on all backends. The Wave 4 AVEVA live gate (userGate, existing recipe in `.claude/rules/historian.md`) checks events paging and that `TimeAverage` is refused. ### Lane B2 — HistoryReadEvents full projection — folded into Lane H2 as its LAST task (opus; review fable) This runs inside H2 because it shares the backends' event read paths with H2's Gateway events-drain fix. It runs after H2's other tasks, and `OtOpcUaNodeManager.cs` is free by then because B merged in Wave 1. **Adds to H2's ownership:** the `HistoricalEvent` contract in Core.Abstractions and the HistoryReadEvents projection in `OtOpcUaNodeManager.cs`. - Carry `EventType`/`ConditionName`, map `SourceNode` when resolvable, and honour an `OfType` where-clause (`R01:U1`). - Test over the wire: a Client.CLI `historyread --events` with a select clause including EventType returns non-null values.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dohertj2/lmxopcua#746