Refactors sobre TicketFlow. Sin solutions.md hasta entregar.
Ejercicio 1 — Repositorio del agregado Reservation
- Define el Protocol
ReservationRepositoryconget,saveyexiste_reserva_activa(event_id, user_id). ImplementaORMReservationRepositorycon la consulta conselect_for_updatede la 10. - Escribe
InMemoryReservationRepositorypara tests: dict en memoria, mismo contrato. Mueve el test de la reserva duplicada (10) a este fake. - Decisión escrita: para
VenueySeat(CRUD simple), ¿mantienes manager directo o repositorio? Justifica en 3 líneas.
Ejercicio 2 — Servicio de aplicación con outbox
- Crea la tabla
OutboxEvent(aggregate_type, aggregate_id, event_type, payload JSONB, created_at, publicado_at nullable) con índice parcial sobrepublicado_at IS NULL. - Modifica
reservar()para escribirReservationConfirmeden el outbox DENTRO de la transacción. Verifica: si la transacción falla (asiento ocupado), no hay fila en outbox. - Escribe el poller:
management commandque lee hasta 50 eventos pendientes ordenados por id, los "publica" (por ahora, print/log) y marcapublicado_at. Idempotente al relanzar.
Ejercicio 3 — DTO de salida
- Implementa
ReservationSummary(dataclass frozen) y la funciónresumen(). Cambia la vista de detalle de reserva para serializar desde el DTO, no desde el Model. - Rompe el acoplamiento del todo: ¿qué pasa si mañana renombras un campo del Model? ¿Cuántos sitios tocan si serializas desde Model vs desde DTO?
- Bonus: añade
expires_in_secondscalculado en el DTO (con Clock inyectado), no en el serializer — ¿por qué ese cálculo es dominio?
Ejercicio 4 — Eventos de dominio, mínimo viable
- Enumera 5 eventos de dominio de TicketFlow (
ReservationConfirmed,ReservationExpired,PaymentSucceeded,RefundIssued,EventPublished) y para cada uno: quién lo emite, quién lo consume, payload mínimo. - Añade
PaymentFailedal outbox desde el servicio de pagos. Escribe el test: pago rechazado → transacción commit + fila outbox conevent_type="PaymentFailed"y payload conreason.
Ejercicio 5 — Deduplicación del consumidor
- En el consumidor de eventos (el poller que "publica"), guarda en Redis
event:{event_id}con TTL 24h al procesar; si ya existe, salta. Escribe el test que publica el mismo evento dos veces y comprueba que el efecto (log/email fake) ocurre UNA vez. - ¿Por qué la deduplicación va en el consumidor y no en el poller? Escribe la respuesta en 2 líneas.
Entrega
Pega la interfaz del repositorio, la migración del outbox, el poller y el DTO. Después: Lección 26 — Manejo de errores centralizado.