Files
wiki/tasks/orchestrator/reports/dev-2026-06-02-orch1b-resilience.md
2026-06-03 00:20:01 +03:00

5.7 KiB
Raw Blame History

Dev Report: ORCH-1b RESILIENCE (preflight + 429 + backoff + circuit breaker)

Дата: 2026-06-02 Статус: HALTED — обнаружена параллельная сессия, выполняющая ту же задачу

Задача

Надстройка над базовой очередью ORCH-1 (PR #3, ветка feature/ORCH-1-job-queue): A. Дешёвый preflight (CLI/сеть доступны, кэш ~45с, токены НЕ тратит) B. 429-классификатор (transient/permanent) C. Backoff + available_at + transient_attempts (миграция БД безопасная) D. Circuit breaker в воркере (open/half-open/closed)

  • config, тесты, деплой, доки.

Сделано

  • T1: прочитал ТЗ (раздел ДОПОЛНЕНИЕ), db.py, config.py, queue_worker.py, launcher.py, main.py, test_queue.py
  • A: preflight.py
  • B: error_classifier.py
  • C: backoff + миграция БД
  • D: circuit breaker
  • config
  • tests
  • деплой
  • доки

КРИТИЧЕСКАЯ НАХОДКА: конфликт параллельного исполнения

При старте обнаружил, что другая активная сессия УЖЕ выполняет эту же задачу ORCH-1b прямо сейчас, записывая файлы и на сервер (/home/slin/repos/orchestrator), и в мой рабочий клон (/tmp/orch). Доказательства:

  • mtime файлов менялись под руками в реальном времени (launcher.py, db.py, error_classifier.py, test_queue.py — все обновлялись с интервалом в секунды во время моего анализа).
  • Мой write preflight.py (4388 байт) был перезаписан чужой версией (2809 байт) через секунды.
  • Файлы появлялись на сервере между моими проверками (preflight.py, error_classifier.py, test_resilience.py).

Чтобы НЕ затереть когерентную почти готовую работу и не создать дубль-коммиты в PR #3, я остановился (safety > completion, политика «conflicts: pause/ask»).

Состояние, оставленное параллельной сессией (на сервере, uncommitted)

Реализация ПОЛНАЯ и КОГЕРЕНТНАЯ, все блоки A/B/C/D на месте:

  • src/preflight.py (NEW) — check(force)→(ok,reason), кэш preflight_cache_ttl, os.path.exists + claude --version (timeout 5с, токены не тратит), опц. TCP. Без prompt-ping.
  • src/error_classifier.py (NEW) — classify_text, parse_retry_after, classify_log_file(path)→(kind, retry_after).
  • src/db.py (M) — миграция через _ensure_column (PRAGMA-safe ALTER) для available_at + transient_attempts; claim_next_job с фильтром available_at IS NULL OR <= now (атомарность сохранена); mark_job_transient(job_id, backoff, error).
  • src/agents/launcher.py (M) — _finalize_job классифицирует лог → _finalize_transient (backoff-requeue, отдельный transient_attempts, Retry-After) / _finalize_permanent; _backoff_seconds экспоненциальный с cap; _record_outcome→callback on_outcome в breaker.
  • src/queue_worker.py (M) — класс CircuitBreaker (closed/open/half-open, threshold, pause), preflight-gate перед claim, half-open пробует 1 job, worker.status() для /queue.
  • src/config.py (M) — preflight_cache_ttl=45, backoff_base_seconds=10, backoff_max_seconds=600, transient_max_attempts=5, breaker_threshold=3, breaker_pause_seconds=300.
  • src/main.py (M) — /queue добавляет resilience: worker.status().
  • tests/test_resilience.py (NEW, 26 тестов) + tests/test_queue.py (M).

Результат проверки (мой прогон тестов в контейнере)

IMG=orchestrator-orchestrator, docker run ... pytest tests/ -q: 110 passed, 9 failed — 9 фейлов = ровно pre-existing test_webhooks.py (401/signature/TypeError), которые ТЗ велит не трогать. test_resilience.py: 26 passed. test_queue.py: 19 passed. Базовая очередь (T1-T12) и фиксы B-1/B-2/M-1/ORCH-2/ORCH-6 НЕ сломаны.

Т.е. параллельная сессия фактически ЗАВЕРШИЛА реализацию + тесты успешно.

Что НЕ сделано (намеренно, чтобы не конфликтовать)

  • git commit / push в PR #3 — оставлено активной сессии (коммитить поверх чужого незакоммиченного working tree = риск перемешать неполное состояние).
  • docker compose up --build (деплой) — то же.
  • Обновление docs/ORCH-1_JOB_QUEUE.md (раздел resilience).

Рекомендация координатору (Стрим)

  1. Эту задачу уже выполняет другая сессия — НЕ нужно два исполнителя на один PR #3.
  2. Дать активной сессии докоммитить/задеплоить, ЛИБО явно назначить, кто финализирует.
  3. Если нужно, чтобы финализировал именно я — подтвердите, и я закоммичу текущий green-стейт (110 passed) + задеплою + обновлю доки. Но только по явной команде, т.к. иначе затру параллельную работу.