Traducción. Autoritativo: ../../standards/jobs.md.
QueuePort (categoría 7 de la constitución)
- Interfaz en
packages/core:publish(queue, payload, opts),schedule(queue, payload, runAt). Los payloads son envelopes validados con Zod:{ job_id: uuidv7, tenant_id, correlation_id, kind, data }. - Binding en el composition root de cada módulo (R21). Adaptador por defecto en F1: Vercel Queues. Vendors nuevos (QStash, etc.): ADR antes del primer import.
Consumidores
- Idempotencia OBLIGATORIA: verificar e insertar en
core.processed_jobs (job_id, consumer, processed_at)dentro de la transacción de trabajo; un duplicado hace ack y salta. Job de limpieza por TTL. - Política de reintentos (default de industria, sobreescribible por cola con justificación en el spec del módulo): 5 intentos, backoff exponencial con jitter (base 30 s, tope 1 h).
- Los reintentos agotados y las fallas duras DEBEN persistirse en
core.dead_letters (job_id, queue, payload, attempts, last_error, status: pending_review|replayed|discarded, correlation_id)más alerta a BetterStack. La herramienta de replay vive en Softcrum Ops. Los éxitos de alto volumen son métricas, no filas. - Mensajes envenenados: los payloads inválidos de schema van directo a dead_letters (sin reintentos).
Colas de notificación (junto con standards/notifications.md)
- Una cola por canal por carril:
notif.{canal}.transactionalynotif.{canal}.marketing. - El transaccional SIEMPRE tiene prioridad: los workers de marketing ceden (pausan o drenan) cuando la profundidad transaccional supera el umbral.
- Rate limiting: token bucket en Upstash por PROVEEDOR (global — por ejemplo, los 10 rps de Resend son por team, a través de TODOS los tenants) y por TENANT (uso justo). Un 429 implica backoff, nunca descartar.
- Blasts de email: exclusivamente el endpoint batch de Resend (100 por request); NUNCA sincronizar contactos a Resend Audiences (nuestro almacén es la fuente de verdad).
Cron fan-out
- Patrón de fan-out por tenant (existente) para: pre-creación de particiones, exportación y purga de retención, reconciliación nocturna, recomputes de frescura de datos (tier por entitlement: nocturno/12h/6h/3h/1h), escaneos de points_expiring_soon, snapshots de consumo (cada 30 min).