Из 115 avito-прогонов со статусом 'banned' 92 (80%) — отказ НАШЕГО браузерного
сайдкара («browser unavailable (proxy may be down)»), 10 — реальный firewall
площадки, 11 — HTTP 429/403. Оба исхода писали разный текст ошибки и получали
один статус: различитель лежал в данных и терялся в момент присвоения. По этому
статусу миграция 206 замедлила avito_full_load_exhaustive более чем вдвое —
основание было ложным.
Разводим не пути, а диагноз:
- AvitoSidecarUnavailableError — подтип AvitoRateLimitedError, поднимается ровно
там, где отказ порождён нашей инфраструктурой. Подтип, а не отдельный класс,
чтобы все `except (AvitoBlockedError, AvitoRateLimitedError)` продолжали ловить
его без изменений — иначе прогон ушёл бы в mark_failed и потерял чекпоинт;
- scrape_runs.ban_kind ('platform' | 'infra', миграция 218) рядом со status,
а не вместо него. Новое значение статуса пришлось бы доучить пяти местам
(CHECK, IN-списки обоих сторожей, Literal admin API, список статусов во
фронте), каждое из которых молча врёт, если про него забыть;
- побочная функция 'banned' — сохранение done_buckets-чекпоинта — остаётся у
ОБОИХ исходов: следующий прогон не начинает с нуля ни при нашем отказе, ни при
блокировке площадкой. Тест стережёт оба.
Признак несётся от места порождения (тип исключения), а не разбирается из текста
постфактум; разбор текста в миграции — разовая ретро-классификация истории.
Возврат такта Авито сюда НЕ входит — он вынесен в #2687 на данные 9-10.08.
Refs #2686