Files
admin/.wiki/concepts/sched-pipelines-local-stack-runbook.md

7.3 KiB
Raw Blame History

title, type, tags, related, updated
title type tags related updated
sched-pipelines-local-stack — ранбук локального стенда (sched + воркеры @apilki) concept
runbook
sched
apilki
worker
deadline
cancel
local-stand
concepts/runbooks-index.md
2026-08-26

sched-pipelines-local-stack — локальный стенд пайплайнов клиентов

⚙️ СЛУЖЕБНЫЙ РАНБУК — только для администратора проекта .admin. Применять/выполнять шаги может только .admin (оператор проекта admin). Другим проектам/агентам — читать по запросу, не выполнять. Из проекта не выносить: не копировать в другие вики, не пересказывать, не публиковать. Нужен деплой или прод-операция по этому ранбуку — поставить задачу админу (.admin) и написать письмо. Админ выполняет, остальные верифицируют.

Локальный стенд: sched daemon + HTTP-воркеры (yandex-market-partner-api-client, ozon-seller-api-client)

  • CDP-browser + локальный ntfy + alert-bridge. Цель — обкатка пайплайнов клиентов @apilki против моков (verdaccio + Gitea) перед миграцией на VDS.

Локация и команды

cd ~/projects/.admin/host-stacks/local/sched-pipelines
node render-tasks.cjs            # рендер tasks.generated.json из tasks.json + .env
docker compose up -d --build     # сборка + запуск
docker compose up -d --force-recreate schedd   # применить НОВЫЙ tasks.json (см. gotcha 2)
docker compose logs -f schedd
  • Admin API sched: 127.0.0.1:18080, ключ SCHED_ADMIN_KEY (pass sched-pipelines/local/*).
  • Триггер рана: POST /api/tasks/<name>/run (Bearer admin key).
  • Секреты: .env (gitignored) ← pass sched-pipelines/local/*.

Компоненты

Сервис Хост-порт Образ
schedd 127.0.0.1:18080 sched-pipelines/schedd:local (daemon с verdaccio)
ym-client-builder 127.0.0.1:18090 sched-pipelines/ym-client-builder:local (из репо yandex)
ozon-seller-builder 127.0.0.1:18091 sched-pipelines/ozon-seller-builder:local (из репо ozon)
browser-cdp, ntfy, alert-bridge, unisender-mock локальные

Воркеры собираются из dev-репо: ../../../../yandex-market-partner-api-client (Dockerfile), ../../../../ozon-seller-api-client (service/Dockerfile). Свежие фичи на стенд = pull репо + docker compose build ym-client-builder ozon-seller-builder + up -d.

Таймаут-сценарий (deadline-stop, ратифицирован 2026-08-26)

Инцидент: sched при poll-timeout помечал ран failed, но НЕ слал воркеру cancel — воркер доделывал пайплайн с реальным publish. Вердикт расходился с реальностью. Закрыт двумя слоями:

  1. Воркер (yandex #1276, ozon #1278, паттерн C): data.timeoutMs (relative) / data.deadlineMs (absolute epoch) / env WORKER_TIMEOUT_MS → локальный таймер ставит флаг, пайплайн стопается на границе стадий ДО мутаций (publish/githubDistro). Вердикт: failed, error: deadline exceeded, result {verdict: 'timeout', timedOut: true, failedStage}. Операторский cancel остаётся cancelled.
  2. sched (#1277, core 0.53.0): при task-ceiling (task.timeoutMs) сам шлёт POST /cancel воркеру перед записью вердикта failed (run timeout after Nms).

Проверено на стенде 2026-08-26:

  • воркер: [deadline] fired ... stop before mutations[cancel] stop before stage fix → failed, verdaccio чист;
  • sched: [cancel] received/flag set runId=<id> в логах воркера → failed, verdaccio чист.

Gotchas (2026-08-26)

  1. task.timeoutMsconfig.timeoutMs. task.timeoutMs — task-level ceiling (run-deadline, при срабатывании sched шлёт cancel + failed «run timeout after Nms»). config.timeoutMs — транспортный таймаут ОДНОГО poll-запроса (дефолт 30s). Если транспортный < ceiling — ран упадёт по транспортному (в ветке poll-ошибки cancel НЕ шлётся!) раньше, чем сработает ceiling. Настройка: task.timeoutMs: 120000 (ceiling) + config.timeoutMs: 300000 (транспортный > ceiling).
  2. applyTask при upsert существующей таски НЕ обновляет data и config.timeoutMs (переносит только task.timeoutMs). Изменение data в tasks.json требует docker compose up -d --force-recreate schedd (просто up -d не пересоздаёт контейнер, таска в БД остаётся старой). Диагностика: GET /api/tasks — сверить, что новое поле реально в API.
  3. Состояние воркеров — bind-mount data-ym/state.json, data-ozon/state.json (не в слое образа). Перед форс-тестом полного пайплайна — сбросить state ({"verdictHistory": []}) с бэкапом. После теста — восстановить из бэкапа, иначе следующий ран пойдёт по-старому.
  4. Логи ранов двух воркеров перемешиваются в одном stdout — различать по runId в строках [deadline]/[cancel] и по таймштампам (docker logs -t).
  5. schedd молчит в stdout — диагностика ранов через admin API (/api/runs, error-поле), события cancel — только в логах ВОРКЕРА ([cancel] received/flag set).
  6. classify: таблица рецептов не прочитана (/app/recipes.json) — рецепты не смонтированы в образ ym-client-builder, все изменения классифицируются как auto. Некритично для мок-стенда, при миграции на VDS смонтировать.
  7. Локальный дедлайн теста: deadlineMs/таймер проверяются на границе стадий — если стадия долгая (generate ~15 мин), стоп случится ПОСЛЕ неё (лог [cancel] stop before stage <next>), это ок.

Связи

  • runbooks-index.md — индекс ранбуков.
  • Таска-источник: .tasks/done/2026-08-20-00746-sched-pipelines-local-stack.md (мок-кампания 2026-08-20/21).
  • publish-model (yandex-market-partner-api-client) — модель пайплайна клиентов.
  • worker-deadline-contract.md (yandex wiki:3254) — конвенция deadline-stop паттерна C.