Skip to content

fix(wait): settle --idle on held-open streams; report settled URL in target#5

Merged
sanketsudake merged 3 commits into
mainfrom
fix/wait-idle-and-settled-target-url
Jul 16, 2026
Merged

fix(wait): settle --idle on held-open streams; report settled URL in target#5
sanketsudake merged 3 commits into
mainfrom
fix/wait-idle-and-settled-target-url

Conversation

@sanketsudake

Copy link
Copy Markdown
Owner

Two wait/nav accuracy fixes surfaced while driving Workday over CDP.

1. wait --idle hung on persistent-connection SPAs

waitIdle required inflight == 0 (requestWillBeSent up, loadingFinished/Failed down). A websocket / long-poll / EventSource request fires requestWillBeSent but never loadingFinished, so inflight never returned to zero and --idle waited out the whole --timeout. Observed live: a 20s timeout on an already-loaded Workday page.

Now settles when either:

  • no requests are in flight for the window (the clean path — unchanged for normal pages), or
  • requests remain open but the connection has been silent for ~2s (the stalled path).

responseReceived/dataReceived reset the silence clock, so an in-progress download is never mistaken for a stalled stream — only a genuinely quiet still-open request settles.

2. Envelope target.url was the pre-action URL

The target was captured before the action, so after a nav or --url/redirect wait it echoed the old URL — a wait --url that matched could even report a target URL not containing the matched substring. Wait now reads the settled location and returns it; targetAction syncs target.url from any result carrying a url key (nav already returned it). No extra round-trips.

Tests

  • TestWaitIdleStalledStream — a held-open request settles via the stalled path in ~2s instead of hanging (teardown ordered so Chrome closes before the httptest server, avoiding a /hang deadlock).
  • TestWaitIdle — still guards the clean path (post-load fetch completes before idle returns).
  • TestNavReportsSettledURL / TestWaitReportsSettledURL — target reflects the settled URL.

Verification

gofmt -l clean · go vet ./... clean · go test -race ./... (full, live Chrome, 300s bound) green.

🤖 Generated with Claude Code

sanketsudake and others added 3 commits July 16, 2026 12:50
wait --idle counted requestWillBeSent up and loadingFinished/Failed down and
required inflight == 0. A websocket / long-poll / EventSource request fires
requestWillBeSent but never loadingFinished, so inflight never returned to
zero and --idle hung until --timeout on SPAs that hold such a stream open
(observed on Workday: a 20s timeout on an already-loaded page).

Settle when EITHER no requests are in flight for the window (the clean path,
unchanged for pages whose requests all complete) OR requests remain open but
the connection has been silent for ~2s (the stalled path). Response/data
events reset the silence clock, so an in-progress download is never mistaken
for a stalled stream — only a genuinely quiet still-open request settles.

Adds TestWaitIdleStalledStream (a held-open request settles via the stalled
path in ~2s instead of hanging); TestWaitIdle still guards the clean path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The envelope's target was captured before the action ran, so after a nav or a
--url / redirect wait it showed the pre-navigation URL — misleading (a wait
--url that matched could echo a target URL that didn't even contain the
matched substring).

Wait now reads the tab's location after the condition holds and returns it as
result.url; targetAction syncs target.url from any result carrying a url key
(nav already returned it). No extra round-trips.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Review follow-up (/simplify + /deslop) — no behavior change:

- waitIdle tracked two clocks (lastZero + lastActivity); lastZero is derivable
  (it only diverged from lastActivity in the pre-Enable in-flight-request edge,
  where a single clock is actually more correct — it respects active bytes
  instead of settling early). Collapse to one lastActivity clock and select the
  threshold by whether requests are in flight: `window` when idle, `idleStall`
  when a stream is held open. Drops a field, a branch, and one idle predicate.
- Dedup the "held-open stream / not-a-stalled-download" rationale that was
  stated three times (doc comment + two inline comments) down to once.

Live idle tests (clean + stalled paths) and the full race suite stay green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@sanketsudake
sanketsudake merged commit 334419c into main Jul 16, 2026
2 checks passed
@sanketsudake
sanketsudake deleted the fix/wait-idle-and-settled-target-url branch July 16, 2026 07:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant