HistoryRead returns BadHistoryOperationUnsupported when the historian backend is unreachable (should be a retryable communication status) #697

Closed
opened 2026-10-13 02:12:08 -04:00 by dohertj2 · 1 comment
Owner

Found by the #692–#694 live AVEVA gate (2026-10-13). A ~2 minute VPN drop hit one run. Pre-existing; affects every historian backend. Low/medium.

Symptom: while the backend (here the HistorianGateway → AVEVA path) is unreachable, HistoryRead Raw/Modified answers BadHistoryOperationUnsupported. That tells clients the node has no history at all and they should stop asking. The real condition is a transient outage they should retry (e.g. BadNoCommunication / BadServerNotConnected / BadCommunicationError, whichever matches the existing driver comms-loss contract).

Where: the generic exception handler on the raw and modified-read paths in OtOpcUaNodeManager maps any backend exception to BadHistoryOperationUnsupported. Check the AtTime / Processed / Events paths too.

Fix sketch:

  • Classify backend failures as transport/unavailable (RpcException Unavailable/DeadlineExceeded, SqlException connection errors, socket errors) versus genuinely unsupported.
  • Map transport/unavailable failures to a communication status.
  • Keep BadHistoryOperationUnsupported for real unsupported cases.
  • Test with each backend's fake throwing its real transport exception.

Check ScadaBridge's handling of history status codes before changing — consumer impact.

Evidence: scratchpad g692/l692-vpn-drop-0600Z.log.

Found by the #692–#694 live AVEVA gate (2026-10-13). A ~2 minute VPN drop hit one run. Pre-existing; affects every historian backend. Low/medium. **Symptom:** while the backend (here the HistorianGateway → AVEVA path) is unreachable, HistoryRead Raw/Modified answers `BadHistoryOperationUnsupported`. That tells clients the node has no history at all and they should stop asking. The real condition is a transient outage they should retry (e.g. `BadNoCommunication` / `BadServerNotConnected` / `BadCommunicationError`, whichever matches the existing driver comms-loss contract). **Where:** the generic exception handler on the raw and modified-read paths in `OtOpcUaNodeManager` maps any backend exception to `BadHistoryOperationUnsupported`. Check the AtTime / Processed / Events paths too. **Fix sketch:** - Classify backend failures as transport/unavailable (`RpcException` Unavailable/DeadlineExceeded, `SqlException` connection errors, socket errors) versus genuinely unsupported. - Map transport/unavailable failures to a communication status. - Keep `BadHistoryOperationUnsupported` for real unsupported cases. - Test with each backend's fake throwing its real transport exception. Check ScadaBridge's handling of history status codes before changing — consumer impact. Evidence: scratchpad `g692/l692-vpn-drop-0600Z.log`.
Author
Owner

Implemented actual transport-outage classification across Raw, Modified, Processed, AtTime and Events: BadNoCommunication. Gateway package/nested gRPC outages and SQL Server/QuestDB connection failures are wrapped consistently at the backend boundary. Unsupported operations retain BadHistoryOperationUnsupported; server cancellation retains BadTimeout. Tests check SDK service/result statuses, nested gRPC errors and repeated real refused database connections. ScadaBridge source/tests contain no HistoryRead consumer. Ready in the pushed branch; this issue closes when PR #699 merges.

Pushed commit 97668d26; PR: #699.

Full solution verified: 14,581 passed, 609 skipped, 0 failed across 62 suites (dotnet test ZB.MOM.WW.OtOpcUa.slnx --verbosity quiet, exit 0). Independent final review found no important defects. New fixes have not been deployed or live-tested end to end through OPC UA.

Implemented actual transport-outage classification across Raw, Modified, Processed, AtTime and Events: BadNoCommunication. Gateway package/nested gRPC outages and SQL Server/QuestDB connection failures are wrapped consistently at the backend boundary. Unsupported operations retain BadHistoryOperationUnsupported; server cancellation retains BadTimeout. Tests check SDK service/result statuses, nested gRPC errors and repeated real refused database connections. ScadaBridge source/tests contain no HistoryRead consumer. Ready in the pushed branch; this issue closes when PR #699 merges. Pushed commit `97668d26`; PR: https://gitea.dohertylan.com/dohertj2/lmxopcua/pulls/699. Full solution verified: 14,581 passed, 609 skipped, 0 failed across 62 suites (`dotnet test ZB.MOM.WW.OtOpcUa.slnx --verbosity quiet`, exit 0). Independent final review found no important defects. New fixes have not been deployed or live-tested end to end through OPC UA.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dohertj2/lmxopcua#697