Skip to content

fix(ingest): exponential backoff on price-service negative cache - #463

Open
matheus1lva wants to merge 3 commits into
mainfrom
fix/negative-cache-backoff
Open

fix(ingest): exponential backoff on price-service negative cache#463
matheus1lva wants to merge 3 commits into
mainfrom
fix/negative-cache-backoff

Conversation

@matheus1lva

@matheus1lva matheus1lva commented Aug 30, 2026

Copy link
Copy Markdown
Collaborator

What

Retry loop against prices.yearn.dev: kong re-requests the same failing historical prices every ~2 minutes, each attempt costing ~14 metered drpc calls (~1.5M/day vs ~700 baseline). #462 bounded the loop; this stops the spin.

Root cause is a cache-ttl asymmetry in packages/ingest/prices.ts: a successful past-day price caches for 24h, a failed one for 2m. With the service failing ~51% of requests, every failure returned to the queue almost immediately — 720 attempts/day per failing key.

How

  • Repeat failures on the same day key double the negative-cache ttl: 2m → 4m → 8m → … capped at 6h (~13 attempts/day worst case).
  • First failure still retries in 2m, so a transient outage can't stick tvl=0 for hours.
  • Attempt counter lives under a separate key with a 24h ttl so it survives the negative marker's expiry.
  • A replay fanout (fanout replays) now flushes the price-service negative markers and attempt counters from Redis before enqueuing, so an escalated 6h marker can't turn the replay into a no-op. Cached real prices are kept.
  • packages/lib/cache.ts gains a keys(pattern) accessor for that flush, backed by node-redis scanIterator (non-blocking SCAN, not KEYS); deletes run in batches of 100.

Tests

  • Updated prices.service-cache.mock.spec.ts for the extra attempts-key write.
  • New test: repeat failures escalate the ttl 2m/4m/8m and cap at 6h.
  • New test: replay clear removes negative markers and attempt counters, keeps cached prices.
  • bun --filter ingest test: 179 passed. bun --filter lib test: 29 passed.

Negative day-cache ttl was fixed at 2m vs 24h for hits, so a failing key
retried 720x/day against prices.yearn.dev. Now each repeat failure doubles
the ttl (2m base, 6h cap, ~13 attempts/day); attempt counter kept under a
separate 24h key so it survives marker expiry.
@vercel

vercel Bot commented Aug 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
kong Ready Ready Preview Aug 30, 2026 12:51pm

Request Review

An escalated negative marker (up to 6h) turned a replay run inside the
backoff window into a silent no-op: the cached 'unavailable' returned
before any fetch and tvl re-wrote the NULL row. Replays now drop the
negative markers and attempt counters first, so recovery heals NULL
days on the first run; cached prices are kept.
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.

1 participant