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,6 +1,66 @@
|
||||
# Plan: Revision-Write Path (`AddRevisionValuesBegin/Value/End`)
|
||||
|
||||
Status: **ARCHITECTURALLY BLOCKED — verified 2026-05-05.** Same root
|
||||
Status: **WCF: ARCHITECTURALLY BLOCKED (verified 2026-05-05).** **gRPC (2023 R2): the
|
||||
non-streamed-original transaction is REACHABLE — Begin/End round-trip LIVE-VERIFIED 2026-06-21.**
|
||||
Same root cause on WCF as `AddS2`: the `TransactionService` relay needs a pre-existing
|
||||
storage-engine *pipe* session no WCF op can create. The 2023 R2 gRPC front door removes that wall
|
||||
(see the §"2023 R2 gRPC — the wall is gone" section immediately below); the legacy WCF analysis is
|
||||
preserved unchanged after it.
|
||||
|
||||
## 2023 R2 gRPC — the wall is gone (non-streamed original writes), LIVE-VERIFIED 2026-06-21
|
||||
|
||||
The whole D2 WCF blocker was: `ITransactionServiceContract2.AddNonStreamValuesBegin2` returns
|
||||
`04 33 00 00 00` = `UnknownClient (51)` because the server-side Trx relay requires a storage-engine
|
||||
pipe session (`STransactPipeClient2` → `aaStorageEngine.exe`) that no WCF op establishes. On the
|
||||
**2023 R2 gRPC** transport that relay is replaced by a first-class `TransactionService` gRPC
|
||||
service, and the gRPC server is itself the gateway to the storage engine — so the client passes the
|
||||
**HistoryService Open2 storage-session GUID** straight in as `strHandle` and the transaction opens.
|
||||
|
||||
**Live probe (`grpc-revision-probe` CLI command / `HistorianGrpcRevisionProbe`):** against the real
|
||||
2023 R2 server (History iface 12), over a **write-enabled** (`0x401`) gRPC session —
|
||||
|
||||
| step | result |
|
||||
|---|---|
|
||||
| `HistoryService.OpenConnection` (write-enabled `0x401`) | ✅ `OpenSucceeded`, client handle + storage GUID returned |
|
||||
| `TransactionService.GetTransactionInterfaceVersion` | ✅ error 0, **version 2** |
|
||||
| `TransactionService.AddNonStreamValuesBegin(strHandle = storage GUID **UPPERCASE**)` | ✅ **`BeginSucceeded`** — returns a real `strTransactionId` (e.g. `…-FE0A-4822-…`) on the **first** handle format tried |
|
||||
| `TransactionService.AddNonStreamValuesEnd(handle, txId, bCommit=**false**)` | ✅ `EndDiscardSucceeded` — transaction discarded, **no data written** |
|
||||
|
||||
So the answer to the roadmap's open M3-over-gRPC question ("does the 2023 R2 gRPC front door expose
|
||||
a non-streamed write that bypasses the legacy storage-engine pipe?") is **YES** — Begin/End is
|
||||
reachable from the pure-managed SDK with no pipe, no native wrapper. The probe is committed as the
|
||||
`grpc-revision-probe` CLI command + the gated test
|
||||
`HistorianGrpcIntegrationTests.NonStreamedWriteTransaction_OverGrpc_BeginsAndDiscards`; re-run any
|
||||
time to confirm the path is still open.
|
||||
|
||||
### Decompile basis (handle + op group)
|
||||
|
||||
`Archestra.Historian.GrpcClient.GrpcHistoryClient` drives the identical three-phase sequence
|
||||
(`AddNonStreamValuesBegin(strHandle) → strTransactionId`; `AddNonStreamValues(strHandle,
|
||||
strTransactionId, btInput)`; `AddNonStreamValuesEnd(strHandle, strTransactionId, bCommit)`), passing
|
||||
the Open2 session GUID as `strHandle`. `btInput` is the **same opaque native VTQ buffer** the 2020
|
||||
path uses. Proto: `src/AVEVA.Historian.Client/Grpc/Protos/TransactionService.proto`.
|
||||
|
||||
### What is proven vs. what remains (do NOT ship yet)
|
||||
|
||||
- ✅ **Proven:** the transaction lifecycle (Begin → End/rollback) is reachable over gRPC. The D2
|
||||
architectural wall is specific to the WCF transport.
|
||||
- ⛔ **Not yet captured:** the `AddNonStreamValues` **`btInput` VTQ buffer byte layout**. Per project
|
||||
discipline ("never guess wire bytes; capture first") no value-commit is implemented. The next step
|
||||
to actually *ship* M3 (`AddHistoricalValuesAsync`) is to capture the native gRPC `AddNonStreamValues`
|
||||
`btInput` (or decode the `GrpcHistoryClient` serializer), build a golden-tested serializer, then do a
|
||||
real `bCommit=true` write + SQL read-back against a sandbox tag created by `EnsureTagAsync`.
|
||||
- 🔒 **Scope:** this is **non-streamed ORIGINAL backfill** (`HistorianDataCategory.NonStreamedOriginal`
|
||||
→ `TransactionService.AddNonStreamValues*`). **Revision EDITS** (`AddRevisionValue(s)` /
|
||||
`RevisionInsert*`, the R4.2 path) are NOT on the gRPC contract even in 2023 R2 — the capability
|
||||
matrix confirms they still ride the storage-engine pipe. The gRPC unlock here is original backfill,
|
||||
not after-the-fact edits.
|
||||
|
||||
---
|
||||
|
||||
## Legacy WCF analysis (preserved — still accurate for the 2020 WCF transport)
|
||||
|
||||
Status (WCF only): **ARCHITECTURALLY BLOCKED — verified 2026-05-05.** Same root
|
||||
cause as `AddS2`: client-side cache rejects values for tags that
|
||||
weren't registered through a configured IO server / Application Server
|
||||
pipeline. Documented below; implementation deferred until / unless that
|
||||
|
||||
Reference in New Issue
Block a user