fix(tradein/proxy): узел, зарезервированный за Домкликом, до Домклика не доходит (#2800 A) #2802

Merged
bot-backend merged 1 commit from fix/2800a-proxy1-affinity into main 2026-08-09 18:15:56 +00:00
Collaborator

Что не так

Узел scrape_proxies.id=1 закреплён за Домкликом миграцией 173 (provider_affinity='domclick'). Живая проба 09.08.2026 тем же трактом, что и работа (сайдкар tradein-browser → camoufox с этим прокси → навигация на robots.txt рабочего хоста площадки):

узел affinity avito ekb.cian.ru realty.yandex.ru bff-search-web.domclick.ru
1 domclick 200 200 «Ошибка — Циан» (374 КБ HTML, не robots) 200 500 NS_ERROR_PROXY_BAD_GATEWAY
9 any 200 200 200 200
10 any 200 200 200 200
11 any 200 200 200 200

До рабочего хоста Домклика (bff-search-web.domclick.ru — туда ходит providers/domclick/serp.py::_BFF_BASE) узел не доходит вообще. При этом Авито и Яндекс через него отвечают штатно.

Резервация работала ровно наоборот задуманному: держала узел за единственным источником, которому он не годен, и прятала от двух, которым годен — acquire() отбирает по provider_affinity IN (source,'any'), а fallback этот узел не берёт (защита последнего узла выделенной affinity).

Попутно опровергнута формулировка из issue: узел мёртв не для «Домклика», а для его BFF-хоста. domclick.ru/robots.txt через него отдаёт 200 — то есть проба по apex-домену была бы зелёной и бесполезной. Это учтено в части B.

Что сделано

  • Миграция 253_scrape_proxy_domclick_affinity_release.sql: provider_affinity 'domclick' → 'any'.
  • Обновлён устаревший комментарий в acquire() (ссылался на «у domclick ровно один узел id=1» как на текущее положение дел).

'any', а не enabled=false: узел жив для двух площадок из четырёх, выключать целиком — терять четверть и без того дефицитного пула (#2638). CHECK-констрейнт не трогаем — значение остаётся допустимым для узла, который до Домклика реально дойдёт.

Границы (что этот PR НЕ делает)

Это не починка Домклика. acquire('domclick') и раньше видел все четыре узла (affinity IN ('domclick','any')), шанс вытянуть узел 1 и потратить первый бакет впустую был и остаётся 1/4. Закрывает это проба по паре «узел × источник» — часть B того же issue, отдельным PR сегодня же.

Побочный эффект до части B: Циан получает 1 шанс из 4 вытянуть узел, для Циана мёртвый (сейчас он его вообще не видел). Ближайший прогон Циана — cian_city_sweep_* 10.08 ~11:24Z, часть B успевает раньше.

Проверка

  • scripts/check-migration-lock-timeout.py✓ блокирующий DDL прикрыт lock_timeout (проверено новых миграций: 2); блокирующего DDL в 253 нет (один UPDATE).
  • pytest tests/services/test_proxy_pool.py tests/test_2723_browser_probe.py tests/test_2657_domclick_proxy_pool.py → 79 passed.
  • Юнит-теста у этого PR нет намеренно: чинится значение в данных, а не ветка кода. Красный-на-старом-коде тест — в части B.

Прод-верификация (критерий записан ДО факта)

Ближайший domclick_city_sweep2026-08-10 04:43:59Z (scrape_schedules.next_run_at). Критерий приёмки для этого PR:

  • в scrape_proxies не остаётся строк с provider_affinity='domclick' (сразу после деплоя);
  • acquire('avito'|'yandex') начинает выдавать узел 1 — видно по proxy_pool: leased proxy id=1 provider=avito|yandex в логах tradein-scraper (до PR такой строки быть не могло).

Прогон Домклика 10.08 — критерий части B, не этой: одна смена affinity его не чинит.

Refs #2800

## Что не так Узел `scrape_proxies.id=1` закреплён за Домкликом миграцией 173 (`provider_affinity='domclick'`). Живая проба 09.08.2026 **тем же трактом, что и работа** (сайдкар `tradein-browser` → camoufox с этим прокси → навигация на `robots.txt` рабочего хоста площадки): | узел | affinity | avito | ekb.cian.ru | realty.yandex.ru | bff-search-web.domclick.ru | |---|---|---|---|---|---| | **1** | domclick | 200 | 200 «Ошибка — Циан» (374 КБ HTML, не robots) | 200 | **500 `NS_ERROR_PROXY_BAD_GATEWAY`** | | 9 | any | 200 | 200 | 200 | 200 | | 10 | any | 200 | 200 | 200 | 200 | | 11 | any | 200 | 200 | 200 | 200 | До рабочего хоста Домклика (`bff-search-web.domclick.ru` — туда ходит `providers/domclick/serp.py::_BFF_BASE`) узел не доходит вообще. При этом Авито и Яндекс через него отвечают штатно. Резервация работала ровно наоборот задуманному: держала узел за единственным источником, которому он **не** годен, и прятала от двух, которым годен — `acquire()` отбирает по `provider_affinity IN (source,'any')`, а fallback этот узел не берёт (защита последнего узла выделенной affinity). Попутно опровергнута формулировка из issue: узел мёртв **не для «Домклика»**, а для его BFF-хоста. `domclick.ru/robots.txt` через него отдаёт 200 — то есть проба по apex-домену была бы зелёной и бесполезной. Это учтено в части B. ## Что сделано - Миграция `253_scrape_proxy_domclick_affinity_release.sql`: `provider_affinity` `'domclick' → 'any'`. - Обновлён устаревший комментарий в `acquire()` (ссылался на «у domclick ровно один узел id=1» как на текущее положение дел). `'any'`, а не `enabled=false`: узел жив для двух площадок из четырёх, выключать целиком — терять четверть и без того дефицитного пула (#2638). CHECK-констрейнт не трогаем — значение остаётся допустимым для узла, который до Домклика реально дойдёт. ## Границы (что этот PR НЕ делает) **Это не починка Домклика.** `acquire('domclick')` и раньше видел все четыре узла (`affinity IN ('domclick','any')`), шанс вытянуть узел 1 и потратить первый бакет впустую был и остаётся 1/4. Закрывает это проба по паре «узел × источник» — **часть B** того же issue, отдельным PR сегодня же. Побочный эффект до части B: Циан получает 1 шанс из 4 вытянуть узел, для Циана мёртвый (сейчас он его вообще не видел). Ближайший прогон Циана — `cian_city_sweep_*` 10.08 ~11:24Z, часть B успевает раньше. ## Проверка - `scripts/check-migration-lock-timeout.py` → `✓ блокирующий DDL прикрыт lock_timeout (проверено новых миграций: 2)`; блокирующего DDL в 253 нет (один `UPDATE`). - `pytest tests/services/test_proxy_pool.py tests/test_2723_browser_probe.py tests/test_2657_domclick_proxy_pool.py` → 79 passed. - Юнит-теста у этого PR нет намеренно: чинится значение в данных, а не ветка кода. Красный-на-старом-коде тест — в части B. ## Прод-верификация (критерий записан ДО факта) Ближайший `domclick_city_sweep` — **2026-08-10 04:43:59Z** (`scrape_schedules.next_run_at`). Критерий приёмки для этого PR: - в `scrape_proxies` не остаётся строк с `provider_affinity='domclick'` (сразу после деплоя); - `acquire('avito'|'yandex')` начинает выдавать узел 1 — видно по `proxy_pool: leased proxy id=1 provider=avito|yandex` в логах `tradein-scraper` (до PR такой строки быть не могло). Прогон Домклика 10.08 — критерий **части B**, не этой: одна смена affinity его не чинит. Refs #2800
bot-backend added 1 commit 2026-08-09 17:57:14 +00:00
fix(tradein/proxy): узел, зарезервированный за Домкликом, до Домклика не доходит (#2800 A)
All checks were successful
CI / changes (pull_request) Successful in 9s
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 3m54s
CI Trade-In / changes (pull_request) Successful in 8s
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
ce5df52259
Живая проба 09.08.2026 тем же трактом, что и работа (сайдкар tradein-browser →
camoufox с этим прокси → навигация на robots.txt рабочего хоста площадки):

  узел | affinity | avito | ekb.cian.ru         | realty.yandex.ru | bff-search-web.domclick.ru
  -----+----------+-------+---------------------+------------------+---------------------------
    1  | domclick | 200   | 200 «Ошибка — Циан» | 200              | 500 NS_ERROR_PROXY_BAD_GATEWAY
    9  | any      | 200   | 200                 | 200              | 200
   10  | any      | 200   | 200                 | 200              | 200
   11  | any      | 200   | 200                 | 200              | 200

Узел 1 закреплён за Домкликом миграцией 173, но до рабочего хоста Домклика
(bff-search-web.domclick.ru — туда ходит providers/domclick/serp.py) не доходит
вообще, а Авито и Яндекс через него отвечают штатно. Резервация работала ровно
наоборот задуманному: держала узел за единственным источником, которому он НЕ
годен, и прятала от двух, которым годен (acquire отбирает по provider_affinity
IN (source,'any'), а fallback этот узел не берёт — защита последнего узла
выделенной affinity).

Миграция 253: provider_affinity 'domclick' → 'any'. Не enabled=false — узел жив
для двух площадок из четырёх, выключать его целиком значит терять четверть и без
того дефицитного пула (#2638). CHECK-констрейнт не трогаем: значение остаётся
допустимым для узла, который до Домклика реально дойдёт.

Границы: это НЕ починка Домклика. acquire('domclick') и раньше видел все четыре
узла, шанс вытянуть узел 1 и потратить первый бакет впустую был и остаётся 1/4 —
закрывает это проба по паре «узел × источник» (часть B того же issue). Здесь
снимается только резервация. Побочно: до части B Циан получает 1 шанс из 4
вытянуть узел, для Циана мёртвый; ближайший прогон Циана — 10.08 11:24Z, часть B
идёт сегодня же.

Refs #2800
bot-backend merged commit 7cd8c63b89 into main 2026-08-09 18:15:56 +00:00
bot-backend deleted branch fix/2800a-proxy1-affinity 2026-08-09 18:15:56 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
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#2802
No description provided.