tasks: handoff — cancel root cause (sched 0.9.0 не применён), мок-publish зелёный, инцидент закрыт

This commit is contained in:
2026-08-21 00:39:35 +03:00
parent 508e69af0e
commit 478b69038e
3 changed files with 48 additions and 51 deletions

View File

@@ -1,64 +1,61 @@
---
_last_updated_: 2026-08-21T00:55:00Z
session_id: sched-pipelines-apply-0.5.0-2026-08-20
_last_updated_: 2026-08-21T01:40:00Z
session_id: sched-cancel-rootcause-2026-08-21
---
# Next session handoff
Сессия: schedd 0.5.0 применён, timeoutMs -1, одновременный dry-run обеих тасок зелёный, мок-publish ТЗ разосланы.
Сессия: cancel-канал доведён до root cause (баг sched daemon-диспетчера), фикс 0.9.0 НЕ применён — первым делом.
## Recent commits (в .admin)
## 🔴 CRITICAL: применить schedd 0.9.0 и повторить cancel-тест
- `7ec721e2` ops: schedd 0.6.0 — timeoutMs применяется к существующим таскам, absent=-1 дефолт (проверено живьём)
- `3060263b` ops: стенд — schedd 0.5.0 (run-deadline), timeoutMs -1, ozon bind-mount state на хост
**sched нашёл root cause cancel-бага (письмо 21:27:46Z):**
- daemon-диспетчер НЕ форвардил `cancel` к per-task раннеру — обёртка Runner содержала только `{run, poll}`, без `cancel`. `runner.cancel` = undefined → `if (ar.cancelUrl && runner.cancel)` = false → **сигнал не слался никогда**, ран финишил `cancelled` с чистым error (провала нет → `signal failed` не откуда). Воркер продолжал стадии.
- Логи 0.8.0 в этом случае врали: `[cancel] no cancelUrl — legacy stop-polling`, хотя cancelUrl был в envelope.
- **Фикс: daemon 0.9.0** (core 0.48.0 остаётся), commit a6c8a4b, на verdaccio latest. Диспетчер форвардит cancel по task.runner; нет хука → no-op.
## Open треки
**Что сделать:**
1. `schedd.Dockerfile`: `@sched/daemon@0.8.0``@sched/daemon@0.9.0` (host-stacks/local/sched-pipelines/)
2. `docker compose up -d --build schedd`
3. Повторить cancel-тест: ран ozon (state сброшен в {} — full run) → cancel на generate → по логам `[sched] [cancel] POST <cancelUrl> runId=...` + `[cancel] ack status=200` + воркер `[cancel] received` + `[cancel] stop before stage ...` + `[stage] ... done` — стоп ДО publish.
4. Если после ack стадии продолжаются — баг воркера (флаг не проверяется), контракт-ревью с sched.
| Трек | Готовность | Entry-point |
|---|---|---|
| `sched-pipelines-local-stack` (🟡 active) | schedd 0.5.0; **оба dry-run зелёные через sched (ozon 8/8, yandex 11/11)**; publish-мок ТЗ на досках команд | `.tasks/sched-pipelines-local-stack.md` |
## Cancel-канал (раунд 3)
- **sched** ✅ (core 0.47.0/daemon 0.7.0, на стенде): cancelUrl-канал. **Контракт ратифицирован с обеих сторон** (письма 00:52Z admin + 00:52:37Z sched): A (cancelUrl) — accepted-envelope несёт cancelUrl; cancel → POST {runId} на cancelUrl (auth + x-sched-run-id), ждёт 2xx, потом cancelled; провал → `cancel signal failed`. sched менять нечего — реализация соответствует. Ждём импл воркеров → контракт-ревью против 05.protocol.md.
- **воркеры** ⚪ `worker-cancel-url` (обе команды): принять cancelUrl, POST /cancel эндпоинт, флаг между стадиями ДО мутаций.
## Раунды ТЗ
**Раунд 1 (мокабельность publish, оба закрыли):**
- ozon `publish-mockable` ✅ (175/175): data.registry/remoteBase/githubApiBase + PUBLISH_* env.
- yandex `publish-mockable` ✅: data.githubApiBase для REST (registry/remoteBase были).
**Раунд 2 (Gitea-совместимость, оба на досках ⚪ `gitea-mock-publish`):**
- Мок-publish = verdaccio (npm) + наш Gitea (git.kzntsv.site, орга apilki, API v1).
- ozon: gh repo create CLI → REST POST /orgs/{owner}/repos (Gitea нет /api/v3); remoteBase URL-join.
- yandex: только remoteBase URL-join (REST уже ок).
- Репо руками НЕ создавать — create-if-missing воркерами (тестируемый сценарий). Gitea push auth проверен: x-access-token:TOKEN@ работает.
**sched** — ✅ ЗАКРЫТО (0.6.0): applyTask timeoutMs + absent=-1 дефолт, проверено живьём.
**Важно про cancel-тест:** cancel теперь реально остановит воркер (если 0.9.0 работает) — воркер не будет публиковать после cancel. Но publish у ozon с `dryRun: true` в таске — безопасно в любом случае.
## Стенд (host-stacks/local/sched-pipelines)
- schedd **0.6.0** (daemon); tasks.json без timeoutMs — дефолт absent=-1 (никогда), применён и проверен.
- Оба воркера свежие (ozon с фиксами ТЗ №1-10: envelope реализован; ym с JSDoc-фиксом).
- Compose: ozon bind-mount `./data-ozon` → /app/data + `data-ozon/state.json` → /app/state.json (раньше state жил в слое образа). ym: `./data-ym` → /app/data.
- Находка для ozon: run.js хардкодит state/output в ROOT образа, /app/data не используется воркером — не включено в их ТЗ (могу добавить позже).
- schedd **0.8.0** (нужно 0.9.0!), ym-client-builder свежий (e7cf3e5 cancel-канал + c740bdc логи), ozon свежий (0649c80 + f021f38 логи).
- tasks.json: ozon stages [...publish] dryRun:true; yandex stages [...publish, githubDistro] dryRun:true. DRY_RUN=1 в compose (безопасный дефолт).
- Ozon state.json на хосте (bind-mount), сейчас {} (сброшен тестами) — следующий ран полный (initial).
- Все контейнеры Up. Исключение: **озон-контейнер был пересоздан** (docker rm + up) — образ тот же, данные в data-ozon/.
## Мок-publish статус
- **Мок-npm = verdaccio** (verdaccio.kzntsv.site), **мок-GitHub = Gitea** (git.kzntsv.site, орга `apilki` создана, API v1, push x-access-token:TOKEN@ проверен).
- **Оба dry-publish зелёные**: yandex 13/13 (publish+githubDistro, reposToCreate честно показан), ozon 10/10 (publish dryRun preview). GitHub/Gitea/verdaccio чисты — ноль мутаций.
- Репо руками НЕ создаём — create-if-missing воркеров (тестируемый сценарий).
- data dryRun в тасках: `registry/remoteBase/githubApiBase` через `__PUBLISH_*__` плейсхолдеры в render-tasks.cjs (из .env, gitignored).
## Команды — все таски закрыты, ждём только применение
- **sched**: timeoutMs (0.6.0), dry-run контракт (0.7.0 был... нет — 0.7.0 это cancel-канал), cancel-канал (0.7.0), cancel-логи (0.8.0), **cancel-форвардинг фикс (0.9.0 — НЕ применён)**.
- **ozon**: publish-mockable ✅, gitea-mock-publish ✅, dry-run-contract-align ✅, worker-cancel-url ✅, cancel-signal-logging ✅.
- **yandex**: publish-mockable ✅, gitea-mock-publish ✅, dry-run-contract-align ✅, worker-cancel-url ✅, cancel-signal-logging ✅.
## Инцидент сессии (важно для истории)
- Yandex **создал репо на github.com** (apilki/yandex-market-typescript) при мок-прогоне — потому что (а) publish без dry-run (тогда ещё не было фикса) и (б) cancel не остановил воркер (баг sched daemon-диспетчера). Репо **удалено** (204→404), npmjs не тронут, verdaccio пуст. GitHub/Gitea сейчас чисты.
- Урок: yandex publish реальный без dryRun — не запускать publish/githubDistro без явного dryRun:true или GO.
## Спроси user'а
1. **Мок-publish стенд**: после фиксов publish-mockable от обеих команд — построить мок-GitHub (локальный HTTP-мок REST + git remote на локальный bare-репо) + мок-npm (verdaccio) и прогнать publish-стадию. Либо просто ждать GO и идти на verdaccio напрямую.
2. **GO на реальный прогон** — пока НЕ дан. План vitya: verdaccio (не npmjs) → books тестирует → релиз. Воркерам: registry verdaccio + NPM_TOKEN verdaccio.
3. **VDS-миграция** — после пары дней локально + зелёных реальных прогонов.
1. Применить schedd 0.9.0 + повторить cancel-тест (см. CRITICAL).
2. GO на реальный мок-publish (снять dryRun:true, публиковать в verdaccio+Gitea) — после зелёного cancel-теста.
3. VDS-миграция — после пары дней локально.
## Не делать
- Не запускать реальные публикации (publish/githubDistro) без явного GO.
- Не слать реальные письма unisender — только мок (data-mail/).
- Не патчить код команд — ТЗ через их инбоксы/доски, они пушат, я пересобираю.
- Не коммитить в репо команд (yandex/ozon/sched) — только в .admin.
## Memory updates за сессию
- **sched run-deadline контракт**: task-level `timeoutMs` (-1 = никогда, >0 = фейл через N мс, absent = legacy 25-мин poll-потолок). Баг: applyTask при upsert не переносит timeoutMs. Требование vitya: -1 = дефолт, absent должен быть -1.
- **ozon publish.js**: npm publish хардкод (нет registry), pushUrl хардкод github.com, GH API хардкод — мокабельность только через data-поля (ТЗ).
- **ym github-distro.js**: data.registry (npm) + data.remoteBase (git remotes) уже есть; GH_API константа — нужен data.githubApiBase (ТЗ).
- Не запускать реальные публикации (publish/githubDistro без dryRun:true) без явного GO.
- Не слать реальные письма unisender — только мок.
- Не патчить код команд — ТЗ через их инбоксы/доски.
- Не коммитить в репо команд — только в .admin.