Skip to content

Hot spots: narrow-leg metadata search, stale-while-revalidate PR titles - #1397

Merged
Zach Dunn (zachdunn) merged 1 commit into
mainfrom
claude/project-thread-qa9hjs
Nov 6, 2026
Merged

Zach Dunn (zachdunn) merged 1 commit into
mainfrom
claude/project-thread-qa9hjs

Conversation

@zachdunn

Copy link
Copy Markdown
Member

Requested by Zach · project thread

This is the follow-up to #1395 from the same query audit. It covers rows 3 and 4 of the audit's hot spot table.

Metadata search with several filters

findObjectsByMetadata with two or more filters intersected one subquery per filter. Without table statistics, SQLite satisfied ORDER BY object_key by walking the whole workspace on the primary key. D1 query insights showed 2,306 calls in a week reading 14,000 to 32,000 rows each. Most came from the CLI's staged-branch lookup, which filters on gh.repo, gh.branch and gh.kind.

It now walks one filter on file_metadata_lookup_idx, pinned with INDEXED BY. That filter is the first one not in BROAD_META_KEYS (gh.kind, gh.repo, gh.status, gh.merged). Every other filter is an EXISTS with a primary-key lookup per row. The prefix, collapse and after wrappers are unchanged.

I ran the old and new SQL read-only on production D1 for one recent branch, with repo + branch + kind:

Rows read Duration Results
Before 45,137 130 ms 3
After 22 0.4 ms 3

There is no new index. file_metadata_lookup_idx already exists in production; I checked sqlite_master. The single-filter form is unchanged.

PR titles on /pulls

/pulls waited up to 1.4 s (the public title budget) whenever an open PR's KV title entry, which lasts 1 hour, had expired. The repo page's PR list took 1.6 to 1.9 s today.

  • When every row already has a stored title it is allowed to show (storedTitleFor), the handler now waits only 250 ms. That is enough time for KV hits. It then answers with the stored titles.
  • The full resolve keeps running after the response (afterResponse) and backfills github_pr_activity. Before, a resolve that ran past the budget was dropped and never backfilled, so the same rows stayed slow.
  • When any row has no stored title, the handler waits the full budget as before.

Testing

  • pr-scope-sqlite: a multi-filter search with the broad keys listed first still drives from gh.branch. EXPLAIN QUERY PLAN shows file_metadata_lookup_idx (workspace=? AND meta_key=? AND meta_value=?) plus primary-key lookups. Prefix and after give correct results.
  • routes-workspace-scope: with a stored title and a title lookup slowed to 600 ms, /pulls answers in under 550 ms with the stored title. The row is then backfilled with the new title and state. On the old code this test fails at 609 ms.
  • Test fakes that parse the search SQL (api FileMetadataTable, mcp worker) now accept aliased meta_key/meta_value pairs.
  • pnpm test (7913 passed), pnpm typecheck, pnpm check.

Generated by Claude Code

Metadata search with several filters (the CLI's staged-branch lookup
filters on gh.repo + gh.branch + gh.kind) intersected one leg per filter.
Without stats SQLite walked the whole workspace on the PK to satisfy
ORDER BY object_key: 14,000 to 45,000 rows read per call. It now walks
the narrowest filter on file_metadata_lookup_idx (INDEXED BY) and checks
the others with a PK lookup per row. On production data: 45,137 rows /
130 ms before, 22 rows / 0.4 ms after, same results. No new index.

/pulls waited up to 1.4 s for PR titles whenever the KV entry for an
open PR had expired. When every row already has a stored title it now
waits only 250 ms (enough for cache hits), answers with stored titles,
and lets the full resolve finish after the response, backfilling the
rows. Before, a resolve that missed the budget was dropped and never
backfilled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeLbkis33mPMcBF5kRguaM
@changeset-bot

changeset-bot Bot commented Nov 6, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 937638b

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@zachdunn Zach Dunn (zachdunn) self-assigned this Nov 6, 2026
@coderabbitai

coderabbitai Bot commented Nov 6, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are limited based on label configuration.

🏷️ Required labels (at least one): 2

  • coderabbit:review
  • review
🚫 Excluded labels (none allowed): 1

  • wip

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 6f91bbf6-fea1-4f3a-b0e3-afd3f72f494e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@zachdunn
Zach Dunn (zachdunn) merged commit 541ff83 into main Nov 6, 2026
4 checks passed
@zachdunn
Zach Dunn (zachdunn) deleted the claude/project-thread-qa9hjs branch November 6, 2026 17:39
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