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
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
Живая проба 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
This commit is contained in:
parent
f3bcb1a25f
commit
ce5df52259
2 changed files with 67 additions and 8 deletions
|
|
@ -228,14 +228,21 @@ def acquire(db: Session, provider: str, *, run_id: int | None = None) -> ProxyLe
|
|||
чужая — только запасной вариант, чтобы источник не голодал при живых свободных узлах
|
||||
чужой affinity (#2600).
|
||||
|
||||
Fallback НЕ трогает последний enabled-узел выделенной (не-'any') affinity — см.
|
||||
173_scrape_proxies_add_domclick_affinity.sql: у domclick ровно один узел (id=1),
|
||||
намеренно вырезанный из общего пула, потому что QRATOR банит все прокси кроме этого
|
||||
одного чистого residential-адреса. Если fallback заберёт его под avito/cian/yandex,
|
||||
domclick останется без прокси вообще — хуже, чем голодание исходного источника,
|
||||
которое фикс призван устранить. Кандидат участвует в fallback, только если его
|
||||
affinity='any' ИЛИ у этой affinity есть ДРУГОЙ enabled-узел (EXISTS-подзапрос) —
|
||||
т.е. выдача не обнулит доступность выделенной affinity целиком.
|
||||
Fallback НЕ трогает последний enabled-узел выделенной (не-'any') affinity: если
|
||||
fallback заберёт его под чужой источник, «свой» останется без прокси вообще — хуже,
|
||||
чем голодание исходного источника, которое фикс призван устранить. Кандидат
|
||||
участвует в fallback, только если его affinity='any' ИЛИ у этой affinity есть ДРУГОЙ
|
||||
enabled-узел (EXISTS-подзапрос) — т.е. выдача не обнулит доступность выделенной
|
||||
affinity целиком.
|
||||
|
||||
Исторический повод для этой защиты (173_scrape_proxies_add_domclick_affinity.sql —
|
||||
единственный residential-узел id=1, закреплённый за domclick, потому что QRATOR
|
||||
банил остальные) снят миграцией 253 (#2800): живая проба показала, что как раз до
|
||||
рабочего хоста Домклика (bff-search-web.domclick.ru) этот узел НЕ доходит, а
|
||||
Авито/Яндекс через него работают — резервация держала узел за источником, которому
|
||||
он не годен, и прятала от тех, кому годен. Узлов с выделенной affinity на проде
|
||||
сейчас нет, но САМА защита остаётся: значение 'domclick' допустимо констрейнтом, и
|
||||
следующий выделенный узел должен получить её сразу, а не после повторного разбора.
|
||||
|
||||
ОБА запроса отсекают узлы с АКТИВНЫМ баном по ЭТОМУ provider'у
|
||||
(scrape_proxy_source_bans.banned_until > now(), #2600 п.2) — узел, забаненный Авито,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
-- 253_scrape_proxy_domclick_affinity_release.sql
|
||||
-- Снять с узла резервацию provider_affinity='domclick' (#2800).
|
||||
--
|
||||
-- WHY (замер, не рассуждение — живая проба 09.08.2026, тракт сайдкар+camoufox,
|
||||
-- POST /fetch на 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
|
||||
--
|
||||
-- Узел, закреплённый 173-й миграцией СПЕЦИАЛЬНО за Домкликом, до рабочего хоста
|
||||
-- Домклика не доходит вообще (NS_ERROR_PROXY_BAD_GATEWAY на bff-search-web —
|
||||
-- именно туда ходит боевой сбор, см. providers/domclick/serp.py::_BFF_BASE), при
|
||||
-- этом Авито и Яндекс через него отвечают штатно. Резервация даёт ровно обратный
|
||||
-- эффект задуманному: единственный источник, которому узел ГОДЕН НЕ БЫЛ, держал его
|
||||
-- за собой, а два источника, которым он годен, его не видели —
|
||||
-- acquire('avito'|'yandex') отбирает по provider_affinity IN (source,'any'), а
|
||||
-- fallback этот узел не берёт (защита последнего узла выделенной affinity).
|
||||
--
|
||||
-- 'any', а НЕ enabled=false: узел жив для двух площадок из четырёх, выключать его
|
||||
-- целиком — терять четверть и без того дефицитного пула (#2638).
|
||||
--
|
||||
-- WHAT:
|
||||
-- provider_affinity='domclick' → 'any' для узлов, у которых affinity именно такая.
|
||||
-- CHECK-констрейнт (173) не трогаем: значение 'domclick' остаётся допустимым, если
|
||||
-- в пуле появится узел, который до Домклика реально доходит.
|
||||
--
|
||||
-- ЧТО ЭТА МИГРАЦИЯ НЕ ДЕЛАЕТ (граница честная):
|
||||
-- Она НЕ чинит Домклик. acquire('domclick') и до неё видел все четыре узла
|
||||
-- (affinity IN ('domclick','any')), т.е. шанс вытянуть узел 1 и потратить первый
|
||||
-- бакет впустую был и остаётся 1/4 — закрывает это проба по паре «узел × источник»
|
||||
-- (#2800 часть B), а не смена affinity. Здесь снимается только резервация.
|
||||
--
|
||||
-- IDEMPOTENCY / SAFETY:
|
||||
-- Один UPDATE в транзакции; повторный прогон не находит строк (no-op) — auto-apply
|
||||
-- strict на деплое это требует. Блокирующего DDL нет (см.
|
||||
-- scripts/check-migration-lock-timeout.py: правило про ALTER/DROP/CREATE INDEX),
|
||||
-- UPDATE берёт row-lock на единичные строки.
|
||||
--
|
||||
-- Dependencies: 157_scrape_proxies.sql, 173_scrape_proxies_add_domclick_affinity.sql
|
||||
|
||||
BEGIN;
|
||||
|
||||
UPDATE scrape_proxies
|
||||
SET provider_affinity = 'any',
|
||||
updated_at = now()
|
||||
WHERE provider_affinity = 'domclick';
|
||||
|
||||
COMMIT;
|
||||
Loading…
Add table
Reference in a new issue