docs(#456): live grind finding — write-trigger structurally impossible
Ran the full item-1 grind (authored a live Modbus equipment tag, connected to the sim, LDAP-authed writes, docker pause the peer). 4 failing wrapped writes produced 0 retry/breaker lines on either central. Root cause (corrects the issue's hypothesis): ModbusDriver.WriteAsync swallows all exceptions and returns WriteResult(StatusBadInternalError) — never throws; CapabilityInvoker feeds only exceptions to Polly; breaker ShouldHandle is Handle<Exception>; Write retry pinned to 0 (R2-02/S-8). So a failing wrapped write emits no line by construction, for any polling driver. The line is reachable ONLY for a session driver (OpcUaClient) faulting mid-Discover/Subscribe (30s Polly timeout throws) — a production timing race, not deterministically forcible on the rig. Behaviour stays unit-proven by the pipeline-builder test. - New: archreview/plans/artifacts/456-retry-breaker-live-finding-2026-07-15.md - FOLLOWUP-10 updated with the structural finding + recommendation to close item 1.
This commit is contained in:
@@ -101,6 +101,28 @@ Original recipe (retained): build central-1/central-2 from source → deploy a M
|
||||
grep central-1 logs for `Driver resilience retry` / `circuit-breaker OPENED` / `closed`. NB the Modbus-path caveat
|
||||
above — an idempotent write (or an S7 driver) is the reliable trigger, not a plain subscribe/read.
|
||||
|
||||
## UPDATE (2026-07-15, Gitea #456) — the write-trigger is STRUCTURALLY IMPOSSIBLE; line is OpcUaClient-only
|
||||
|
||||
Ran the full grind (authored a live Modbus equipment tag, connected to the sim, drove LDAP-authed writes, then
|
||||
`docker pause`d the peer). **4 failing wrapped writes → 0 retry/breaker lines** on either central.
|
||||
[Finding artifact](artifacts/456-retry-breaker-live-finding-2026-07-15.md). Root cause corrects the recipe's
|
||||
"idempotent write is the reliable trigger" note:
|
||||
|
||||
- **`ModbusDriver.WriteAsync` swallows every exception → returns `WriteResult(StatusBadInternalError)` — it
|
||||
never throws** (`ModbusDriver.cs:964-967`); the `CapabilityInvoker` only feeds *exceptions* to Polly
|
||||
(`CapabilityInvoker.cs:84/112/147`, no result-status inspection); breaker `ShouldHandle` is `Handle<Exception>`
|
||||
and `Write` retry is pinned to 0 (R2-02/S-8). So a failing wrapped **write** emits **no line by construction**,
|
||||
for **any** polling driver (they all map write faults to a status). Even an idempotent write to a dead endpoint
|
||||
returns a bad status, not a throw.
|
||||
- Polling drivers' other wrapped sites don't throw through the seam either (`SubscribeAsync` lazy poll-reg;
|
||||
`DiscoverAsync` offline/config-driven).
|
||||
- **The line is reachable ONLY for a session driver (OpcUaClient)** whose session faults *mid-`Discover`/
|
||||
`Subscribe`* (the 30 s Polly timeout on the post-connect discovery loop throws `TimeoutRejectedException` →
|
||||
`Discover` retry ×2). That is a genuine production event but an inherent **timing race** (connect must succeed,
|
||||
the fault must land during the wrapped call before keepalive drops the driver to `Reconnecting`) — not
|
||||
deterministically forcible on the rig. The behaviour stays **unit-proven** by the pipeline-builder logging test.
|
||||
**Recommend closing item 1 on this finding.**
|
||||
|
||||
---
|
||||
|
||||
## (Original filed analysis — retained for history; superseded by OUTCOME above)
|
||||
|
||||
Reference in New Issue
Block a user