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

Lección 30 — Brokers de mensajería

RabbitMQ, Kafka y SQS: entrega at-least-once, orden y dead-letter queues.

Publicada
En esta lección
  1. Ejercicio 1 — El stream con consumer groups
  2. Ejercicio 2 — Deduplicación del consumidor
  3. Ejercicio 3 — DLQ operada
  4. Ejercicio 4 — La matriz de decisión
  5. Ejercicio 5 — Comando vs evento
  6. Entrega

Streams, DLQ y garantías. Sin solutions.md hasta entregar.

Ejercicio 1 — El stream con consumer groups

  1. Con Redis local: crea el stream ticketflow:events, el grupo notificaciones y publica 3 eventos (2 ReservationConfirmed, 1 PaymentFailed). Consume con XREADGROUP desde 2 "workers" (dos shells) y verifica: cada mensaje lo toma UNO solo.
  2. Simula un consumidor muerto: lee SIN ack, cierra el shell, y reclama con XAUTOCLAIM desde otro. ¿Qué pasa con los mensajes pendientes?
  3. Escribe el poller outbox→stream (25): lee pendientes del outbox, XADD con event_id y marca publicado. Test: dos pollers en paralelo no duplican (el índice parcial + FOR UPDATE SKIP LOCKED de la 25).

Ejercicio 2 — Deduplicación del consumidor

  1. Añade al consumidor del grupo notificaciones la dedup event:{event_id} con cache.add (25). Test: publica el MISMO evento dos veces → el efecto (email fake) ocurre una vez.
  2. Publica eventos de la MISMA reserva desordenados (updated_at 10:00, 10:05, 10:02) y verifica que el consumidor aplica el guard: if msg.updated_at < state.updated_at: skip.
  3. Escribe la regla de partición: ¿por qué el stream/agrupación va por reserva y no global? ¿Qué pasaría con el throughput global si fuera por reserva y tuvieras 1M de reservas concurrentes? (respóndelo en 3 líneas, la 55 retoma el número).

Ejercicio 3 — DLQ operada

  1. Implementa la cola ticketflow:dlq (lista Redis o stream) y la política en el worker: tras 5 reintentos fallidos, XADD a la DLQ con causa, payload y trace_id (45). Test: tarea que lanza siempre → 5 intentos → DLQ depth 1.
  2. Escribe manage.py dlq_replay --since 2h --dry-run: lista sin aplicar; sin --dry-run re-encola. Test: mensaje en DLQ → dry-run lo lista sin sacarlo; replay lo re-encola y el consumidor arreglado lo procesa.
  3. Documenta la alerta: dlq_depth > 0 durante 15 min → aviso; > 50 → incidente (47). ¿Qué haría TÚ al recibir la alerta de > 50? Escribe el runbook en 5 pasos.

Ejercicio 4 — La matriz de decisión

  1. Completa la tabla para TUS volúmenes (estima mensajes/día de cada flujo: emails, webhooks salientes, analytics, sagas):

Redis listas / Redis streams / RabbitMQ / Kafka / SQS — con: garantía, orden, replay, operación, coste mensual estimado.

  1. Escribe el ADR (48) de 10 líneas: "Broker de eventos de TicketFlow: Redis Streams" con las 3 razones, la alternativa descartada y el umbral de revisión.

Ejercicio 5 — Comando vs evento

  1. Clasifica: enviar_email, ReservationConfirmed, cobrar_intent, PaymentFailed, expirar_reservas, EventPublished. ¿Cuál va por broker de tareas y cuál por stream de eventos?
  2. Rompe a propósito la regla: publica enviar_email como EVENTO en el stream y ReservationConfirmed como TAREA. ¿Qué se rompe conceptualmente? (la respuesta está en quién decide el efecto y cuándo).

Entrega

Pega la evidencia del consumer group, el test de dedup, el runbook de la DLQ y el ADR. Después: Lección 31 — Tareas programadas y lotes.