fix(tradein/avito): повтор после блока терял прокси и уходил с адреса машины #3143
No reviewers
Labels
No labels
Fable 5 ревью
GG-форсайт
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
feedback/max
generative
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
ИРД
вторичка
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#3143
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/3034-detail-retry-loses-proxy"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Найдено при проверке, помогла ли правка отпечатка из #3034. Помогла — и вскрыла следующий слой.
Дефект
Обе ветки повтора в
fetch_detail— 403/firewall и 429 — пересоздавали эфемерную сессию вызовом_build_detail_session()безconfig. Прокси kit-версия читает только изconfig.scraper_proxy_url, поэтому такая сессия уходила напрямую.Замысел ветки прямо обратный, он записан в её же комментарии:
И ветка вообще исполняется только при
backconnect=True, который вычисляется как «заданconfig.scraper_proxy_url». То есть в момент вызова достоверно известно, что прокси есть — и ровно здесь он терялся.Почему это не было видно
Пока адрес самой машины не был заблокирован, прямой повтор часто срабатывал, и подмена канала выглядела как успех.
Замер 27.08 из прод-контейнера, один и тот же URL Авито, один и тот же код:
С момента, когда адрес машины попал под ограничение, каждый повтор после блока стал обречён.
Совпадение с данными
Обогащение
avito_detail_backfillпо суткам:Почасовой срез показывает, что ноль наступает начиная с окна, в котором сменился адрес машины, и держится все последующие прогоны подряд.
Попутно это закрывает вопрос по #3034: правка отпечатка дала рост примерно с 4 до 140 обогащений в сутки и держалась пять суток. Обвал — другая причина, и она здесь.
Тесты
Три штуки:
config— собственно инвариант.configпрокси в сессии действительно нет — доказываем цену пропуска на настоящей сессии, а не верим на слово.Проверил, что тест краснеет на старом коде:
Тот же класс ошибки чинили в #2330 для
build_warmed_session— в пути повтора он оставался.Refs #3034, #3045
Обе ветки повтора в `fetch_detail` — 403/firewall и 429 — пересоздавали эфемерную сессию вызовом `_build_detail_session()` БЕЗ `config`. Прокси kit-версия читает только из `config.scraper_proxy_url`, поэтому такая сессия уходила напрямую. Замысел ветки прямо обратный, он записан в её же комментарии: «эфемерная свежая сессия (новый CONNECT-туннель = свежий exit-IP)». Ветка вообще исполняется только при backconnect=True, а он вычисляется как «задан config.scraper_proxy_url» — то есть в момент вызова достоверно известно, что прокси есть, и он терялся. ПОЧЕМУ НЕ БЫЛО ВИДНО. Пока адрес самой машины не был заблокирован, прямой повтор часто срабатывал, и подмена канала выглядела как успех. Замер 27.08 из прод-контейнера, один и тот же URL Авито: через прокси — 200, 3.3 МБ страницы напрямую — 429, «доступ ограничен», firewall С этого момента каждый повтор после блока обречён. Обогащение avito_detail_backfill по суткам: 21-25.08 — 178/129/147/138/111, 26.08 — 23, 27.08 — 0 при 25 блоках. Обвал начинается ровно с окна, в котором сменился адрес машины. Тот же класс ошибки чинили в #2330 для build_warmed_session; в пути повтора он оставался. Три теста: обе ветки на месте (страховка от проверки пустоты), ни одна не строит сессию без config, и отдельно доказано, что без config прокси в сессии действительно нет. Проверил красноту на старом коде — падает с точным текстом. Прогон: 107 тестов scrapers зелёные, ruff чист. Refs #3034, #3045Дополнение: диагноз подтверждается естественным опытом, который уже поставлен за нас.
Соседний провайдер делает то же самое — но правильно
providers/avito/serp.py::_build_cffi_session— метод, читающийself._config.scraper_proxy_url:Его пересоздание (
_reset_cffi) сделано ради ровно той же цели — «новый CONNECT-туннель = свежий exit-IP» — и прокси при этом не теряет, потому что берёт его из состояния объекта, а не из аргумента.В
detail.pyта же операция вынесена в свободную функцию с необязательнымconfig, и два места из четырёх вызывали её пустой.Что из этого следует для чисел
Если диагноз верен, страдать должен ровно
detail_backfill, а свипы черезserp.py— нет. Проверил поscrape_runs, деля на «до/после 21.08 17:02» (правка отпечатка):avito_city_sweepavito_newbuilding_sweepavito_detail_backfillСвипы держат свои полтора-восемь десятых и никак не реагируют на блокировку адреса машины — они через него и не ходят. Умер только тот путь, где повтор сваливался на прямое соединение.
Проверил заодно остальные
_build_*_session()в kit: вызовов без аргументов больше нет нигде, кроме этих двух исправленных.