5.7 KiB
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→callbackon_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).
Рекомендация координатору (Стрим)
- Эту задачу уже выполняет другая сессия — НЕ нужно два исполнителя на один PR #3.
- Дать активной сессии докоммитить/задеплоить, ЛИБО явно назначить, кто финализирует.
- Если нужно, чтобы финализировал именно я — подтвердите, и я закоммичу текущий green-стейт (110 passed) + задеплою + обновлю доки. Но только по явной команде, т.к. иначе затру параллельную работу.