fix(media): follow-up self-heal — чистка негативкэша на рестарте + LRU-кап + тесты #48

Merged
vvzvlad merged 2 commits from fix/43-selfheal-followup into main 2026-07-10 05:08:16 +03:00

2 Commits

Author SHA1 Message Date
agent_coder ffdc39e7e5 test(media): покрыть backoff-кап + best-effort restart-колбэк (ревью #48)
- test_backoff_capped_at_max: 8 фейлов подряд (сырая экспонента 7680с) ->
  _download_backoff_remaining <= _DOWNLOAD_BACKOFF_MAX (600с). Мутация: убрать
  min()-кап -> тест краснеет (7680>600).
- test_restart_callback_error_does_not_abort: бросающий restart-колбэк на
  verified-рестарте -> recovery завершается (watchdog пере-армлен, _restarting
  сброшен, SIGTERM-fallback не сработал), ошибка залогирована. Мутация: убрать
  try/except вокруг колбэка -> исключение уходит наружу -> тест краснеет.

Только тесты; прод-код байт-в-байт не тронут.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 04:41:18 +03:00
agent_coder 26c6a08e36 fix(media): follow-up self-heal (ретро-ревью #43) — чистка негативкэша на рестарте + кап + тесты
По ретроспективному ревью 3c9ce72:

Finding A (medium): негативный кэш падений (_download_failures) НЕ чистился после
успешного self-heal рестарта -> выздоровевший файл отдавал 503 до _DOWNLOAD_BACKOFF_MAX
(до часа), сам ретраиться не мог (sweeper continue, get_media fast-503) -> прямое
противоречие цели фикса. Теперь: telegram_client._restart_client на ВЕРИФИЦИРОВАННОМ
рестарте (verify_get_me ok, verify_ok=True) зовёт колбэк, зарегистрированный
api_server через client.set_restart_callback -> _download_failures.clear(). Колбэк
НЕ срабатывает на упавшем/прерванном рестарте/SIGTERM-fallback (исключение колбэка
подавляется). Зависимость односторонняя (telegram_client не импортит api_server).
_DOWNLOAD_BACKOFF_MAX 3600->600с (система самолечится за минуты). Retry-storm
ограничен: каждый retry timeout-bounded, заново взводит backoff.

Finding B (low): _download_failures рос безлимитно -> OrderedDict + LRU-кап
_DOWNLOAD_FAILURES_MAX=10000 (move_to_end на запись сбоя, popitem(last=False) сверх
капа; eviction безвреден).

Тесты (+10, мутационно проверены): hung-download отменяется по таймауту и
освобождает слот; стрик эскалирует к РОВНО одному рестарту и верифицированный
рестарт ЧИСТИТ кэш; провал verify -> кэш НЕ чистится; консистентность ключа
(str(channel),int(post_id),fid) на всех путях после канонизации #24; LRU-кап.
Doc-коммент: стрик считает ТОЛЬКО consecutive-таймауты, не-таймаут ошибки
streak-нейтральны (поведение не менялось).

closes #43

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 04:28:50 +03:00