Skip to content

test(studio): keep the undo socket gate's sockets pinned past Chrome's idle media suspend - #5108

Merged
miguel-heygen merged 2 commits into
mainfrom
fix/undo-socket-pool-fresh-media
Oct 6, 2026
Merged

miguel-heygen merged 2 commits into
mainfrom
fix/undo-socket-pool-fresh-media

Conversation

@miguel-heygen

@miguel-heygen miguel-heygen commented Oct 6, 2026 •

Copy link
Copy Markdown
Collaborator

What broke

The Studio: timeline viewport gate job on main went red in the merge queue with round 1: only 2 media responses held open; the fixture must pin 6. The same refusal hit 5 runs since Oct 4 (round 1 with 0, 1 or 2 held open, once round 0 with 1). This was the gate's setup failing, not the product: Studio's undo was never measured in those runs.

Root cause

The gate needs Chrome's 6 sockets for the host to be busy before it presses undo. It relied on the fixture's paused videos to hold them, but Chrome cancels a paused video's request roughly 15 s after the player was last used and never reopens it. Logged on the devbox: 7 responses held for about 15 s after round 0's undo, then 3 cancelled together (net::ERR_ABORTED), and the count stayed at 4 until the 30 s wait ran out. Locally the rounds run under a second apart, so they finish inside that window. A slower runner doesn't. With a 20 s gap between rounds, the unchanged gate failed 2 of 8 runs on the devbox.

Chrome 154 has no switch for this idle suspend (disable-media-suspend does not exist in the binary), so a launch flag can't fix it.

Fix

Once the preview is up, the gate opens one unread fetch per fixture video from the Studio page, sent with cookies as the videos' requests are. Unlike a paused video, a fetch has no idle timer, so each holds the socket it gets for the rest of the run. A cookie-carrying Studio request (the regression this gate exists for) has to wait behind them. A ?pin marker keeps Studio's own fetches of the same files out of the count. The video scan retries with the file's until(), so a frame that is mid-navigation can't hard-fail the run. Nothing in the product changes.

Known limits, kept on purpose:

  • The pins never release. A future correct build that needs a cookie-carrying same-origin load mid-test (a preview reload, a lazy module) would wait behind them and fail the gate. Today's flow makes no such request.
  • pinned in the evidence JSON counts pins and video responses together, and it over-counts. Main already read 7 and 8, above Chrome's 6. The precondition no longer depends on that count being exact, because the pins fill the cookie-carrying pool regardless. The broken-build check below shows this.

Proof (devbox, Chrome for Testing 154, Vite dev server as in CI)

  • Unchanged gate, 20 s between rounds: 2 of 8 runs fail with the same refusal as CI.
  • This head, unchanged rounds: 3/3 green. With 20 s between rounds: 3/3 green.
  • Still catches the regression it was written for: with studioApiFetch forced back to credentials: "same-origin" (Studio's requests send cookies again), 4/4 runs fail, normal and with 20 s gaps. They fail on the undo or the edit before it never getting a socket, or (earlier head) the undo waiting 11489 ms against the 250 ms limit.
  • oxfmt, oxlint, comment ratchet and comment citations pass.

No visible change

Test-only change to packages/studio/tests/e2e/undo-socket-pool.mjs.

Why this PR stands alone

A red main-CI gate fix, ordered for today; no other open PR in this repo from this lane can carry it.

@miguel-heygen
miguel-heygen marked this pull request as ready for review October 6, 2026 07:16

@jrusso1020 jrusso1020 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving 1fcee326. This is a test-only change, and it fixes the cause rather than loosening the gate.

  • Root cause holds: the gate's precondition depended on paused videos keeping their requests open, and Chrome drops those requests after about 15 s idle. One unread fetch of each 60 MB fixture file is far larger than Chrome buffers, so it holds its socket for the whole run with no idle timer. The pins send cookies (same origin, default credentials), so they fill the same cookie-carrying pool the regression is about.
  • The gate still measures: the ?pin marker keeps Studio's own fetches out of the pin set. The "did not answer" check now skips pins that are still queued. Pins 7 and 8 legitimately wait, because only 6 sockets exist. Without that skip they would read as stuck Studio requests. The broken-build run in the body, with credentials: "same-origin" forced back so 4 of 4 fail, is the right check that the gate hasn't gone blind.
  • It ran in CI at this head: Studio: timeline viewport gate printed pinned 6, 12, 12 with stallMs 0 on all three rounds.
  • Video scan: retrying it with the file's own until(), and treating a frame that throws as empty, removes the other way setup could fail.
  • Known limits: the never-released pins and the over-counted pinned are both stated in the body. I agree neither matters for today's flow.
  • Optional follow-up: the pins now carry the precondition, so the fixture's eight 60 MB videos matter only as pin targets. A later change could pin fewer or smaller files, which would cut the 480 MB the job generates. That doesn't block this PR.

— Rames

@miguel-heygen
miguel-heygen added this pull request to the merge queue Oct 6, 2026
Merged via the queue into main with commit 43d0778 Oct 6, 2026
146 of 147 checks passed
@miguel-heygen
miguel-heygen deleted the fix/undo-socket-pool-fresh-media branch October 6, 2026 11:05
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.

2 participants