60 lines
4.4 KiB
Markdown
60 lines
4.4 KiB
Markdown
---
|
||
work_item: ORCH-063
|
||
stage: architecture
|
||
author_agent: architect
|
||
status: proposed
|
||
created_at: 2026-06-09
|
||
model_used: claude-opus-4-8
|
||
---
|
||
|
||
# adr-0024: Disk-watchdog — фоновый heartbeat-демон мониторинга заполнения хост-ФС
|
||
|
||
> Сквозной (cross-cutting) ADR: вводит **новый фоновый компонент** оркестратора в ряду
|
||
> `reconciler` (adr-0007) и `job_reaper` (adr-0011). Детальное решение задачи —
|
||
> `docs/work-items/ORCH-063/06-adr/ADR-001-disk-watchdog.md`.
|
||
|
||
## Статус
|
||
Proposed (ORCH-063)
|
||
|
||
## Контекст
|
||
07.06.2026 диск хоста mva154 тихо дорос до 100% и положил **весь self-hosting-конвейер** (один
|
||
прод-инстанс `orchestrator` обслуживает все прод-проекты из общей БД/очереди). Проактивного сигнала
|
||
о заполнении диска у системы не было. Оркестратор уже имеет два проверенных фоновых daemon-потока с
|
||
единым каркасом (`threading.Thread(daemon=True)` + `threading.Event`, `start/stop/status`,
|
||
never-raise, снимок в `GET /queue`): `reconciler` (ORCH-053) и `job_reaper` (ORCH-065). Новый
|
||
эксплуатационный watchdog логично встроить тем же паттерном.
|
||
|
||
## Решение
|
||
Вводится третий фоновый компонент **disk-watchdog** (`src/disk_watchdog.py`):
|
||
- **Калька каркаса** `reconciler`/`reaper`: daemon-поток, чистый stop через `_stop.wait(interval)`,
|
||
контракт `start()`/`stop(timeout)`/`status()`, старт/стоп в `main.lifespan` (старт последним —
|
||
после `reaper.start()`; стоп первым в reverse-порядке), наблюдаемость — аддитивный блок
|
||
`disk_monitor` в `GET /queue`.
|
||
- **Замер** заполнения **хост-ФС** через смонтированные bind-пути (`/repos`, `/app/data`) stdlib
|
||
`shutil.disk_usage` (не overlay `/` контейнера, не субпроцесс `df`); дедуп путей по `st_dev`.
|
||
- **Решение об алерте** — pure-функция от `(used_pct, threshold, prev_state, now, realert_s)`:
|
||
алерт на пересечении порога (дефолт 85%), ограниченный cooldown-повтор, recovery при возврате
|
||
ниже порога. Состояние анти-спама — in-memory (без миграции БД).
|
||
- **Алерт** — `send_telegram` (notifying), best-effort. Kill-switch `disk_monitor_enabled`.
|
||
- **Только сигнал, не лечение:** watchdog читает и уведомляет, не трогает диск/контейнер, не
|
||
рестартит прод (self-hosting безопасность). Авто-очистка диска — отдельная задача.
|
||
|
||
**Инварианты:** `STAGE_TRANSITIONS`, реестр `QG_CHECKS`, `check_*`, схема БД — **не меняются**
|
||
(watchdog — эксплуатационный демон, не Quality Gate, как `reconciler`/`reaper`). never-raise на
|
||
уровнях per-path / per-tick / per-send. При выключенном kill-switch — поведение 1:1 как сейчас
|
||
(нулевая регрессия для enduro-trails).
|
||
|
||
## Последствия
|
||
- **+** Ранний сигнал предотвращает групповой простой всех проектов; дёшево, без внешних
|
||
зависимостей (принцип «всё в Docker на одном сервере, минимум зависимостей»).
|
||
- **+** Знакомый паттерн фонового демона → низкий риск, простое сопровождение.
|
||
- **−** In-memory состояние / best-effort Telegram — допустимы для раннего сигнала (не SLA).
|
||
- **Откат:** `ORCH_DISK_MONITOR_ENABLED=false`; миграций БД нет.
|
||
|
||
## Ссылки
|
||
- Задачный ADR: `docs/work-items/ORCH-063/06-adr/ADR-001-disk-watchdog.md`
|
||
- Родственные компоненты: [adr-0007-reconciler.md](adr-0007-reconciler.md),
|
||
[adr-0011-job-reaper-lease-reclaim.md](adr-0011-job-reaper-lease-reclaim.md)
|
||
- Топология host-разделов: `docs/operations/INFRA.md`
|
||
</content>
|