Живая актуализация цен и остатков (live-refresh)
Публичное API отдаёт цены/остатки по состоянию базы Tracium. Когда клиенту нужна актуальная цена и наличие «на сейчас» (просчёт сметы перед коммерческим предложением), система по запросу опрашивает поставщика напрямую:
- под кредами клиента (кабинет → «Учётные данные») — приоритет: поставщик отдаёт договорные цены клиента;
- под системными кредами Tracium — fallback: публичные цены поставщика;
- деградация до базы — если живой опрос невозможен: позиция возвращается с cached-данными и причиной.
Каждый успешный живой ответ прогревает базу (записывается наблюдение) — данные для всех последующих запросов становятся свежее.
Метки источника (на каждый оффер каждой позиции)
source | Значение |
|---|---|
live_customer | Живой ответ поставщика под кредами клиента (договорная цена) |
live_system | Живой ответ под системным кредом (публичная цена) |
cached | Живой опрос не удался — данные из базы; поле reason объясняет причину |
reason: no_credentials (нет ни клиентских, ни системных кредов),
rate_limited (бюджет запросов к поставщику исчерпан), supplier_error,
supplier_timeout, not_supported (поставщик без point-опроса: сейчас
russvet, dkc; или неизвестный), not_found (позиция не раскрылась в офферы).
При source=cached поля price/stock в ответе refresh-контура НЕ заполняются
(observed_at=null) — клиент сохраняет ранее полученные cached-значения
из сметы/каталога.
Сценарии
1. Точечная синхронная проверка (до 20 позиций)
POST /v1/offers/refresh — ждёт до timeout_seconds (1–30, дефолт 15) и
возвращает 200 с частичным результатом: что успело — live, что нет — cached с
причиной, partial=true. job_id в ответе продолжает жить — недостающее
дочитывается опросом job-endpoint’а.
curl -sS https://api.tracium.ru/v1/offers/refresh \
-H "Authorization: Bearer $API_KEY" -H 'Content-Type: application/json' \
-d '{"positions":[{"supplier":"etm","supplier_sku":"9145661"},
{"product_id":"<canonical-uuid>"}],
"targets":["price","stock"],"timeout_seconds":15}'2. Асинхронная актуализация списка (до 500 позиций)
# создать задачу → 202 {job_id,...}
curl -sS -X POST https://api.tracium.ru/v1/offers/refresh-jobs \
-H "Authorization: Bearer $API_KEY" -H 'Content-Type: application/json' \
-d '{"positions":[...],"targets":["price","stock"]}'
# инкрементальный опрос по курсору (как estimate jobs)
curl -sS "https://api.tracium.ru/v1/offers/refresh-jobs/$JOB?after=$CURSOR" \
-H "Authorization: Bearer $API_KEY"
# отмена
curl -sS -X POST "https://api.tracium.ru/v1/offers/refresh-jobs/$JOB/cancel" \
-H "Authorization: Bearer $API_KEY"Scope ключа: offers:refresh.
3. Актуализация внутри расчёта сметы
POST /v1/estimates/jobs, в estimate-request.v1 добавляется:
"refresh": {"enabled": true, "targets": ["price","stock"], "include_alternatives": true}Каждая строка досчитывается живыми данными по выбранному предложению (+ до 3
альтернатив-аналогов при include_alternatives) ДО записи строки — опрос
задачи и WS-поток сразу отдают актуализированные строки:
price.source_mode="live", price.live_source, price.refreshed_at; при
неуспехе — прежние cached-значения + stock.live_attempt_reason. Синхронный
POST /v1/estimates/proposals флаг игнорирует (обратная совместимость 1С).
4. Подписка на события задач (не-1С клиенты): WebSocket
GET wss://api.tracium.ru/v1/jobs/{kind}/{id}/events, kind:
offers-refresh | estimates. Auth — тот же Bearer API-ключ.
Протокол: после upgrade клиент МОЖЕТ первым сообщением послать
{"after": <seq>} (5с на решение; молчание = 0). Сервер отдаёт replay строк
с seq > after, затем live-хвост:
{"type":"line","seq":7,"line":{…тот же объект, что lines[] в REST…}}
{"type":"progress","seq":7,"job":{"status":"running","progress":{"total":20,"done":7,"percent":35}}}
{"type":"final","seq":20,"job":{"status":"completed"}} → Close 1000
{"type":"lagged"} → переподключиться с последним увиденным seqДедупликация — по seq (at-least-once). Ping/pong стандартные, idle 60с.
1С WebSocket не поддерживает — остаётся REST-опрос по курсору (эквивалентные
данные).
5. gRPC (контракт, сервер позже)
docs/docs/20-architecture/schemas/api/tracium/v1/job_events.proto +
README рядом — та же схема событий, JobEvents.Watch(job_kind, job_id, after_seq) → stream JobEvent.
Гарантии и ограничения
- Позиция никогда не «роняет» задачу: худший исход —
cached+reason. - Живые ответы идемпотентно прогревают
offer_observations(клиентский кред → наблюдение уровня клиента, системный → общее). - Rate-бюджеты кредов общие с ingestion — refresh не может «выесть» лимиты поставщика бесконтрольно.
- Поставщики v1 с живым опросом: etm, iek, systeme. russvet (bulk-only API) и
dkc (auth-модель) —
not_supported, follow-up.