feat(tradein/scrapers): хранилище авторизованной сессии Яндекс.Недвижимости #3195
Merged
bot-backend
merged 3 commits from 2026-08-28 19:02:06 +00:00
feat/3192-yandex-session-store into main
3 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
4c3a767f45 |
fix(tradein/sql): миграция 274 без lock_timeout роняла гейт #2752
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 4m55s
CI / changes (pull_request) Successful in 11s
CI / backend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Successful in 1m5s
CREATE INDEX без lock_timeout встаёт в очередь за чужой долгой сессией и уводит за собой запросы приложения. Таблица новая и пустая, но очередь блокировок этого не знает, а гейт check-migration-lock-timeout.py держит правило на каждом PR — и правильно делает. Заодно поправлена шапка миграции: там осталась моя опровергнутая версия, будто ценность в mainPhone и одиннадцати номерах. mainPhone лежит в паспортном блоке рядом с login/passportHost/passportPhones — это номер НАШЕЙ учётки, а не продавца, и собирать его нельзя. Настоящее различие между режимами — author.phoneNumbers (0 без кук, 2 с куками, одинаково на обеих карточках); encryptedPhones в обоих режимах одинаков. Refs #3192 |
||
|
|
bb59caa90c |
feat(tradein/scrapers): хранилище авторизованной сессии Яндекс.Недвижимости
Some checks failed
CI Trade-In / changes (pull_request) Successful in 9s
CI / changes (pull_request) Failing after 8s
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 / browser-tests (pull_request) Successful in 1m6s
CI Trade-In / backend-tests (pull_request) Successful in 4m48s
Замер через прод-сайдкар, две карточки, один тракт с куками и без: поле author.phoneNumbers присутствует только в авторизованном режиме (0 без кук, 2 с куками, одинаково на обеих), плюс три номера автора сверху. Это контакты продавца с тегом канала и redirectId. encryptedPhones при этом одинаков в обоих режимах (54) — зашифрованные токены отдаются всегда, различие не в них. listings.phones (jsonb) существует в схеме и пуст у всех 51 251 активного объявления по всем четырём источникам. Яндекс станет первым источником с контактами. Форма таблицы и сервиса повторяет работающие в проде cian_session_cookies и domclick_session_cookies: pgp_sym_encrypt, expires_at_estimate, last_used_at/last_invalid_at, предупреждение о протухании. Два отличия от образцов, оба намеренные: Хранится ПОЛНЫЙ CDP-объект куки (name/value/domain/path/httpOnly/ secure/expires), а не плоский dict name→value. У Яндекса куки живут на трёх доменах (.yandex.ru, .passport.yandex.ru, .realty.yandex.ru) и дублируют имена (pi ×4, yashr ×4) — плоский словарь их схлопывает. Сайдкар сегодня принимает только плоский формат; когда его контракт починят, хранилище уже готово. Набор сохраняется целиком, минус очевидная аналитика (_ym_*, yabs-*, _yasc*). Список критичных кук используется ТОЛЬКО для проверки, что дамп похож на авторизованную сессию, и не является фильтром сохранения: замер сделан на полном наборе 44 кук, и какая из них существенна — неизвестно. Сужение до allowlist сломало бы измеренное; это защищено комментариями и тестом. Роуты закрыты на двух уровнях: Caddy basic_auth снаружи и rbac_guard внутри (role=admin для /api/v1/admin/*). Refs #3192 |
||
|
|
e2863f6be9 |
fix(tradein/domclick): каждый запрос получал чистый браузерный контекст, куки реплеились протухшими
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 9s
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 / browser-tests (pull_request) Successful in 1m7s
CI Trade-In / backend-tests (pull_request) Successful in 4m49s
Сайдкар на каждый /fetch делал browser.new_page() поверх AsyncCamoufox — это новый изолированный контекст, cookie-jar умирал сразу после ответа. Туда вливался замороженный снимок кук из domclick_session_cookies, где qrator_jsid2 живёт ~2.5 часа, а хранится 30 дней. Первый запрос проходил с ещё живым токеном, все следующие показывали QRATOR один и тот же протухший — он отдавал челлендж-страницу без __SSR_STATE__. Отсюда двухнедельное attempted=4, enriched=1, blocked=3. Замер на проде 28.08: через сайдкар 26 запросов подряд — 100% блоков, включая свежеротированный exit-IP; те же карточки в тёплом контексте — 5 из 5 успешно, ~2 сек каждая. Сайдкар получил переиспользуемый per-provider контекст: куки вливаются один раз при создании, дальше jar живёт сам; страница закрывается после ответа, контекст остаётся. Закрытие контекста подшито к _close_browser, так что relaunch и shutdown его не теряют. Флаг opt-in: при reuse_context=False payload /fetch не получает новых ключей вовсе, поведение остальных поставщиков не меняется. Сброс сожжённого контекста — ровно один на обнаруженный блок, через отложенный флаг BrowserFetcher.request_context_reset(): fetch_detail() в kit не прокидывает reset_context, и менять этот промежуточный слой ради одного поставщика не хотелось. NB для деплоя: правка работает только если tradein-browser пересобран вместе с бэкендом. Старый сайдкар новые поля молча проигнорирует — не упадёт, но и не починит. Refs #3190, #3118 |