Skip to content

Stop refetching tokens without a price source on every block#112

Merged
TaprootFreak merged 1 commit into
developfrom
fix/retry-storm-unlisted-tokens
May 14, 2026
Merged

Stop refetching tokens without a price source on every block#112
TaprootFreak merged 1 commit into
developfrom
fix/retry-storm-unlisted-tokens

Conversation

@TaprootFreak
Copy link
Copy Markdown

Summary

  • Several collateral tokens have no CoinGecko listing — the endpoint returns {} (HTTP 200), fetchSourcesCoingecko() then returns undefined, and updatePrices() discards the result without touching the cache entry.
  • Because the entry's timestamp never advances, oldEntry.timestamp + 300_000 < Date.now() stays true and updatePrices() retries the same token on every block tick (every 6–12 s via ApiService.updateWorkflow).
  • The in-cluster pricing proxy absorbs most of that with its 60s cache, but one upstream MISS per minute per token still leaks through. With three unlisted tokens active across two API instances, that is ~300 upstream calls per hour — the largest remaining CoinGecko quota consumer after Honor euro-price TTL inside updatePrices #110.
  • Bump the entry's timestamp on a failed fetch as well, so a missing price obeys the same 5-minute retry window as a successful one.

Test plan

  • yarn build (note: existing TS errors in savings/savings.core.service.ts are pre-existing on develop, unrelated to this change)
  • On a running instance: confirm the upstream call rate to simple/token_price/ethereum?contract_addresses=… for the unlisted-token addresses drops from ~50/h to ~12/h
  • Verify GET /prices/list still returns those tokens (without a price field, as before)

When fetchPrice() returns null/undefined (e.g. CoinGecko returns {}
for an unlisted collateral token), updatePrices() left the cache
entry untouched and the 5-minute staleness check (timestamp +
300_000 < now) was still true on the next block tick. Combined
with the 6-12s block polling that drives updatePrices(), this
made the same handful of unlisted tokens generate ~50 upstream
calls per hour per API instance — the dominant CoinGecko quota
consumer after #110.

Bump the entry's timestamp on a failed fetch too, so the retry
honours the same 5-minute window as a successful fetch.
@TaprootFreak TaprootFreak marked this pull request as ready for review May 14, 2026 17:06
@TaprootFreak TaprootFreak merged commit 9b0a98c into develop May 14, 2026
1 check passed
TaprootFreak added a commit to JuiceDollar/api that referenced this pull request May 15, 2026
Same retry-storm bug we fixed in d-EURO API (PR d-EURO#112):
when fetchPrice() returns no usd value (e.g. an unlisted collateral
token where CoinGecko returns {}), updatePrices() left the cache
entry untouched and the 5-minute staleness check
(timestamp + 300_000 < now) was still true on the next block tick.
Combined with the 10 s block polling that drives updatePrices(),
this made the same handful of unlisted tokens generate a steady
upstream MISS on every cycle, leaking through the pricing-proxy's
60 s cache once per minute per token.

Bump the entry's timestamp on a failed fetch too, so the retry
honours the same 5-minute window as a successful fetch.
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