sprint: набран спринт 2026-08-06 под цель распознавания
- в наборе шесть задач: локаль TVDB и confidence-гейт под цель, плюс баги и техдолг помимо неё - взятым дописаны разделы своего типа: «Затрагивает», критерии с оракулами, воспроизведение - решены развилки: оба расхождения код↔спека правятся спекой (и потому стали chore), опрос qBittorrent тормозится бэкоффом до минутного потолка
This commit is contained in:
@@ -1,14 +1,13 @@
|
||||
# 🐞 Не штормить ERROR при недоступном qBittorrent и эскалировать устойчивый сбой тика
|
||||
# 🐞 Тормозить опрос qBittorrent бэкоффом при недоступности и эскалировать устойчивый сбой
|
||||
|
||||
- **Тип:** fix
|
||||
- **Категория:** Инфраструктура
|
||||
- **Зачем:** Остаток задачи логирования: ext.* ERROR-шторм при недоступном qBittorrent + эскалация устойчивого сбоя тика _(ревью Fable)_
|
||||
- **Теги:** goal:operational-resilience
|
||||
- **Зачем:** недоступный qBittorrent опрашивается каждые 5 с и даёт WARN на каждом тике: нужен экспоненциальный бэкофф до минутного потолка со сбросом по первому успеху и ERROR на устойчивой деградации
|
||||
|
||||
Остаток от задачи «классификация доменных ошибок + конвенции логирования»
|
||||
(основное реализовано, см. ниже). Здесь — два смежных пункта про уровень
|
||||
повторяющихся сбоев фоновых циклов, каждый требует небольшого решения, а не
|
||||
только правки.
|
||||
(основное реализовано, см. ниже) плюс бэкофф опроса, заказанный 2026-08-06.
|
||||
Речь о поведении фонового цикла, пока зависимость лежит: с какой частотой он её
|
||||
дёргает и каким уровнем об этом пишет.
|
||||
|
||||
## Что уже сделано (не переоткрывать)
|
||||
|
||||
@@ -29,29 +28,63 @@
|
||||
|
||||
## Остаток
|
||||
|
||||
### ERROR-шторм при недоступном qBittorrent
|
||||
**Шум `ext.*` ERROR решено оставить как есть (2026-08-06).** Запись
|
||||
«зависимость недоступна» на каждом тике — легитимный сигнал транспортного слоя,
|
||||
и гасится он уровнем сбора логов, а не кодом. Варианты с пониженным уровнем у
|
||||
`logging.ExtCall` и с дедупом отклонены: первый заводит второе правило уровня
|
||||
для того же класса вызовов, второй даёт транспортному логгеру память о
|
||||
состоянии.
|
||||
|
||||
Клиент `qbt` логирует `ext.*` `Failure` → **ERROR** на каждом тике поллинга
|
||||
(`torrents/info`, `internal/qbt/qbt.go`), пока qBittorrent недоступен (рестарт
|
||||
демона, сеть). Домен уже пишет `poll failed` = WARN (по новой конвенции), но
|
||||
транспортная `ext.*`-запись остаётся ERROR по правилу ext-конвенции («сервис
|
||||
недоступен → ERROR»). При частом поллинге это шумит.
|
||||
Остаются две вещи, и обе стоят на одном счётчике подряд-идущих сбоев тика.
|
||||
|
||||
Развилка (решить до правки):
|
||||
**Бэкофф опроса (решение 2026-08-06).** Пока qBittorrent недоступен, цикл
|
||||
продолжает дёргать его каждые `poll_interval` (5 с) — недоступную зависимость
|
||||
незачем опрашивать с рабочей частотой. Интервал растёт экспоненциально от
|
||||
`poll_interval` до потолка порядка минуты; первый успешный ответ возвращает
|
||||
рабочий интервал сразу, без ступенчатого спуска. Бэкофф заодно снимает и остроту
|
||||
шума: записей становится столько же на событие, но событий — единицы в минуту.
|
||||
|
||||
- (а) Ввести у `logging.ExtCall` вариант с пониженным уровнем для рутинно-частых
|
||||
вызовов (симметрично `SuccessDebug`) — поллинг-вызовы (`torrents/info`) на
|
||||
транзиентном сбое пишут WARN, не ERROR;
|
||||
- (б) Дедуп/circuit-breaker: первый ERROR, дальше тишина до восстановления;
|
||||
- (в) Оставить как есть, признав `ext.*` ERROR легитимным сигналом «зависимость
|
||||
лежит» (тогда шум гасить уровнем сбора, а не кодом).
|
||||
**Эскалация уровня.** Сейчас сбой тика — **всегда WARN**, сколько бы тиков
|
||||
подряд он ни падал. `docs/conventions/logging.md` требует иного: устойчивый сбой
|
||||
N тиков подряд — это реальная деградация, и она пишется ERROR.
|
||||
|
||||
### Эскалация устойчивого сбоя тика
|
||||
## Воспроизведение
|
||||
|
||||
Сейчас транзиентный сбой тика = WARN всегда. Договорённость на будущее
|
||||
(`logging.md`): устойчивый сбой N тиков подряд эскалировать в ERROR (реальная
|
||||
деградация, а не разовый промах). Не реализовано — нужен счётчик подряд-сбоев по
|
||||
циклу и порог в конфиге.
|
||||
1. Остановить qBittorrent (локально, не на umbar).
|
||||
2. Смотреть лог воркера в течение нескольких минут поллинга.
|
||||
3. Наблюдается: запрос к qBittorrent уходит каждые 5 секунд всё время
|
||||
недоступности, а доменная запись `poll failed` идёт WARN на каждом тике и
|
||||
остаётся WARN бесконечно.
|
||||
4. Ожидается: интервал опроса растёт до минутного потолка, а после N
|
||||
подряд-идущих неудачных тиков уровень поднимается до ERROR — деградация
|
||||
отличается от разового промаха.
|
||||
5. Поднять qBittorrent обратно: опрос возвращается к `poll_interval` с первого
|
||||
успешного ответа.
|
||||
|
||||
Вердикт: мелкая надёжностная полировка, не блокер. Делать вместе (обе про
|
||||
уровень сбоев фоновых циклов) или отдельной строкой.
|
||||
## Затрагивает
|
||||
|
||||
- цикл поллинга воркера (`internal/worker`) — счётчик подряд-идущих сбоев,
|
||||
текущий интервал тика и его сброс по успеху;
|
||||
- секция `[worker]` конфига и `config.example.toml` — потолок бэкоффа и порог
|
||||
эскалации;
|
||||
- `docs/database.md`, таблица «Настройки с числовым значением» — дом обоих
|
||||
чисел;
|
||||
- `docs/architecture.md`, «Характер потока» — там сказано, что фон непрерывный с
|
||||
периодом поллинга; переменный интервал это уточняет;
|
||||
- `docs/conventions/logging.md` — правило эскалации уже записано, меняться не
|
||||
должно; задача приводит код к нему.
|
||||
|
||||
## Критерии приёмки
|
||||
|
||||
- При подряд-идущих сбоях интервал опроса растёт экспоненциально от
|
||||
`poll_interval` и упирается в потолок из конфига, дальше не растёт (оракул:
|
||||
тест цикла с подставным клиентом и управляемыми часами — проверяет
|
||||
последовательность интервалов).
|
||||
- Первый успешный ответ возвращает `poll_interval` немедленно (оракул: тот же
|
||||
тест, сценарий «серия сбоев, успех, сбой» — после успеха интервал рабочий).
|
||||
- Сбой тика ниже порога пишется WARN, начиная с N-го подряд — ERROR, а успешный
|
||||
тик сбрасывает счётчик (оракул: тест, считающий уровни записей на сценарии
|
||||
«сбой, сбой, успех, сбой»).
|
||||
- Потолок бэкоффа и порог эскалации читаются из конфига и описаны в
|
||||
`config.example.toml` с единицами и диапазоном (оракул: `task gate`, шаг
|
||||
канона — сверка с `database.md`).
|
||||
|
||||
Reference in New Issue
Block a user