🧪 Problem-Driven Systems Lab

🐍 Caso 15 — Python 3.12#

⬅️ Caso 15 · ⚖️ Comparativa de los 7 stacks · 🐍 Perfil de Python · 🧬 Todos los perfiles

Stack Python del caso 15. Cola sin capacidad contra cola acotada con política explícita.

La política se elige en la firma de put()#

Las tres políticas del caso no son tres estructuras distintas: son tres formas de llamar al mismo método.

python
q.put(msg)                    # bloquea: backpressure hacia el productor
q.put_nowait(msg)             # levanta queue.Full: el llamador decide
q.put(msg, timeout=0.05)      # espera acotada y después decide

Es la API más explícita del laboratorio en este punto: no hay un modo por defecto que «haga algo razonable» a tus espaldas. Si no elegís, no hay comportamiento — tenés que escribir cuál de las tres querés.

El reverso está una línea más arriba: queue.Queue() sin maxsize es la versión sin límite, y se escribe con menos caracteres que la acotada.

Primitivas nativas#

PrimitivaRol
queue.Queue(maxsize=N)La cola acotada. Sin maxsize, no hay techo.
put / put_nowait / put(timeout=)Las tres políticas, en la firma del mismo método.
threading.ThreadEl consumidor, que drena a un mensaje cada consume_ms.
time.sleepEl tiempo de consumo. Libera el GIL, así que la contención es real.

Rutas#

RutaQué muestra
/healthliveness
/produce-unbounded?messages=120&consume_ms=2queue_depth_peak = total producido; oldest_msg_age_ms_peak sin techo
/produce-bounded?...&policy=blockprofundidad acotada a capacity; producer_blocked_ms > 0, nada se pierde
/produce-bounded?...&policy=drop_oldestprofundidad acotada; dropped > 0, el productor nunca se frena
/produce-bounded?...&policy=dead_letterprofundidad acotada; dead_lettered > 0, revisable en /dlq
/queue/stateprofundidad pico, bytes ocupados y edad del mensaje más viejo
/dlq?limit=20contenido de la dead letter queue
/diagnostics/summaryacumulado por variante y política
/reset-lablimpia DLQ y contadores

Parámetros: messages (1–2000), capacity (1–1000), consume_ms (0–100, cuánto tarda el consumidor por mensaje), policy (block · drop_oldest · dead_letter).

Hub#

bash
docker compose -f compose.python.yml up -d --build
curl "http://127.0.0.1:8200/15/produce-unbounded?messages=120&consume_ms=2"
curl "http://127.0.0.1:8200/15/produce-bounded?messages=120&capacity=32&policy=block&consume_ms=2"
curl "http://127.0.0.1:8200/15/queue/state"

La lección que ningún stack cambia#

Las tres políticas pagan algo distinto y ninguna es gratis:

PolíticaQué paga
blocklatencia: la lentitud viaja aguas arriba hasta el cliente
drop_oldestdatos: se pierden mensajes, y en silencio salvo que se cuenten
dead_letterdeuda operativa: alguien tiene que mirar esa cola (caso 20)

Una cola sin límite parece una cuarta opción sin costo. No lo es: solo difiere el pago hasta el OOM.

Ver esta carpeta en GitHub ↗