diff --git a/README.md b/README.md index cfe3362..a57ea9b 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ request rides the RPC but the server faults on an unmet precondition) · | `ReadEventsAsync` | ✅ | ⚠️ | tooled + routed over gRPC: the full CM_EVENT registration replay (`UpdateClientStatus`→`RegisterTags`→`EnsureTags` + discovery probes) runs and `StartEventQuery` succeeds, but `GetNextEventQueryResultBuffer` **long-polls** on no data (it blocks to the deadline rather than returning the synchronous 5-byte code-85 terminal the WCF op gives). The read is **hard-bounded** (≤30s) and throws `ProtocolEvidenceMissingException` on the no-row path rather than assert a false empty. Row-level retrieval is **not yet live-verified** — the dev box holds no events; pending a capture against an event-bearing 2023 R2 server. Use WCF for event reads | | `SendEventAsync` | ✅ | 🔌 | rides `AddStreamValues` family; no distinct event-send RPC, framing uncaptured over gRPC | | `EnsureTagAsync` / `DeleteTagAsync` / `RenameTagsAsync` | ✅ | ✅ | live-verified 2026-06-22 over gRPC (`HistoryService.EnsureTags` / `DeleteTags` / `StartJob`, write-enabled 0x401 session, WCF serializers reused) via a self-cleaning sandbox-tag lifecycle. Rename is an async StartJob — transiently rejectable right after create, so callers should retry | -| `AddTagExtendedPropertiesAsync` | ✅ | ✅ | live-verified 2026-06-22 over gRPC (`HistoryService.AddTagExtendedProperties`, write-enabled session); a written prop now round-trips through `GetTagExtendedPropertiesAsync` (the multi-property parser fix above). gRPC also exposes `DeleteTagExtendedProperties` (WCF delete was server-blocked) | +| `AddTagExtendedPropertiesAsync` | ✅ | ✅ | live-verified 2026-06-22 over gRPC (`HistoryService.AddTagExtendedProperties`, write-enabled session); a written prop now round-trips through `GetTagExtendedPropertiesAsync` (the multi-property parser fix above). `DeleteTagExtendedProperties` stays unshipped: probed over gRPC 2026-06-22 (prime `GetTgByNm`+`GetTepByNm` then `DelTep`, all on the one shared channel) — the server still rejects the delete (native code=1) and the property survives, so gRPC's multiplexed channel does **not** lift the WCF per-connection working-set wall | | `GetConnectionStatusAsync` | ✅ | ✅ | live-verified 2026-06-22 over gRPC — measured from the handshake (`OpenConnection` yields a storage-session GUID ⇒ connected). No dedicated RPC on either transport; store-forward connectivity stays false (D2-gated) | | `ReadBlocksAsync` | ❌ | ❌ | `StartBlockRetrievalQuery` never captured on either transport — throws `ProtocolEvidenceMissingException` | diff --git a/docs/plans/grpc-tooling-completion.md b/docs/plans/grpc-tooling-completion.md index 9ff589f..dfea609 100644 --- a/docs/plans/grpc-tooling-completion.md +++ b/docs/plans/grpc-tooling-completion.md @@ -140,8 +140,19 @@ _Original notes (still the reference for the registration replay):_ ### Out of scope - `ReadBlocks` (`StartBlockRetrievalQuery`) — never captured on either transport; leave throwing `ProtocolEvidenceMissingException`. -- `DeleteTagExtendedProperties` — server-blocked on WCF (per-connection working set); - gRPC's single multiplexed channel *might* fix it — opportunistic probe only. +- `DeleteTagExtendedProperties` — ❌ **PROBED 2026-06-22, multiplexed-channel hypothesis DISPROVEN.** + The WCF block (server resolves the property from a per-connection working set the SDK's separate + per-service channels can't populate) is NOT lifted by gRPC. The probe + (`HistorianGrpcTagWriteOrchestrator.ProbeDeleteTagExtendedPropertiesAsync`) runs the native + `GetTgByNm` → `GetTepByNm` → `DelTep` sequence over ONE write-enabled (0x401) session on gRPC's + single shared channel. Live against the 2023 R2 server (History iface 12): both primes succeed on the + shared channel (`TgPrimeBytes=98`, `TepPrimePages=1`) yet `DelTep` is still rejected with native + **code=1** (the 5-byte error buffer's byte0=132 is the universal `0x84` marker, not a code) and the + property survives. Conclusion: the working set the server consults is populated by something the SDK + can't reproduce even over one connection — most likely the native client's in-process registration + object, not the wire session. Stays server-blocked on BOTH transports; not shipped publicly. Pinned + by the gated negative test `DeleteTagExtendedProperties_OverGrpc_ProbeMultiplexedChannel` (flips if a + future server/registration lifts the wall). ## Live verification setup (every live run)