Errores, idempotencia y paginación
Errores tipados, reintentos seguros con idempotencia, y cómo paginar.
Errores, idempotencia y paginación
Tres cosas que hacen robusta cualquier integración: entender los errores, reintentar sin duplicar, y recorrer listas grandes.
Errores tipados
Todos los errores de la API traen un cuerpo con type, code, message y un request_id (envíalo al soporte si algo falla). El SDK los mapea a clases:
import { MetRateLimitError, MetAuthError, MetInvalidRequestError } from '@meteor.ia/sdk';
try {
await met.runs.create({ input: 'x' });
} catch (err) {
if (err instanceof MetRateLimitError) {
console.log(`Reintentar en ${err.retryAfter}s`);
} else if (err instanceof MetAuthError) {
console.log('Key inválida o revocada');
} else if (err instanceof MetInvalidRequestError) {
console.log(err.code, err.message);
} else throw err;
}
La taxonomía es un conjunto cerrado:
type | Clase | HTTP |
|---|---|---|
authentication_error | MetAuthError | 401 |
invalid_request_error | MetInvalidRequestError | 400 |
rate_limit_error | MetRateLimitError | 429 |
agent_error | MetAgentError | 5xx del Met |
api_error | MetApiError | otros |
Reintentos e idempotencia
El SDK reintenta solo los 429 y 5xx con backoff exponencial (respeta Retry-After). No tienes que reimplementarlo.
Para que reintentar un POST no duplique (por ejemplo, crear dos runs por un corte de red), el SDK manda una Idempotency-Key automática en cada POST con efectos. Si el request se reenvía con la misma key, la API devuelve el mismo resultado sin volver a ejecutar.
// Ambas llamadas comparten idempotencia automática; un retry no crea dos runs.
await met.runs.create({ input: 'x' });
Con curl, manda tú el header:
-H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000"
Paginación
Los endpoints de lista devuelven { data, has_more } con un cursor opaco. El SDK lo recorre por ti:
for await (const run of met.runs.iterate()) {
// ...cada run, todas las páginas
}
Si prefieres controlar el cursor a mano, list() acepta limit y starting_after:
const page = await met.runs.list({ limit: 20 });
if (page.has_more) {
const next = await met.runs.list({ limit: 20, starting_after: page.data.at(-1).id });
}