Ejercicio 1 — Matriz
(a) REST + OpenAPI: universidad de clientes, caché, curl. (b) gRPC: contratos binarios estrictos entre servicios tuyos, streaming, sin caché necesario. (c) GraphQL podría (dashboards configurables) — pero si el dashboard tiene 3 formas fijas, REST con BFF ligero gana; GraphQL se justifica con combinatoria real. (d) WebSocket: bidireccional real. (e) SSE o push de cola (notificación): unidireccional, "listo" ocurre una vez — ni WS ni GraphQL.
- Hoy ninguno es urgente: polling cacheado de disponibilidad resuelve hasta tener usuarios reales mirando mapas simultáneos. El push se compra cuando el negocio pide el instante — ADR-0007 lo registra.
Ejercicio 2 — SSE
curl -Nmuestra los eventos llegando (event: availability,data: {"free": 41}): la conexión permanece abierta.- El PUBLISH desde redis-cli aparece al instante: el stream es un canal, el estado vive en Redis/BD.
- Sin tráfico, intermediarios (proxy LB, Nginx buffers) asumen conexión muerta y la cierran (30-60s típico). El keepalive cada <timeout mantiene NAT/proxies vivos;
proxy_buffering offevita que Nginx acumule el stream en buffer y lo entregue en ráfagas (o nunca, si el buffer nunca llena).
Ejercicio 3 — Del commit al push
- En el código:
transaction.on_commit(lambda: redis.publish(...))— Django lo ejecuta solo si el commit fue real. - Si publicas dentro de atomic() y luego hay rollback, el cliente recibió "asiento vendido" que nunca pasó (el rollback restauró): el push MIENTE. La regla general de la 30 (outbox): solo publicar tras commit;
on_commites la versión simple.
Ejercicio 4 — Carga
- 200 ESTAB y el proceso aguanta (I/O async). Memoria por conexión de Uvicorn: KB, no MB. Con keepalive 1s vs 15s: solo cambia el tráfico del ping (no el número de conexiones); más ping = más CPU trivial y menos proxies que corten.
- Con 2.000 conexiones:
ulimit -n(ficheros abiertos por proceso — cada socket es un fd) salta con el default 1024: se sube (systemd LimitNOFILE) y se dimensiona LB/keepalive. La lección de operación: el límite que importa no es CPU, es fds y memoria por conexión — la 05/55.
Ejercicio 5 — ADR-0007 (esqueleto)
Contexto: compradores miran mapas y los asientos se venden bajo sus pies; polling cacheado genera consultas duplicadas y el "instante" reduce frustración de checkout. Decisión: SSE con Redis pubsub + Last-Event-ID; polling como fallback. Alternativas: polling (no instantáneo), WS (sobrecoste bidireccional sin caso). Consecuencias: conexiones persistentes (dimensionar fds/LB), keepalive y buffering off en Nginx, duplicados en reconexión (client dedup por evento), y una pieza nueva de operación (Redis pubsub ya está: el broker de la 29 lo usa).
Resumen del profesor
- REST público, gRPC interno si hay microservicios, GraphQL solo con combinatoria real, push solo con negocio que exige el instante.
- SSE unidireccional + reconnect nativo cubre disponibilidad en vivo; WS espera bidireccionalidad.
- Publica tras commit (
on_commit): un push de un rollback es una mentira al cliente. - El límite real de streams: fds y proxies (keepalive/buffering), no CPU.
Después: Lección 17 — Webhooks y APIs de terceros.