Tareas Programadas (Cron)
Las tareas programadas te permiten ejecutar código de forma recurrente usando expresiones cron. Son ideales para limpieza de datos, generación de reportes, sincronización y monitoreo.
Conceptos clave
@cron({ name, cron, disabled? }): registra una clase como tarea cron.ICronHandler: interfaz conhandle()y opcionalmentehandleError().runCronHandlers([]): activa el scheduler de tareas cron.
Paso 1: Definir una tarea cron
import { cron, ICronHandler } from '@wabot-dev/framework'
@cron({ name: 'daily-cleanup', cron: '0 2 * * *', // Todos los días a las 2:00 AM})export class DailyCleanupHandler implements ICronHandler { constructor(private cleanupService: CleanupService) {}
async handle() { await this.cleanupService.removeExpiredSessions() await this.cleanupService.archiveOldRecords() }
async handleError(error: any) { console.error('Error en limpieza diaria:', error) // Notificar al equipo, enviar alerta, etc. }}Paso 2: Expresiones cron
Referencia rápida del formato cron (5 campos):
┌───────────── minuto (0-59)│ ┌───────────── hora (0-23)│ │ ┌───────────── día del mes (1-31)│ │ │ ┌───────────── mes (1-12)│ │ │ │ ┌───────────── día de la semana (0-7, 0 y 7 = domingo)│ │ │ │ │* * * * *| Expresión | Descripción |
|---|---|
* * * * * | Cada minuto |
*/5 * * * * | Cada 5 minutos |
0 * * * * | Cada hora (minuto 0) |
0 9 * * * | Todos los días a las 9:00 AM |
0 2 * * * | Todos los días a las 2:00 AM |
0 9 * * 1 | Cada lunes a las 9:00 AM |
0 9 * * 1-5 | Lunes a viernes a las 9:00 AM |
0 0 1 * * | Primer día de cada mes a medianoche |
0 9,18 * * * | A las 9:00 AM y 6:00 PM |
Paso 3: Deshabilitar temporalmente
Puedes deshabilitar una tarea sin eliminarla usando disabled: true:
@cron({ name: 'heavy-report', cron: '0 3 * * 0', // Domingos a las 3:00 AM disabled: true, // Deshabilitado temporalmente})export class HeavyReportHandler implements ICronHandler { async handle() { // No se ejecutará hasta que disabled sea false }}Paso 4: Activar el scheduler
import { runCronHandlers } from '@wabot-dev/framework'
runCronHandlers([ DailyCleanupHandler, WeeklyReportHandler, OfferExpiryChecker,])Ejemplo completo
Tareas de mantenimiento para un bot de ventas:
import { cron, ICronHandler, singleton, runCronHandlers } from '@wabot-dev/framework'
// --- Limpieza diaria ---
@cron({ name: 'expire-old-offers', cron: '0 0 * * *', // Medianoche})export class ExpireOffersHandler implements ICronHandler { constructor(private offerRepository: OfferRepository) {}
async handle() { const activeOffers = await this.offerRepository.findActiveOffers()
for (const offer of activeOffers) { if (offer.isExpired) { offer.updateStatus('expired', 'Vencida automáticamente') await this.offerRepository.update(offer) } } }
async handleError(error: any) { console.error('Error expirando ofertas:', error) }}
// --- Reporte semanal ---
@cron({ name: 'weekly-sales-report', cron: '0 9 * * 1', // Lunes a las 9:00 AM})export class WeeklySalesReportHandler implements ICronHandler { constructor( private offerRepository: OfferRepository, private reportService: ReportService, ) {}
async handle() { const lastWeek = new Date() lastWeek.setDate(lastWeek.getDate() - 7)
const accepted = await this.offerRepository.findAcceptedInDateRange( lastWeek.toISOString(), new Date().toISOString(), )
const totalRevenue = accepted.reduce((sum, offer) => sum + offer.totalPrice, 0)
await this.reportService.generate({ period: 'weekly', totalOffers: accepted.length, totalRevenue, generatedAt: new Date().toISOString(), }) }}
// --- Seguimiento de prospectos inactivos ---
@cron({ name: 'inactive-prospect-followup', cron: '0 10 * * 1-5', // Lunes a viernes a las 10:00 AM})export class InactiveProspectFollowUpHandler implements ICronHandler { constructor( private prospectRepository: ProspectRepository, private async: Async, ) {}
async handle() { const inactive = await this.prospectRepository.findInactiveProspects(3)
for (const prospect of inactive) { await this.async.runCommand(SendNotificationCommand, { prospectId: prospect.id, type: 'followup', message: 'Hola, hace unos días conversamos sobre nuestras soluciones. ¿Tienes alguna pregunta?', }) } }}
// --- Registro ---runCronHandlers([ ExpireOffersHandler, WeeklySalesReportHandler, InactiveProspectFollowUpHandler,])Siguiente paso
Aprende a configurar tu aplicación con variables de entorno: Variables de Entorno.