search dialog: cron-warmed KV blob for Live Leaders + Trending (perf) - #707
Merged
Conversation
Fixes the slow Live Leaders skeleton: dialog used to fetch /api/citable
on every open (~50 KB, full benchmark assembly server-side, frequently
visible 1-2 s skeleton). Now a Vercel cron pre-builds a 12-card subset
every minute, persists it as a single Upstash KV blob, and the dialog
opens with data already prefetched at page load.
Architecture:
- src/lib/search-featured.ts: builds the slim blob (featured + trending
cards: slug, title, category, unit, value, leader). Single source of
truth for the dialog's hardcoded slug lists.
- src/app/api/cron/warm-search-featured/route.ts: every minute, calls
buildFeaturedLeaders + writeCohortSnapshot('search-featured'). Same
CRON_SECRET gate + soft-no-op-on-missing-creds pattern as the existing
cohort cron jobs.
- src/app/api/search/featured/route.ts: KV-first reader with live-build
fallback (cold-start safety). Aggressive edge cache (s-maxage=60,
swr=300) — most requests served by Vercel edge with zero origin hit.
- SearchProvider: prefetches /api/search/featured at mount (idempotent)
and exposes featured + prefetchFeatured via context. Re-fetch hook on
trigger hover/focus.
- SearchTrigger: onMouseEnter + onFocus call prefetchFeatured. Dialog
almost always opens with the blob in memory; the brief 'skeleton'
state is now invisible to the user.
- SearchDialog: consumes featured/trending arrays from context (zipped
against the search index), drops the per-mount /api/citable fetch.
Search-results rows still get leader logos via the same warmed blob
when the bench appears in featured/trending; otherwise fall back to
the kind-icon (no extra API calls).
- vercel.json: cron schedule * * * * * for warm-search-featured.
Graceful degradation:
- No CRON_SECRET / no Upstash creds → cron 200s with configured:false,
endpoint falls through to live build path, dialog still works.
- Upstash unreachable → endpoint falls through to live build, same UX
as the old /api/citable path (slow but functional).
- Worker dies → endpoint serves last-good KV until 24h safety TTL
expires, then falls through to live build.
Payload size: ~50 KB (/api/citable, full index) → ~2 KB
(/api/search/featured, 12 cards).
TTFB: ~1-2 s server-side assembly → ~5-10 ms KV GET (edge-hit: ~0 ms).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Most durable fix for the slow Live Leaders skeleton in the search dialog.
Before
/api/citable(full ~30-bench index, ~50 KB)After
/api/cron/warm-search-featuredruns every minute → callsbuildFeaturedLeaders()→ writes a single ~2 KB JSON blob to Upstash KV (ocb:cohort:search-featured:v1)/api/search/featured→ 1 KV GET (~5-10 ms) → returns slim payloadfeatured/trendingarrays from context. Drops the per-mount/api/citablefetch entirely.Edge cache
s-maxage=60, stale-while-revalidate=300→ most requests served by Vercel edge with zero origin hit.Graceful degradation
CRON_SECRET/ no Upstash creds → cron returns{configured: false}, endpoint falls through to live build, dialog still works.Files
src/lib/search-featured.ts— single source of truth for featured + trending slugs + the build function.src/app/api/cron/warm-search-featured/route.ts— token-gated cron, same pattern as snapshot-perp-cohort.src/app/api/search/featured/route.ts— KV-first reader with live fallback.src/components/search/search-provider.tsx— addsfeatured+prefetchFeaturedto context, mount-time prefetch.src/components/search/search-trigger.tsx— onMouseEnter + onFocus prefetch.src/components/search/search-dialog.tsx— drops /api/citable fetch, consumes context blob.vercel.json— adds the cron schedule.Test plan
curl https://openchainbench.com/api/search/featured | jq '.source, .featured | length, .trending | length'→"kv", 6, 6(or whichever subset has live leaders).