Адаптеры провайдеров
Адаптер провайдера — изолированный слой интеграции (anti-corruption layer, ACL), который переводит внешний контракт поставщика (игровой провайдер, платежный шлюз, KYC/AML, риск-скоринг, нотификации и т. д.) во внутренний доменный язык и обратно. Он экранирует домен от нестабильных API, сетевых аномалий, эволюций схем и политик безопасности.
Ключевые цели:1. Декуплинг: никакой «сырой» внешний payload не попадает в ядро.
2. Надежность: управляйте сбоями (timeouts, retries, DLQ, circuit breaker).
3. Согласованность: идемпотентность, порядок по ключу, транзакционный месседжинг.
4. Эксплуатация: метрики, трейсинг, лимиты, пер-тенантная изоляция и residency.
1) Зона ответственности адаптера
Контракты: описание внешних схем/эндпоинтов; маппинг → внутренние команды/события.
Транспорт: REST/gRPC/WebSocket/SQS/Kafka/SFTP; пул соединений, backpressure.
Безопасность: mTLS, OAuth2, HMAC, ключи/сертификаты per tenant/region, ротация секретов.
Надежность: таймауты, ретраи с джиттером, circuit breaker, дедупликация.
Идемпотентность: `Idempotency-Key`/`request_id`, хранение ответов/статусов.
Наблюдаемость: метрики SLO, структурные логи, трассировка.
Версионирование: поддержка нескольких версий схем/эндпоинтов.
Операции: фичефлаги, канареечные релизы, песочницы, сертификация.
2) Где применяются (примеры контекстов)
Game/RGS: старт/закрытие раунда, ставки/выигрыши, токены сессий, статусы провайдера.
Payments/PSP: депозиты/выводы, webhooks статусов, chargeback, 3-D Secure.
KYC/AML: верификации, санкционные/PEP-проверки, мониторинг транзакций.
Risk/Fraud: скоринг, триггеры, рекомендации блокировок.
Comms: e-mail/SMS/push, лимиты рассылок, шаблоны.
Каждый тип имеет свою стейт-машину событий и SLA — адаптер обязан нормализовать ее.
3) Контракт и маппинг (внутренний ↔ внешний)
Принципы:- Вводим Published Language внутри адаптера и никогда не протаскиваем наружу поля провайдера.
- Все сообщения несут `tenant_id`, `region`, `provider_id`, `operation_id`, `version_ts`.
- Поддерживаем несколько версий внешних схем через мапперы.
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) Идемпотентность и порядок
Request de-dup: `Idempotency-Key: <operation_id>` в запросах; сторим `(op_id → финальный статус/ответ)` с TTL.
Webhook de-dup: таблица `inbox(provider, event_id)` как PK.
Порядок по ключу: сериализуем вызовы и обработку по `aggregate_id` (например, `round_id` или `psp_tx_id`).
Outbox/Inboxing: транзакционный месседжинг на обоих краях конвейера.
5) Надежность: таймауты, ретраи, circuit breaker
Таймауты: короткие client-side (p95-ориентированные), отдельные для connect/read.
Ретраи: только на retryable (5xx/timeout/429), экспоненциальный backoff + full jitter, лимит попыток и общий дедлайн.
Circuit Breaker: открывать при росте ошибок/латентности; graceful degradation (например, отключить второстепенные фичи RGS, ставить «ожидание результата»).
DLQ: «ядовитые» сообщения с богатой мета-информацией, безопасный редрайв.
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, квоты, конкурентность
Соблюдайте ограничения провайдера (RPS, burst, concurency).
Реализуйте пер-тенантный WFQ/DRR (fairness), чтобы «шумный» клиент не съедал бюджет.
Уважайте `Retry-After`/`X-RateLimit-` заголовки.
Внутренние очереди + backpressure на продьюсере.
7) Безопасность и соответствие
Транспорт: mTLS, TLS 1.2+, актуальные cipher suites, pinning сертификатов по возможности.
Аутентикация: OAuth2 client-credentials/MTLS, HMAC (подписанные хэши тела + timestamp), API-ключи.
PII-минимизация: только необходимые поля; маскировка/редакция в логах и DLQ.
Секреты: KMS/HashiCorp Vault, автоматическая ротация, изоляция per tenant/region.
Комплаенс: PCI DSS для PSP, хранение токенов вместо PAN, GDPR/локальные законы о данных.
8) Мульти-тенант и мульти-регион
Конфигурация ключей/эндпоинтов на тенанта/регион.
Data residency: вызовы делаются из «домашнего» региона; кросс-регион — только агрегаты.
Изоляция: собственные пулы соединений и лимиты 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) Наблюдаемость: метрики, логи, трейсинг
Метрики:- Успехи/ошибки по классам (2xx/4xx/5xx/timeout/429).
- p50/p95/p99 latency по методу.
- Rate-limit срабатывания, открытие/закрытие breaker, DLQ-rate, redrive-success.
- Структурные логи: `tenant_id`, `provider_id`, `operation_id`, `endpoint`, `status`, `attempt`, `backoff_ms`.
- Трейсинг: единый `trace_id`, спаны «serialize → send → receive → map → publish», теги `schema_version`, `region`.
10) Версионирование и фичефлаги
Поддерживайте параллельно v1/v2 внешнего контракта; миграция — канареечная/по тенантам.
Любая новая фича провайдера — за флагом; переключения без релиза.
Договор об эволюции: additive-first, строгая валидация схем (JSON Schema/Proto).
11) Плейбуки (runbooks)
1. Шквал 429/лимиты: включить глобальный троттлинг, уважать `Retry-After`, перераспределить окна между тенантами.
2. Рост таймаутов: уменьшить concurrency, увеличить таймауты осторожно, открыть breaker, включить деградацию фич.
3. Schema mismatch: заморозить редрайв, включить совместимый маппер, выполнить backfill/репроцессинг.
4. Флап вебхуков: перейти на pull/reconcile режим, применить inbox-дедуп.
5. Инцидент у провайдера: переключить на песочницу/резервный DC (если есть), активировать «отложенные» операции.
12) Тестирование
Контрактные тесты: producer/consumer против зафиксированных фикстур провайдера.
Хаос-тесты: задержки, дропы, out-of-order, дубликаты, частичный ответ, разрыв соединения.
Performance: стресс на burst-спайках; измерение p95/p99, поведение breaker.
Идемпотентность: повтор одинаковых `operation_id` не создает дополнительных эффектов.
E2E в песочницах: сценарии happy-path/chargeback/споры/отмена/рекальк.
13) Варианты реализации (deployment patterns)
Отдельный сервис-адаптер: + изоляция, независимые релизы; − доп. сеть.
Sidecar/плагин: + локальность вызовов; − сложнее управлять версиями.
Библиотека: + просто встраивать; − высокий coupling и разношерстные версии.
Рекомендация: сервис-адаптер с четким API и своим релизным циклом.
14) Пример API адаптера (псевдо)
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"
}
Вебхук провайдера → адаптер → ядро:
- Вебхук с `provider_event_id` → `inbox` (PK на `(provider,event_id)`) → маппинг → доменное событие `PaymentAuthorized`.
15) Типичные ошибки
Протаскивание «сырой» внешней схемы в домен → жесткая связность и дорогие миграции.
Отсутствие идемпотентности и inbox/outbox → дубли эффектов и фантомные состояния.
Ретраи без джиттера/лимитов → шторм и бан по rate limit.
Единственный глобальный пул без fairness → один тенант «кладет» всех.
Логи без PII-редакции/идентификаторов → нельзя расследовать инциденты и риск комплаенса.
Нет канареек/флагов → релиз ломает всех сразу.
Игнорирование `Retry-After` и расписаний обслуживания провайдера.
16) Чек-лист перед продом
- Маппинг внешних схем → внутренний язык; версии и обратная совместимость.
- Идемпотентность запросов/вебхуков (`operation_id`, `inbox`).
- Таймауты, ретраи с full-jitter, circuit breaker, DLQ и безопасный редрайв.
- Rate limits и fairness per tenant; уважение `Retry-After`.
- mTLS/OAuth/HMAC, ротация секретов, PII-минимизация, аудит доступа.
- Региональная изоляция и data residency; конфиги per tenant/region.
- Метрики p95/p99, ошибка по классам, breaker/429/DLQ-rate; трейсинг.
- Песочницы и контрактные тесты; канареечный rollout и фичефлаги.
- Плейбуки инцидентов и обучение on-call.
- Документация: SLA, лимиты, схемы, процессы эволюции.
Заключение
Адаптеры провайдеров — это щит и переводчик между вашим доменом и внешним миром. Сильный ACL с идемпотентностью, контролем ошибок и наблюдаемостью делает интеграции предсказуемыми, снижает стоимость изменений у провайдера и защищает от «сбоев по цепочке». Проектируйте адаптеры как самостоятельные, управляемые компоненты — и ваш «внешний мир» перестанет ломать внутреннюю архитектуру.