Files
orchestrator/docs/work-items/ORCH-026/02-trz.md

11 KiB
Raw Blame History

02-ТЗ — Управление зависимостями задач (B ждёт A) в очереди

Work Item: ORCH-026 · Repo: orchestrator · Стадия: analysis

ТЗ фиксирует ТРЕБОВАНИЯ к изменениям (модули, контракты, артефакты). Конкретный механизм сериализации и место хранения связей — решение архитектора (ADR в 06-adr/); ниже отмечены как «КАНДИДАТ / решает архитектор». Аналитик не предлагает архитектуру.


1. Задействованные модули src/

Модуль Роль в задаче Уровень
src/queue_worker.py Планировщик: _drain_once / claim_next_job — точка учёта зависимостей и сериализации при выборе job. A + B
src/db.py Очередь jobs / tasks; claim_next_job, enqueue_job, count_running_jobs. Кандидат на хранение связей и блокировки claim. A + B
src/merge_gate.py merge-lease (ORCH-065), branch_is_behind_main / auto_rebase_onto_main (ORCH-043) — опора для proactive pre-merge rebase и расширения окна сериализации. A
src/qg/checks.py check_branch_mergeable (под-гейт ребра deploy-staging → deploy) — точка форсированного pre-merge rebase. A
src/stage_engine.py advance_stage — врезки гейтов; точка интеграции сериализации/верификации. A
src/webhooks/plane.py handle_work_item_created / start_pipeline — приём задачи; точка чтения relations (если источник — Plane). B
src/plane_sync.py set_issue_blocked, get_project_states (blocked/needs_input), relations API. B
src/notifications.py live-карточка: индикация Blocked / «ждёт ORCH-NNN». B
src/config.py Новые kill-switch + scope-настройки (паттерн *_enabled / *_repos). A + B
src/reconciler.py / src/job_reaper.py Не ломать: skip заблокированных задач (как уже делается для Blocked/Needs-Input, ORCH-060/068); реклейм ресурсов сериализации. A + B

2. Требования к изменениям — Уровень A (сериализация merge/деплоя)

2.1 Proactive pre-merge rebase (A-2)

  • На ребре deploy-staging → deploy, ДО фактического merge (в составе check_branch_mergeable или соседнего под-гейта), ветка задачи всегда догоняется на свежий origin/mainне только при branch_is_behind_main/конфликте.
  • Переиспользовать merge_gate.auto_rebase_onto_main (rebase + push --force-with-lease ТОЛЬКО ветки задачи). Текстовый конфликт → существующий контракт: rebase --abort → откат на development (как ORCH-043).
  • Инвариант: никаких push/force-push в main.

2.2 Расширение окна merge-lease (A-1, A-3, A-4)

  • КАНДИДАТ (решает архитектор): держать per-repo merge-lease (ORCH-065) не только «на момент merge», а на окно «merge → main-updated» (для self — до подтверждения merged_to_main: true / done), чтобы B не дошла до своего merge, пока A не в main.
  • Acquire — неблокирующий (как сейчас): занято → defer задачи B через enqueue_job(available_at_delay_s=...), bounded бюджет (анти-livelock; ср. merge_defer_max_attempts). Откат на development НЕ применять для defer.
  • Release — holder-aware (как release_merge_lease), на merged-вебхуке / deploy→done / откате / по проактивному реклейму (ORCH-065 reclaim_stale_lease).
  • Сериализация строго per-repo (.merge-lease-<repo>.json) — кросс-репо параллелизм не затрагивается (A-3).

2.3 Условность и безопасность (A-5)

  • Реально только для применимых репо: kill-switch + CSV-scope (паттерн merge_gate_repos / merge_verify_repos; пусто → только self-hosting orchestrator).
  • STAGE_TRANSITIONS, Confirm Deploy (ORCH-059), exit-коды deploy-хука, БАГ-8, terminal-sync — без изменений.
  • Контракт never-raise для всех новых функций (как соседи в merge_gate.py).

3. Требования к изменениям — Уровень B (декларативные зависимости)

3.1 Декларация связи (B-1)

  • КАНДИДАТ хранения (решает архитектор, см. BRD §4.1):
    • вариант Plane relations: читать blocked-by через Plane API в handle_work_item_created;
    • вариант БД: новая таблица job_deps(task_id, depends_on_task_id) или поле в tasks (idempotent _ensure_column миграция, как ORCH-065 jobs.pid);
    • гибрид: Plane — декларация, БД — кэш для планировщика (offline-устойчивость).
  • Миграция БД (если выбран вариант с таблицей/колонкой) — только аддитивная (CREATE TABLE IF NOT EXISTS / _ensure_column), безопасная на живой прод-БД с общими данными enduro-trails.

