feat(grpc-events): v6 StartEventQuery request + capture-event harness scenario
Captured the stock 2023 R2 client doing a gRPC event read (50 rows flowed) to resolve the open "gRPC event ROW retrieval returns zero rows" item. Two captured differences from our SDK's path; this lands the first (necessary) one plus the capture tooling. - HistorianEventQueryProtocol.CreateStartEventQueryAttempts: add a `version` parameter (default 5 = the 2020 WCF format, unchanged). The gRPC event orchestrator now opts into version 6 — the leading `06` plus a 5-byte trailing zero pad — which is the envelope the stock 2023 R2 client sends. The two buffers are otherwise byte-identical (filter block, UTC string, metadata namespace). Golden test Version6EmptyFilterMatchesCapturedGrpcEnvelope pins it. - Grpc2023CaptureHarness: new `capture-event` scenario drives HistorianAccess over an Event-type gRPC connection (CreateEventQuery -> EventQueryArgs -> StartQuery -> MoveNext) so the wide-net instrument-grpc-nonstream rewrite dumps StartEventQuery.requestBuffer + the row result. Hostname defaults sanitized to HISTORIAN_GRPC_HOST / "localhost" (removed hardcoded server name). NECESSARY BUT NOT SUFFICIENT: live validation shows v6 alone does not make rows flow — the read also requires an Event-type connection, which our SDK's v6 Open2 format cannot express (see the companion docs commit). The gated ReadEventsAsync_OverGrpc_* test correctly still pins the no-row throw. 322/322 offline tests pass; WCF event path unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B6mcaT2PjRFKcogzp9UkfC
This commit is contained in:
@@ -266,11 +266,17 @@ internal sealed class HistorianGrpcEventOrchestrator
|
||||
new GrpcRetrieval.GetRetrievalInterfaceVersionRequest(), connection.Metadata, Deadline(), cancellationToken);
|
||||
HistorianServerVersionGate.Validate(HistorianServiceInterface.Retrieval, retrievalVersion.UiVersion, _options);
|
||||
|
||||
// Version 6 envelope: the stock 2023 R2 client sends v6 (the WCF path's v5 request is accepted
|
||||
// here but is the legacy format). NECESSARY but not alone sufficient — live validation 2026-06-22
|
||||
// showed rows still don't flow on v6 because the read also requires an EVENT-type connection
|
||||
// (the stock client opens ConnectionType=Event; our OpenSession opens a Process-style 0x402
|
||||
// session). See docs/reverse-engineering/grpc-event-query-capture.md "remaining gate".
|
||||
IReadOnlyList<HistorianEventQueryAttempt> attempts = HistorianEventQueryProtocol.CreateStartEventQueryAttempts(
|
||||
startUtc.ToUniversalTime(),
|
||||
endUtc.ToUniversalTime(),
|
||||
eventCount: 5,
|
||||
filter);
|
||||
filter,
|
||||
version: 6);
|
||||
byte[] requestBuffer = attempts[0].RequestBuffer;
|
||||
|
||||
GrpcRetrieval.StartEventQueryResponse startResponse = retrievalClient.StartEventQuery(
|
||||
|
||||
Reference in New Issue
Block a user