[2026-10-15 09:52:43] taiga-vault: family/documents/vault-sync/2026-10-15-http402-balance-outage-9d.md
This commit is contained in:
1 parent
43676802ab
commit
26271498d9
1 file changed
+101
@@ -0,0 +1,101 @@
|
|||||||
|
---
|
||||||
|
tags: [vault-sync, incident, cron, llm-provider]
|
||||||
|
date: 2026-10-15
|
||||||
|
severity: high
|
||||||
|
status: resolved
|
||||||
|
---
|
||||||
|
|
||||||
|
# Инцидент: vault-sync стоял 8,93 суток — HTTP 402 Insufficient Balance (2026-10-06 → 2026-10-15)
|
||||||
|
|
||||||
|
## Итог одной строкой
|
||||||
|
|
||||||
|
Задача `sync-vault` (cron `*/5`, id `29851c413903`) **не выполнялась 8 дней 22,4 часа**:
|
||||||
|
2572 тика подряд упали с `RuntimeError: HTTP 402: Insufficient Balance` (провайдер
|
||||||
|
DeepSeek). Баланс пополнен ~2026-10-15 09:50 UTC — синк восстановился сам на очередном
|
||||||
|
тике, бэклог влит fast-forward, потерь данных нет.
|
||||||
|
|
||||||
|
## Хронология (UTC)
|
||||||
|
|
||||||
|
| Время | Событие |
|
||||||
|
|---|---|
|
||||||
|
| 2026-10-06 11:25:44 | последний успешный тик (в логе `[syncthing] Pushed ✓` 11:25:30) |
|
||||||
|
| 2026-10-06 ~11:30 | первый 402; за сутки 10-06 — 150 отказов, 138 успехов |
|
||||||
|
| 10-07 … 10-14 | ровно **288 отказов в сутки** = 100 % тиков, ни одного запуска скрипта |
|
||||||
|
| 10-15 00:00 … 09:45 | 118 отказов (все слоты до 09:45) |
|
||||||
|
| 2026-10-15 09:50:21 | тик **completed**, скрипт отработал все три фазы, бэклог влит |
|
||||||
|
| 2026-10-15 09:51 | `failure_streak` сброшен, /vault, bare, /obsidian-syncthing на одном SHA `43676802` |
|
||||||
|
|
||||||
|
Длительность: 10-06 11:25:44 → 10-15 09:50:21 = **12 864,9 мин = 8,93 суток**.
|
||||||
|
Число подряд упавших тиков: **2572** (= `failure_streak` в `/opt/data/cron/jobs.json`).
|
||||||
|
|
||||||
|
## Диагностика (что и где смотреть)
|
||||||
|
|
||||||
|
1. **Разрыв в `/tmp/vault-sync.log`**: 10-06 11:25:30 → 10-15 09:50:21. Лог **не**
|
||||||
|
обнулялся (первая строка 2026-09-15 11:35:19) — значит контейнер не пересоздавался,
|
||||||
|
это отказ LLM-петли, а не потеря лога.
|
||||||
|
2. **`/opt/data/cron/jobs.json`** — самое быстрое доказательство:
|
||||||
|
`"failure_streak": 2572`, `"last_status": "error"`,
|
||||||
|
`"last_error": "RuntimeError: HTTP 402: Insufficient Balance (request_id: …)"`.
|
||||||
|
`failure_streak × 5 мин` = длительность простоя.
|
||||||
|
3. **`/opt/data/cron/executions.db`** — окно только за последние 1001 запись (≈3,5 суток):
|
||||||
|
в нём 1000 × `failed` с тем же текстом 402 и одна `running` (текущий тик).
|
||||||
|
Данные старее обрезаны, поэтому длительность по БД **не** измеряется.
|
||||||
|
4. **`/opt/data/cron/usage_audit.jsonl`** — полная хронология без обрезки (12 231 строка,
|
||||||
|
с 2026-09-02): `error` есть → тик не запускал скрипт; `error: null` → запускал.
|
||||||
|
Разбивка 402 по суткам: 10-06 — 150, 10-07…10-14 — по 288, 10-15 — 118.
|
||||||
|
|
||||||
|
## Причина
|
||||||
|
|
||||||
|
Задача — **prompt-задача** (`"prompt": "bash /opt/data/sync-vault.sh >> …"`), её исполняет
|
||||||
|
LLM-раунд. Нет баланса у провайдера → нет LLM-раунда → скрипт не вызывается вообще
|
||||||
|
(не «git упал», а «скрипт не стартовал»). Git-инфраструктура и bare-репозиторий при этом
|
||||||
|
были полностью живы: Eagle пушил в bare всё это время (12 коммитов 10-07, 18 — 10-08,
|
||||||
|
14 — 10-09, …, 42 — 10-14, 49 — 10-15).
|
||||||
|
|
||||||
|
## Что не потеряно
|
||||||
|
|
||||||
|
- bare всё это время принимал коммиты Eagle напрямую — история целая.
|
||||||
|
- Телефон (Syncthing) держал свои правки локально и отдал их сегодня коммитом
|
||||||
|
`57061535` (`personal/documents/*`, `personal/shopping-order.md`, `Расходы руб.md`).
|
||||||
|
- Первый удачный тик 10-15 09:50 влил бэклог: **178 коммитов** с 10-06 11:00,
|
||||||
|
`Merge … origin/main` + fast-forward, без конфликтов.
|
||||||
|
- Проверка: три SHA равны (`43676802…`) в `/vault`, `/vault.git`, `/obsidian-syncthing`;
|
||||||
|
`git status --porcelain` и `git ls-files -u` пусты в обоих клонах; новых
|
||||||
|
`*.sync-conflict-*` / `*.bak-*` за период нет.
|
||||||
|
|
||||||
|
## Корневая проблема: стоимость prompt-тика
|
||||||
|
|
||||||
|
Один тик этой «пустой» задачи съедает десятки-сотни тысяч prompt-токенов, потому что
|
||||||
|
агент собирает весь системный промпт и навыки на каждый запуск:
|
||||||
|
|
||||||
|
- замер по `usage_audit.jsonl` за последние полные сутки (10-06): **138 успешных тиков,
|
||||||
|
18 503 331 токен суммарно**, максимум **378 455 токенов за один тик**;
|
||||||
|
- при полной каденции 288 тиков/сутки это ≈ **38 млн токенов в сутки** ради
|
||||||
|
`git add/commit/merge/push`, который сам по себе стоит 0 токенов.
|
||||||
|
|
||||||
|
Отсюда и опустошение баланса: 402-класс уже наблюдался 09-14, 09-21, 09-25, 09-28 —
|
||||||
|
это не разовый сбой, а режим, в котором счёт провайдера выедается задачей-синхронизатором.
|
||||||
|
|
||||||
|
## Рекомендации (решение владельца)
|
||||||
|
|
||||||
|
1. **Убрать LLM из петли** — основной фикс:
|
||||||
|
`hermes cron edit 29851c413903 --no-agent --script <path>`.
|
||||||
|
Ловушка: `--script` ждёт файл под `~/.hermes/scripts/`, `/root/.hermes` в контейнере
|
||||||
|
не переживает рекреацию — нужен персистентный путь (симлинк на `/opt/data/`).
|
||||||
|
Тогда тик не зависит ни от баланса, ни от доступности провайдера.
|
||||||
|
2. Как минимум — зафиксировать модель/провайдера подешевле и урезать системный промпт
|
||||||
|
для этой задачи (`enabled_toolsets`, `skills: []` уже пусто, но промпт всё равно
|
||||||
|
собирается целиком).
|
||||||
|
3. Мониторинг: алерт при `failure_streak > 12` (час простоя) в `jobs.json` —
|
||||||
|
иначе отказ виден только по дырке в логе, а он «локальный» (`deliver: local`),
|
||||||
|
Алексею ничего не приходит.
|
||||||
|
4. `deliver: local` для этой задачи — правильно (не спамить), но именно поэтому
|
||||||
|
9-дневный отказ прошёл незамеченным. Стоит сделать отдельный health-check-тик,
|
||||||
|
который при простое шлёт одно сообщение в Telegram.
|
||||||
|
|
||||||
|
## Оценка класса
|
||||||
|
|
||||||
|
Предыдущие эпизоды 402: 09-21 — 6 тиков (35 мин), 09-25 — 53, 09-28 — 14.
|
||||||
|
Текущий — **2572 тика / 8,93 суток**, на два порядка больше. Разница не в механизме,
|
||||||
|
а в том, что баланс не пополняли: провайдер отвечает 402 мгновенно (1,7–7,6 с на тик),
|
||||||
|
поэтому самовосстановления нет по определению — нужен внешний сигнал.
|
||||||
Reference in new issue
Block a user