Repository navigation
perf(api): cache the live link item lookup for public item pages - #1083
Conversation
Public item pages (/c/<id>/<item>) resolved an item id by scanning the live link's scope and hashing every key until one matched, on every request. Keep each live link's hashed scope list in a named Cache API cache for 60 seconds. A cached hit is served only after a one-row check that its key is still in scope; an id missing from the list costs one query for rows newer than the list, and only rebuilds the list when one of them matches. Closes #1072
|
|
Important Review skippedAuto reviews are limited based on label configuration. 🏷️ Required labels (at least one) (2)
🚫 Excluded labels (none allowed) (1)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
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. Comment |
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
uploads-api | 13e3357 | Commit Preview URL Branch Preview URL |
Oct 05 2026, 11:45 AM |
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
uploads-web | 13e3357 | Commit Preview URL Branch Preview URL |
Oct 05 2026, 11:45 AM |
In plain terms
A public live link item page (
/c/<id>/<item>) used to find its item by listing the live link's whole scope and hashing every object key until one matched the item id. That ran on every request, with no sign-in and no cache. PR comments now link every file to its item page, so this path gets more traffic. This change keeps each live link's hashed scope list in a short-lived server-side cache, so most item page requests skip the scan.What it does / what it is not
withheld, and missing objects are stillmissing.workers.devpreviews), every lookup scans as before.{v,u,h}, the private count cap and itsnullsemantics, title privacy, andhydrateFeedItems.GET /public/feeds/:id?cursor=already narrows its lookup to rows that share one exact timestamp (an indexed equality), so it does not do the 2,000-row scan. I left it as is.APIservice binding with no client IP, so a per-IP key would put all SSR traffic in one bucket. A rate limit belongs at the edge on/c/*if one is needed.gh.repotimestamp (for example, apathrow added later to an existing file) can 404 on its item page until the cached list expires (60 seconds at most).Technical notes
apps/api/src/live-link-index.ts(findLiveLinkItem).publicFeedItemPagenow takes prev/next ids from the list instead of hashing them again.pr-scope.ts:scanScopeKeystakessince(updated_at >= ?, served byfile_metadata_gh_repo_recent_idx), and the newscopeHasKeychecks a single key.@uploads/apiis ignored by changesets).Test plan
pnpm --filter @uploads/api test: new cases inroutes-feeds.test.tswith an in-memorycachesfake. They count scope queries to cover: a cached hit with no rescan, a 404 for an unknown id with one bounded query, a file uploaded after caching, a deleted file never served from the cache, a file made private after caching (withheld), list isolation between two live links, a revoked link, and TTL expiry.pnpm --filter @uploads/api typecheck,pnpm check/c/<id>/<item>pages from a PR comment and confirm the neighbours and the withheld items look right.Closes #1072