fix(tradein/domclick): свип ходил на QRATOR без кук и вис на PoW каждым запросом (#3264) #3265

Merged
lekss361 merged 1 commit from fix/3264-domclick-sweep-cookies into main 2026-08-30 07:02:01 +00:00
Owner

Закрывает #3264.

Что было

serp.py не передавал куки сессии вообще — слова cookie в файле не было. Свип приходил к QRATOR с чистым браузером и был обязан решать proof-of-work с нуля на каждый запрос.

Прод, прогон 5330 (30.08 03:49–03:55), status=failed, error='fetch errors — 0 listings':

9 × челлендж висит Nмс — перезагружаю страницу (1/2)
9 × челлендж висит Nмс — перезагружаю страницу (2/2)
9 × fetch error  url='https://bff-search-web.domclick.ru/api/offers/count/v1?...'

Прокси при этом честно ротировался (lease id=9 провалил 3 /fetch подряд, узел 9 → 10) — не помогло, узел тут ни при чём. Добор с тем же сайдкаром и тем же пулом в ту же ночь взял 37 карточек из 37 без единого блока. Разница ровно в куках.

Почему это стало возможно только сейчас

Свип ходит не на ekaterinburg.domclick.ru, а на отдельный API-хост bff-search-web.domclick.ru. До правки _cookie_domain (PR #3262) сайдкар положил бы куки на .bff-search-web.domclick.ru, и с сессией площадки они бы не совпали. Теперь оба хоста схлопываются в общий .domclick.ru — тот же снимок, что чинит добор, впервые применим и к свипу.

Как прокинуто

Снимок приходит параметром снаружи, а не читается внутри kit: kit не импортирует app.* (strangler-инвариант #2133).

  1. backend/app/services/product_handlers.py_job_domclick_city_sweep грузит domclick_session.load_session(db) и зовёт свип; зарегистрирован под ключом domclick_city_sweep, переопределяя kit-native. build_registry это прямо допускает («последнее слово за продуктом», registry.update(product_handlers)).
  2. orchestration/pipeline.pyrun_domclick_city_sweep(..., cookies=...) → в конструктор скрапера.
  3. providers/domclick/serp.pyDomClickScraper(cookies=...) → оба fetcher.fetch() (count-проба и пагинация).

Отсутствие сессии не авария: load_session вернул None → свип идёт как раньше, без инъекции, факт логируется один раз INFO.

Проверено, что override не разъезжается по охвату: wildcard-варианта domclick_city_sweep_* в kit нет (в отличие от avito/cian/yandex), в проде одно расписание с этим source — переопределение покрывает его целиком.

Цена решения и чем она закрыта

Override повторяет вызов kit-джобы целиком, а не оборачивает её, — иначе чтение БД пришлось бы тащить внутрь kit. Значит параметр, добавленный в kit-native джобу, в override молча не появится, и свип по расписанию поедет со старым набором.

Добавлен тест, который зовёт оба джоба с одинаковыми db/run_id/params/ctx и сравнивает наборы kwargs, допуская расхождение ровно в cookies. Проверен мутацией: с искусственно добавленным в kit-версию region_code=66 тест краснеет, после отката — зелёный. (Первая редакция теста мутацию не ловила — патчила sweep только в пространстве имён pipeline, тогда как kit-джоба связывает имя на импорте модуля; исправлено.)

Тесты

245 passed, 1 skipped (-k "domclick or parity"), включая все существующие domclick- и parity-тесты. ruff check чист на всех четырёх файлах.

Что НЕ проверено

Реальное поведение QRATOR на свипе — правка ждёт первого прогона по расписанию (04:14 UTC) или ручного запуска после деплоя.

Побочно

Формулировку #2854 надо обновить: свип больше не «кладётся на первой корзине» — по логу 5330 он идёт по корзинам 245+ последовательно, просто каждая падает целиком. Отдельной правки в этом PR нет.

Закрывает #3264. ## Что было `serp.py` не передавал куки сессии вообще — слова `cookie` в файле не было. Свип приходил к QRATOR с чистым браузером и был обязан решать proof-of-work с нуля на каждый запрос. Прод, прогон 5330 (30.08 03:49–03:55), `status=failed`, `error='fetch errors — 0 listings'`: ``` 9 × челлендж висит Nмс — перезагружаю страницу (1/2) 9 × челлендж висит Nмс — перезагружаю страницу (2/2) 9 × fetch error url='https://bff-search-web.domclick.ru/api/offers/count/v1?...' ``` Прокси при этом честно ротировался (`lease id=9 провалил 3 /fetch подряд`, узел 9 → 10) — не помогло, узел тут ни при чём. Добор с тем же сайдкаром и тем же пулом в ту же ночь взял **37 карточек из 37 без единого блока**. Разница ровно в куках. ## Почему это стало возможно только сейчас Свип ходит не на `ekaterinburg.domclick.ru`, а на отдельный API-хост **`bff-search-web.domclick.ru`**. До правки `_cookie_domain` (PR #3262) сайдкар положил бы куки на `.bff-search-web.domclick.ru`, и с сессией площадки они бы не совпали. Теперь оба хоста схлопываются в общий `.domclick.ru` — тот же снимок, что чинит добор, впервые применим и к свипу. ## Как прокинуто Снимок приходит **параметром снаружи**, а не читается внутри kit: kit не импортирует `app.*` (strangler-инвариант #2133). 1. `backend/app/services/product_handlers.py` — `_job_domclick_city_sweep` грузит `domclick_session.load_session(db)` и зовёт свип; зарегистрирован под ключом `domclick_city_sweep`, переопределяя kit-native. `build_registry` это прямо допускает («последнее слово за продуктом», `registry.update(product_handlers)`). 2. `orchestration/pipeline.py` — `run_domclick_city_sweep(..., cookies=...)` → в конструктор скрапера. 3. `providers/domclick/serp.py` — `DomClickScraper(cookies=...)` → оба `fetcher.fetch()` (count-проба и пагинация). Отсутствие сессии не авария: `load_session` вернул `None` → свип идёт как раньше, без инъекции, факт логируется один раз INFO. Проверено, что override не разъезжается по охвату: wildcard-варианта `domclick_city_sweep_*` в kit нет (в отличие от avito/cian/yandex), в проде одно расписание с этим source — переопределение покрывает его целиком. ## Цена решения и чем она закрыта Override повторяет вызов kit-джобы целиком, а не оборачивает её, — иначе чтение БД пришлось бы тащить внутрь kit. Значит параметр, добавленный в kit-native джобу, в override молча не появится, и свип по расписанию поедет со старым набором. Добавлен тест, который зовёт оба джоба с одинаковыми `db`/`run_id`/`params`/`ctx` и сравнивает наборы kwargs, допуская расхождение ровно в `cookies`. **Проверен мутацией:** с искусственно добавленным в kit-версию `region_code=66` тест краснеет, после отката — зелёный. (Первая редакция теста мутацию не ловила — патчила sweep только в пространстве имён `pipeline`, тогда как kit-джоба связывает имя на импорте модуля; исправлено.) ## Тесты `245 passed, 1 skipped` (`-k "domclick or parity"`), включая все существующие domclick- и parity-тесты. `ruff check` чист на всех четырёх файлах. ## Что НЕ проверено Реальное поведение QRATOR на свипе — правка ждёт первого прогона по расписанию (04:14 UTC) или ручного запуска после деплоя. ## Побочно Формулировку #2854 надо обновить: свип больше не «кладётся на первой корзине» — по логу 5330 он идёт по корзинам `2` → `4` → `5+` последовательно, просто каждая падает целиком. Отдельной правки в этом PR нет.
lekss361 added 1 commit 2026-08-30 06:41:04 +00:00
fix(tradein/domclick): свип ходил на QRATOR без кук и вис на PoW каждым запросом (#3264)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI / changes (pull_request) Successful in 10s
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
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 4m53s
44633b0df4
serp.py не передавал куки сессии вообще — слова cookie в файле не было.
Свип приходил к QRATOR с чистым браузером и был обязан решать
proof-of-work с нуля на каждый запрос. Прод, прогон 5330 (30.08
03:49-03:55): 9 запросов к bff-search-web.domclick.ru, все 9 зависли на
челлендже (перезагрузка 1/2, 2/2, отказ), status=failed, 0 лотов. Прокси
при этом ротировался (узел 9 → 10) — узел тут ни при чём.

Добор с тем же сайдкаром и тем же пулом в ту же ночь взял 37 карточек из
37 без единого блока. Разница ровно в куках.

Чинить это стало возможно только сейчас: свип ходит не на
ekaterinburg.domclick.ru, а на отдельный хост bff-search-web.domclick.ru,
и до правки _cookie_domain (PR #3262) куки легли бы на
.bff-search-web.domclick.ru, не совпав с сессией площадки. Теперь оба
хоста схлопываются в общий .domclick.ru.

Снимок приходит параметром снаружи, а не читается внутри kit: kit не
импортирует app.* (strangler-инвариант #2133). Поэтому джоба
domclick_city_sweep переопределена продуктовым Handler'ом — build_registry
это прямо допускает («последнее слово за продуктом»), а БД читает только
app-сторона.

Отсутствие сессии не авария: load_session вернул None → свип идёт как
раньше, без инъекции, факт логируется один раз.

Цена решения — override повторяет вызов kit-джобы целиком и может тихо с
ней разойтись. Добавлен тест, который зовёт оба джоба одинаково и
сравнивает наборы kwargs, допуская расхождение ровно в cookies. Проверен
мутацией: с искусственно добавленным в kit-версию аргументом краснеет,
без него зелёный.

Тесты: 245 passed, 1 skipped (domclick + parity).
lekss361 closed this pull request 2026-08-30 06:51:58 +00:00
lekss361 reopened this pull request 2026-08-30 06:52:16 +00:00
lekss361 merged commit 8169d6f1ec into main 2026-08-30 07:02:01 +00:00
lekss361 deleted branch fix/3264-domclick-sweep-cookies 2026-08-30 07:02:01 +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#3265
No description provided.