docs(c2): record WCF event-read spike live result (RED — transport not served on 2023 R2)
WCF net.tcp (RemoteTcpIntegrated) against the live 2023 R2 historian is reset
at the socket-write/framing layer before any auth — both the event spike and a
basic Probe/ReadRaw throw the identical CommunicationException/SocketException
("forcibly closed by the remote host"). The 2023 R2 box does not serve the
legacy WCF transport; C2's "route via WCF" unblock is moot on this server class.
Sanitized: counts + native return codes + buffer lengths only.
Claude-Session: https://claude.ai/code/session_012SDSQ3AcaXqPcBtDESBRii
This commit is contained in:
@@ -0,0 +1,63 @@
|
|||||||
|
# WCF event-read spike — live result (2026-06-25): WCF transport not served on 2023 R2
|
||||||
|
|
||||||
|
Settles the open question behind **C2** ("event reads over gRPC are gated; the only listed unblock is
|
||||||
|
*route event reads via WCF*"). The gRPC event-read path is a proven server-side dead-end
|
||||||
|
(`grpc-event-query-capture.md`: auth fully solved, every client-controllable layer byte-matched to the
|
||||||
|
stock client, yet the server scopes 0 rows to our connection). This spike tested the **WCF** leg.
|
||||||
|
|
||||||
|
## What was run
|
||||||
|
|
||||||
|
A Windows-only, env-gated diagnostic (`tests/AVEVA.Historian.Client.Tests/WcfEventReadSpikeTests.cs`,
|
||||||
|
gated by `HISTORIAN_WCF_EVENT_HOST`) drove `HistorianWcfEventOrchestrator.ReadEventsAsync` directly
|
||||||
|
over `RemoteTcpIntegrated` (WCF `net.tcp`, port 32568) against the **live 2023 R2 historian**, with a
|
||||||
|
−90d window (the engine holds tens of thousands of events in that range), run from the native Windows
|
||||||
|
capture rig over VPN. Auth supplied as explicit domain credentials (consumed by the app-level
|
||||||
|
`ValidateClientCredential` SSPI rounds).
|
||||||
|
|
||||||
|
## Result — RED (transport not served), sanitized
|
||||||
|
|
||||||
|
Event spike:
|
||||||
|
|
||||||
|
| field | value |
|
||||||
|
|---|---|
|
||||||
|
| outcome | `THREW System.ServiceModel.CommunicationException` ("The socket connection was aborted") |
|
||||||
|
| inner | `System.Net.Sockets.SocketException` — "An existing connection was forcibly closed by the remote host" |
|
||||||
|
| events observed | 0 |
|
||||||
|
| LastUpdC3ReturnCode / LastRTag2ReturnCode / LastAddReturnCode(EnsT2) | 0 / 0 / 0 |
|
||||||
|
| LastEnsT2PayloadSha256 | empty |
|
||||||
|
| LastResultBufferLength | 0 |
|
||||||
|
|
||||||
|
All native return codes are `0` and the EnsT2 payload sha256 is empty: the chain failed at the **first
|
||||||
|
WCF call** (`GetInterfaceVersion`), *before* any auth token round or CM_EVENT registration ran.
|
||||||
|
|
||||||
|
Corroboration — a basic (non-event) `RemoteTcpIntegrated` `ProbeAsync` + `ReadRawAsync` (the committed
|
||||||
|
`RemoteTcpIntegrationTests`) throws the **identical** exception, with the stack landing in
|
||||||
|
`System.ServiceModel.Channels.SocketConnection.WriteAsync` — i.e. the failure is **transport-wide**, not
|
||||||
|
event-specific, and not auth-specific (it never reaches auth).
|
||||||
|
|
||||||
|
Phase 0 (reachability) had confirmed TCP 32568 is **open** (the connect succeeds). So the port accepts a
|
||||||
|
socket, but the moment the SDK writes its `net.tcp` binary-SOAP framing the server **resets the
|
||||||
|
connection** (RST at the socket-write layer).
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
The **2023 R2 historian does not serve the legacy WCF NetTcp transport.** A raw RST at the first socket
|
||||||
|
write — before any security negotiation, SOAP fault, or auth exchange — is the signature of a listener
|
||||||
|
that does not speak `net.tcp` binary SOAP, not of an auth/SPN problem or event-row scoping. (The earlier
|
||||||
|
WCF event-chain native return codes 76/85 documented in `HistorianWcfEventOrchestrator` were only ever
|
||||||
|
observed against a **2020** historian; against 2023 R2 there is no WCF endpoint to reach at all.)
|
||||||
|
|
||||||
|
Therefore **C2's "route event reads via WCF" unblock is moot on 2023 R2** — there is no WCF endpoint to
|
||||||
|
route to. Event reads are unavailable on the 2023 R2 historian over **both** transports:
|
||||||
|
|
||||||
|
- **gRPC** — auth-solved but retrieval-server-gated (server scopes 0 rows to our connection;
|
||||||
|
`grpc-event-query-capture.md`).
|
||||||
|
- **WCF (`net.tcp`)** — transport not served on 2023 R2 (connection reset at framing).
|
||||||
|
|
||||||
|
The WCF event-read managed path would only ever apply to a legacy **2020** historian, which the gateway
|
||||||
|
does not target (the gateway runs `RemoteGrpc` against 2023 R2). The only remaining theoretical unblock
|
||||||
|
is server-side (AVEVA exposing event-row retrieval to a managed gRPC connection) — not client-fixable.
|
||||||
|
|
||||||
|
**C2 is closed won't-fix** for the gateway's target (2023 R2). `ReadEventsAsync` over gRPC keeps its
|
||||||
|
honest no-row throw; the gating messages are corrected so they no longer point operators at the WCF
|
||||||
|
transport as a live fallback on 2023 R2.
|
||||||
Reference in New Issue
Block a user