docs(c2): record 2020-vs-2023R2 positive control for the event-read server gate
Adds the positive control that the prior C2 evidence lacked. The SAME native WCF event-read client returns real events (5) from a local AVEVA Historian 2020 but 0 from the 2023 R2 server over the identical sequence and window, while both boxes hold tens of thousands of events in SQL — isolating the zero-rows to the 2023 R2 server, not the client, protocol, or serializers. - wcf-event-read-spike-results.md: new "2026-06-26 positive control" section (2020 vs 2023 R2 A/B from one WCF client; stock-2020-client version-self-block caveat; stock-2023R2 gRPC cross-check). - grpc-event-query-capture.md: re-control note — the 2026-06-22 stock 50-row capture did NOT reproduce; the stock 2023 R2 client now also returns 0 rows. - HistorianGrpcIntegrationTests: correct the stale "capture-gated, NOT server-gated" comment to the server-gate conclusion backed by the controls. Sanitized throughout (counts, native return codes, buffer lengths only). Claude-Session: https://claude.ai/code/session_012SDSQ3AcaXqPcBtDESBRii
This commit is contained in:
@@ -517,19 +517,26 @@ public sealed class HistorianGrpcIntegrationTests
|
||||
}
|
||||
|
||||
// Plan #2: ReadEvents over gRPC. The chain runs end-to-end and StartEventQuery succeeds
|
||||
// (no InvalidOperationException), but — confirmed live 2026-06-22 — GetNextEventQueryResultBuffer
|
||||
// LONG-POLLS and returns zero rows: the gRPC server blocks to the deadline instead of
|
||||
// returning the synchronous 5-byte code-85 terminal the 2020 WCF op returns, so the orchestrator
|
||||
// reaches its no-data terminal with zero rows and (rather than assert a possibly-false "no events"
|
||||
// empty) throws ProtocolEvidenceMissingException.
|
||||
// (no InvalidOperationException), but GetNextEventQueryResultBuffer LONG-POLLS and returns zero
|
||||
// rows: the gRPC server blocks to the deadline instead of returning the synchronous 5-byte
|
||||
// code-85 terminal the 2020 WCF op returns, so the orchestrator reaches its no-data terminal
|
||||
// with zero rows and (rather than assert a possibly-false "no events" empty) throws
|
||||
// ProtocolEvidenceMissingException.
|
||||
//
|
||||
// IMPORTANT (2026-06-22): the zero rows are NOT "no events on the server". Verified against the
|
||||
// live 2023 R2 box, which holds 19,356 events in the last 30 days (SQL ground truth via the INSQL
|
||||
// linked server, Runtime.dbo.Events). The EMPTY-FILTER gRPC event query simply does not match
|
||||
// them. So the gate here is the empty-filter request shape (filter / namespace / event-tag
|
||||
// registration), NOT data availability — this is capture-gated (needs a native gRPC event-query
|
||||
// capture), not server-gated. Flip to asserting parsed rows once that capture lands and the
|
||||
// request is corrected. The chain stays BOUNDED (no multi-minute hang) via the short
|
||||
// SERVER-GATED on 2023 R2 (settled 2026-06-26; supersedes a 2026-06-22 draft that read the zero
|
||||
// rows as a client-side empty-filter/request-shape "capture gate"). Three live controls against
|
||||
// the same event-bearing 2023 R2 server retire the request-shape theory:
|
||||
// 1. The STOCK AVEVA 2023 R2 client (aahClientManaged, native Event connection, its OWN correct
|
||||
// event query — not our empty-filter shape) returns 0 rows over 30d / 90d / 365d / 3yr.
|
||||
// The 2026-06-22 "50 rows" stock capture did NOT reproduce.
|
||||
// 2. SQL ground truth (Runtime.dbo.Events) shows the server holds tens of thousands of events
|
||||
// in those windows (newest minutes old) — so it is emphatically NOT "no events".
|
||||
// 3. POSITIVE CONTROL: the same native WCF event-read client (protocol byte-replayed from stock
|
||||
// 2020 captures) returns real events (5) from a local AVEVA Historian 2020 over the identical
|
||||
// sequence, but 0 (10-byte 0-row header + long-poll) from this 2023 R2 server.
|
||||
// The protocol works; the 2023 R2 server simply does not scope event rows to a managed connection.
|
||||
// Not client-fixable (see docs/reverse-engineering/grpc-event-query-capture.md +
|
||||
// wcf-event-read-spike-results.md). The chain stays BOUNDED (no multi-minute hang) via the short
|
||||
// registration + poll deadlines. (Set a small HISTORIAN_GRPC_TIMEOUT to keep this snappy.)
|
||||
HistorianClient client = new(BuildOptions(host));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user