🧪 Problem-Driven Systems Lab

🐍 Caso 09 β€” Python 3.12 con adapter y cache defensiva#

Implementacion operativa del caso 09 para contrastar una integracion externa directa contra una variante endurecida.

⬅️ Caso 09 Β· βš–οΈ Comparativa de los 7 stacks Β· 🐍 Perfil de Python Β· 🧬 Todos los perfiles

🎯 Que resuelve#

Modela un consumo de catalogo externo donde el proveedor puede:

  • cambiar esquema sin aviso;
  • responder con payload parcial o malformado;
  • reenviar eventos duplicados;
  • fallar en un subconjunto de items del batch.

La variante catalog-hardened agrega sanitizacion de SKU, validacion de esquema, idempotencia por event_id y procesamiento parcial tolerante a fallos.

πŸ’Ό Por que importa#

Este caso deja visible que la resiliencia frente a terceros no depende solo del timeout. TambiΓ©n importa la estabilidad del contrato, la validez de los identificadores y la capacidad de operar con informacion parcialmente valida sin contaminar el catalogo interno.

πŸ”¬ Analisis Tecnico de la Implementacion (Python)#

Las APIs de terceros fallan en formas sutiles. Este caso implementa integracion defensiva usando expresiones regulares, operadores de fusion y gestion de idempotencia en memoria.

  • Llamado Vulnerable (legacy): La funcion run_legacy_sync() acepta la respuesta del proveedor sin ninguna validacion. Si el proveedor envia un SKU con caracteres invalidos (SKU 100 con espacio, o X), el codigo lo acepta y lo inserta directamente en el catalogo interno. Si el proveedor omite un campo esperado (ej. price ausente), el acceso item["price"] lanza un KeyError que derrumba el batch completo. Si el mismo evento llega dos veces, se procesa dos veces sin deteccion de duplicado. El resultado es un catalogo potencialmente corrupto y un comportamiento no deterministico bajo condiciones de red reales.
  • Aislado Robusto (hardened): Introduce tres capas defensivas. Primero, sanitize_sku(sku) valida el SKU con re.match(r"^[A-Z0-9-]{4,20}$", sku) y retorna un default determinista si no pasa. Segundo, validate_schema(item) verifica la presencia de campos requeridos antes de procesar, descartando items invalidos en lugar de fallar el batch completo. Tercero, la idempotencia se gestiona con un set de processed_event_ids: if event_id in processed_event_ids: continue. Esto garantiza que eventos duplicados del proveedor sean silenciosamente ignorados sin afectar total_processed. El procesamiento parcial permite que items validos del batch sean aceptados aunque otros sean invalidos.

🧱 Servicio#

  • app β†’ API Python 3.12 con proveedor externo simulado, adapter de contrato, cache de idempotencia y metricas de calidad de datos.

πŸš€ Arranque#

bash
docker compose -f compose.yml up -d --build

Puerto local: 839 (modo aislado, ver opciones abajo).

Como consumir (dos opciones)#

Hub Python (recomendado, 8200 en compose.python.yml): este caso queda servido en http://localhost:8200/09/... junto a los otros 11 casos.

Modo aislado (839 en este compose.yml): levanta solo este caso, util cuando la medicion necesita procesar limpio (sin otros casos compartiendo runtime).

πŸ”Ž Endpoints#

bash
curl http://localhost:8200/09/
curl http://localhost:8200/09/health
curl "http://localhost:8200/09/catalog-legacy?scenario=malformed_sku&batch_size=10"
curl "http://localhost:8200/09/catalog-hardened?scenario=malformed_sku&batch_size=10"
curl http://localhost:8200/09/integration/state
curl "http://localhost:8200/09/sync-events?limit=10"
curl http://localhost:8200/09/diagnostics/summary
curl http://localhost:8200/09/metrics
curl http://localhost:8200/09/metrics-prometheus
curl http://localhost:8200/09/reset-lab

πŸ§ͺ Escenarios utiles#

  • schema_drift β†’ muestra normalizacion de contrato versus ruptura directa por KeyError.
  • malformed_sku β†’ legacy acepta SKUs invalidos; hardened sanitiza o rechaza.
  • duplicate_events β†’ legacy procesa dos veces; hardened detecta por event_id.
  • partial_failure β†’ legacy falla todo el batch; hardened procesa los items validos.

🧭 Que observar#

  • cuantos corrupted_items acumula legacy vs cuantos rejected_items registra hardened;
  • si idempotent_skips sube en hardened con el escenario duplicate_events;
  • como cambia data_quality_score entre modos en /diagnostics/summary;
  • si el batch completo falla en legacy ante un solo item invalido.

βš–οΈ Nota de honestidad#

No reemplaza una integracion real con colas, DLQ ni proveedores de terceros. Si reproduce las decisiones operativas que importan aqui: adapter, contrato defensivo, idempotencia y tolerancia a fallos parciales.

Ver esta carpeta en GitHub ↗