|
1 | 1 | import {accessSync, readFileSync} from 'node:fs'; |
2 | 2 | import {dirname, join, resolve} from 'node:path'; |
3 | 3 | import {fileURLToPath} from 'node:url'; |
| 4 | +import { fetch, Agent } from 'undici'; |
4 | 5 |
|
5 | 6 | import * as chains from 'viem/chains'; |
6 | 7 |
|
| 8 | +const agent = new Agent({ connectTimeout: 10000 }); |
| 9 | + |
7 | 10 | export const DEFAULT_CONFIG = 'https://circuitscan.org/cli.json'; |
8 | 11 | export const MAX_POST_SIZE = 6 * 1024 ** 2; // 6 MB |
9 | 12 |
|
@@ -124,21 +127,26 @@ export function viemChain(nameOrId) { |
124 | 127 | } |
125 | 128 |
|
126 | 129 | export async function fetchWithRetry(url, options = {}, retries = 5, delay = 1000) { |
127 | | - for (let attempt = 0; attempt < retries; attempt++) { |
128 | | - try { |
129 | | - const response = await fetch(url, options); |
130 | | - return response; |
131 | | - } catch (error) { |
132 | | - if (error.message.includes('ETIMEDOUT') || error.message.includes('fetch failed')) { |
133 | | - if (attempt < retries - 1) { |
134 | | - console.warn(`Retrying fetch (${attempt + 1}/${retries}) after timeout...`); |
135 | | - await new Promise(res => setTimeout(res, delay * Math.pow(2, attempt))); // Exponential backoff |
136 | | - } else { |
137 | | - throw new Error(`Fetch failed after ${retries} retries: ${error.message}`); |
138 | | - } |
139 | | - } else { |
140 | | - throw error; // If it's not a timeout error, rethrow it immediately |
141 | | - } |
142 | | - } |
| 130 | + for (let attempt = 0; attempt < retries; attempt++) { |
| 131 | + try { |
| 132 | + const response = await fetch(url, { ...options, dispatcher: agent }); |
| 133 | + return response; |
| 134 | + } catch (error) { |
| 135 | + const errorCode = error?.cause?.code; |
| 136 | + console.error(`Fetch attempt ${attempt + 1} failed:`, errorCode, error.message); |
| 137 | + |
| 138 | + const shouldRetry = errorCode === 'ETIMEDOUT' || |
| 139 | + errorCode === 'ENOTFOUND' || |
| 140 | + error.message.includes('fetch failed'); |
| 141 | + |
| 142 | + if (!shouldRetry) throw error; |
| 143 | + |
| 144 | + if (attempt < retries - 1) { |
| 145 | + console.warn(`Retrying fetch (${attempt + 1}/${retries}) after error: ${errorCode}`); |
| 146 | + await new Promise(res => setTimeout(res, delay * Math.pow(2, attempt))); // Exponential backoff |
| 147 | + } else { |
| 148 | + throw new Error(`Fetch failed after ${retries} retries: ${error.message}`); |
| 149 | + } |
143 | 150 | } |
| 151 | + } |
144 | 152 | } |
0 commit comments