Skip to content

fix(tanstack): isolate pending page resolution between requests - #541

Open
viktormarinho wants to merge 1 commit into
mainfrom
fix/request-scoped-page-flight
Open

viktormarinho wants to merge 1 commit into
mainfrom
fix/request-scoped-page-flight

Conversation

@viktormarinho

@viktormarinho viktormarinho commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

A stalled loadCmsPage currently holds a module-global promise keyed by URL. Later visitors to the same URL join that promise, even when their own page resolution could succeed. The shared result also contains request-derived device, flags and URL values.

Scope pending page resolution to the incoming Request with a WeakMap. Concurrent callers within one request still deduplicate; separate visitors resolve independently. Completed and rejected work is removed, and query strings, navigation mode and globals options remain distinct.

Validation:

  • 15 tests pass across requestSingleFlight.test.ts and cmsRoute.test.ts. Coverage includes a stuck first visitor with a healthy second visitor, within-request deduplication, rejection cleanup and distinct page options.
  • TanStack package TypeScript check and the Granado website production build pass.
  • Ran the actual built Granado worker in workerd with a production CMS snapshot and recorded anonymous catalog responses. Injected one stalled globals-cache read. Before: ?p=1 returned 200, but a second request to the original URL timed out at 1,503 ms. After: that second request returned the expected Sabonete Barra page with HTTP 200 in 37 ms. Production fixtures remain outside this repository.

This is a demonstrated fault-amplification mechanism, not confirmation that pageInflight caused Granado's production 524s. Healthy local heap snapshots showed no retained entries in this map after requests completed. The map predates the KV migration; KV introduced another asynchronous dependency that can expose the problem.

Complementary website change: https://github.com/deco-sites/granadobr-tanstack/pull/492 bounds KV operations and is the immediate mitigation for an unsettled cache operation. This PR does not add another cache deadline. A visitor whose own dependency stalls still needs that deadline.

Tradeoff: simultaneous cache misses from separate visitors can perform more work because whole-page resolution is no longer shared across requests. Shared value caches remain in place; any future coalescing must operate on request-independent data.


Summary by cubic

Scopes pending page resolution to the incoming request so a stalled loadCmsPage for one visitor no longer blocks later visitors to the same URL. Previously, a module-global promise keyed by URL shared the result across requests, including request-specific device, flags, and URL values.

Concurrent callers within the same request still deduplicate, but separate visitors resolve independently. Completed and rejected work is removed, and query strings, navigation mode, and globals options remain distinct. Simultaneous cache misses from separate visitors may perform more work because whole-page resolution is no longer shared across requests. This PR does not add a cache deadline; a complementary website change bounds KV operations.

Validation: 15 tests pass, TypeScript check and production build pass, and a manual worker test confirmed the fix.

Written for commit 07cd2f5. Summary will update on new commits.

Review in cubic

@viktormarinho
viktormarinho requested a review from a team September 9, 2026 02:14
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