fix(tradein/imv): домовая оценка ходит в сайдкар через пул, а не через чужой env-прокси (#2698) #2708

Merged
bot-backend merged 1 commit from fix/2698-imv-outage into main 2026-08-06 06:52:16 +00:00

1 commit

Author SHA1 Message Date
aef43df650 fix(tradein/imv): домовая оценка ходит в сайдкар через пул, а не через чужой env-прокси (#2698)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 11s
CI / changes (pull_request) Successful in 10s
CI / backend-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 3m10s
Домовая оценка Авито не сохранила ни одной записи с 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
2026-08-06 11:47:41 +05:00