feat(grpc): route ReadEvents over gRPC + extract shared CM_EVENT registration
Adds HistorianGrpcEventOrchestrator: opens a read-only gRPC session, replays the CM_EVENT registration (UpdateClientStatus -> 6 GetSystemParameter -> RegisterTags -> cross-service version probes -> EnsureTags), then StartEventQuery -> loop GetNextEventQueryResultBuffer -> EndEventQuery, reusing the WCF query builder and row parser verbatim. Routed in Historian2020ProtocolDialect on UseGrpc. The captured registration buffers (CmEventTagId, UpdC3 blob, RTag2 buffer, GETHI builder, pre-register param list, native-error decode) are extracted into a shared HistorianEventRegistrationProtocol so the WCF and gRPC paths can't drift; the WCF orchestrator is refactored onto it with no behavior change. Live finding (2026-06-22): the chain runs and StartEventQuery succeeds, but the gRPC server long-polls GetNextEventQueryResultBuffer on no data (it blocks to the deadline instead of returning the synchronous 5-byte code-85 terminal the WCF op returns). Per-call gRPC-Web deadlines proved unreliable over a tunnel, so the read is hard-bounded by an overall linked-CTS budget (<=30s; gRPC honors token cancellation). On the no-row path it throws ProtocolEvidenceMissingException rather than assert a false-empty list. Row-level retrieval awaits an event-bearing 2023 R2 server (the dev box holds no events). 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:
@@ -44,8 +44,9 @@ internal sealed class Historian2020ProtocolDialect
|
||||
|
||||
public IAsyncEnumerable<HistorianEvent> ReadEventsAsync(DateTime startUtc, DateTime endUtc, HistorianEventFilter? filter, CancellationToken cancellationToken)
|
||||
{
|
||||
HistorianWcfEventOrchestrator orchestrator = new(_options);
|
||||
return orchestrator.ReadEventsAsync(startUtc, endUtc, filter, cancellationToken);
|
||||
return UseGrpc
|
||||
? new HistorianGrpcEventOrchestrator(_options).ReadEventsAsync(startUtc, endUtc, filter, cancellationToken)
|
||||
: new HistorianWcfEventOrchestrator(_options).ReadEventsAsync(startUtc, endUtc, filter, cancellationToken);
|
||||
}
|
||||
|
||||
public Task<HistorianConnectionStatus> GetConnectionStatusAsync(CancellationToken cancellationToken)
|
||||
|
||||
Reference in New Issue
Block a user