Runbook: полный каталог и details-обогащение поставщиков

Severity (default): P1, если supplier catalog не обнаруживает новые SKU; P2, если новые SKU есть, но не доезжают характеристики. Owner: Ассортимент / platform ingestion.

Симптом

  • На публичном сайте поставщика существует товар, но в supplier_offers нет его SKU или manufacturer article.
  • Полный catalog job завершается success, хотя в connector_events нет ingestion.bulk.cycle.completed.
  • У уже загруженного offer нет характеристик или Код ТН ВЭД.

catalog обнаруживает все внешние SKU, details обогащает только уже существующие offers. ETM Web — details-only source; он не может обнаружить новый SKU. Полный проход не имеет item/page cap: provider page size, RPS, burst, retry и timeout остаются обязательными ограничителями API.

Диагностика

После deploy из git-шаблона убедитесь, что bootstrap создал независимые расписания. Не исправляйте deploy/.env вручную: следующий deploy затрёт изменение.

SELECT supplier_ref, job_kind, job_key, interval_seconds, target_params,
       enabled, last_outcome, last_success_at
  FROM ingestion_schedules
 WHERE supplier_ref IN ('etm', 'etm_web', 'iek', 'systeme', 'russvet')
 ORDER BY supplier_ref, job_kind;

Ожидаемый минимум:

  • etm/catalog — 86400 s, etm/details — 300 s, etm/commerce — 900 s;
  • etm_web/details — 1800 s и нет etm_web/catalog;
  • iek, systeme, russvet имеют catalog без max_pages_per_tick/max_items_per_tick;
  • target_params catalog jobs — {}.

Проверить последние реальные jobs:

SELECT supplier, job_kind, status, started_at, completed_at,
       item_count, ok_count, partial_count, errored_count, error_message
  FROM ingestion_job_runs
 WHERE supplier IN ('etm', 'etm_web', 'iek', 'systeme', 'russvet')
 ORDER BY started_at DESC
 LIMIT 60;

Полным считать только цикл с terminal evidence:

SELECT supplier, payload->>'job_kind' AS job_kind, outcome, created_at,
       payload->>'item_count' AS full_cycle_item_count,
       payload->>'full_cycle_exact' AS full_cycle_exact
  FROM connector_events
 WHERE event = 'ingestion.bulk.cycle.completed'
   AND supplier IN ('etm', 'iek', 'systeme', 'russvet')
 ORDER BY created_at DESC
 LIMIT 40;

Если job закрывается без этого события, это не полный проход: pipeline обязан вернуть ingestion.connector.partial_success и оставить cursor для повторного прохода.

Для контрольного ETM товара TR-JB303 (ETM SKU 103354) сначала проверить offer, затем raw characteristics:

SELECT id, supplier, supplier_sku, manufacturer_article, mpn_norm,
       canonical_id, last_seen_at
  FROM supplier_offers
 WHERE supplier = 'etm'
   AND (supplier_sku = '103354' OR mpn_norm = 'trjb303');
 
SELECT ocr.observed_at, ocr.supplier_code, ocr.display_name, ocr.raw_value
  FROM offer_characteristic_raw ocr
  JOIN supplier_offers so ON so.id = ocr.offer_id
 WHERE so.supplier = 'etm'
   AND so.supplier_sku = '103354'
   AND lower(ocr.display_name) IN ('код тн вэд', 'код тнвэд')
 ORDER BY ocr.observed_at DESC;

Ожидаем Код ТН ВЭД со значением 7616999008. Затем проверить downstream стадии по offer ID: charnorm mapping/raw, match decision и canonical assignment.

Смягчение

  1. Если catalog не имеет terminal event, не помечайте его завершённым и не запускайте Web scraper как замену discovery.
  2. Проверьте активные system credentials через Credentials BC / безопасный DB metadata query, не читая и не выводя секрет. Для ETM сравните visibility SgGds API с публичным SKU 103354.
  3. Дождитесь или запустите штатный ETM catalog job; после появления offer details jobs ETM API и ETM Web автоматически могут его обогатить.
  4. При provider 429/5xx сохраняйте RPS/burst и cursor. Не повышайте concurrency и не вводите SKU cap как постоянное «лечение».

Устранение root cause

  • Исправлять только в исходниках и deploy/prod-env-template.env, затем deploy запуском, который выполняет ingestion-bootstrap --from-env.
  • Для catalog не устанавливать *_CATALOG_MAX_ITEMS, max_pages_per_tick или max_items_per_tick выше нуля. Значение 0 означает весь каталог.
  • Details-specific sources также не должны иметь искусственный SKU cap: SUPPLIER_ETM_DETAILS_MAX_ITEMS=0, SUPPLIER_SYSTEME_CARD_DETAILS_MAX_ITEMS_PER_TICK=0, SUPPLIER_RUSSVET_SPECS_MAX_ITEMS_PER_TICK=0.
  • Не менять provider page size, RPS/burst/retry/timeout без отдельного provider-rate-limit анализа.

Проверка живого контура

Используйте DB-backed system credentials и проведите полный контур:

  1. supplier-sync ETM catalog → DB/raw storage → наличие 103354;
  2. ETM API details и ETM Web details → offer_characteristic_raw;
  3. charnorm-workermatcher-worker с LLM → canonical-assignment-worker;
  4. DB assertions для offer, raw characteristics, mapping, match decision и canonical assignment;
  5. по одному terminal catalog event для IEK, Systeme и Russvet.

Ограниченный live tick полезен для доступности credentials, но не доказывает полный catalogue cycle. Реальная проверка должна следовать live supplier contour.

Эскалация

  • Если public SKU недоступен через supplier API после полного terminal cycle, приложите credential scope, timestamp и безопасный provider status в тикет поставщику: это visibility/account issue, не matcher issue.
  • Если terminal marker не приходит, эскалировать владельцу ingestion connector с job run, cursor scope и provider page diagnostics.
  • Если offer и raw characteristics есть, но их нет в канонике, эскалировать charnorm/matcher/canonical-assignment по результатам downstream assertions.

Связано