Rate Budget ETM
NOTE
Статус: Target service boundary. Документ описывает целевую сервисную границу. Код либо полностью отсутствует, либо существует только как scaffold — смотрите секцию «Статус документа» ниже для точного указания на код. Правила маркировки — в
50-processes/documentation-standard.md.
Стратегия обхода rate-лимитов ETM с учётом множественных credentials.
См. ../../../../10-business/contexts/credentials.md для модели credentials.
Лимиты ETM (per credential)
Лимиты ETM применяются к учётной записи, не к нашему IP-аккаунту целиком (это нормально для дистрибьюторов: ограничения по login).
POST /user/login— 1 req / 2 мин на одну учётку.GET /goods/*— 1 req / сек на одну учётку.GET /goods/remains?store=X— рекомендуем не чаще 1 req / 10 сек на учётку.- Async jobs
/job/create,/job/{uuid}— без явного лимита, polling разумный.
Превышение по конкретной учётке → блокировка (а не блокировка нашего IP в целом).
Множитель от credentials
Если у нас:
- 1 системная credential (ETM-договор нашей компании);
- N клиентских credentials (договоры наших клиентов с ETM);
то catalog discovery (товарная канва: характеристики, жизненный цикл, медиа, справочник производителей) опрашивается через все credentials по схеме round-robin — это всегда обогащает наш общий каталог (и не нарушает privacy, т.к. характеристики одинаковы для всех клиентов одного и того же товара).
Pricing/Stock observations не масштабируются множителем, поскольку наблюдения per-customer не взаимозаменяемы. Но через дедупликацию (SupplierCredentialGroup) одинаковые credentials у разных клиентов опрашиваются один раз, экономя rate budget.
При N=20 клиентских credentials catalog rate budget вырастает в ~21 раз. Это позволяет, например, обновлять характеристики 100% каталога ежедневно вместо 14 дней.
Стратегия по операциям
1. Сессии (per credential)
- Одна постоянная сессия на каждую активную credential.
- Refresh каждой за ~90 минут до истечения 2h.
- Login per credential лимитируется 1 req / 2 min — у каждой credential свой bucket.
- Распределённый lock в Redis для защиты от одновременного re-login per credential.
- При 403 от запроса с конкретной credential → инвалидировать её сессию и повторно залогиниться.
2. Полная выгрузка номенклатуры (SgGds)
- Через системную credential — раз в сутки.
- Через клиентские credentials с
shared_for_catalog— round-robin, чтобы получить более широкое покрытие (некоторые SKU видны только определённым категориям клиентов). - Каждая выгрузка SgGds = отдельная async job; результаты мёржатся.
3. Catalog discovery / характеристики (/goods/{id})
Самое масштабируемое направление.
- Нужно обновить ~500k SKU.
- При 1 credential: ~6 суток на полный обход (1 req/sec, 86k/сутки).
- При 21 credential (1 system + 20 shared): один полный обход за ~7 часов.
Стратегия:
- Очередь приоритетов SKU (hot → warm → cold).
- Пул воркеров: по одному воркеру на каждую активную credential.
- Каждый воркер берёт следующий SKU из приоритетной очереди и делает запрос через свою credential.
- Полученный payload пишется как observation от этой credential, но характеристики применяются к общему SupplierOffer (товарная канва общая).
4. Pricing / Stock — per customer
Здесь нет round-robin, поскольку наблюдения не взаимозаменяемы:
- Customer X имеет credential → его цены/остатки обновляются через его credential.
- Customer Y → через свою.
- Customer без credential → используется системная (B2C / fallback).
Каждая customer credential обновляет:
- Цены товаров, которые этот клиент когда-либо запрашивал — приоритет.
- Полный его прайс — раз в сутки (через batch или ручной обход hot-SKU).
- Остатки на интересующих складах — каждые 6 часов.
Системная credential обновляет:
- Цены и остатки для всех остальных SKU (для B2C / новых клиентов / для обогащения).
5. Webhooks (если ETM будет поддерживать в будущем)
При получении webhook для credential X → немедленная обработка, без расходования polling budget.
Реализация в конфиге
configs/connectors/etm.yaml:
rate_limit_per_credential:
login: { rate: 1, period: 120s }
goods_read: { rate: 1, period: 1s }
price_read: { rate: 1, period: 1s }
stock_read: { rate: 1, period: 1s }
stock_batch: { rate: 1, period: 10s }
async_poll: { rate: 1, period: 60s }
credential_buckets:
# bucket key pattern: ratelimit:etm:{credential_id}:{endpoint}
isolation: per_credential
routing:
catalog_discovery:
strategy: round_robin
eligible_credentials: "all_active" # все active credentials, независимо от scope
pricing:
strategy: customer_first
fallback: system
freshness_ttl: 6h
stock:
strategy: customer_first
fallback: system
freshness_ttl: 2h
dedup:
strategy: by_fingerprint # одинаковые fingerprint опрашиваются один раз через primaryСуточный бюджет (пример)
Допустим: 1 system + 5 customer credentials (3 из них shared_for_catalog).
| Операция | Доступные credentials | req/credential/day | Total req/day |
|---|---|---|---|
| Catalog discovery (hot+warm) | 1+3 = 4 | ~20 000 | ~80 000 |
| SgGds (jobs) | 1+3 = 4 | ~50 (poll) | ~200 |
| Stock batch | 1+5 = 6 | ~50 | ~300 |
| Customer pricing (per customer) | 1 (own) | ~10 000 | по ~10 000 на каждого |
| System pricing/stock (B2C/fallback) | 1 (system) | ~25 000 | 25 000 |
Использование лимита одной credential — ≤ 50%.
Итог: при 5 customer credentials catalog обновляется в 4× быстрее vs single-credential, и каждый customer получает свежие данные через свою credential.
Мониторинг
Метрики per credential:
etm_api_requests_total{credential_id, endpoint, status}— все запросы с разбивкой по credential.etm_credential_usage_ratio{credential_id}— % использования лимита.etm_credential_failures_total{credential_id, type}— auth / rate / 5xx.etm_observations_recorded_total{credential_scope, type}— observations по типу.
Алерты:
-
85% использования лимита одной credential за час.
- 5+ подряд ошибок авторизации одной credential → пометить как
failing, уведомить клиента. - Customer credential не давала observations > 24 часов при наличии активных запросов клиента.
Резервный сценарий при деградации
- Падение системной credential → переключение catalog discovery на customer (shared) credentials; B2C-pricing вынужденно использует stale-данные с пометкой.
- Падение customer credential → его pricing использует системную с пометкой «приближённо».
- Падение всех credentials → деградация ingestion, алерт, UI показывает stale-данные с явной пометкой.
TBD
- Фактический размер каталога (нужно получить от менеджера).
- Возможность договориться на более высокий rate (платный tier).
- Использование batch-метода для цен — оценить реальную эффективность.
- Политика биллинга для клиентов с
shared_for_catalog(бенефит).