fix(tradein/domclick): перезапуск браузера на карточку уничтожал пропуск QRATOR (#3212) #3217

Merged
lekss361 merged 1 commit from fix/3212-domclick-keep-context into main 2026-08-29 11:16:40 +00:00
Owner

Закрывает #3212. Откатывает подход #3205, сохраняя его полезную часть.

Причина

ДомКлик закрыт QRATOR с proof-of-work:

  1. первый запрос → 401 + крошечная заглушка с задачей PoW;
  2. браузер её решает → GET /__qrator/validate?pow=…&nonce=…;
  3. 200 и пропуск в кукахqrator_jsid2 + qrator_jsr;
  4. дальше карточки открываются свободно, validate больше не вызывается.

Пропуск живёт в cookie jar, то есть в browser context'е. Прод брал каждую карточку через browser.new_page() — новый контекст, новая банка кук, пропуск выброшен. Повторная валидация с того же IP получала 403 и страницу bot-mitigation на 26 625 байт.

Замер (прод, прод-прокси, по 6 карточек на условие)

условие успех вызовы /__qrator/validate
один контекст, одна вкладка 6/6 [] на каждой карточке
один контекст, новая вкладка на карточку 6/6 [] на каждой карточке
новый контекст на карточку (= прод) 1/6 [304, 403] на каждой
боевой путь POST /fetch + reuse_context 6/6 0 перезапусков, 1 контекст

Последняя строка снята на отдельном экземпляре сайдкара с BROWSER_RECYCLE_PAGES_DOMCLICK=1000, чтобы перезапуск не подменял собой проверяемый механизм.

Правки

  1. _RECYCLE_PAGES_DEFAULT_BY_PROVIDER{} — снят domclick: 1. Перезапуск процесса гарантированно уничтожает контекст, то есть #3205 лечил симптом, который сам же и создавал (побочно: ~23.6 с на карточку и всё равно 18/20). Ручка per-provider (env + словарь) и domclick как отдельный провайдер — полезные части #3205 — остаются.
  2. Сброс контекста в бэкфилле: был на каждый блок → стал один раз за прогон. Это объясняет провал #3193: сброс выбрасывает пропуск → следующий фетч блокируется гарантированно → снова сброс. Одна осечка превращалась в необратимый каскад, что и дало приёмке «1 успех из 10». Одна попытка начать с чистого листа за прогон остаётся — на случай действительно протухшей сессии (TTL пропуска ~2.5 ч).
  3. Снята неверная формулировка «отказ, а не челлендж» из #3204/#3205. Челлендж есть; 26 624 байта — это результат проваленного PoW, а не статика вместо него. Ошибка вышла из метода: HTML читали на 4.5-й секунде, когда заглушка уже заменена, и ни разу не смотрели в сетевой лог.

Тесты

159 passed (сайдкар), 4972 passed / 37 skipped (backend).

Два теста кодировали снятый domclick=1. Не удалены, а переписаны через подставной _RECYCLE_PAGES_DEFAULT_BY_PROVIDER, чтобы уровень приоритета «код-дефолт поставщика» продолжал проверяться, а не исчез вместе с записью. Добавлен test_domclick_is_not_restarted_per_page — прямой сторож против возврата порога 1. Тест сброса контекста требует ровно одну попытку за прогон.

Не в этом PR

Пункт 3 из #3212 остаётся открытым: _CHALLENGE_MARKERS в сайдкаре ищет startpow, а заглушка QRATOR несёт __qrator, и при BROWSER_WAIT_MS=4500 HTML читается раньше, чем PoW решён. На поведение после этого PR не влияет (челлендж решается на прогреве origin один раз за прогон), но распознавание всё равно неверное.

Закрывает #3212. Откатывает подход #3205, сохраняя его полезную часть. ## Причина ДомКлик закрыт QRATOR с proof-of-work: 1. первый запрос → `401` + крошечная заглушка с задачей PoW; 2. браузер её решает → `GET /__qrator/validate?pow=…&nonce=…`; 3. `200` и **пропуск в куках** — `qrator_jsid2` + `qrator_jsr`; 4. дальше карточки открываются свободно, `validate` больше не вызывается. Пропуск живёт в cookie jar, то есть **в browser context'е**. Прод брал каждую карточку через `browser.new_page()` — новый контекст, новая банка кук, пропуск выброшен. Повторная валидация с того же IP получала `403` и страницу bot-mitigation на 26 625 байт. ## Замер (прод, прод-прокси, по 6 карточек на условие) | условие | успех | вызовы `/__qrator/validate` | |---|---|---| | один контекст, одна вкладка | **6/6** | `[]` на каждой карточке | | один контекст, новая вкладка на карточку | **6/6** | `[]` на каждой карточке | | новый контекст на карточку (= прод) | **1/6** | `[304, 403]` на каждой | | боевой путь `POST /fetch` + `reuse_context` | **6/6** | 0 перезапусков, 1 контекст | Последняя строка снята на отдельном экземпляре сайдкара с `BROWSER_RECYCLE_PAGES_DOMCLICK=1000`, чтобы перезапуск не подменял собой проверяемый механизм. ## Правки 1. **`_RECYCLE_PAGES_DEFAULT_BY_PROVIDER` → `{}`** — снят `domclick: 1`. Перезапуск процесса гарантированно уничтожает контекст, то есть #3205 лечил симптом, который сам же и создавал (побочно: ~23.6 с на карточку и всё равно 18/20). Ручка per-provider (env + словарь) и `domclick` как отдельный провайдер — полезные части #3205 — остаются. 2. **Сброс контекста в бэкфилле: был на каждый блок → стал один раз за прогон.** Это объясняет провал #3193: сброс выбрасывает пропуск → следующий фетч блокируется гарантированно → снова сброс. Одна осечка превращалась в необратимый каскад, что и дало приёмке «1 успех из 10». Одна попытка начать с чистого листа за прогон остаётся — на случай действительно протухшей сессии (TTL пропуска ~2.5 ч). 3. **Снята неверная формулировка «отказ, а не челлендж»** из #3204/#3205. Челлендж есть; 26 624 байта — это **результат проваленного** PoW, а не статика вместо него. Ошибка вышла из метода: HTML читали на 4.5-й секунде, когда заглушка уже заменена, и ни разу не смотрели в сетевой лог. ## Тесты `159 passed` (сайдкар), `4972 passed / 37 skipped` (backend). Два теста кодировали снятый `domclick=1`. Не удалены, а переписаны через подставной `_RECYCLE_PAGES_DEFAULT_BY_PROVIDER`, чтобы уровень приоритета «код-дефолт поставщика» продолжал проверяться, а не исчез вместе с записью. Добавлен `test_domclick_is_not_restarted_per_page` — прямой сторож против возврата порога 1. Тест сброса контекста требует ровно одну попытку за прогон. ## Не в этом PR Пункт 3 из #3212 остаётся открытым: `_CHALLENGE_MARKERS` в сайдкаре ищет `startpow`, а заглушка QRATOR несёт `__qrator`, и при `BROWSER_WAIT_MS=4500` HTML читается раньше, чем PoW решён. На поведение после этого PR не влияет (челлендж решается на прогреве origin один раз за прогон), но распознавание всё равно неверное.
lekss361 added 1 commit 2026-08-29 11:09:58 +00:00
fix(tradein/domclick): перезапуск браузера на карточку уничтожал пропуск QRATOR (#3212)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 10s
CI / changes (pull_request) Successful in 19s
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 1m10s
CI Trade-In / backend-tests (pull_request) Successful in 5m23s
09bdd7888b
ДомКлик закрыт QRATOR с proof-of-work: первый запрос отдаёт 401 и заглушку с
задачей, браузер её решает, дёргает /__qrator/validate и получает пропуск в куках
(qrator_jsid2 + qrator_jsr). Пропуск живёт в cookie jar, то есть в browser
context'е — а прод брал каждую карточку в новом контексте, выбрасывая его.
Повторная валидация с того же IP получала 403 и страницу bot-mitigation.

Замер (прод, прод-прокси, по 6 карточек):
  общий контекст, одна вкладка       6/6, validate не вызывался ни разу
  общий контекст, вкладка на карточку 6/6, validate не вызывался ни разу
  новый контекст на карточку (= прод) 1/6, validate = [304, 403] на каждой
  боевой путь /fetch с reuse_context  6/6 при 0 перезапусков и 1 контексте

Что правится:
  * снят код-дефолт domclick=1 из #3205: перезапуск процесса гарантированно
    уничтожает контекст, то есть лечил симптом, который сам же и создавал.
    Ручка per-provider и domclick как отдельный провайдер остаются;
  * сброс контекста в бэкфилле был на КАЖДЫЙ блок — стал один раз за прогон.
    Это и объясняет провал #3193: сброс выбрасывал пропуск, следующий фетч
    блокировался гарантированно, что снова вызывало сброс. Приёмка тогда дала
    ровно 1 успех из 10;
  * снята неверная формулировка «отказ, а не челлендж» из #3204/#3205 —
    26 624 байта это РЕЗУЛЬТАТ проваленного PoW, а не статика вместо него.
    Ошибка вышла из метода: HTML читали на 4.5-й секунде и не смотрели в сеть.

Замер 6/6, которым обосновывали #3205, был испорчен: в логах сайдкара после
каждой страницы стоит «recycle threshold (1) достигнут, перезапуск браузера».

Тесты: два кодировали domclick=1 — переписаны через подставной словарь, чтобы
уровень «код-дефолт поставщика» продолжал проверяться, а не исчез вместе с
записью. Тест сброса требует ровно одну попытку за прогон.
159 passed (сайдкар), 4972 passed / 37 skipped (backend).
lekss361 merged commit fbc8e89b6f into main 2026-08-29 11:16:40 +00:00
lekss361 deleted branch fix/3212-domclick-keep-context 2026-08-29 11:16:40 +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#3217
No description provided.