Spaces:
Sleeping
Sleeping
Jose Salazar
Integracion de pipeline de IA y pruebas de modelos en hf spaces, documentacion de modulos
94ad3aa | /** | |
| * Cliente HTTP reutilizable con retry y timeout. | |
| * | |
| * Responsabilidades: | |
| * - Realizar peticiones GET y POST usando fetch nativo de Node.js. | |
| * - Aplicar timeout via AbortController. | |
| * - Reintentar automaticamente ante errores de red o HTTP 429/5xx. | |
| * - Backoff exponencial con tope de 30s. | |
| * - Inyectar User-Agent: PolySignal/1.0 en todas las peticiones. | |
| * | |
| * Uso: | |
| * const data = await httpGet(url, { headers, timeout, retries }); | |
| * const data = await httpPost(url, body, { headers, timeout, retries }); | |
| */ | |
| import { logger } from './logger.js'; | |
| const DEFAULT_TIMEOUT_MS = 10_000; | |
| const DEFAULT_RETRIES = 3; | |
| const RETRYABLE_STATUSES = new Set([429, 500, 502, 503, 504]); | |
| function backoff(attempt) { | |
| return Math.min(1_000 * 2 ** attempt, 30_000); | |
| } | |
| async function request(url, init = {}, { timeout = DEFAULT_TIMEOUT_MS, retries = DEFAULT_RETRIES } = {}) { | |
| for (let attempt = 0; attempt <= retries; attempt++) { | |
| const controller = new AbortController(); | |
| const timeoutId = setTimeout(() => controller.abort(), timeout); | |
| try { | |
| const res = await fetch(url, { | |
| ...init, | |
| headers: { 'User-Agent': 'PolySignal/1.0', ...init.headers }, | |
| signal: controller.signal, | |
| }); | |
| clearTimeout(timeoutId); | |
| if (RETRYABLE_STATUSES.has(res.status) && attempt < retries) { | |
| const wait = backoff(attempt); | |
| logger.warn({ url, status: res.status, attempt, wait }, 'retrying request'); | |
| await new Promise((r) => setTimeout(r, wait)); | |
| continue; | |
| } | |
| const text = await res.text(); | |
| const data = text ? JSON.parse(text) : null; | |
| if (!res.ok) { | |
| const err = Object.assign(new Error(`HTTP ${res.status} β ${url}`), { | |
| status: res.status, | |
| body: data, | |
| }); | |
| throw err; | |
| } | |
| return data; | |
| } catch (err) { | |
| clearTimeout(timeoutId); | |
| if (err.name === 'AbortError') { | |
| throw Object.assign(new Error(`Timeout after ${timeout}ms β ${url}`), { code: 'TIMEOUT' }); | |
| } | |
| // network error (no HTTP status) β retry | |
| if (!err.status && attempt < retries) { | |
| const wait = backoff(attempt); | |
| logger.warn({ url, err: err.message, attempt, wait }, 'network error, retrying'); | |
| await new Promise((r) => setTimeout(r, wait)); | |
| continue; | |
| } | |
| logger.error({ url, err: err.message }, 'request failed'); | |
| throw err; | |
| } | |
| } | |
| } | |
| export const httpGet = (url, { headers, ...opts } = {}) => | |
| request(url, { method: 'GET', headers }, opts); | |
| export const httpPost = (url, body, { headers, ...opts } = {}) => | |
| request( | |
| url, | |
| { method: 'POST', headers: { 'Content-Type': 'application/json', ...headers }, body: JSON.stringify(body) }, | |
| opts, | |
| ); | |