🧪 Problem-Driven Systems Lab

🔵 Caso 08 — .NET 8#

⬅️ Caso 08 · ⚖️ Comparativa de los 7 stacks · 🔵 Perfil de .NET · 🧬 Todos los perfiles

Stack .NET operativo del caso 08. Cutover gradual con proxy de compatibilidad de contrato + event bus thread-safe basado en event Action.

Primitivas .NET nativas#

PrimitivaRol
Func<PriceRequestOld, PriceRequestNew>Proxy de compatibilidad. Traduce contrato viejo {cost_usd} ↔ nuevo {price, currency} en vuelo.
event Action<string> + ImmutableList<Action<string>>EventBus thread-safe. Reads paralelos sin lock; writes (subscribe/unsubscribe) generan una copia. Espejo del EventEmitter Node y del CopyOnWriteArrayList Java.
record PriceRequestOld/NewSnapshots inmutables de cada contrato.
ConcurrentDictionary<string, bool>Progreso de cutover por consumer.

Contraste#

Big-bang — cambio de contrato rompe consumers sensibles:

csharp
// Nuevo modulo solo entiende {Price, Currency}; consumer manda {CostUsd}
return "contract_violation";   // checkout, partners, backoffice todos rotos

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

csharp
PriceRequestNew translated = compatProxy(old);   // {CostUsd}→{Price,Currency}
cutoverProgress[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.dotnet.yml up -d --build
curl "http://127.0.0.1:8500/08/pricing-compatible?consumer=checkout&sku=ABC&cost_usd=100"
curl http://127.0.0.1:8500/08/flows

Modo aislado#

docker compose -f cases/08-critical-module-extraction-without-breaking-operations/dotnet/compose.yml up -d --build
curl http://127.0.0.1:858/health

Por que ImmutableList<Action<string>> y no List<Action<string>> con lock#

Reads del event bus son frecuentes (cada emit recorre todos los suscriptores). Writes (add/remove subscriber) son raros. ImmutableList<T> es exactamente este trade-off: lectores nunca se bloquean ni copian; escritores generan una nueva lista persistente (caro, pero infrecuente). Espejo arquitectonico del EventEmitter Node y del CopyOnWriteArrayList<Consumer> Java — el mismo problema resuelto con la primitiva idiomatica de cada plataforma.

Ver esta carpeta en GitHub ↗