> ## Documentation Index
> Fetch the complete documentation index at: https://docs.jelou.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Tarea cron programada

> Ejecuta tareas periódicas como limpiar datos expirados, sincronizar registros o generar reportes con schedules declarativos.

Ejecuta tareas periódicas: limpiar datos expirados, sincronizar registros, generar reportes. Tu función se dispara automáticamente según el schedule que configures.

**Patrón:** `config.cron` + guard `isCron` + secrets para conexiones externas.

```typescript index.ts theme={null}
import { define, z } from "@jelou/functions";

export default define({
  name: "cleanup-job",
  description: "Limpia sesiones expiradas y sincroniza registros",
  input: z.object({}),
  config: {
    cron: [
      { expression: "0 3 * * *", timezone: "UTC" },
      { expression: "0 15 * * 1-5", timezone: "America/Guayaquil" },
    ],
    mcp: false,
  },
  handler: async (_input, ctx) => {
    if (!ctx.isCron) {
      return { skipped: true, reason: "solo se ejecuta por cron" };
    }

    ctx.log("Ejecutando limpieza", { cron: ctx.trigger.cron });

    // Evitar duplicados con ctx.memory
    if (ctx.memory.available) {
      const yaEjecutado = await ctx.memory.get("limpieza_hoy", false);
      if (yaEjecutado) {
        ctx.log("Ya se ejecutó hoy, omitiendo");
        return { skipped: true, reason: "ya ejecutado" };
      }
    }

    const dbUrl = ctx.env.get("DATABASE_URL");
    const apiKey = ctx.env.get("EXTERNAL_API_KEY");

    const staleRecords = await fetch(`${dbUrl}/api/sessions?expired=true`)
      .then((r) => r.json());

    let cleaned = 0;
    for (const record of staleRecords) {
      await fetch(`${dbUrl}/api/sessions/${record.id}`, {
        method: "DELETE",
        headers: { Authorization: `Bearer ${apiKey}` },
      });
      cleaned++;
    }

    // Notificar al admin por WhatsApp
    if (ctx.jelou.available && cleaned > 0) {
      await ctx.jelou.send({
        type: "text",
        to: ctx.env.get("ADMIN_PHONE") || "",
        text: `Limpieza completada: ${cleaned} registros eliminados.`,
      });
    }

    // Marcar como ejecutado (expira en 20h)
    if (ctx.memory.available) {
      await ctx.memory.set("limpieza_hoy", true, 72000);
    }

    ctx.log("Limpieza completada", { cleaned, total: staleRecords.length });
    return { cleaned, checked: staleRecords.length };
  },
});
```

## Configurar secrets

```bash theme={null}
jelou secrets set cleanup-job DATABASE_URL=https://db.example.com EXTERNAL_API_KEY=YOUR_API_KEY
```

## Por qué funciona así

* `config.cron` define cuándo se ejecuta. Puedes tener múltiples schedules con distintas zonas horarias.
* El guard `if (!ctx.isCron)` previene que alguien ejecute la limpieza por HTTP accidentalmente.
* `config.mcp: false` — una tarea de mantenimiento no es un tool de IA.
* `ctx.trigger.cron` te dice cuál schedule disparó la ejecución.
