Skip to content

Stabilize prerender "distinct pages per realm" against cross-affinity steal#4856

Merged
habdelra merged 1 commit into
mainfrom
worktree-prerender-flaky-realm-isolation
May 18, 2026
Merged

Stabilize prerender "distinct pages per realm" against cross-affinity steal#4856
habdelra merged 1 commit into
mainfrom
worktree-prerender-flaky-realm-isolation

Conversation

@habdelra
Copy link
Copy Markdown
Contributor

Summary

  • Flake fix for does not reuse across different realms (default) in prerendering-test.ts (failing check, shard 2 first attempt). Both r1.pool.pageId and r2.pool.pageId came back equal — the signature of the brand-new-affinity cross-affinity-steal fallback in PagePool.#selectEntryForAffinity. That path repurposes an idle donor tab when #ensureStandbyPool can't produce a fresh standby (a transient browser-context creation failure under CI load); #reassignAffinityTab preserves the donor's pageId, so two different realms momentarily share the same Chrome page.
  • Add Prerenderer.warmStandbys() (thin wrapper over PagePool.warmStandbys) and await it from the formats and pooling module's disposeAllRealms beforeEach. Every affinity-pooling test now starts with a fully warm standby pool, so r2's getPage always finds a standby and never reaches the steal.
  • Add diagnostics in case the underlying refill failure ever resurfaces:
    • PagePool.getPage: log.warn when entry.affinityKey !== requested affinityKey (uniquely the cross-affinity-steal signature) with live standbys / creating / active / maxPages counts and both affinity keys.
    • Test assertion: dumps both pageIds, both timings.waits blocks, and getQueueDepthSnapshot() so a future failure shows exactly which step ran short.

Test plan

  • CI runs prerendering-test.ts shard 2 — the affinity-pooling subtree is deterministic on the standby path now.
  • If CI still flakes here, the warn log + enriched assertion message will show whether #ensureStandbyPool is the underlying problem (and which counts looked wrong when the steal fired).

🤖 Generated with Claude Code

… steal

When `#ensureStandbyPool` can't conjure a fresh standby (transient
browser-context creation failure under CI load), the brand-new-affinity
fallback in `PagePool.#selectEntryForAffinity` reassigns an idle tab
from another realm. `#reassignAffinityTab` keeps the donor's `pageId`,
so two different realms can momentarily share the same Chrome page —
the very state-leak risk the test guards against.

Three pieces:

  1. Add `Prerenderer.warmStandbys()` (wraps `PagePool.warmStandbys`).
  2. Await it from `disposeAllRealms` in the formats-and-pooling
     module's beforeEach so every affinity-pooling test starts on a
     fully-warm standby pool — r2's getPage always finds a standby
     and never falls to the cross-affinity steal.
  3. Warn-log inside `getPage` when entry.affinityKey != requested
     affinityKey (the cross-affinity-steal signature) with live
     standby/creating/active/maxPages counts, and enrich the test
     assertion to dump pageIds, timings.waits, and queue snapshot.
     If the underlying refill failure ever resurfaces, CI logs will
     show exactly where the standby pool was when the race fired.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Stabilizes the does not reuse across different realms (default) prerender flake by ensuring the standby page pool is fully warmed between affinity-pooling tests, and adds diagnostics around the cross-affinity-steal fallback so future regressions are easier to triage.

Changes:

  • Add Prerenderer.warmStandbys() wrapper over PagePool.warmStandbys and await it from the affinity-pooling disposeAllRealms beforeEach.
  • Log a warn in PagePool.getPage when an entry comes back tagged for a different affinity (the cross-affinity-steal signature), including standby/creating/active counts.
  • Enrich the distinct pages per realm assertion message with both pageIds, wait timings, and a queue depth snapshot.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
packages/realm-server/tests/prerendering-test.ts Awaits warmStandbys() between realm disposals and expands the distinct-pages assertion message with diagnostics.
packages/realm-server/prerender/prerenderer.ts Adds public warmStandbys() method delegating to PagePool.
packages/realm-server/prerender/page-pool.ts Adds log.warn breadcrumb when an entry's affinity differs from the requested key prior to reassignment.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 18, 2026

Host Test Results

    1 files      1 suites   1h 30m 48s ⏱️
2 659 tests 2 644 ✅ 15 💤 0 ❌
2 678 runs  2 663 ✅ 15 💤 0 ❌

Results for commit 8313a37.

Realm Server Test Results

    1 files      1 suites   9m 4s ⏱️
1 386 tests 1 386 ✅ 0 💤 0 ❌
2 614 runs  2 614 ✅ 0 💤 0 ❌

Results for commit 8313a37.

@habdelra habdelra requested a review from a team May 18, 2026 14:39
@habdelra habdelra merged commit 9a8c91e into main May 18, 2026
101 of 102 checks passed
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.

3 participants