Skip to content

Let coalesced live searches hand back their admission slot - #6066

Open
backspace wants to merge 4 commits into
mainfrom
cs-12908-admission-slot-tracks-computes
Open

Let coalesced live searches hand back their admission slot#6066
backspace wants to merge 4 commits into
mainfrom
cs-12908-admission-slot-tracks-computes

Conversation

@backspace

Copy link
Copy Markdown
Contributor

What this does

A live _federated-search that the LiveSearchCache resolves by joining an in-flight computation or serving a cached body now hands its search-admission slot back the moment the cache decides so. Only the request that computes keeps its slot until its response ends.

  • LiveSearchCache.getOrPopulate takes an optional onOutcome hook, called synchronously when the outcome is decided: as a miss starts its populate, before a joiner begins waiting, and before a hit returns.
  • searchAdmission leaves the slot's release on the request state, and releaseSearchAdmission(ctxt) lets a handler hand it back early; it is idempotent and a no-op for requests the gate never saw.
  • The search handler's live path releases the slot on join and hit.
  • The comments on SERVER_MAX_IN_FLIGHT_SEARCHES and the gate describe the ceiling as a bound on concurrent computations, sized so a full gate of distinct ones fits a 2 GB heap, rather than as a bound on requests.

Why this shape

The admission gate runs before the body is parsed, so it cannot tell a request that will compute from one that will share another's result, and it counted every request for its whole lifetime. With the live-search cache in place, identical concurrent requests cost roughly one result document, so counting each of them made the gate shed exactly the traffic the cache had made cheap, and left the ceiling tracking request concurrency while heap is held by computations.

Releasing the slot at the cache's decision keeps the gate's cheap pre-parse shed and keeps the default ceiling where the heap analysis put it, while letting a burst of identical searches flow through: each joiner occupies a slot only for the milliseconds between admission and the cache lookup, so its release admits the next arrival. In steady state the gate's count is the number of searches assembling their own result document plus the requests briefly in that window, which is the quantity the ceiling was sized for.

Out of scope

  • Admitting a would-be joiner past a gate that is full of computations. It still waits for a slot like any other arrival; slots now free far faster under identical load, but the gate does not read the body to recognise a joiner ahead of admission.
  • Raising the default ceiling. Its heap rationale holds for the all-distinct case, which coalescing does not change.

Test plan

  • packages/realm-server/tests/live-search-cache-test.ts: onOutcome reports miss as the populate starts, join before the joiner has anything to wait on, and hit synchronously on the call.
  • packages/realm-server/tests/search-admission-test.ts: a handler that releases early drops the in-flight count to zero while its response is still open, a full gate then admits a waiter on the strength of the freed slot, and the release is not repeated when the response ends.

🤖 Generated with Claude Code

The search admission gate bounds concurrent requests, but the quantity
that holds heap is concurrent computations: a live search the
LiveSearchCache resolves by joining an in-flight compute or serving a
cached body builds no result document of its own. Counting those
requests against the ceiling for their whole lifetime made the gate shed
exactly the traffic the cache had made cheap, and left the ceiling
tracking something other than heap.

The cache now announces its decision through an onOutcome hook the
moment it makes it, and the search handler uses that to release the
request's admission slot on a join or hit, so only the computing request
keeps its slot until its response ends. The middleware leaves the release
on the request state for the handler to find. The ceiling's comments now
describe it as a bound on computations, sized so a full gate of distinct
ones fits a 2 GB heap.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 10, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-10T12:59:21.221691Z 385c10e PR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 385c10ebd3

ℹ️ 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".

Comment thread packages/realm-server/handlers/handle-search.ts
@github-actions

github-actions Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Host Test Results

    1 files  ± 0      1 suites  ±0   2h 40m 57s ⏱️ + 10m 27s
4 733 tests +10  4 719 ✅ +10  14 💤 ±0  0 ❌ ±0 
4 748 runs  +10  4 734 ✅ +10  14 💤 ±0  0 ❌ ±0 

Results for commit 4866dd5. ± Comparison against earlier commit ba2b5c2.

Realm Server Test Results

    1 files  ± 0    210 suites  +2   1h 14m 35s ⏱️ - 3m 54s
2 766 tests +43  2 766 ✅ +43  0 💤 ±0  0 ❌ ±0 
2 805 runs  +43  2 805 ✅ +43  0 💤 ±0  0 ❌ ±0 

Results for commit 4866dd5. ± Comparison against earlier commit ba2b5c2.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Indexing requests can be undercounted, and the production route lacks integration coverage for hit/join release.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR lets coalesced live searches release admission slots immediately on cache hits or joins.

Changes:

  • Added synchronous cache outcome callbacks.
  • Added idempotent early slot release.
  • Updated admission documentation and tests.
File summaries
File Reviewed changes
packages/runtime-common/search-bounds.ts Clarifies admission ceiling semantics.
packages/realm-server/tests/search-admission-test.ts Tests early slot release behavior.
packages/realm-server/tests/live-search-cache-test.ts Tests synchronous outcome callbacks.
packages/realm-server/search-inflight.ts Documents computation-based admission semantics.
packages/realm-server/middleware/index.ts Exposes and stores early slot release.
packages/realm-server/live-search-cache.ts Implements outcome notifications.
packages/realm-server/handlers/handle-search.ts Releases slots for live cache hits and joins.
Review details

Suppressed comments (1)

packages/realm-server/middleware/index.ts:271

  • [Claude Code 🤖] This stores the early-release hook for requests that searchAdmission classified as indexing. If DURING_PRERENDER_HEADER is present without a complete job-scoped cache tuple, handle-search takes the live-cache branch; a hit/join then calls this hook and decrements an unconditional admission, so inFlight undercounts and distinct searches can exceed the limit. Keep the hook unset for isIndexing requests (or otherwise make the handler distinguish that lane).
  ctxt.state[SEARCH_ADMISSION_RELEASE] = releaseSlot;
  • Files reviewed: 7/7 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread packages/realm-server/handlers/handle-search.ts
backspace and others added 2 commits September 10, 2026 16:12
The live search path wrapped the cache's body string in a Response,
which encodes it into a stream that setContextResponse then decodes back
into a per-request string, so every response to a shared body made two
more copies of it before Koa wrote a third. With joiners and hits no
longer holding an admission slot, that per-response cost is what bounds
a burst of identical searches on the way out, so the handler now hands
the shared string to Koa directly and each response costs its write
alone.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The unit tests pin the cache's onOutcome timing and the middleware's
release helper separately; this drives the production wiring end to
end. A cache whose compute waits on the test holds the first request
mid-compute, a second identical request joins it, and the gate's count
stays at one while both are in flight. Also notes on the release helper
that it applies to indexing-lane admissions for the same reason.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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