fix(tradein/domclick): detail-бэкфилл ходил в сайдкар мимо прокси-пула (#3197 ч.1) #3222

Merged
bot-backend merged 2 commits from fix/3197-domclick-backfill-proxy-pool into main 2026-08-29 12:46:43 +00:00
Owner

Часть 1 из #3197, только точка Домклика. Точки Циана и Яндекса поедут отдельными PR — issue сам предписывает подключать по одной с суточной паузой, чтобы при поломке было понятно, у кого именно.

Дефект

domclick_detail_backfill.py строил фетчер так:

async with BrowserFetcher(
    source="domclick", endpoint=settings.browser_http_endpoint, reuse_context=True
) as bf:

Без proxy_provider/use_pool/environment тело POST /fetch не несёт "proxy", сайдкар берёт свой env-прокси (SCRAPER_PROXY_URL), и прогон идёт мимо пула целиком: ни выбора узла, ни scrape_proxy_source_bans, ни ротации при блоке. Тот же дефект уже чинили на avito_detail_backfill и house_imv_backfill (#2698) — этот call site оставался последним.

Оба параметра нужны вместе: при use_pool=False переданный proxy_provider игнорируется (providers/_base.py:203,211-213). environment тоже обязателен — без него отказ «пул пуст» на этом пути мёртвый код и фетчер молча уходит на env-прокси (#2616 шаг 1).

Заодно: неверный комментарий

Комментарий над конструктором ссылался на scrape_proxies.provider_affinity='domclick' и миграцию 173. На проде такого больше нет — миграция 253 сняла резервацию узла (#2800), и на 29.08 у всех четырёх включённых узлов (id 1, 9, 10, 11) стоит provider_affinity='any'. Переписан по факту.

Почему это безопасно — замер на проде 29.08

Главный риск был в том, что мобильные узлы 9/10/11 не проходят QRATOR, и подключение пула даст три быстрых бана вместо одного. Опровергнуто замером. Шесть карточек подряд через узел 11 (asocks-mobile-3) с reuse_context=true:

# статус размер итог
1 401 7 086 челлендж PoW, контекст создаётся
2–6 200 540–847 КБ __SSR_STATE__, 5/5

Контроль без reuse_context, те же карточки: каждая вторая — страница блока ровно 26 625 байт, и так на всех четырёх узлах. То есть прежние отказы объяснялись выбрасыванием browser context (#3212, починено #3217), а не качеством узлов.

Прогрев тратится один раз на прогон, а не на карточку: lease липкий — browser_fetcher.py:381 берёт его один раз в __aenter__, ре-acquire только на :730 после трёх подряд неудачных /fetch. Смена узла (а с ней и потеря тёплого контекста) остаётся редким осознанным событием.

Тесты

  • Новый tests/test_3197_domclick_proxy_pool_wiring.py — 2 теста в стиле test_2698_imv_sidecar_wiring.py: use_pool берётся из конфига (проверены обе ветки, prod/dev), proxy_provider непустой, environment доезжает, reuse_context=True не сломан. Сеть/БД/камуфокс замоканы.
  • tests/test_3118_domclick_warm_context.py — старый assert_called_once_with фиксировал точную сигнатуру и ломался бы на любом новом kwarg. Заменён на проверку значимых kwargs; полная проводка теперь покрыта отдельным тестом, ссылка проставлена в комментарии.

Прогон: 24/24 зелёных (test_3197 + test_3118 + test_3196), ruff чист. Ревью — APPROVE, критичных и минорных замечаний нет.

Приёмка после деплоя

Плановый domclick_detail_backfill в 15–18 UTC. Смотреть в scrape_runs.counters: узел должен приходить из пула, а не быть постоянным, и enriched — вырасти относительно нынешних 0–2 из 3–6 попыток.

Refs #3197, #3212, #2698, #2616.

Часть 1 из #3197, только точка Домклика. Точки Циана и Яндекса поедут отдельными PR — issue сам предписывает подключать по одной с суточной паузой, чтобы при поломке было понятно, у кого именно. ## Дефект `domclick_detail_backfill.py` строил фетчер так: ```python async with BrowserFetcher( source="domclick", endpoint=settings.browser_http_endpoint, reuse_context=True ) as bf: ``` Без `proxy_provider`/`use_pool`/`environment` тело `POST /fetch` не несёт `"proxy"`, сайдкар берёт свой env-прокси (`SCRAPER_PROXY_URL`), и прогон идёт мимо пула целиком: ни выбора узла, ни `scrape_proxy_source_bans`, ни ротации при блоке. Тот же дефект уже чинили на `avito_detail_backfill` и `house_imv_backfill` (#2698) — этот call site оставался последним. Оба параметра нужны вместе: при `use_pool=False` переданный `proxy_provider` игнорируется (`providers/_base.py:203,211-213`). `environment` тоже обязателен — без него отказ «пул пуст» на этом пути мёртвый код и фетчер молча уходит на env-прокси (#2616 шаг 1). ## Заодно: неверный комментарий Комментарий над конструктором ссылался на `scrape_proxies.provider_affinity='domclick'` и миграцию 173. На проде такого больше нет — миграция 253 сняла резервацию узла (#2800), и на 29.08 у **всех четырёх** включённых узлов (id 1, 9, 10, 11) стоит `provider_affinity='any'`. Переписан по факту. ## Почему это безопасно — замер на проде 29.08 Главный риск был в том, что мобильные узлы 9/10/11 не проходят QRATOR, и подключение пула даст три быстрых бана вместо одного. **Опровергнуто замером.** Шесть карточек подряд через узел 11 (`asocks-mobile-3`) с `reuse_context=true`: | # | статус | размер | итог | |---|---|---|---| | 1 | 401 | 7 086 | челлендж PoW, контекст создаётся | | 2–6 | 200 | 540–847 КБ | `__SSR_STATE__`, 5/5 | Контроль без `reuse_context`, те же карточки: каждая вторая — страница блока ровно 26 625 байт, и так на всех четырёх узлах. То есть прежние отказы объяснялись выбрасыванием browser context (#3212, починено #3217), а не качеством узлов. **Прогрев тратится один раз на прогон, а не на карточку**: lease липкий — `browser_fetcher.py:381` берёт его один раз в `__aenter__`, ре-acquire только на :730 после трёх подряд неудачных `/fetch`. Смена узла (а с ней и потеря тёплого контекста) остаётся редким осознанным событием. ## Тесты - Новый `tests/test_3197_domclick_proxy_pool_wiring.py` — 2 теста в стиле `test_2698_imv_sidecar_wiring.py`: `use_pool` берётся из конфига (проверены обе ветки, prod/dev), `proxy_provider` непустой, `environment` доезжает, `reuse_context=True` не сломан. Сеть/БД/камуфокс замоканы. - `tests/test_3118_domclick_warm_context.py` — старый `assert_called_once_with` фиксировал точную сигнатуру и ломался бы на любом новом kwarg. Заменён на проверку значимых kwargs; полная проводка теперь покрыта отдельным тестом, ссылка проставлена в комментарии. Прогон: 24/24 зелёных (`test_3197` + `test_3118` + `test_3196`), ruff чист. Ревью — ✅ APPROVE, критичных и минорных замечаний нет. ## Приёмка после деплоя Плановый `domclick_detail_backfill` в 15–18 UTC. Смотреть в `scrape_runs.counters`: узел должен приходить из пула, а не быть постоянным, и `enriched` — вырасти относительно нынешних 0–2 из 3–6 попыток. Refs #3197, #3212, #2698, #2616.
lekss361 added 1 commit 2026-08-29 12:29:26 +00:00
fix(tradein/domclick): backfill ходил в сайдкар мимо прокси-пула (#3197 ч.1)
Some checks failed
CI Trade-In / changes (pull_request) Successful in 9s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / changes (pull_request) Successful in 11s
CI / backend-tests (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) Failing after 4m53s
fd95c962bb
BrowserFetcher(source="domclick", reuse_context=True) конструировался без
proxy_provider/use_pool/environment -- тела POST /fetch не несли "proxy",
сайдкар брал свой env-прокси, и прогон шёл мимо пула целиком: ни выбора узла
по affinity, ни scrape_proxy_source_bans, ни ротации при блоке. Тот же дефект
уже чинили на avito_detail_backfill/house_imv_backfill (#2698) -- этот call
site оставался последним непочиненным. environment обязателен: без него
отказ «пул пуст» на этом пути мёртв (#2616 шаг 1). reuse_context=True
сохранён без изменений.

Заодно поправлен устаревший комментарий над конструктором: ссылался на
scrape_proxies.provider_affinity='domclick' и миграцию 173 -- на проде
такого больше нет (миграция 253 сняла резервацию узла, #2800), все четыре
включённых узла (id 1/9/10/11) имеют provider_affinity='any'.

test_3118_domclick_warm_context.py обновлён под новую сигнатуру вызова
(assert_called_once_with -> точечная проверка нужных kwargs).
bot-backend added 1 commit 2026-08-29 12:41:13 +00:00
test(tradein/domclick): второй assert_called_once_with на конструкторе (#3197 ч.1)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI / changes (pull_request) Successful in 11s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (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 4m58s
301d803ac5
CI Trade-In / backend-tests упал на tests/tasks/test_domclick_detail_backfill.py:165 —
там тот же хрупкий assert_called_once_with, что уже был поправлен в
tests/test_3118_domclick_warm_context.py: он фиксирует ТОЧНУЮ сигнатуру вызова
BrowserFetcher и ломается на любом новом kwarg.

Лечение то же самое: assert_called_once() + точечная проверка source/endpoint/
reuse_context. Полная проводка пула покрыта отдельным
tests/test_3197_domclick_proxy_pool_wiring.py.

Причина пропуска: локально прогонялась выборка из трёх файлов, а не весь набор.
Теперь прогнан весь: 4974 passed, 37 skipped, 0 failed.
bot-backend merged commit fa62d69fb9 into main 2026-08-29 12:46:43 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#3222
No description provided.