Repository navigation
fix(e2e): stop executor stalls from timing out chat-06 on the mock lane - #662
Conversation
cucumber polls every in-flight scenario from one task, and most steps run `rocm` synchronously, so that thread is blocked whenever another scenario's command runs. The chat round trip was polled from that same thread: its client timeout kept counting while nothing read the in-process mock's reply, so a server that answers in milliseconds was reported as a client timeout once those stalls outgrew the 10s budget. The ComfyUI reinstall scenarios added in #546 pushed them past it on the hosted mock lane: each new scenario's first `rocm` call pays the CLI's startup update check (a real uv download and Python preparation) for its fresh data dir, 10-15s on that thread. chat-06 then failed with "budget 10s ... failed after 17.1s". Run the exchange as its own task on the runtime's worker threads, so the budget times the server again, and cover it with a test that blocks the awaiting task past the budget while the server answers. Fixes #661 Signed-off-by: Roman Inflianskas <Roman.Inflianskas@amd.com>
With a runtime planted, each reinstall scenario's first `rocm` call ran the CLI's startup update check for it: a real uv download, a managed Python setup and a package-index query, 10-15s per scenario on a hosted runner. None of these scenarios is about updates, and every second of it blocks the thread cucumber polls all other scenarios from. The nine scenarios added in #546 stretched those stalls from about 20s to over 100s on a 4-CPU run, enough to expire time-bounded steps elsewhere, such as the 30s autostart claim automations-04 plants. Disable the check for the commands these scenarios run. Refs #661 Signed-off-by: Roman Inflianskas <Roman.Inflianskas@amd.com>
jussielo-amd
left a comment
There was a problem hiding this comment.
🔴 Automated review · pr-review-watcher · 4de2b7b
This automation never files a GitHub approval, so no approving review will appear here whatever the outcome — the merge decision stays with a human reviewer.
Review — no blocking findings
Full review of the whole change (both commits on fix/e2e-chat06-mock-lane, 3ea98361 + 4de2b7be, against base ee3131be).
Fixes #661 (chat-06 intermittent timeout on the mock lane) — the diff matches the issue's described failure mode and root cause exactly; issue remains open pending merge, as expected.
Blocking
None
Non-blocking
None
Decisions for the author
- Fix moves contention rather than eliminating it (tradeoff) —
request_chat_completionnow runs the chat exchange viatokio::spawnonto the shared multi-thread runtime's worker pool (confirmed: plaintokio::spawn, notspawn_blocking, and this is the right primitive here since nothing blocks an OS thread). But other scenario steps still runrocmas a synchronous subprocess call on worker threads (per the PR's own "Not fixed here" section), so on a small CPU-pinned runner (CI pins 4 cores) a worker-thread-starved moment could in principle still delay the spawned chat task's scheduling, not just its old polling-thread read. The PR discloses this adjacent class of risk directly ("Synchronousrun_rocm*calls inside async steps can still stall the whole suite... any step with a time window is exposed to that") and reports 3/3 clean CI mock-suite runs under the fix. Nothing indicates this PR's own fix is unreliable; flagging only because the disclosed residual risk and this fix's mechanism are the same shape of problem, scoped out deliberately rather than overlooked. - Two commits under one PR, same investigation (tradeoff) — commit 1 fixes the actual chat-06 timing bug; commit 2 removes a second, independently-discovered stall source (ComfyUI scenarios' startup update check) found while reproducing the same flake. Defensible as one PR since both trace to the same root investigation of #661, though a stricter split-by-mechanism reading could argue for two PRs. Not a defect either way.
Positive signals
describe_request_error— including its comment explaining it exists because an ambiguousreqwest::Error::Displayonce cost "a full log archaeology" — was moved verbatim into the new module rather than dropped or rewritten, preserving that institutional knowledge through the refactor.- The new regression test (
a_blocked_scenario_thread_does_not_time_out_a_request_the_server_answers) was verified to actually exercise the failure mechanism (a blocking sibling step racing the chat exchange on a 2-worker multi-thread runtime, timeout well inside the blocking window) rather than passing vacuously. ROCM_CLI_DISABLE_STARTUP_UPDATE_CHECKis applied per-scenario viaCommand::env(), not process-globalstd::env::set_var, so it can't leak into concurrently-running sibling scenarios — the right call in a harness that explicitly runs scenarios concurrently.
Deployment notes
None — test-harness-only change, no production code, no user-observable behavior, confirmed by all three independent passes.
What this covered
Full fan-out: three independent passes — (1) code-correctness, reading chat_request.rs, lib.rs, e2e.rs (full 1369 lines), comfyui_steps.rs, plus callers (chat_steps.rs, mock_server.rs, therock.rs, main.rs, event_loop.rs); (2) AGENTS.md compliance, covering leak scan, DCO/signing, regression-test requirement, Gherkin-scenario applicability, docs sync, architecture guardrails, CI status, and scope; (3) history, tracing the predecessor commit, checking for dropped rationale/comments, overlapping in-flight PRs, and harness-wide async invariants. All three completed normally. Diffed ee3131be...4de2b7be (PR head not checked out).
Design review (Step 7) folded into the history pass's findings rather than a separate round, given the strength of what that pass already surfaced (the disclosed residual-risk overlap) and the empirical CI evidence (3/3 clean mock-suite runs, all CI lanes green). CI checked live via gh pr view --json statusCheckRollup: every check passing except E2E tests (MI300X) which was still QUEUED (self-hosted GPU hardware availability, not a failure) at review time.
Did not run: commit-signature cryptographic trust verification locally (no allowed_signers file available) — relied on GitHub's own Commit signatures + sign-off CI gate, which passed. Not reconciled against any PR discussion or review thread — none was read, per this review's blind-findings method.
|
Thanks. On the two decisions:
|
Fixes #661.
What broke. Since #546 (
ee3131be), the requiredE2E testsjob fails chat-06 (@id:chat-tool-definitions-accepted), onmainand on every PR. The error isGET …/v1/models failed after 17.1s … client timeout, against a 10s budget.Why.
rocmsynchronously. While one scenario's command runs, no other scenario is polled.rocmcall runs the CLI's startup update check against the planted runtime: a realuvdownload, a managed-Python setup and a package-index query, 10–15s each.f0d4c17bto ~106s atee3131be. In CI'sreport.json, a pure-assertion step took 17.4s during such a stall.Changes.
e2e_cucumber::chat_request), so its budget measures the server again. A step failure still carries the exchange's own diagnostics.a_blocked_scenario_thread_does_not_time_out_a_request_the_server_answerspolls the request and a blocking step from one task, the way cucumber polls scenarios.budget 0.5s … failed after 2.0s … client timeout.ROCM_CLI_DISABLE_STARTUP_UPDATE_CHECK=1. They don't test updates, and the check made them reach the network. This cuts the longest local stall to ~35s.Verification.
cargo xtask e2e, pinned to 4 CPUs like the hosted runner):ee3131be: 1 of 1 runs failed, on chat-06.-p e2e-cucumber --lib(143),--test feature_naming,cargo check --test e2e;-D warnings(workspace all-targets, and-p e2e-cucumber --test e2e);User-observable behaviour: none. This changes only the test harness. The scenario it repairs is chat-06.
Not fixed here. Synchronous
run_rocm*calls inside async steps can still stall the whole suite for up to ~35s, and any step with a time window is exposed to that. Making those helpers async would remove this class of failure; it is a larger change. Other scenarios that plant a runtime also still run the real-network update check, which predates #546.