Repository navigation
Coalesce queued preview renders latest-wins (bd-r8iqmg2f) - #970
Merged
Merged
Conversation
Phase 1 of the 2026-10-24 main-thread render-path plan (finding 2). A
burst of N content updates previously executed N full render pipelines;
the serial render queue now coalesces waiting (not yet started) renders
latest-wins per entry point, so a burst executes at most the in-flight
render plus the latest queued one. renderPageInProjectWithAttribution
(the ReactPreview entry) was not queued at all before — burst renders
overlapped on non-reentrant VFS state; it now routes through the queue.
Superseded callers settle by rejecting with RenderSupersededError;
ReactPreview/Preview swallow it (name-matched so partial
vi.mock('@quarto/preview-runtime') doubles can't break the check). The
lastContentRef stale-result guards stay as the second line of defense
and now fire only for the in-flight render. First render after an idle
queue still starts immediately (no debounce).
Measured (Node driver, real WASM, warm SASS cache; before = same
driver at HEAD): a 10-keystroke burst at ~99 KB executes 2 renders
instead of 10 (8 superseded), wall 3026 -> 554 ms; at ~800 KB, 2
instead of 5, wall 12367 -> 4476 ms. Envelope JSON.parse bytes per
burst 106.9 -> 21.4 MB at 1x. Details in the plan.
Tests: renderQueue.test.ts flips the Phase 0 no-coalescing pin to the
new contract (5 tests). preview-runtime 86/86, hub-client test:ci
437 passed / 28 skipped, npm run build:all green. No snapshot changes.
Contributor
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
PR review of bd-r8iqmg2f: nothing imports the helper. The two preview
components deliberately inline the name check so partial
vi.mock('@quarto/preview-runtime') doubles — which would omit the
import just as they omit the class — cannot break it, so the helper's
only possible consumers cannot use it under their own constraint.
Removes the function from the package surface (index.ts re-exports
wasmRenderer wholesale).
PR review of bd-r8iqmg2f, simplification: the waiting-slots store was an array plus a find() with the 'at most one per coalesce key' invariant asserted only in a comment. A Map<key, slot> expresses it in the data structure; insertion-ordered iteration is exactly the FIFO the pump drains in, and supersede mutates the slot in place so it keeps its position (the anti-starvation property). Behavior unchanged; the existing characterization tests pin it.
…bd-gj6fk5hc) PR review of bd-r8iqmg2f found renderPrintable still bypassed the queue with a live caller (hub-client's openPrintableDocument): a print fired while a preview render was in flight ran concurrently against the non-reentrant WASM VFS state — the bug class bd-r8iqmg2f fixed for the ReactPreview entry. It now enqueues like the other render entries, but under a FRESH coalesce key per call: prints serialize with everything else yet never supersede, since each print is an explicit user action that must run. renderQmd stays unqueued (exported but caller-less). Tests pin both halves: a print fired mid-render waits its turn (never concurrent, FIFO), and overlapping prints all execute.
Dev-server smoke (Playwright, vite dev + test hub + real WASM, since deleted per the Phase 0 driver precedent): a paced 10-keystroke burst on a ~300 KB document ran ~3 burst renders with 6-7 superseded (two consecutive runs), the print fired mid-burst serialized FIFO and its popup contained the burst text, the preview converged to the last content, and no RenderSupersededError leaked. Recipe + gotchas recorded in the plan.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase 1 of the main-thread render-path plan (finding 2, bd-r8iqmg2f).
Before, a burst of N keystrokes ran N full preview renders. Now the render queue keeps only the newest waiting render per entry point, so a burst runs at most 2 renders: the one in flight plus the latest. The ReactPreview render entry also goes through the queue now — before, it skipped the queue entirely and burst renders could overlap on non-reentrant VFS state.
Superseded renders settle with a
RenderSupersededErrorrejection that both preview components swallow (name-matched, so partialvi.mock('@quarto/preview-runtime')doubles cannot break the check). ThelastContentRefstale-result guards stay as the second line of defense and now fire only for the in-flight render.Measured
Node burst driver against the real WASM with a warm SASS cache; "before" is the same driver run at HEAD (reproduces the Phase 0 baseline):
Envelope
JSON.parsebytes per burst fell 106.9 to 21.4 MB at 1x.Tests
renderQueue.test.ts: 7 queue-level tests; the Phase 0 no-coalescing pin flips to the new contract.test:ci437 passed / 28 skipped,npm run build:allgreen, strict render of the plan file green. No snapshot changes.RenderSupersededErrorleaked — and a print fired mid-burst serialized FIFO (popup contained the burst text). Two consecutive passes; recipe and observed output recorded in the plan.