fix(api): scope DB stale-fallback cache keys by network [BUG-006] - #215
fix(api): scope DB stale-fallback cache keys by network [BUG-006]#215Morenikeoa wants to merge 1 commit into
Conversation
withDbCacheFallback's dbCache Map was keyed by bare strings the caller passes in (e.g. "markets:all", "funding:global") with no network dimension, even though every live query it backs already filters by network at the DB layer. If the configured network changed between the call that populated the cache and a later call that fails (redeploy, config flip, or any shared-DB deployment with multiple networks), the stale-fallback path could silently serve one network's cached data under a different network's request. Suffix the internal cache key with getNetwork() inside withDbCacheFallback itself, so every current and future caller gets network-scoped fallback caching automatically without needing to remember to include it in the cacheKey they pass. Added a regression test: seed the cache while serving devnet, switch to mainnet, fail the live query under the same bare key, and assert a clean 503 rather than a 200 silently carrying devnet's stale data. Verified the test fails against the pre-fix code (200 with wrong-network data) and passes against the fix. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
|
@Princessdada is attempting to deploy a commit to the Khubair Nasir's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
Warning Review limit reached
More reviews will be available in 44 minutes and 42 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
Problem
withDbCacheFallback'sdbCacheMap (src/middleware/db-cache-fallback.ts) is keyed by the bare strings each route passes in —"markets:all","markets:stats","crank:status","prices:markets","funding:global","stats:platform"— with no network dimension. Every live query these routes run already filters.eq("network", getNetwork()), but the fallback cache entry itself carries no record of which network's data it holds.Impact
If the configured network changes between the call that successfully populated a cache entry and a later call that fails (a redeploy, a config flip, or any shared-DB deployment serving multiple networks from the same process over its lifetime),
withDbCacheFallbackwould serve the previously-cached network's data under the new network's request — a 200 response silently carrying the wrong network's markets/stats/funding data, with no way for the caller to detect the mismatch.Fix
Suffix the internal cache key with
getNetwork()insidewithDbCacheFallbackitself (one line, applied transparently):`${cacheKey}:${getNetwork()}`. This fixes it once at the shared-utility level rather than touching all 6 call sites individually — every current and future caller gets network-scoped fallback caching automatically without needing to remember to include it themselves.Proof of Fix
New test: seeds the cache while
getNetwork()returns"devnet", then switches to"mainnet"and fails the live query under the same bare cache key. Asserts a clean 503 (no usable cache for the new network) rather than a 200 silently serving devnet's stale data.Verified this is a genuine regression test: reverted just the source change and reran — failed with the response actually being a 200 carrying
{ network: "devnet-data" }under the mainnet request, exactly the bug. Restored the fix and it correctly returns 503.tsc --noEmitclean (no separate lint script in this repo).Test Output
Full suite: 295/296 passed (294 baseline + 1 new). The 1 failure (
tests/sdk-smoke.test.ts) is pre-existing and unrelated — it asserts on an exact@percolatorct/sdkerror-message string that has drifted from the locally-resolved SDK version in this environment.Related
Found during a broader API audit; no existing open issue/PR covers this specific cache (distinct from #192/#199/PR #204, which address live-query and view-level network isolation, not this stale-fallback cache).