Apariencia
Jobs y schedules
Jobs: la cola
Todo lo que sale fuera (emails, SMS, WhatsApp, webhooks, IA) se encola dentro de la transacción de negocio y lo ejecuta el worker después del commit, con reintentos y espera creciente (api/src/jobs/queue.ts).
ts
import { enqueue } from "@host/jobs/queue";
await enqueue(trx, "notas.aviso", { notaId });Los manejadores se declaran en el ZModule:
ts
jobs: {
"notas.aviso": async (payload: { notaId: string }, job) => {
// trabajo idempotente: el worker puede reintentarlo
},
},- Los tipos siguen el formato
modulo.accion. enqueue(db, tipo, payload, { runAt?, maxAttempts? }).- El manejador recibe el
payloady la fila del job. Si lanza, el job se reintenta con espera creciente hastamaxAttempts. - Varios workers pueden convivir: los trabajos se reclaman con
FOR UPDATE SKIP LOCKED. - Hazlos idempotentes: un reinicio del worker o un reintento puede ejecutarlos más de una vez.
Schedules: tareas periódicas
El worker ejecuta schedules del ZModule:
ts
import type { Schedule } from "@host/modules/types";
export const notasSchedules: Schedule[] = [
{
name: "notas.recordatorio",
every: "hour",
run: async (ctx) => {
// ctx: { db, config, realtime, log }
},
},
];| Campo | Tipo | Descripción |
|---|---|---|
name | texto | Identificador de la tarea (modulo.accion). |
every | "minute" | "hour" | "day" | Frecuencia. |
at | "HH:MM" | Solo con "day": hora local; por defecto 07:00. |
runWhenDisabled | booleano | Limpieza de datos (RGPD, caducidad): se ejecuta aunque el módulo esté apagado. Sin esto, las tareas de un módulo opcional apagado se saltan solas. |
run | (ctx: ScheduleContext) => Promise<void> | ScheduleContext = { db, config, realtime, log }. |
Reglas:
- Debe ser idempotente: si el worker se reinicia puede ejecutarse de nuevo. Guarda tu propio estado (por ejemplo con
getSetting/setSetting) para no repetir un aviso diario. - Las tareas de un plugin se registran al cargarlo, igual que las de un módulo integrado.
- Para avisar al equipo usa
notify(@host/lib/notify) conpermissionpara limitar los destinatarios, yctx.realtime.publish("notifications", "notification.created", {})para actualizar los paneles abiertos.