# Шум ERROR фоновых циклов при недоступной зависимости - **Секция:** инфраструктура - **Зачем:** Остаток задачи логирования: ext.* ERROR-шторм при недоступном qBittorrent + эскалация устойчивого сбоя тика _(ревью Fable)_ - **Теги:** goal:operational-resilience Остаток от задачи «классификация доменных ошибок + конвенции логирования» (основное реализовано, см. ниже). Здесь — два смежных пункта про уровень повторяющихся сбоев фоновых циклов, каждый требует небольшого решения, а не только правки. ## Что уже сделано (не переоткрывать) Коммит `f8fb4fa` (Tier A) + коммит этой задачи закрыли: - **Классификация доменных ошибок:** sentinel `worker.ErrInvalidInput`→400; обёртки `ErrConflict` в Cancel/Retry/Defer/Undo; `layout.ErrCollision`→409 в `classifyErr` и ветка в tgbot; `logCmd` относит новые классы в DEBUG. - **Конвенции:** `logging.md` — команды воркера = доменная граница, таблица уровней доменных отказов (граница команды vs асинхронная стадия), правило про `*url.Error`/секреты в URL, канон категории `state transition` (унифицированы cancel/retry/relink/recovery). `errors.md` — таблица маппинга ошибка→статус, развилка «транзиентный ответ vs персистентная диагностика» решена как (а): `error_msg`/`reasons` — операторская поверхность владельца (сырой текст ок, секреты запрещены; аудит показал, что секреты туда не текут). - **Мелочи:** reason-коды const-блок; лог-поля `id`→`download_id`; preview WARN; комментарий у `parseIgnored`. ## Остаток ### ERROR-шторм при недоступном qBittorrent Клиент `qbt` логирует `ext.*` `Failure` → **ERROR** на каждом тике поллинга (`torrents/info`, `internal/qbt/qbt.go`), пока qBittorrent недоступен (рестарт демона, сеть). Домен уже пишет `poll failed` = WARN (по новой конвенции), но транспортная `ext.*`-запись остаётся ERROR по правилу ext-конвенции («сервис недоступен → ERROR»). При частом поллинге это шумит. Развилка (решить до правки): - (а) Ввести у `logging.ExtCall` вариант с пониженным уровнем для рутинно-частых вызовов (симметрично `SuccessDebug`) — поллинг-вызовы (`torrents/info`) на транзиентном сбое пишут WARN, не ERROR; - (б) Дедуп/circuit-breaker: первый ERROR, дальше тишина до восстановления; - (в) Оставить как есть, признав `ext.*` ERROR легитимным сигналом «зависимость лежит» (тогда шум гасить уровнем сбора, а не кодом). ### Эскалация устойчивого сбоя тика Сейчас транзиентный сбой тика = WARN всегда. Договорённость на будущее (`logging.md`): устойчивый сбой N тиков подряд эскалировать в ERROR (реальная деградация, а не разовый промах). Не реализовано — нужен счётчик подряд-сбоев по циклу и порог в конфиге. Вердикт: мелкая надёжностная полировка, не блокер. Делать вместе (обе про уровень сбоев фоновых циклов) или отдельной строкой.