next.js
058de279 - Restore dev-mode cache-fill timeout for `'use cache'` (#93055)

Commit
27 days ago
Restore dev-mode cache-fill timeout for `'use cache'` (#93055) When `'use cache'` fills during `next dev`, there was no timeout, so a stalled fill could hang the request indefinitely. This change restores a dev-mode cache-fill timeout that fires 50 seconds after the fill starts, matching the 50s timeout we already have during prerender. The timer sets `workStore.invalidDynamicUsageError` to a `UseCacheTimeoutError` and aborts the signal passed to React's `renderToReadableStream`, which errors the cache stream. From there the existing handling of `invalidDynamicUsageError` in app-render surfaces the error in the Redbox and the CLI output without any additional plumbing. Prior to PR #85747, `spawnDynamicValidationInDev` reused the prerender store and inherited the prerender cache timeout as a side effect. After that change the validation became staged-rendering based and the timeout stopped applying to dev renders. This PR closes that gap. The timeout is skipped when the render is already in the Dynamic stage, which mirrors prerender, where caches past `await connection()` aren't executed at all. The check is written as exact equality on `RenderStage.Dynamic` rather than a numeric `< Dynamic` comparison because `RenderStage.Abandoned` is numerically higher than Dynamic but semantically represents an aborted initial prospective render whose pending caches still need to be timed out while the outer flow awaits `cacheSignal.cacheReady()`. The 50s duration is shared with the prerender path via a new `USE_CACHE_FILL_TIMEOUT_MS` constant and carries a TODO to derive it from the user-configurable `staticPageGenerationTimeout`. The tests model a realistic migration hazard: a module-scoped in-flight fetch dedupe loader (the hand-rolled variant of the documented `React.cache`-based preload pattern) joined by a `'use cache'` function. That configuration deadlocks because the outer fetch is parked on the Dynamic stage in dev, or returns an intentionally hanging promise during prerender, and the cache never fills.
Author
Parents
Loading