3.2 Гейт планировщика (B-2)

  • При выборе job (claim_next_job / _drain_once) задача с незавершёнными depends-on не клеймится (аналог available_at-gate): пропускается до тех пор, пока все depends-on не done. Не должна занимать слот max_concurrency.
  • Реализация — leaf-функция с чистой логикой «готова ли задача к запуску» (тестируемо юнитами, never-raise), по образцу staging_verdict.py / post_deploy.py.

3.3 Защита от дедлоков (B-3)

  • Детектор циклов в графе depends-on (DFS/обнаружение цикла) — чистая функция, юнит-тестируемая.
  • Цикл → задача(и) НЕ запускается молча: set_issue_blocked + alert (Telegram/Plane) с указанием цикла. Не блокировать поток других задач.

3.4 Видимость (B-4)

  • Заблокированная задача: Plane-статус Blocked (set_issue_blocked) и/или строка ожидания в Telegram-карточке (« ждёт ORCH-NNN»). Использовать существующий механизм карточки (notifications.update_task_tracker), контракт never-raise / silent.
  • reconciler F-1 уже пропускает Blocked/Needs-Input (ORCH-060/068) — убедиться, что новые заблокированные-по-зависимости задачи тоже пропускаются (не «разблокируются» ошибочно).

4. Изменения API (endpoints)

  • Новые HTTP endpoints не требуются.
  • Наблюдаемость: расширить снимок GET /queue блоком о зависимостях/сериализации (по образцу блоков reconcile / reaper / post_deploy / merge_verify): кол-во заблокированных задач, держатель merge-lease, defer-счётчики, обнаруженные циклы. Read-only, никогда не источник истины для решений.

5. Изменения схемы БД

  • КАНДИДАТ (если выбран БД/гибрид для Уровня B): аддитивная таблица job_deps или колонка в tasks (см. §3.1). Только CREATE TABLE IF NOT EXISTS / _ensure_column. Без изменения существующих колонок jobs/tasks. Restart-safe, безопасно на общей прод-БД.
  • Уровень A (сериализация) — без изменения схемы БД (merge-lease файловый, как ORCH-065).

6. Требования к новым QG checks

  • Новый зарегистрированный QG-чек НЕ вводится (паттерн ORCH-071/058: под-гейт — врезка в advance_stage или расширение check_branch_mergeable, а не новая запись в QG_CHECKS).
  • Реестр QG_CHECKS — без изменений.

7. Конфигурация (src/config.py)

Новые настройки по паттерну *_enabled (kill-switch) + *_repos (CSV scope, пусто → self-hosting). КАНДИДАТ-имена (финализирует архитектор):

  • Уровень A: merge_serialize_enabled / merge_serialize_repos (или расширение merge_gate_*); опционально premerge_rebase_always (вкл proactive rebase).
  • Уровень B: task_deps_enabled / task_deps_source (plane|db|hybrid). Дефолты — обратная совместимость (для не-self репо — прежнее поведение).

8. Артефакты pipeline (создать/обновить В ТОМ ЖЕ PR)

  • 06-adr/ADR-001-*.md — решение по сериализации (A) и хранению зависимостей (B).
  • Обновить docs/architecture/README.md (раздел про очередь/merge-gate/сериализацию).
  • Обновить CLAUDE.md (паспорт: конвейер/инварианты, если меняется поведение очереди).
  • Обновить CHANGELOG.md (## [Unreleased]).
  • Если вводится таблица БД — отразить в 08-data-requirements.md (создаёт архитектор).
  • 07-infra-requirements.md — если требуется новый Plane-статус/настройка relations.

9. Инварианты (НЕ нарушать)

  1. STAGE_TRANSITIONS, реестр QG_CHECKS, check_deploy_status/check_staging_status, Confirm Deploy (ORCH-059), БАГ-8, terminal-sync — без изменений.
  2. Никаких push/force-push в main; force только --force-with-lease на ветку задачи.
  3. Сериализация — строго per-repo; кросс-репо параллелизм сохранён.
  4. never-raise во всех новых функциях; restart-safe состояние.
  5. ORCH-026 дополняет рубежи ORCH-073, не заменяет.
  6. Прод-контейнер orchestrator не рестартится вне штатного Confirm Deploy.