Adaptadores de proveedores
El adaptador del proveedor es una capa de integración aislada (layer anticorrupción, ACL) que traduce el contrato externo del proveedor (proveedor de juegos, pasarela de pago, KYC/AML, puntuación de riesgo, notificaciones, etc.) al lenguaje de dominio interno y de vuelta. Protege el dominio de API inestables, anomalías de red, evoluciones de esquemas y políticas de seguridad.
Objetivos clave:1. Decupling: ningún payload externo «crudo» entra en el núcleo.
2. Fiabilidad: gestione los fallos (timeouts, retries, DLQ, circuit breaker).
3. Consistencia: idempotencia, orden por clave, mensajería transaccional.
4. Operación: métricas, treysing, límites, aislamiento per-tenant y residency.
1) Área de responsabilidad del adaptador
Contratos: descripción de esquemas/endpoints externos; mapping → comandos/eventos internos.
Transporte: NAT/gRPC/WebSocket/SQS/Kafka/SFTP; agrupación de conexiones, backpressure.
Seguridad: mTLS, OAuth2, HMAC, claves/certificados por tenant/región, rotación de secretos.
Fiabilidad: temporizadores, retraídas con jitter, circuit breaker, deduplicación.
Idempotencia: 'Idempotency-Key '/' request _ id', almacenamiento de respuestas/estados.
Observabilidad: métricas de SLO, registros estructurales, rastreo.
Versioning: admite múltiples versiones de circuitos/endpoints.
Operaciones: fichflags, lanzamientos canarios, sandbox, certificación.
2) Dónde se aplican (ejemplos de contextos)
Game/RGS: inicio/cierre de la ronda, apuestas/ganancias, tokens de sesión, estados del proveedor.
Pagos/PSP: depósitos/retiros, estados de webhooks, chargeback, 3-D Secure.
KYC/AML: verificación, verificación de sanciones/RR, supervisión de transacciones.
Risk/Fraud: puntuación, disparadores, recomendaciones de bloqueo.
Comms: e-mail/SMS/push, límites de boletín, plantillas.
Cada tipo tiene su propia máquina de estate de eventos y el adaptador SLA está obligado a normalizarlo.
3) Contrato y mapping (interno ↔ externo)
Principios:- Introduzca el Lenguaje publicado dentro del adaptador y nunca arrastre hacia fuera el campo del proveedor.
- Todos los mensajes llevan 'tenant _ id', 'region', 'provider _ id', 'operation _ id', 'version _ ts'.
- Soportamos varias versiones de circuitos externos a través de mappers.
yaml mapping:
provider: "AcmeRGS"
version: "v3"
inbound:
SpinResultV3 -> Round. Resulted
BonusWinV3 -> Bonus. Wagered outbound:
StartRound -> POST /v3/sessions/{id}/start
Stake -> POST /v3/spins compat:
accepts: ["v2","v3"]
emits: ["v3"]
4) Idempotencia y orden
Request de-dup: 'Idempotency-Key: <operation_id>' en las solicitudes; storim '(op_id → estado final/respuesta)' con TTL.
Webhook de-dup: tabla 'inbox (proveedor, event_id)' como PK.
Orden por clave: serializamos las llamadas y el procesamiento por 'aggregate _ id' (por ejemplo, 'round _ id' o 'psp _ tx _ id').
Outbox/Inboxing: mensajería transaccional en ambos bordes de la línea de montaje.
5) Confiabilidad: temporizadores, retrayas, circuit breaker
Timeout: short client-side (orientado a p95), separado para connect/read.
Retraídas: sólo en retriable (5xx/timeout/429), retroceso exponencial + full jitter, límite de intento y dedupline total.
Circuit Breaker: abrir cuando crecen los errores/latencia; degradación graceful (por ejemplo, desactivar los fichajes secundarios de RGS, poner una «espera de resultado»).
DLQ: mensajes «venenosos» con una rica información meta, un redrive seguro.
yaml reliability:
timeout_ms:
connect: 1000 read: 1500 retry:
max_attempts: 6 initial_backoff_ms: 200 max_backoff_ms: 8000 jitter: full retry_on: [TIMEOUT, 5xx, 429]
circuit_breaker:
failure_rate_threshold: 20% # за окно slow_call_threshold_ms: 1500 half_open_max_calls: 10
6) Rate limits, cuotas, competitividad
Respete las restricciones del proveedor (RPS, burst, concurrency).
Implementa un WFQ/DRR (fairness) pluma-tenant para que el cliente «ruidoso» no se coma el presupuesto.
Respete los títulos 'Retry-After '/' X-RateLimit-'.
Colas internas + backpressure en el productor.
7) Seguridad y cumplimiento
Transporte: mTLS, TLS 1. 2 +, actuales cipher suites, certificados de pinning siempre que sea posible.
Autenticación: OAuth2 client-credentials/MTLS, HMAC (hashes firmados del cuerpo + timestamp), claves API.
Minimización PII: sólo los campos necesarios; enmascaramiento/edición en logs y DLQ.
Secretos: KMS/HashiCorp Vault, rotación automática, aislamiento per tenant/region.
Cumplimiento: PCI DSS para PSP, almacenamiento de tokens en lugar de PAN, GDPR/leyes de datos locales.
8) Multi-tenant y multi-región
Configuración de claves/endpoints por tenante/región.
Residencia de datos: los retos se hacen desde la región «doméstica»; región cruzada - sólo unidades.
Aislamiento: grupos de conexiones propios y límites per tenant.
yaml tenants:
T1:
region: eu-central provider_keys:
acme_rgs: { client_id: "...", cert_ref: "vault://..." }
psp_foo: { hmac_key_ref: "kms://..." }
endpoints:
acme_rgs: "https://eu. api. acme-rgs. com"
psp_foo: "https://eu. api. psp-foo. com"
T2:
region: sa-east
...
9) Observabilidad: métricas, registros, treysing
Métricas:- Aciertos/errores por clase (2xx/4xx/5xx/timeout/429).
- p50/p95/p99 latencia por método.
- Rate-limit activación, apertura/cierre breaker, DLQ-rate, redrive-success.
- Registros estructurales: 'tenant _ id', 'provider _ id', 'operation _ id', 'endpoint', 'status', 'attempt',' backoff _ ms'.
- Senderismo: un solo 'trace _ id', durmiendo 'serialize → nat → receive → map → publish', etiquetas 'schema _ version', 'region'.
10) Versioning y fichflags
Mantener un contrato externo paralelo v1/v2; migración - canario/por tenantes.
Cualquier nueva ficha del proveedor está detrás de la bandera; conmutación sin lanzamiento.
Tratado de evolución: additive-first, validación rigurosa de esquemas (JSON Schema/Proto).
11) Playbooks (runbooks)
1. Aluvión 429/límites: habilitar el trottling global, respetar 'Retry-After', redistribuir ventanas entre tenantes.
2. Crecimiento de los temporizadores: reducir la concurrencia, aumentar los temporizadores con cuidado, abrir el breaker, incluir la degradación del fich.
3. Schema mismatch: congelar el redrive, habilitar el mapper compatible, realizar el backfill/recrecking.
4. Flap webhooks: cambiar a modo pull/reconcile, aplicar inbox-dedoop.
5. Incidente en el proveedor: cambiar a sandbox/respaldo DC (si lo hay), activar operaciones «diferidas».
12) Pruebas
Pruebas contractuales: producer/consumer contra fixturas fijas del proveedor.
Pruebas de caos: retrasos, drops, out-of-order, duplicados, respuesta parcial, ruptura de conexión.
Performance: estrés en las especias de burst; medición p95/p99, comportamiento breaker.
Idempotencia: la repetición de los mismos 'operation _ id' no crea efectos adicionales.
E2E en sandbox: escenarios happy-path/chargeback/disputas/cancelaciones/recalco.
13) Opciones de implementación (deployment patterns)
Adaptador de servicio separado: + aislamiento, lanzamientos independientes, − red opcional.
Sidecar/plugin: + localización de llamadas, − más difícil de administrar versiones.
Biblioteca: + simplemente incrustar, − alta coupling y versiones de varios lados.
Recomendación: adaptador de servicio con una API clara y su ciclo de lanzamiento.
14) Ejemplo de API del adaptador (pseudo)
http
POST /adapters/psp/authorize
Headers:
X-Tenant: T1
Idempotency-Key: op-uuid
Body:
{ "amount":"10. 00","currency":"EUR","method":"card","card_token":"tok_..." }
→ 202 Accepted
{
"operation_id":"op-uuid",
"status":"PENDING",
"as_of":"2025-10-31T12:00:00Z"
}
El webhook del proveedor → el adaptador → el núcleo:
- Webhook con 'provider _ event _ id' → 'inbox' (PK on '(provider,event_id)') → mapping → evento de dominio 'PaymentAuthorized'.
15) Errores típicos
Arrastrar un esquema externo «crudo» a un dominio → conectividad rígida y migraciones costosas.
Falta de idempotencia e inbox/outbox → tomas de efectos y estados fantasma.
Retraídas sin jitter/límites → tormenta y ban por límite de velocidad.
La única piscina global sin fairness → un tenant «pone» a todos.
Los registros sin la edición PII/identificadores → no se pueden investigar incidentes y riesgos de cumplimiento.
No hay canarios/banderas → la liberación rompe a todos a la vez.
Ignora 'Retry-After' y los horarios de servicio del proveedor.
16) Lista de verificación antes de la venta
- Mapping de circuitos externos → lenguaje interno; versiones y compatibilidad con versiones anteriores.
- Idempotencia de consultas/webhooks ('operation _ id', 'inbox').
- Taimautas, retraídas con full-jitter, circuito breaker, DLQ y redrive seguro.
- Rate limits и fairness per tenant; respeto 'Retry-After'.
- mTLS/OAuth/HMAC, rotación de secretos, minimización PII, auditoría de acceso.
- Aislamiento regional y residencia de datos; configuraciones per tenant/region.
- Métricas p95/p99, error por clase, breaker/429/DLQ-rate; treising.
- Sandbox y pruebas contractuales; rollout canario y fichflagi.
- Playbucks de incidentes y entrenamiento on-call.
- Documentación: SLA, límites, esquemas, procesos de evolución.
la Conclusión
Los adaptadores de proveedores son un escudo y un traductor entre su dominio y el mundo exterior. Una ACL fuerte con idempotencia, control de errores y observabilidad hace que las integraciones sean predecibles, reduce el costo de los cambios en el proveedor y protege contra «fallos de cadena». Diseñe los adaptadores como componentes autogestionables y controlables, y su «mundo exterior» dejará de romper la arquitectura interna.