🧪 Problem-Driven Systems Lab

☕ Caso 08 — Java 21#

⬅️ Caso 08 · ⚖️ Comparativa de los 7 stacks · ☕ Perfil de Java · 🧬 Todos los perfiles

Stack Java operativo del caso 08. Cutover gradual con proxy de compatibilidad de contrato + event bus thread-safe.

Primitivas nativas#

PrimitivaRol
Function<PriceRequestOld, PriceRequestNew>Proxy de compatibilidad. Traduce contrato viejo {cost_usd} ↔ nuevo {price, currency} en vuelo.
CopyOnWriteArrayList<Consumer<String>>EventBus thread-safe — equivalente al EventEmitter de Node, sin libreria externa. Reads paralelos sin lock; writes raros copian el array.
record PriceRequestOld/NewSnapshots inmutables de cada contrato.
ConcurrentHashMap<String, Boolean>Progreso de cutover por consumer.

Contraste#

Big-bang — cambio de contrato rompe consumers sensibles:

java
// Nuevo modulo solo entiende {price, currency}; consumer manda {cost_usd}
return "contract_violation";   // checkout, partners, backoffice todos rotos

Compatible — proxy traduce old→new + event bus notifica avance:

java
PriceRequestNew translated = compatProxy.apply(old);   // {cost_usd}→{price,currency}
cutoverProgress.put(consumer, true);
emit("cutover_done:" + consumer);                       // bus notifica suscriptores

Rutas#

RutaQue muestra
/healthliveness
/pricing-bigbang?consumer=checkout&sku=ABC&cost_usd=100contract_violation (rompe)
/pricing-compatible?consumer=checkout&sku=ABC&cost_usd=100translated payload + cutover_done=true + emite evento
/flowscutover_progress por consumer + recent_events (max 50)
/diagnostics/summaryproxy_hits, contract_tests_passed, bigbang_broken
/reset-lablimpia state

Hub#

docker compose -f compose.java.yml up -d --build
curl "http://127.0.0.1:8400/08/pricing-compatible?consumer=checkout&sku=ABC&cost_usd=100"
curl http://127.0.0.1:8400/08/flows

Modo aislado#

Puerto 848.

Por que CopyOnWriteArrayList y no synchronized List#

Reads del event bus son frecuentes (cada emit recorre todos los suscriptores). Writes (add/remove subscriber) son raros. CopyOnWriteArrayList es exactamente este trade-off: lectores no se bloquean nunca; escritores copian todo el array (caro, pero infrecuente). Espejo arquitectonico del EventEmitter Node sin dependencias.

Ver esta carpeta en GitHub ↗