Skip to content

fix(studio): a slow thumbnail job keeps a reader that other clips still decode from - #6643

Merged
vanceingalls merged 2 commits into
mainfrom
fix/studio-thumbnail-reader-progress
Oct 28, 2026
Merged

vanceingalls merged 2 commits into
mainfrom
fix/studio-thumbnail-reader-progress

Conversation

@vanceingalls

@vanceingalls vanceingalls commented Oct 28, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Follow-up to #6629, from Genesis's review. A thumbnail job that timed out judged its reader by its own progress only: whether it had waited for the open, or had decoded a frame itself. Take a poster job that got an already-open reader while a sibling clip was decoding on it, and then needed more than its budget to reach its one frame (a slow link, or Chrome's six connections held). It logged a timeout and retired a healthy reader, so the next clip re-read the index (at a 3.4 GB offset for a long camera file).

Now the pooled reader counts the frames that every job decodes from it (progress.framesFromAnyJob). A timed-out job retires the reader only if no frame came from it while that job held it. A job that waited for the open still counts that open as progress, as before.

No visible change

The reader's frame count in thumbnailSourcePool.ts and thumbnailVideoDecoder.ts: 17 lines, no .tsx, .css or .html. A thumbnail looks the same; a slow clip no longer makes the next one re-read its source.

What I measured

  • thumbnailVideoDecoder.test.ts + thumbnailScheduler.test.ts: 65 pass, including the new keeps the reader when a clip times out while another clip decodes frames from it.
  • The existing drops a reader for one clip's timeout only once the clip still decoding on it ends still passes. Its sibling has decoded no frame when the timeout fires, so the reader is still retired.
  • fails without the fix: when each job gets its own counter (progress = { framesFromAnyJob: 0 } per acquire, the old per-job rule), the new test fails: the timeout is logged and the next clip reopens the source.
  • Pre-commit hooks (lint, format, fallow, typecheck) pass.

What I did NOT exercise

  • A real slow link in the browser. This is the decision rule, tested with mediabunny mocks.
  • Genesis suggested counting completed reads as well as decoded frames. I count frames only: a frame is the result every job is waiting for, and counting reads would mean threading a counter through mediaFetch.

🤖 Generated with Claude Code

…ll decode from

A job that timed out judged the reader by its own progress only. A poster job that got
an already-open reader while a sibling was decoding on it, and took more than its
budget to reach its one frame (a slow link, Chrome's six connections held), logged a
timeout and retired a healthy reader, so the next clip re-read the index.

The pooled reader now counts the frames every job decodes from it, and a timed-out job
retires it only when no frame came from it while the job held it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…its name, not a comment

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@github-actions

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 271 (base branch 271), smooth 121 of those

The gate passes.
Smoothness is reported in the artifact, not gated. A case fails only if it fails 2 of 3 runs.

Quarantined, measured but not gated (0)

Unstable (3)

  • seqplainkeys-none-center-r0-root-z100: tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo false, teleport true / tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true / tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true
  • seqplainkeys-none-px-r0-nested-z100: tracking 0.07, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo false, teleport true / tracking 0.07, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true / tracking 0.07, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true
  • seqplainkeys-none-pct-r0-root-z100: tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo false, teleport true / tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true / tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true

@heygengenesis heygengenesis Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Verdict: APPROVE · 0 blocker · 0 important · 0 nits · debfe5ee

The shared counter is snapshotted after acquire, so only frames decoded while this job held the reader count. The waited-for-open rule and the existing sibling-ends test are unchanged. CI, Comments and PR captures are green on this head. One interaction with #6642 is noted there: keeping the reader alive also keeps its in-flight reads retrying.

— Genesis

@vanceingalls
vanceingalls added this pull request to the merge queue Oct 28, 2026
Merged via the queue into main with commit fa137cd Oct 28, 2026
75 of 76 checks passed
@vanceingalls
vanceingalls deleted the fix/studio-thumbnail-reader-progress branch October 28, 2026 09:50
@heygengenesis heygengenesis Bot mentioned this pull request Oct 28, 2026
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