Server never dispatches HistoryRead to a driver's IHistoryProvider #655

Closed
opened 2026-10-08 20:51:44 -04:00 by dohertj2 · 1 comment
Owner

Found in the #649 review (batch b647). OtOpcUaNodeManager serves HistoryRead only from the server-wide IHistorianDataSource (gateway or Null); nothing routes a HistoryRead for a raw/UNS node to the owning driver's IHistoryProvider capability. So driver-side history (e.g. OpcUaClient ExecuteHistoryReadAsync, fixed in #649) is reachable only from tests — no OPC UA client can read an upstream server's history through OtOpcUa today.

Decide: (a) wire a per-node dispatch (historized-by-driver nodes → driver capability, others → historian source), incl. excluding refusals (HistoryAggregateNotSupportedException / HistoryReadStatusException) from the retry/breaker pipeline, or (b) declare driver history out of scope and delete the dead capability. docs/drivers/OpcUaClient.md already states the fix is latent.

Found in the #649 review (batch b647). `OtOpcUaNodeManager` serves HistoryRead only from the server-wide `IHistorianDataSource` (gateway or Null); nothing routes a HistoryRead for a raw/UNS node to the owning driver's `IHistoryProvider` capability. So driver-side history (e.g. OpcUaClient `ExecuteHistoryReadAsync`, fixed in #649) is reachable only from tests — no OPC UA client can read an upstream server's history through OtOpcUa today. Decide: (a) wire a per-node dispatch (historized-by-driver nodes → driver capability, others → historian source), incl. excluding refusals (`HistoryAggregateNotSupportedException` / `HistoryReadStatusException`) from the retry/breaker pipeline, or (b) declare driver history out of scope and delete the dead capability. docs/drivers/OpcUaClient.md already states the fix is latent.
dohertj2 added the driver/opcuaclient label 2026-10-08 20:51:44 -04:00
Author
Owner

Resolved by deletion on master — merge 862d8a75 (commits f7d497e5, f7f7d948, 67059e47), pushed 2026-10-09.

Nothing ever dispatched HistoryRead to a driver, so the dead surface is removed rather than wired: IHistoryProvider, the OpcUaClient history passthrough, DriverCapability.HistoryRead (resilience tier + AdminUI row), HistoryReadStatusException and the node-manager catches. HistoryRead stays served only by the server-wide IHistorianDataSource (HistorianGateway); client-visible results are unchanged (rig smoke before/after identical). A stored ResilienceConfig with a HistoryRead key still parses (diagnostic only). isHistorized on an OpcUaClient tag means OtOpcUa records it, not that upstream history is proxied.

Also: Client.Shared DefaultSessionAdapter now surfaces a Bad HistoryRead status as an error (BadNoData excepted) instead of "0 values returned". Docs: OPC-009, OpcUaClient, OpcUaServer, Client.CLI, CLAUDE.md.

Resolved by deletion on master — merge `862d8a75` (commits `f7d497e5`, `f7f7d948`, `67059e47`), pushed 2026-10-09. Nothing ever dispatched HistoryRead to a driver, so the dead surface is removed rather than wired: `IHistoryProvider`, the OpcUaClient history passthrough, `DriverCapability.HistoryRead` (resilience tier + AdminUI row), `HistoryReadStatusException` and the node-manager catches. HistoryRead stays served only by the server-wide `IHistorianDataSource` (HistorianGateway); client-visible results are unchanged (rig smoke before/after identical). A stored `ResilienceConfig` with a `HistoryRead` key still parses (diagnostic only). `isHistorized` on an OpcUaClient tag means OtOpcUa records it, not that upstream history is proxied. Also: Client.Shared `DefaultSessionAdapter` now surfaces a Bad HistoryRead status as an error (BadNoData excepted) instead of "0 values returned". Docs: OPC-009, OpcUaClient, OpcUaServer, Client.CLI, CLAUDE.md.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dohertj2/lmxopcua#655