Commit ca4237e
committed
test+docs(maker-checker): mark TTL race resolved; add stress regression guard
CLAUDE.md flagged a "~40% flaky" race in MakerCheckerTransactionRequestTest:
in the multi-challenge path, the request-scoped proxy connection sometimes
failed to propagate (via TransmittableThreadLocal) to a read Future's worker
thread, so the read landed on a fresh pool connection and saw 0 uncommitted
challenge rows. Two empirical sweeps + an in-JVM stress run all show the
race no longer reproduces on current develop:
- 8 instrumented runs (logged `currentProxy.get() == null` and row counts at
every challenge write/read): all PASS, `proxyNull=false` on every read,
across many worker threads, multi-user path included.
- 12 clean runs (no instrumentation, separate JVMs): all PASS.
- 1 stress run (20-iteration loop of multi-challenge creates in one warm JVM,
hammering the exact write→read surface): all 20 iterations PASS, both
challenges read back into the 201 response every time.
40 consecutive multi-challenge create→read cycles with zero failures. At the
historical ~40% per-cycle rate, P ≈ 1.3×10⁻⁹ — the rate definitively no
longer holds. Almost certainly fixed by the RequestScopeConnection hardening
already on develop:
1. `currentProxy.childValue(parent) → null` (overridden in
`RequestScopeConnection.scala`). Its own comment describes exactly the
failing symptom: "workers stuck with a stale proxy then read 0 rows for
the current request's freshly-written data, since the underlying real
connection was closed by the original request's WBT."
2. The stale-proxy `isClosed()` guard added in
`RequestAwareConnectionManager.newConnection`, which now falls back to a
fresh vendor connection rather than returning a stale (already-closed)
proxy.
This commit locks the resolution in and updates the stale TODO:
- **MakerCheckerTransactionRequestTest** — add a new scenario,
"Stress: repeated multi-challenge creates must always read back both
challenges (RequestScopeConnection regression guard)". Reuses the existing
multi-user setup (REQUIRED_CHALLENGE_ANSWERS=2, two-user view access,
maker-checker enforcement) and fires 20 INITIATED creates in one warm JVM,
asserting both per-user challenges round-trip into each 201 response. No
money moves (INITIATED only), so it's safe to loop. Iteration is recorded
via `withClue` so a regression points at the offending iteration.
- **CLAUDE.md** — strike through the "Flaky MakerCheckerTransactionRequestTest"
bullet under "Other TODOs", explain it's resolved by the RequestScopeConnection
hardening, link the regression guard, and keep the historical diagnosis +
original fix directions in case a regression resurfaces.
No core connector / payment-path code is changed — the proper fix already
landed in `RequestScopeConnection`; this commit adds the safety net.1 parent 4c262e4 commit ca4237e
2 files changed
Lines changed: 57 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
363 | 363 | | |
364 | 364 | | |
365 | 365 | | |
366 | | - | |
| 366 | + | |
Lines changed: 56 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
267 | 267 | | |
268 | 268 | | |
269 | 269 | | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
270 | 326 | | |
271 | 327 | | |
272 | 328 | | |
| |||
0 commit comments