Módulo 6 · Procesamiento asíncrono y mensajería

Lección 29 — Colas y jobs en segundo plano

Celery en TicketFlow: la expiración de reservas deja de ser un cron humano.

Publicada
En esta lección
  1. Ejercicio 1 — El worker local
  2. Ejercicio 2 — La expiración con transporte nuevo
  3. Ejercicio 3 — on_commit o el email fantasma
  4. Ejercicio 4 — Idempotencia de la tarea
  5. Ejercicio 5 — Clasificación de tareas
  6. Entrega

Celery sobre la lógica extraída en la 28. Sin solutions.md hasta entregar.

Ejercicio 1 — El worker local

  1. Levanta el stack: Redis (broker), worker (celery -A ticketflow worker -l info --concurrency=2) y beat (celery -A ticketflow beat). Escribe el docker-compose.override.yml de dev si usas compose (40 lo formaliza).
  2. Crea la tarea saludo(name) que devuelve "hola, {name}" y lánzala con saludo.delay("TicketFlow") desde el shell. Verifica el resultado con AsyncResult.
  3. Mata el worker MIENTRAS procesa una tarea lenta (sleep 30) y vuelve a subirlo: con acks_late, ¿la tarea se re-ejecutó? Pega la evidencia del log.

Ejercicio 2 — La expiración con transporte nuevo

  1. Convierte expirar_reservas (28) en tarea con autoretry_for=(OperationalError,), retry_backoff=True, retry_jitter=True, max_retries=5.
  2. Programa el beat cada minuto. Verifica en 3 minutos consecutivos que solo UNA ejecución toca reservas (los logs deben mostrar refs [] en los dos minutos sin vencidas — sin doble-marca).
  3. Test con eager mode: override_settings(CELERY_TASK_ALWAYS_EAGER=True) y FakeClock — la tarea corre en el mismo proceso del test y el assert cuenta las ref expiradas.

Ejercicio 3 — on_commit o el email fantasma

  1. Escribe el test que DEMUESTRA el bug: encola enviar_email_confirmacion.delay() dentro de una transacción que luego falla (asiento duplicado forzado); en eager mode, el email fake salió igual. Pégalo rojo.
  2. Cambia a transaction.on_commit(...) y verifica: rollback → cero emails; commit → un email.
  3. Aplica on_commit a TODAS las .delay() del proyecto: git grep -n "\.delay(" | grep -v on_commit debe devolver vacío.

Ejercicio 4 — Idempotencia de la tarea

  1. Añade a enviar_email_confirmacion el dedup Redis (email:{ref}:confirmed, TTL 7 días, cache.add). Test: lanza la tarea 3 veces seguidas (simulando el at-least-once del broker) → UN email en el outbox del fake de SMTP.
  2. La tarea de cobro: pasa intent.id como Idempotency-Key a la pasarela fake (14). Test: la pasarela fake recibe 2 llamadas con mismo intent → 1 cargo registrado, misma respuesta ambas veces.

Ejercicio 5 — Clasificación de tareas

  1. Haz la tabla de tareas de TicketFlow: email confirmación, email recordatorio 24h antes, webhooks salientes (17), expiración, liquidación mensual de comisiones, disponibilidad. Marca cada una: crítica (retry infinito + alerta) vs desechable (3 reintentos y al DLQ), latencia tolerada, y mecanismo de idempotencia.
  2. Implementa el "retry infinito con alerta" para las críticas: max_retries=None + header de tarea que tras 10 intentos publica a la métrica task_retry_total{task} (46 la alerta formaliza).

Entrega

Pega la evidencia del acks_late, el test rojo→verde del on_commit, el test de dedup y la tabla de clasificación. Después: Lección 30 — Brokers de mensajería.