Streams, DLQ y garantías. Sin solutions.md hasta entregar.
Ejercicio 1 — El stream con consumer groups
- Con Redis local: crea el stream
ticketflow:events, el gruponotificacionesy publica 3 eventos (2ReservationConfirmed, 1PaymentFailed). Consume con XREADGROUP desde 2 "workers" (dos shells) y verifica: cada mensaje lo toma UNO solo. - Simula un consumidor muerto: lee SIN ack, cierra el shell, y reclama con
XAUTOCLAIMdesde otro. ¿Qué pasa con los mensajes pendientes? - Escribe el poller outbox→stream (25): lee pendientes del outbox, XADD con
event_idy 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
- Añade al consumidor del grupo
notificacionesla dedupevent:{event_id}concache.add(25). Test: publica el MISMO evento dos veces → el efecto (email fake) ocurre una vez. - Publica eventos de la MISMA reserva desordenados (
updated_at10:00, 10:05, 10:02) y verifica que el consumidor aplica el guard:if msg.updated_at < state.updated_at: skip. - 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
- 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. - Escribe
manage.py dlq_replay --since 2h --dry-run: lista sin aplicar; sin--dry-runre-encola. Test: mensaje en DLQ → dry-run lo lista sin sacarlo; replay lo re-encola y el consumidor arreglado lo procesa. - 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
- 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.
- 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
- Clasifica:
enviar_email,ReservationConfirmed,cobrar_intent,PaymentFailed,expirar_reservas,EventPublished. ¿Cuál va por broker de tareas y cuál por stream de eventos? - Rompe a propósito la regla: publica
enviar_emailcomo EVENTO en el stream yReservationConfirmedcomo 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.