Коннектор ETM

NOTE

Статус: Target service boundary. Документ описывает целевую сервисную границу. Код либо полностью отсутствует, либо существует только как scaffold — смотрите секцию «Статус документа» ниже для точного указания на код. Правила маркировки — в 50-processes/documentation-standard.md.

Этот README описывает целевой коннектор поставщика ETM внутри границы ingestion. Читайте его, когда нужно понять специфику API ETM, маппинг данных и ограничения по rate/session handling.

Назначение

Модуль, подключающий поставщика ETM к системе через их HTTP API и публикующий сырые payload’ы в общий ingestion pipeline.

Статус документа

  • Тип знания: target service boundary
  • Статус реализации: ETM ingestion connector, provider-contract suite и mock уже реализованы
  • Текущее место кода: backend/internal/core/ingestion/infra/etm/, backend/internal/core/normalization/infra/etm/, backend/test/provider-contract/, deploy/docker/resources/mock-etm/
  • Что читать дальше: ../framework.md, spec.md, mapping.md, rate-budget.md

ETM в Supplier Network

ETM — пример узла с множественной ролью в графе поставщиков (см. ../../../../10-business/contexts/supplier-network.md).

При получении offer через ETM SupplyChainTrace строится так:

  • observed_via_supplier_ref = ETM
  • api_provider_ref = ETM
  • sales_agent_ref = ETM
  • distributor_ref = ETM
  • warehouse_operator_refs = [ETM-РЦ-11, ETM-РЦ-12, ...]
  • manufacturer_ref = <Manufacturer из mnf_code>

Область действия

Входит:

  • Авторизация и управление сессией (POST /user/login).
  • Полная выгрузка номенклатуры через async job.
  • Запрос характеристик, остатков и цен по SKU.
  • Загрузка справочника производителей.
  • Сохранение raw payload в S3 и публикация в Kafka.

Не входит:

Публичный контракт

Вход

  • Cron-триггеры на full catalog и stock refresh.
  • События на догрузку отсутствующих характеристик.
  • Ручной запуск из административного потока.

Выход

  • Kafka-топик raw.supplier.etm.payload.v1.
  • Raw payload в S3: raw/etm/<yyyy>/<mm>/<dd>/<payload_id>.json.

Внутренняя архитектура

В целевом состоянии код коннектора должен жить в backend/internal/connectors/etm/ и следовать общему connector pattern:

  • domain/ — ETM-specific модели и ошибки.
  • app/ — команды fetch и портовые интерфейсы.
  • infra/integration/ — HTTP client, session, parser, async job polling.
  • infra/persistence/ — raw writer в S3/Kafka.

Общий orchestration/runtime слой описан в ../../README.md и ../framework.md.

Зависимости

  • PostgreSQL (supplier_session, async_supplier_job, raw_payload_ref).
  • Kafka.
  • Redis.
  • S3.
  • Secret backend / master key provider для credentials ETM.

Хранилище

  • Читает: supplier и supplier_warehouse.
  • Пишет: supplier_session, async_supplier_job, raw_payload_ref.

Конфигурация

Ключевые настройки ETM-коннектора:

enabled: true
api:
  base_url: "https://ipro.etm.ru/api/v1"
  test_base_url: "https://itest2.etm.ru/api/v1"
  mock_base_url: "http://mock-etm:9000"
  active: "test"
  timeout: 30s
credentials_ref: "secret://connectors/etm/system"
session:
  ttl: 90m
  login_backoff: 5m
rate_limit:
  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: 4, period: 60s }
  async_poll:   { rate: 1, period: 60s }

Детали параметров и лимитов — в rate-budget.md.

Локальный запуск

Выделенного ingestor runtime в текущем репозитории пока нет, поэтому команды вроде make run/ingestor относятся к целевому состоянию и сейчас не работают.

Сейчас можно только поднять инфраструктурный контур:

make infra-up
make web-up

Тестирование

  • Для будущей реализации обязательны unit-тесты ETM-specific parsing/session logic.
  • Есть integration/provider-contract тесты против mock-сервера API ETM.
  • Есть fixture-based regression tests на реальные payload’ы.
  • Есть gated live-smoke TestETMContract_RealServiceSmoke для itest2/prod.

Наблюдаемость

В целевом состоянии коннектор должен публиковать метрики:

  • etm_api_requests_total{endpoint,status}
  • etm_api_duration_seconds{endpoint}
  • etm_rate_limit_wait_seconds{endpoint}
  • etm_session_refreshes_total
  • etm_async_jobs_total{state}
  • etm_raw_payloads_written_total{type}

Сейчас отдельной observability-поверхности у коннектора ETM нет.

Открытые вопросы / TODO

  • Запросить права на изображения без водяных знаков.
  • Проверить, возможны ли webhooks у ETM.
  • Вынести общие паттерны в shared base после появления второго коннектора.

Связанные документы