Repository navigation
feat(ppr): capture scheduling telemetry, bake-cost attribution, inert-store guard - #803
Merged
Merged
Conversation
…-store guard Three operability gaps from the #801 incident: a queue-dropped capture reported only its wait (now: priority class + backlog at enqueue on the skip event and the rango.background span); bake cost was invisible (now: bakeWaitMs names the slowest gate-holding source on stored attempts, with a once-per-key dev warning past 2s carrying the nest/cache()/loading() remedy ladder); and a store whose shell family can only no-op (KV-less CFCacheStore, declared via SegmentCacheStore.shellFamilyInert) still burned a full background render per MISS (now: skip-inert-store at the scheduling gate).
commit: |
…ability # Conflicts: # packages/rangojs-router/docs/internal/feature-map.md # packages/rangojs-router/src/rsc/__tests__/shell-capture.test.ts
ivogt
force-pushed
the
feat/ppr-capture-operability
branch
from
July 18, 2026 15:19
51172b6 to
6f2f2e9
Compare
1 of 5 tasks
ivogt
added a commit
that referenced
this pull request
Sep 23, 2026
… ssr:false
Only loader(Def, { ssr: false }) bakes at PPR capture since #813/#820. Update the capture diagnostics (bake cost, no usable shell, identity refusal, rejected loader, redirect/notFound refusal) and the cookies()/headers() capture error, which still advised loading() or nested promises. Share one PPR_LANE_HINT. Make resolveLoaderData the canonical statement of the lane rule and point other comments and docs at it. Fix stale JSDoc examples, resolve the #803 conflict leftover in feature-map.md, and register the /shell-cache/guard fixture loader with ssr: false so the identity guard is exercised again.
ivogt
added a commit
that referenced
this pull request
Sep 23, 2026
… ssr:false (#871) Only loader(Def, { ssr: false }) bakes at PPR capture since #813/#820. Update the capture diagnostics (bake cost, no usable shell, identity refusal, rejected loader, redirect/notFound refusal) and the cookies()/headers() capture error, which still advised loading() or nested promises. Share one PPR_LANE_HINT. Make resolveLoaderData the canonical statement of the lane rule and point other comments and docs at it. Fix stale JSDoc examples, resolve the #803 conflict leftover in feature-map.md, and register the /shell-cache/guard fixture loader with ssr: false so the identity guard is exercised again.
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.
Problem
Three operability gaps around the PPR capture queue, all surfaced by the #801 incident:
skip-queue-timeoutreported only how long the capture waited — not its priority class or how many captures were ahead when it enqueued. Diagnosing the prefetch-starvation incident required a trace deep-dive that these two numbers would have answered immediately.CFCacheStorewithout a KV namespace warns that its shell family is a no-op — but the scheduler still ran a complete background render per ppr MISS whoseputShellcould only discard the result, occupying the queue for nothing.Before vs. after
Debug event for a queue-dropped capture:
Stored attempt on a promise-heavy route (and, in dev past 2s, a once-per-key console warning naming the source):
KV-less
CFCacheStore+ ppr route, per MISS:Consumer-visible surface
ShellCaptureDebugEvent: new optional fieldsqueuePriority,queueAhead,bakeWaitMs; new outcomeskip-inert-store. Additive — existing sinks are unaffected.rango.backgroundspan: newrango.background.queue_priorityandrango.background.queue_aheadattributes, set at enqueue.SegmentCacheStore.shellFamilyInert?: boolean— a store can declare its shell family present-but-inert;CFCacheStoresets it when constructed without KV. Custom stores that no-op their shell family under some configuration should declare it to get the same scheduling skip.top-level pushed handle promises/bake-lane segment loader "<id>") and the remedy ladder — nest it ({ data: promise }→ per-request hole),cache()it (capture replays the value), orloading()it (live lane).End-to-end consumer example
Dev console after the first capture:
Semantics
skip-queue-timeout)bakeWaitMsreported (noise floor)bakeWaitMson event; dev warning past 2s, once per keyputShellskip-inert-store, render never scheduledshellFamilyInert: true(KV-lessCFCacheStore)NODE_ENVguard); event/span fields remainCode changes
src/rsc/capture-queue.ts— exportedcaptureQueueDepths()(waiting counts per class + running flag; lazily-pruned timed-out entries excluded).src/rsc/shell-capture.ts— inert-store gate inscheduleShellCapture(same store defaulting as the write site); priority/backlog span attributes + skip-event fields at enqueue; bake observers aroundholdUntil's sources (side-channel.then(record, record)— the gate contract is untouched); fold intostats.bakeWaitMs+warnBakeCostOnce(thresholdSHELL_CAPTURE_BAKE_WARN_MS = 2000, dev-only, once per key); new event fields/outcome documented onShellCaptureDebugEvent.src/cache/types.ts—SegmentCacheStore.shellFamilyInertcontract.src/cache/cf/cf-cache-store.ts— declaresshellFamilyInert: truewhen constructed without KV.ppr-shell-resume.md,feature-map.md.Test plan
captureQueueDepthscounts (new export), skip-eventqueuePriority/queueAhead(undefined on base), both inert-skip tests (base schedules the capture), bake attribution (nobakeWaitMs, no warning), CFshellFamilyInertflag (undefined on base). One additional base failure ("hands off before the completed capture's caller can enqueue more work") is fallout of the red run itself — the failed depths test leaves the module queue locked — not an independent regression.pnpm run typecheck(16/16),pnpm run test:unit:all,pnpm run lint,pnpm run format,pnpm check:docs-api(182 identifiers).queue_priority === "document"andqueue_ahead >= 1on the terminal span — passed in both modes.Notes
queueAheadis a snapshot at enqueue (active capture + waiting same-or-higher priority), not a live gauge;queueWaitMsremains the measured truth.queue_aheadon the span there is now data to justify it if pressure recurs.