feat(disk-watchdog): host-FS fill heartbeat + Telegram alert at >=85% (ORCH-063)
Adds src/disk_watchdog.py — a background daemon thread modelled on reconciler/job_reaper that measures host-FS fill via the mounted bind-paths (/repos, /app/data) with shutil.disk_usage and Telegram-alerts the operator at >= threshold (default 85%). The missing proactive signal: on 07.06.2026 the mva154 host disk silently hit 100% and stalled the whole self-hosting pipeline. - Pure decide_action(used_pct, threshold, prev, now, realert_s): alert on crossing up, cooldown re-alert, single recovery below threshold (unit-tested without a thread/timer; clock injected). - measure_paths: shutil.disk_usage per path, dedup by st_dev, per-path never-raise (a broken path never fails the tick). - Config flags ORCH_DISK_MONITOR_* with defensive validation (threshold 1..100, positive intervals -> default + warning). Kill-switch -> daemon does not start. - Additive disk_monitor block in GET /queue; start/stop in main.lifespan. - never-raise (per-path/per-tick/per-send); STAGE_TRANSITIONS/QG_CHECKS/check_*/ DB schema untouched, no migration (anti-spam state in-memory). Tests: tests/test_disk_watchdog.py (TC-01..TC-12, 18 cases); full suite green (1296). Docs: INFRA.md, .env.example, CHANGELOG.md (architecture/README.md + ADRs authored at architecture stage). Refs: ORCH-063 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -58,6 +58,27 @@ ADR `docs/work-items/ORCH-040/06-adr/ADR-001-run-agents-as-host-uid.md` и гл
|
||||
- `~/.orchestrator-ssh` → `/home/slin/.ssh` (ro, деплой по ssh; target в HOME агента,
|
||||
согласован с `HOME=/home/slin` из launcher — ORCH-040, ранее `/root/.ssh`)
|
||||
|
||||
### Disk-watchdog: мониторинг заполнения диска mva154 (ORCH-063)
|
||||
07.06.2026 диск хоста mva154 тихо дорос до 100% и положил **весь конвейер всех проектов**
|
||||
(один прод-инстанс `orchestrator` на общей БД/очереди). Чтобы такой инцидент сигнализировался
|
||||
**заранее**, работает фоновый daemon-поток `src/disk_watchdog.py` (каркас `reconciler`/`job_reaper`):
|
||||
- **Что мониторится:** заполнение **хост-разделов** по смонтированным bind-путям (`/repos` →
|
||||
host `/home/slin/repos`, `/app/data` → host `./data`) через stdlib `shutil.disk_usage` — НЕ
|
||||
overlay `/` контейнера (иначе замер ложно-низкий). Пути с одним физическим устройством (`st_dev`)
|
||||
дедуплицируются → один алерт, не два.
|
||||
- **Порог и период:** при заполнении **≥ 85%** (`ORCH_DISK_MONITOR_THRESHOLD_PCT`) шлётся
|
||||
Telegram-алерт оператору; замер — раз в 300с (`ORCH_DISK_MONITOR_INTERVAL_S`). Пока диск выше
|
||||
порога, повтор — не чаще раза в ~6ч (`ORCH_DISK_MONITOR_REALERT_S`, анти-спам). При возврате
|
||||
ниже порога — однократное recovery-сообщение.
|
||||
- **Как отключить:** `ORCH_DISK_MONITOR_ENABLED=false` (демон не стартует; `GET /queue` →
|
||||
`disk_monitor.enabled=false`; поведение 1:1 как сейчас). Наблюдаемость — блок `disk_monitor` в
|
||||
`GET /queue` (последний замер: `used_pct`/`free_gb`/`alerting`/`last_alert_at` по каждому пути).
|
||||
- **Что делать при алерте:** watchdog **только сигнализирует** — он не трогает диск/контейнер и не
|
||||
рестартит прод (self-hosting безопасность). Освобождение места — **ручная** операция оператора:
|
||||
типовые «пожиратели» — старые worktree-каталоги `/home/slin/repos/_wt/*` завершённых задач,
|
||||
логи, dangling Docker-образы/слои (`docker image prune`, `docker builder prune`). Авто-очистка —
|
||||
вне объёма ORCH-063 (отдельная задача).
|
||||
|
||||
## Переменные окружения (карта; значения — в `.env`)
|
||||
|
||||
| Переменная | Назначение |
|
||||
@@ -91,6 +112,11 @@ ADR `docs/work-items/ORCH-040/06-adr/ADR-001-run-agents-as-host-uid.md` и гл
|
||||
| `ORCH_RECONCILE_GRACE_DEFAULT_S` | порог «застряла» по `tasks.updated_at`, сек; дефолт `600` |
|
||||
| `ORCH_RECONCILE_GRACE_OVERRIDES_JSON` | per-stage пороги, напр. `{"development":300}`; невалидный JSON → дефолт |
|
||||
| `ORCH_RECONCILE_NOTIFY_UNBLOCK` | слать Telegram при разблокировке застрявшей задачи; дефолт `true` |
|
||||
| `ORCH_DISK_MONITOR_ENABLED` | kill-switch disk-watchdog (ORCH-063); дефолт `true`. `false` → демон не стартует, поведение 1:1 как сейчас |
|
||||
| `ORCH_DISK_MONITOR_INTERVAL_S` | период heartbeat-замера заполнения диска, сек; дефолт `300` |
|
||||
| `ORCH_DISK_MONITOR_THRESHOLD_PCT` | порог заполнения для алерта, %; дефолт `85` (валидация 1..100, иначе → дефолт) |
|
||||
| `ORCH_DISK_MONITOR_REALERT_S` | cooldown повторного алерта, пока выше порога, сек; дефолт `21600` (~6 ч) |
|
||||
| `ORCH_DISK_MONITOR_PATHS` | CSV отслеживаемых **хост**-bind-путей; пусто → `/repos,/app/data` |
|
||||
| `DEPLOY_SSH_USER` / `_HOST` / `DEPLOY_HOOK_SCRIPT` | параметры деплой-хука |
|
||||
|
||||
**Секреты — только в `.env` / `.env.staging` на хосте, в гит НЕ коммитятся.** Канон — `.env.example`, `.env.staging.example`.
|
||||
|
||||
Reference in New Issue
Block a user