fix: fetch configured CoinPaprika tickers by id#3555
Conversation
|
@alceops is attempting to deploy a commit to the World Monitor Team on Vercel. A member of the Team first needs to authorize it. |
Greptile SummaryThis PR replaces the CoinPaprika bulk
Confidence Score: 3/5Safe to merge after addressing the Promise.all fail-fast issue in the shared helper One P1 finding: the all-or-nothing error behavior in fetchCoinPaprikaTickersById is a reliability regression vs. the original implementation, and the shared helper is used by all three seeders, so the blast radius is wide. P1 ceiling is 4; the wide blast radius and a secondary rate-limit concern bring it to 3. scripts/_seed-utils.mjs — the Promise.all fail-fast behavior in fetchCoinPaprikaTickersById affects all three consumer seeders Important Files Changed
Sequence DiagramsequenceDiagram
participant S as Seeder<br/>(crypto/stablecoin/token)
participant U as _seed-utils<br/>fetchCoinPaprikaTickersById
participant CP as CoinPaprika API<br/>/v1/tickers/{id}
S->>U: fetchCoinPaprikaTickersById(paprikaIds)
U->>U: dedupe IDs via Set
par Promise.all — one request per ID
U->>CP: GET /v1/tickers/btc-bitcoin?quotes=USD
CP-->>U: 200 { id, quotes }
and
U->>CP: GET /v1/tickers/eth-ethereum?quotes=USD
CP-->>U: 200 { id, quotes }
and
U->>CP: GET /v1/tickers/bad-id?quotes=USD
CP-->>U: 404 Not Found
end
Note over U: Promise.all rejects on first error —<br/>all other ticker data is discarded
U-->>S: throws Error("CoinPaprika bad-id HTTP 404")
Reviews (1): Last reviewed commit: "fix: fetch configured CoinPaprika ticker..." | Re-trigger Greptile |
| const tickers = await Promise.all(ids.map(async (id) => { | ||
| const resp = await fetchFn(`https://api.coinpaprika.com/v1/tickers/${encodeURIComponent(id)}?quotes=USD`, { | ||
| headers, | ||
| signal: AbortSignal.timeout(timeoutMs), | ||
| }); | ||
| if (!resp.ok) throw new Error(`CoinPaprika ${id} HTTP ${resp.status}`); | ||
| return resp.json(); | ||
| })); |
There was a problem hiding this comment.
Promise.all fail-fast drops all data on any single ticker error
Promise.all rejects immediately if any one per-ID request returns a non-OK status (404 for a deprecated ticker, 429 from rate limiting, or a transient 503). The old bulk-fetch path only filtered the result set, so a missing ID was a silent no-op rather than a total failure. Now a single bad ID (or a transient CoinPaprika hiccup on any one request) aborts the entire fetchFromCoinPaprika call, losing all ticker data from the seeder's fallback path.
Consider Promise.allSettled with a filter so partial failures are logged but surviving tickers are still returned:
const results = await Promise.allSettled(ids.map(async (id) => {
const resp = await fetchFn(`https://api.coinpaprika.com/v1/tickers/${encodeURIComponent(id)}?quotes=USD`, {
headers,
signal: AbortSignal.timeout(timeoutMs),
});
if (!resp.ok) throw new Error(`CoinPaprika ${id} HTTP ${resp.status}`);
return resp.json();
}));
const failed = results.filter(r => r.status === 'rejected');
if (failed.length) {
console.warn(` [CoinPaprika] ${failed.length} ticker(s) failed: ${failed.map(r => r.reason?.message).join(', ')}`);
}
return results.filter(r => r.status === 'fulfilled').map(r => r.value);| const tickers = await Promise.all(ids.map(async (id) => { | ||
| const resp = await fetchFn(`https://api.coinpaprika.com/v1/tickers/${encodeURIComponent(id)}?quotes=USD`, { | ||
| headers, | ||
| signal: AbortSignal.timeout(timeoutMs), | ||
| }); | ||
| if (!resp.ok) throw new Error(`CoinPaprika ${id} HTTP ${resp.status}`); | ||
| return resp.json(); | ||
| })); |
There was a problem hiding this comment.
Concurrent burst may trigger CoinPaprika rate limits
All N per-ID requests are fired simultaneously via Promise.all. CoinPaprika's free tier enforces a request-per-minute cap. seed-token-panels.mjs combines DeFi and AI token IDs into ALL_IDS, which could be large enough to trigger a 429 on the burst. Because the rate-limit 429 from any single request causes a Promise.all rejection (per the fail-fast concern above), the entire fallback path would fail instead of just the one token.
A small sequential delay between requests, or batching (e.g., groups of 5 with a pause), would reduce the risk without significantly affecting total latency.
Review🛑 Blocking1. The issue's primary target file is untouched. Issue #3528 explicitly cites
|
Summary
/v1/tickers?quotes=USDfallback reads with per-ID/v1/tickers/{id}?quotes=USDrequests for configured IDs.Fixes #3528
Verification
node --test tests/coinpaprika-targeted-fetch.test.mjs✅node --check scripts/_seed-utils.mjs✅node --check scripts/seed-crypto-quotes.mjs✅node --check scripts/seed-stablecoin-markets.mjs✅node --check scripts/seed-token-panels.mjs✅git diff --check✅