From 7bd4f94ae6a983081e3d0c999f2bba191bf5b154 Mon Sep 17 00:00:00 2001 From: Paul Noel Date: Fri, 21 Jun 2024 12:27:09 -0400 Subject: [PATCH] database: add retries to coingecko --- database/src/coingecko.ts | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/database/src/coingecko.ts b/database/src/coingecko.ts index e9bb01d4..4edd5f5f 100644 --- a/database/src/coingecko.ts +++ b/database/src/coingecko.ts @@ -62,6 +62,7 @@ const createConfig = (apiKey: string) => ({ }); export const fetchPrices = async (coinIds: string[], apiKey?: string): Promise => { + const FIVE_MINUTES_IN_MS = 5 * 60 * 1000; const [baseUrl, config] = apiKey ? [COIN_GECKO_PRO_API_BASE_URL, createConfig(apiKey)] : [COIN_GECKO_API_BASE_URL, undefined]; @@ -70,13 +71,34 @@ export const fetchPrices = async (coinIds: string[], apiKey?: string): Promise(url, config); - console.log(`fetched ${Object.keys(response.data).length} prices`); - prices = { - ...prices, - ...response.data, - }; + let done: boolean = false; + while (!done) { + try { + const response = await axios.get(url, config); + console.log(`fetched ${Object.keys(response.data).length} prices`); + prices = { + ...prices, + ...response.data, + }; + done = true; + } catch (e) { + console.error(`failed to fetch prices: ${e}`); + if (isAxiosError(e) && e.response?.status === 429) { + if (currentBackoff > FIVE_MINUTES_IN_MS) { + console.error('Exceeded max backoff time querying CoinGecko API, giving up.'); + throw e; + } + console.log(`backing off for ${currentBackoff}ms`); + await sleep(currentBackoff); + currentBackoff *= 2; + } else { + // Only want to retry on 429s + throw e; + } + } + } await sleep(COIN_GECKO_API_SLEEP_MS); } return prices;