Сайдкар МЕРЫ: зона браузера по IP узла, якорь Домклика без Яндекса, автологин Циана через пул, время навигации в логах #3563
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#3563
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/browser-sidecar"
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?
Четыре задачи по браузерному сайдкару МЕРЫ (
tradein-browser), по коммиту на каждую. Три закрыты полностью. Для #3419 сделан только первый шаг: сайдкар начал писать в лог время навигации. Решение по порогу таймаута будет после 48 часов данных.#3187: таймзона браузера теперь берётся из IP узла, а не задаётся жёстко как МСК
Что было. В
_launch_browserстоялиgeoip=Trueиconfig={"timezone": "Europe/Moscow"}. Camoufox 0.5.5 (utils.launch_options) при geoip ставит координаты из GeoIP-записи exit-IP безусловно, а таймзону — черезsetdefault. В итоге ручная МСК перебивала зону из IP, а координаты оставались по IP. На ручную зону библиотека пишетLeakWarning: Please use the geoip parameter.Улики.
Прод,
docker logs --since 13h tradein-browserна 17.09: 4715 таких предупреждений на 665 запусков браузера.Включённые узлы пула по RIPE whois, 17.09:
T2 Russia IP Network (NSK), geoloc 55.03/82.97, Новосибирск, UTC+7;POOL-MEGAFON-AMS-3, Самара, UTC+4;Получается, что заявленная МСК расходится с адресом у трёх узлов из четырёх.
Опасение из старого комментария («BackConnect ротирует IP на каждый запрос») к текущему пулу не подходит. Health-логи за 48 часов показывают, что ротация меняет адрес внутри подсети оператора: у узла 15 это 176.59.137.x и 176.59.144.x, у узла 14 — 178.176.78-79.x. При смене узла браузер перезапускается (
_launched_proxy), поэтому зона, взятая при запуске, не устаревает.Что сделано. Ручная таймзона убрана. Зону и координаты теперь ставит geoip из одной записи.
Тест
test_server_proxy_override.py::test_launch_leaves_timezone_to_geoipподменяетcamoufox.async_apiи проверяет реальные kwargs запуска:geoip is True, прокси разобран, вconfigнет ключейtimezoneиgeolocation:*. Это ровно те ключи, на которые camoufox пишет предупреждение.Фальсификация: вернул строку
"config": {"timezone": "Europe/Moscow"}.Приёмка на проде (через час после деплоя, не раньше 18.09):
docker logs --since 1h tradein-browser 2>&1 | grep -c 'Please use the .geoip. parameter'должно дать 0 (сейчас около 360 в час);scrape_runsза сутки не выросла по сравнению с 16–17.09.Closes #3187
#3263: якорь Домклика открывает свою выдачу напрямую, без поиска Яндекса
Что было. По умолчанию
BROWSER_ANCHOR_VIA_SEARCH="domclick": якорная вкладка шла наyandex.ru/searchи кликала по результату.Почему плохо.
docker logs tradein-browserза 15–16.09: все 7 попыток закончились «капча на выдаче Яндекса», и каждая из них через 0,2 с — «якорная вкладка не поднялась (Error)». После этого карточка получалаBanPageDetectedError.providers/domclick/detail.py,referer=origin.Что сделано. Значение
BROWSER_ANCHOR_VIA_SEARCHпо умолчанию теперь пустое. Путь через поиск остаётся, но включается только явным env. Владелец предлагал именно этот вариант. Тесты пути через Яндекс включают его явно через фикстуру.Новый тест
test_default_env_domclick_anchor_goes_straight_to_originзагружает модуль заново без env. В подделке на выдаче Яндекса стоит капча. Тест проверяет, чтоgoto_calls == [{"url": origin, "referer": None}].Фальсификация: вернул значение по умолчанию
"domclick".Приёмка на проде (через 1–2 дня после деплоя, не раньше 19.09):
tradein-browser0 строк[domclick]: капча на выдаче Яндекса;[domclick]: якорная вкладка не поднялась— 0 или единичные случаи;Если якорь без Яндекса тоже не поднимается (Error), причина не в поиске. Это отдельный разбор.
Closes #3263
#3410: автологин в Циан идёт через узел пула, а не через мёртвый env-узел сайдкара
Что было.
login_handlerвызывал_no_live_proxy(provider, None)и_ensure_browser(provider)без override.BrowserFetcher.loginне клалproxyв тело запроса.cian_auto_loginсознательно не передавала провайдер (#3197): аренда там была бы холостой.В итоге логин всегда шёл через
SCRAPER_PROXY_URLсайдкара. На проде 17.09 это190.2.145.131:10313, то есть узел 9: вscrape_proxiesу негоenabled=false, 324 провала подряд, «НЕ ИСПОЛЬЗУЕТСЯ (владелец, 12.09.2026)». Ручка восстановления cian-сессии не работала вовсе.Что сделано. Три места, каждое по образцу соседа:
/loginберётproxyиз тела так же, как/fetch: guard и_ensure_browser(provider, proxy_override=…). При перезапуске после краша_do_loginсохраняет_launched_proxy, то есть тот же узел.login()кладёт в тело узел текущей аренды (_current_proxy()), как это делает_post_fetch._kit_proxy_provider(), как debug-карточка DomClick в том же файле. Пустой пул на проде даёт 503 «Нет свободного узла прокси для cian в пуле — логин не запускался», а не 502 «Browser login failed» и не заход на мёртвый env-узел (#2616).Совместимость при деплое в любом порядке. Старый сайдкар игнорирует
proxyв теле/login, новый безproxyведёт себя по-старому.Тесты #3197, которые утверждали «логин без пула», переписаны на обратные утверждения.
Тесты:
test_login_handler_prod_uses_body_proxy(2 случая): с proxy в теле и без env-прокси —_ensure_browser("cian", "http://pool:8080"); без proxy в теле — overrideNone;test_login_body_carries_lease_proxy(2 случая): при аренде в теле/loginлежатproxyиproxy_kindаренды, аренда отпускается; без пула этих полей нет;test_cian_auto_login_logs_in_through_pool_lease: провайдер передан,acquire == ["cian"], логин видит узел аренды,released == [13];test_cian_auto_login_empty_pool_in_production_is_honest_503: 503 со словом «пул», логин не запускался;test_cian_auto_login_dev_without_browser_pool_uses_env: аренды нет, проксиNone.Фальсификация в трёх слоях сразу (сайдкар без override, kit без
body["proxy"], ручка без провайдера):Отдельно проверил ветку 503: заменил
except NoProxyAvailableErrorна посторонний класс.Приёмка на проде (после деплоя, когда в пуле есть свободный cian-узел; нужно до 27.09, когда истекает текущая cian-сессия):
POST /api/v1/admin/scrape/cian/auto-loginвозвращаетok;tradein-browserесть[cian]: браузер запущен (proxy_override=True)рядом сlogin OK;Запуск ручки сохраняет сессию в БД, поэтому это решение владельца, агент её не вызывал.
Closes #3410
#3419 (частично): в логах /fetch появилось время целевой навигации
Что было. Порог
BROWSER_NAV_TIMEOUT_MS=60000не с чем было сравнить:Сейчас на проде (
docker logs --since 24h, 17.09): у[cian]54TimeoutError: Page.gotoна примерно 1350 страниц (90 перезапусков по порогу × 15), это около 4 %.Что сделано.
_fetch_onceмеряет только целевуюpage.gotoчерезtime.monotonicвfinally, поэтому время пишется и при таймауте. Обе строки несутnav_ms, «fetch OK» переведён на INFO.nav_ms=Noneозначает, что до цели не дошли (упал прогрев origin); прошлое значение в этом случае не наследуется.Тест
test_server_nav_timing.pyподменяет часы только в модуле сервера:nav_ms == 12345;60000;None.Фальсификация.
assert [60000, 60000] == [60000, None].finally, а только при успехе:assert [None, None] == [60000, None].Что осталось (Refs, не Closes). Собрать 48 часов данных. Посчитать p50/p90/p99
nav_msуспешных cian-fetch по типу страницы (cat/sale/zhk по URL в той же строке) и сравнить с долей таймаутов. Решить: разметить отказ площадки, поднять порог до обоснованного значения или сменитьwait_until. Замер не раньше 19.09 вечером.Refs #3419
Тесты
tradein-mvp/browser:pytest -q -rs→ 252 passed, rc=0. До правок было 246, добавлено 6.tradein-mvp/backend:DATABASE_URL=… uv run python -m pytest tests/ -q -p no:cacheprovider→ 6227 passed, 42 skipped, rc=0.uv run ruff check app tests→ All checks passed.ruff format --checkпо изменённым Python-файлам backend и kit → already formatted.packages/scraper-kit: своих тестов нет (no tests ran, rc=5). Тесты kit лежат вbackend/tests.Деплой
tradein-browser(browser/),tradein-backendиtradein-scraper(backend/ и packages/scraper-kit/** пересобирают backend-образ).tradein-browserубивает все активные браузерные прогоны,tradein-scraper— тоже. Перед мержем проверитьSELECT count(*) FROM scrape_runs WHERE status='running'в том же блоке, что и мерж.🤖 Generated with Claude Code