Cron Jobs
El worker ejecuta tareas programadas via Cloudflare Cron Triggers.
Configuración
Tarea: Auto-refresh de tokens
Renueva automáticamente los tokens OAuth que estén por vencer en los próximos 5 días.
flowchart TD
CRON["⏰ Cron Trigger<br/>3:00 AM UTC diario"] --> A["Buscar tokens con<br/>expires_at < ahora + 5 días"]
A --> B{¿Hay tokens<br/>por vencer?}
B -->|No| C["Log: No tokens expiring"]
B -->|Sí| D["Para cada token:"]
D --> E["exchangeMPToken()<br/>grant_type: refresh_token"]
E --> F{¿Éxito?}
F -->|Sí| G["Actualizar token en DB<br/>Log: Refreshed"]
F -->|No| H["Log error<br/>Continuar con siguiente"]
G --> I{¿Más tokens?}
H --> I
I -->|Sí| D
I -->|No| J["Fin"]
Tolerancia
El refresh se hace 5 días antes de la expiración. Si falla, hay 5 días para solucionarlo manualmente antes de que el token expire y las llamadas a MercadoPago dejen de funcionar.
Implementación
El handler scheduled se exporta junto con fetch en el worker:
export default {
fetch: app.fetch,
scheduled: async (
controller: ScheduledController,
env: CloudflareBindings,
ctx: ExecutionContext,
) => {
const db = createDb(env.webhook_db);
await refreshExpiringTokens(db, env);
},
} satisfies ExportedHandler<CloudflareBindings>;
La función refreshExpiringTokens usa exchangeMPToken() de lib/mercadopago.ts, la misma función centralizada que usan las rutas de OAuth para renovar tokens.
Monitoreo
Los logs del cron aparecen en Cloudflare Dashboard → Workers → Logs:
Cuando renueva:
[Cron] Refreshed token for 'mi-cliente', expires: 2025-09-01T14:00:00.000Z
[Cron] Refreshed token for 'otro-cliente', expires: 2025-09-02T10:30:00.000Z
Si un refresh falla:
Si falla un refresh
El cron no se detiene si falla un cliente. Continúa con los demás y loguea el error. Si un token no se puede renovar (ej: refresh_token expirado), hay que re-hacer el flujo OAuth manualmente desde /oauth/login.
Testing local
Para testear el cron localmente con Miniflare: