SendEvent over gRPC: implement + live-validate (was capture-gated)
Captured the native 2023 R2 client's gRPC event send (new capture-send-event harness scenario): it rides HistoryService.AddStreamValues with the SAME "OS" (0x534F) storage-sample buffer the WCF path already uses (HistorianEventWrite- Protocol) — confirming "no distinct RPC", and that it is NOT the historical write's "ON" buffer. Diffed the write-enabled vs read-only v8 Event open: byte- identical apart from per-session crypto, so the existing OpenSession event path is reused unchanged. So SendEvent-over-gRPC was pure assembly of proven parts: - HistorianGrpcEventWriteOrchestrator = v8 Event open + CM_EVENT registration (UpdC3/RegisterTags/EnsureTags) + AddStreamValues(OS buffer). - HistorianClient.SendEventAsync now routes to it for RemoteGrpc (WCF otherwise). Live-validated end-to-end against the 2023 R2 server: pure-managed SDK send → AddStreamValues BSuccess=true → the event reads back from the server (markers confirmed in returned event rows). The native gRPC RegisterTags(24B) + EnsureTags(86B) byte-match our serializers (new GrpcEventSendProtocolTests golden, closing the 83-vs-86 EnsureTags question). Gated live test SendEventAsync_OverGrpc_AcceptsEvent (opt-in HISTORIAN_GRPC_EVENT_SEND=1). 331 offline tests pass. 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:
@@ -233,6 +233,37 @@ public sealed class HistorianGrpcIntegrationTests
|
||||
Assert.Contains(samples, s => s.NumericValue is { } v && Math.Abs(v - expected) < 0.01);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SendEventAsync_OverGrpc_AcceptsEvent()
|
||||
{
|
||||
string? host = Environment.GetEnvironmentVariable("HISTORIAN_GRPC_HOST");
|
||||
// Gated additionally on a dedicated opt-in so this WRITE test never runs by accident — it
|
||||
// appends a clearly-marked test event to the server's event history. Captured 2026-06-23:
|
||||
// the gRPC event send rides HistoryService.AddStreamValues with the same "OS" buffer the WCF
|
||||
// path uses (HistorianEventWriteProtocol), on a v8 Event session + CM_EVENT registration.
|
||||
if (string.IsNullOrWhiteSpace(host)
|
||||
|| string.IsNullOrEmpty(Environment.GetEnvironmentVariable("HISTORIAN_USER"))
|
||||
|| Environment.GetEnvironmentVariable("HISTORIAN_GRPC_EVENT_SEND") is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
HistorianClient client = new(BuildOptions(host));
|
||||
|
||||
var evt = new HistorianEvent(
|
||||
Id: Guid.NewGuid(),
|
||||
EventTimeUtc: DateTime.UtcNow,
|
||||
ReceivedTimeUtc: DateTime.UtcNow,
|
||||
Type: "SdkSendProbe",
|
||||
SourceName: "SdkSendProbe",
|
||||
Namespace: "SdkCapture",
|
||||
RevisionVersion: 0,
|
||||
Properties: new Dictionary<string, object?> { ["SdkProbeProp"] = "SdkProbeValue" });
|
||||
|
||||
bool sent = await client.SendEventAsync(evt, CancellationToken.None);
|
||||
Assert.True(sent, "gRPC SendEvent should be accepted by the server (AddStreamValues BSuccess).");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReadAggregateAsync_OverGrpc_ReturnsTimeWeightedAverageRows()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user