Домовая оценка Авито не сохранила ни одной записи с 03.07 — 34 дня, каждый
прогон 35 отказов из 35 попыток. Отказ приходил от НАШЕГО сайдкара
(tradein-browser:3000/fetch-json): 1240 домов «503 Service Unavailable»
(до 02.08), затем 83 «500 Internal Server Error» и 31 «403 auth rejected»
(05.08). При этом сам сайдкар был жив.
1. Проводка пула. backfill_house_imv конструировал
BrowserFetcher(source="avito", endpoint=...) без proxy_provider/use_pool/
environment — единственный avito-путь без пула (avito_city_sweep его
подключает, orchestration/pipeline.py:519). Без них тело POST /fetch-json
уходит БЕЗ "proxy", и сайдкар берёт свой env-прокси SCRAPER_PROXY_URL. На
проде это узел пула id=1 (asocks-residential-1, provider_affinity='domclick')
— узел, который proxy_pool.acquire('avito') не выдал бы никогда: он отбирает
affinity IN (provider,'any'), а последний узел выделенной affinity ещё и
защищён от fallback (173_scrape_proxies_add_domclick_affinity.sql).
Контрольная группа в тех же сутках: avito_city_sweep и
avito_newbuilding_sweep тянули сотни объявлений через ТОТ ЖЕ сайдкар и тот
же инстанс камуфокса (01.08: 78/69 и 484/447), пока house_imv_backfill
получал 35 отказов из 35. Разница ровно одна — поле "proxy" в теле запроса.
Второй эффект этой же дыры: запрос без "proxy" роняет сайдкару желаемый
прокси на env → relaunch камуфокса на каждый дом (server.py::_ensure_browser),
то есть путь IMV ещё и сбивал тёплый браузер sweep'ам.
environment пробрасывается ради #2616 шаг 1: иначе прод-отказ «пул пуст»
на этом пути мёртв и фетчер молча уходит на тот самый env-прокси.
2. Причина отказа больше не выбрасывается. Сайдкар кладёт её в тело
({"error": "browser unavailable (proxy may be down)"} / {"error": "Error:
Page.goto: NS_ERROR_PROXY_BAD_GATEWAY"}), а resp.raise_for_status() печатает
только код: ровно строка «Server error '503 Service Unavailable' for url
'http://tradein-browser:3000/fetch-json'» и лежала 34 дня в
houses.imv_error_reason у 1240 домов. Общий _raise_for_sidecar_status в
browser_fetcher (оба вызова, /fetch и /fetch-json) добавляет тело в текст
ошибки; тип исключения прежний (HTTPStatusError ⊂ HTTPError), retry-политика
не меняется.
Тесты: проводка пула доезжает до фетчера; причина сайдкара доезжает до
вызывающего на обоих эндпоинтах. Прежний parity-тест эндпоинта расширен
новыми аргументами (не ослаблен).
Не чинится кодом (в #2704): 403 от самой площадки и живость единственного
исходящего IP — ротация пула ждёт ASOCKS_API_TOKEN (#2638).
Refs #2698