Query-backed linksToMany: skip live re-query inside a prerender#4927
Conversation
The query-field SearchResource was constructed with isLive: true
unconditionally. Inside a prerender the parent doc's
relationships.{field}.data is already the authoritative cardinality
for the field — the indexer just wrote it. Live re-query there
turns into a _federated-search round-trip per query-backed
linksToMany field per loaded card, and additionally introduces an
internal-inconsistency window (live result vs serialized
relationships) that is unique to the prerender code path.
This change:
* query-field-support: derives isLive from
!globalThis.__boxelRenderContext so prerender gets a non-live
resource and the SPA path is unchanged.
* SearchResource: when isLive is false and a seed is provided,
short-circuits after applying the seed and skips the search
perform entirely. The seed cards are the authoritative result;
bypassing the query/realm equality check below means a
signature drift between the parent doc's links.search and the
recomputed query cannot sneak a fetch back in.
* tests: adds a non-live + seed module to the search resource
integration tests that asserts (a) no _federated-search fires
when isLive=false with a seed under a render context, (b)
live + seed still resolves to the correct set, (c) non-live
+ no-seed still fetches.
Related: CS-11235
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 50e65b0fc8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Pull request overview
This PR optimizes prerender performance for query-backed linksToMany fields by avoiding redundant live _federated-search round-trips when the relationship can be resolved from the parent document’s serialized seed data.
Changes:
- In prerender contexts, query-field
SearchResourceinstances are created as non-live so they can resolve from seed data without re-querying. SearchResource.modify()short-circuits whenisLive=falseand a seed is present to avoid re-running the search/equality checks.- Adds integration tests to assert “non-live + seed” does not fire
_federated-search, while ensuring other paths still behave as expected.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| packages/host/tests/integration/resources/search-test.ts | Adds integration coverage for non-live SearchResource behavior with/without seed and compares against live behavior. |
| packages/host/app/resources/search.ts | Updates SearchResource.modify() to treat non-live seeded resolution as authoritative and skip subsequent search execution. |
| packages/base/query-field-support.ts | Sets query-field SearchResource isLive based on prerender context to prevent prerender search cascades. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Preview deploymentsHost Test Results 1 files 1 suites 1h 49m 41s ⏱️ Results for commit aed6c4b. Realm Server Test Results 1 files ±0 1 suites ±0 11m 17s ⏱️ +39s Results for commit aed6c4b. ± Comparison against earlier commit 50e65b0. |
Only short-circuit the perform() call when the seed is authoritative — either seed.cards.length > 0, or seed.searchURL is set. An empty seed with no searchURL is the explicit unresolved signal from query-field-support's shouldTreatEmptySeedAsUnresolved branch, and must still run the fallback fetch — otherwise relationship items go missing in the rendered HTML. Adds a regression test covering the empty-unresolved-seed shape in prerender context. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
linksToManyfields no longer construct a liveSearchResourceinside a prerender; they resolve from the seed that the parent doc already serialized.linksToManyfields fanning out across M loaded child cards, the per-render_federated-searchcascade collapses from O(N*M) to just the top-level type searches the template itself issues.The mechanism
Today:
query-field-support.tscreates aSearchResourcewithisLive: truefor query-backedlinksToManyfields. Correct for the live SPA — a user expects the list to reflect concurrent writes. Inside a prerender it triggers a_federated-searchround-trip per field per loaded card to re-validate what the parent doc'srelationships.{field}.dataalready states.After:
isLive: !Boolean(globalThis.__boxelRenderContext). In prerender theSearchResourceresolves from the seed and exits before issuing any search; in the SPA, behavior is unchanged.To make the seed-only path authoritative regardless of small signature drift between the parent doc's
links.searchand the recomputed query,SearchResource.modifywas updated: whenisLiveisfalseand a seed is provided, afterapplySeedit returns early and skips the query/realm equality check below.Why not live in prerender
isLive: trueintroduces in prerender mode specifically, andisLive: falsecloses.Scope of other
isLive: falsecallersAudited every other non-live caller of
getSearchResource/getSearch. None pass aseed, so the new "non-live + seed = skip search" short-circuit only affects the query-field path.Test plan
_federated-searchfetch fires in prerender mode (__boxelRenderContext = true) when a seed is presentRelated: CS-11235