M3 probe: non-streamed write transaction reachable over 2023 R2 gRPC (Begin/End live-verified)
The D2 storage-engine-pipe wall is WCF-transport-specific. On the 2023 R2 gRPC front door, TransactionService is a first-class service AND the gateway to the storage engine, so the Open2 storage-session GUID (uppercase) is accepted directly as strHandle with no legacy pipe. Live-verified against the real 2023 R2 server over a write-enabled (0x401) gRPC session: AddNonStreamValuesBegin returns a real strTransactionId, and AddNonStreamValuesEnd(bCommit=false) discards it cleanly (no data written). On 2020 WCF the same op returns UnknownClient(51) for every handle + priming chain. - HistorianGrpcRevisionProbe + grpc-revision-probe CLI command + gated test NonStreamedWriteTransaction_OverGrpc_BeginsAndDiscards (live pass). - HistorianGrpcHandshake.OpenSession gains an optional connectionMode param (default read-only 0x402; pass 0x401 for write-enabled) — non-breaking. - Docs: revision-write-path.md "the wall is gone" section; roadmap M3 section, R3.1-R3.3 rows, one-glance table, and status note updated honestly. Not yet shipped: the AddNonStreamValues btInput VTQ buffer is uncaptured (never guess wire bytes), so no value-commit is implemented. Scope is non-streamed ORIGINAL backfill; revision EDITS (R4.2) remain pipe-only even on gRPC. 272 unit tests pass; sanitization scan clean. 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:
@@ -1,3 +1,4 @@
|
||||
using AVEVA.Historian.Client.Grpc;
|
||||
using AVEVA.Historian.Client.Models;
|
||||
|
||||
namespace AVEVA.Historian.Client.Tests;
|
||||
@@ -123,6 +124,30 @@ public sealed class HistorianGrpcIntegrationTests
|
||||
Assert.All(names, n => Assert.StartsWith("Sys", n, StringComparison.Ordinal));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task NonStreamedWriteTransaction_OverGrpc_BeginsAndDiscards()
|
||||
{
|
||||
string? host = Environment.GetEnvironmentVariable("HISTORIAN_GRPC_HOST");
|
||||
if (string.IsNullOrWhiteSpace(host) || string.IsNullOrEmpty(Environment.GetEnvironmentVariable("HISTORIAN_USER")))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// M3 reachability probe: on 2020 WCF this op group is walled (TransactionService relay
|
||||
// returns UnknownClient(51) — the storage-engine-pipe requirement, see
|
||||
// docs/plans/revision-write-path.md). On the 2023 R2 gRPC front door the native client
|
||||
// passes the Open2 storage-session GUID straight to TransactionService and it works.
|
||||
// This asserts the wall is gone: a write-enabled session opens and AddNonStreamValuesBegin
|
||||
// returns a transaction id, which we immediately End with bCommit=false (writes nothing).
|
||||
var probe = new HistorianGrpcRevisionProbe(BuildOptions(host));
|
||||
HistorianGrpcRevisionProbeResult result = await probe.ProbeBeginAsync(CancellationToken.None);
|
||||
|
||||
Assert.True(result.OpenSucceeded);
|
||||
Assert.True(result.BeginSucceeded, "AddNonStreamValuesBegin should return a transaction id over gRPC.");
|
||||
Assert.False(string.IsNullOrEmpty(result.BeginTransactionId));
|
||||
Assert.True(result.EndDiscardSucceeded, "AddNonStreamValuesEnd(bCommit:false) should discard cleanly.");
|
||||
}
|
||||
|
||||
private static HistorianClientOptions BuildOptions(string host)
|
||||
{
|
||||
string? user = Environment.GetEnvironmentVariable("HISTORIAN_USER");
|
||||
|
||||
Reference in New Issue
Block a user