71 lines
5.0 KiB
Markdown
71 lines
5.0 KiB
Markdown
---
|
||
work_item: ORCH-090
|
||
stage: architecture
|
||
author_agent: architect
|
||
status: proposed
|
||
created_at: 2026-06-09
|
||
model_used: claude-opus-4-8
|
||
---
|
||
|
||
# 08 — Требования к данным: ORCH-090 — Механизм отмены задачи (STOP)
|
||
|
||
Work Item: **ORCH-090** · Repo: **orchestrator** · Стадия: architecture
|
||
|
||
> Общая прод-БД (orchestrator + enduro). Все изменения — **только аддитивные и идемпотентные**
|
||
> (`_ensure_column`); существующие таблицы-контракты не переопределяются (NFR-2, AC-9).
|
||
|
||
## Изменения схемы БД
|
||
|
||
### Таблица `tasks` — аддитивные колонки (через `_ensure_column`)
|
||
| Колонка | Тип | Назначение |
|
||
|---------|-----|------------|
|
||
| `cancelled_at` | `TEXT` | durable-метка времени отмены (аудит/наблюдаемость). NULL для неотменённых. |
|
||
| `cancel_requested_at` | `TEXT` | durable-метка «отмена запрошена, но отложена» (STOP в критическом окне merge/deploy, ADR-001 D7). Снимается при доведении отмены до конца. |
|
||
|
||
Никаких `ALTER` существующих колонок. `init_db` идемпотентен (повторный вызов — no-op).
|
||
|
||
### Без DDL-изменений (расширение допустимых значений TEXT)
|
||
- **`jobs.status`** — добавляется значение `cancelled` к набору `queued|running|done|failed`.
|
||
Колонка уже `TEXT`; DDL не меняется. `claim_next_job` выбирает только `status='queued'` →
|
||
`cancelled` исключён нативно.
|
||
- **`tasks.stage`** — добавляется терминальное значение `cancelled` (сток, параллельно `done`).
|
||
Колонка уже `TEXT DEFAULT 'created'`; DDL не меняется. `STAGE_TRANSITIONS` exit-гейты рёбер
|
||
**не меняются** — `cancelled` это терминальное состояние, не новое ребро.
|
||
|
||
### Без изменений
|
||
`job_deps`, `agent_runs`, `repo_freeze`, `tracker_messages`, индексы — контракты нетронуты.
|
||
`QG_CHECKS` / `check_*` — без изменений.
|
||
|
||
## Новые/изменённые сущности
|
||
|
||
### Тумбстон натуральных ключей отменённой задачи (ADR-001 D4)
|
||
На cancel выполняется UPDATE отменённой строки `tasks`:
|
||
- `plane_id := plane_id || '#cancelled-' || id`
|
||
- `work_item_id := work_item_id || '#cancelled-' || id`
|
||
- `stage := 'cancelled'`, `cancelled_at := datetime('now')`
|
||
- `plane_issue_id` — **сохраняется нетронутым** (аудит-связь с issue Plane).
|
||
|
||
Цель: освободить натуральные ключи, чтобы повторный «To Analyse» создал свежую задачу
|
||
(`get_task_by_plane_id(plane_id)` → `None`; anti-dup `create_task_atomic` /
|
||
`ensure_unique_work_item_id` не коллизируют), сохранив строку для аудита. Формат суффикса
|
||
`#cancelled-<id>` детерминирован и парсится.
|
||
|
||
### Отмена job'ов (ADR-001 D3)
|
||
`cancel_jobs_for_task(task_id)` — guarded UPDATE
|
||
`SET status='cancelled', finished_at=datetime('now') WHERE task_id=? AND status IN ('queued','running')`.
|
||
Терминальный исход, нигде не реквью'ящийся.
|
||
|
||
## Совместимость данных / миграции
|
||
|
||
- **Аддитивность/идемпотентность:** только `_ensure_column` (no-op если колонка есть) и
|
||
расширение наборов TEXT-значений; деструктивных/несовместимых миграций нет (AC-9). Повторная
|
||
`init_db` после рестарта не падает.
|
||
- **Restart-safe (NFR-4):** durable терминал = `tasks.stage='cancelled'` (уже понимается
|
||
терминал-скипом реконсилятора, стр. 196). После рестарта `requeue_running_jobs` флипает только
|
||
`running` → отменённые job'ы (`cancelled`) не оживают; отменённая задача не реконсилируется.
|
||
- **Влияние на общую прод-БД:** изменения строго per-task; enduro не затрагивается, при
|
||
`stop_status_enabled=False` или отсутствии отменённых задач — поведение БД 1:1 как сейчас.
|
||
- **Кросс-каттинг (adr-0026):** предикат «задача незавершена» в `serial_gate`/`task_deps`
|
||
расширяется `stage != 'done'` → `stage NOT IN ('done','cancelled')`, иначе отменённая задача
|
||
заклинит очередь репо. Чтение БД (offline hot-path) не приобретает новых сетевых вызовов (NFR-6).
|