Выключить домклик-свипы 77/50: в текущем виде они по построению не могут ничего собрать #3567

Merged
lekss361 merged 1 commit from fix/domclick-msk-disable-until-incremental-save into main 2026-09-17 08:23:06 +00:00
Owner

Откатывает включение, которое я сделал миграцией 306 (#3545). Строки остаются заведёнными, но выключенными — код wildcard-хендлера и гео-профили верны и проверены на проде, не работает конвейер сбора.

Замер, который это показал

Одиночный прогон, без соседей по сайдкару и пулу — специально чтобы снять подозрение на одновременность, из-за которой был #3546.

run 7344, domclick_city_sweep_moskva, прокси id=13, старт 06:12:48. За два часа пройдено 2 бакета из 6: st — 34.2 мин, 1 — 86+ мин и не закончился. Watchdog прогона — 11100 с (3 ч 05 мин).

Прогон был единственным, узел не банился, QRATOR-блока в логе нет. Значит ни одновременность, ни блок площадки.

Причина структурная

ДомКлик ограничивает offset двумя тысячами, поэтому на больших выдачах скрейпер делит диапазон по цене бисекцией, и каждый лист пагинируется отдельно. У Москвы ≈23 690 лотов вторички против ≈6 300 у ЕКБ — листьев кратно больше.

Формула watchdog'а (run_domclick_city_sweep) считает число фетчей как _DOMCLICK_NUM_BUCKETS * pages = 6 * 100 и объём выдачи не учитывает вовсе:

11100 = 600 * (6 + 12) + 300

Она линейна по pages, поэтому уменьшение pages_per_anchor урезает и сам watchdog — лечения не даёт. Это была первая гипотеза, и она неверна.

Хуже, чем «не успевает»

_domclick_phase — «единственная citywide-фаза: fetch_city + save». Лоты копятся в памяти и сохраняются одним save_listings после всех шести бакетов. Снятие фазы по watchdog (asyncio.wait_forTimeoutError) теряет всё собранное.

А чекпоинт #3118 пишется после этого, из живой ссылки на скрейпер:

_checkpoint = sorted(skip_buckets | set(_s.completed_buckets))
runs.update_heartbeat(db, run_id, _payload())

То есть бакеты помечаются пройденными, хотя ни одна их строка не сохранена, и следующий прогон пропускает их через skip_buckets. Два-три таких прогона закрывают чекпоинт целиком — итоговый сбор по 77/50 равен нулю навсегда.

Почему не «пусть висит, вдруг соберёт»

Пока строки включены, вред не нулевой: каждые трое суток каждая забирает один из двух узлов с provider_affinity='any' (id 13 и 14) на три часа и не отдаёт ничего. 17.09 из-за этого ЕКБ-свип run 7339 отбился banned за 0 секунд, пока оба узла держали московские прогоны. Выключение восстанавливает статус-кво ЕКБ.

Что нужно для возврата

Это правки кода в scraper-kit, не миграция:

  1. Инкрементальное сохранение по бакетамsave_listings внутри цикла fetch_city через колбэк on_bucket, как у run_cian_full_load. Тогда снятие по watchdog сохраняет собранное, а чекпоинт перестаёт врать.
  2. Watchdog от объёма выдачи (snippetsCount), а не только от pages.
  3. Кооперативная отмена по бакетамruns.is_cancelled сейчас проверяется только перед SERP-фазой, поэтому повисший свип нельзя снять до watchdog'а (та же находка, что в #3546).
  4. Сброс унаследованного чекпоинта прогонов 7333/7344 при возврате, иначе resume пропустит бакеты st и 1, по которым ничего не сохранено.

ЕКБ-строка domclick_city_sweep не трогается: её выдача помещается в watchdog (run 7219 от 16.09 — 70 минут, 6372 seen / 237 new), дефект на ней не проявляется.

Состояние прода

Строки уже выключены вручную (UPDATE 2), чтобы прекратить расход узлов немедленно. Миграция делает это состояние воспроизводимым на чистой БД: 306 создаёт строки через ON CONFLICT DO NOTHING с enabled = true, и без 308 свежая база подняла бы их включёнными.

tests/test_migration_numbering.py → 1 passed, 2 skipped. Номер сверен с forgejo/main (последняя — 307).

🤖 Generated with Claude Code

https://claude.ai/code/session_01NQb6WeJtagZwZnUsSjDizs

Откатывает включение, которое я сделал миграцией 306 (#3545). Строки остаются заведёнными, но выключенными — код wildcard-хендлера и гео-профили верны и проверены на проде, не работает конвейер сбора. ## Замер, который это показал Одиночный прогон, без соседей по сайдкару и пулу — специально чтобы снять подозрение на одновременность, из-за которой был #3546. **run 7344**, `domclick_city_sweep_moskva`, прокси id=13, старт 06:12:48. За **два часа пройдено 2 бакета из 6**: `st` — 34.2 мин, `1` — 86+ мин и не закончился. Watchdog прогона — 11100 с (3 ч 05 мин). Прогон был единственным, узел не банился, QRATOR-блока в логе нет. Значит ни одновременность, ни блок площадки. ## Причина структурная ДомКлик ограничивает `offset` двумя тысячами, поэтому на больших выдачах скрейпер делит диапазон по цене бисекцией, и **каждый лист пагинируется отдельно**. У Москвы ≈23 690 лотов вторички против ≈6 300 у ЕКБ — листьев кратно больше. Формула watchdog'а (`run_domclick_city_sweep`) считает число фетчей как `_DOMCLICK_NUM_BUCKETS * pages` = `6 * 100` и объём выдачи не учитывает вовсе: ``` 11100 = 600 * (6 + 12) + 300 ``` Она **линейна по `pages`**, поэтому уменьшение `pages_per_anchor` урезает и сам watchdog — лечения не даёт. Это была первая гипотеза, и она неверна. ## Хуже, чем «не успевает» `_domclick_phase` — «единственная citywide-фаза: fetch_city + save». Лоты копятся в памяти и сохраняются **одним** `save_listings` после всех шести бакетов. Снятие фазы по watchdog (`asyncio.wait_for` → `TimeoutError`) теряет всё собранное. А чекпоинт #3118 пишется **после** этого, из живой ссылки на скрейпер: ```python _checkpoint = sorted(skip_buckets | set(_s.completed_buckets)) runs.update_heartbeat(db, run_id, _payload()) ``` То есть бакеты помечаются пройденными, хотя ни одна их строка не сохранена, и следующий прогон пропускает их через `skip_buckets`. Два-три таких прогона закрывают чекпоинт целиком — **итоговый сбор по 77/50 равен нулю навсегда**. ## Почему не «пусть висит, вдруг соберёт» Пока строки включены, вред не нулевой: каждые трое суток каждая забирает один из **двух** узлов с `provider_affinity='any'` (id 13 и 14) на три часа и не отдаёт ничего. 17.09 из-за этого ЕКБ-свип run 7339 отбился `banned` за 0 секунд, пока оба узла держали московские прогоны. Выключение восстанавливает статус-кво ЕКБ. ## Что нужно для возврата Это правки кода в scraper-kit, не миграция: 1. **Инкрементальное сохранение по бакетам** — `save_listings` внутри цикла `fetch_city` через колбэк `on_bucket`, как у `run_cian_full_load`. Тогда снятие по watchdog сохраняет собранное, а чекпоинт перестаёт врать. 2. **Watchdog от объёма выдачи** (`snippetsCount`), а не только от `pages`. 3. **Кооперативная отмена по бакетам** — `runs.is_cancelled` сейчас проверяется только *перед* SERP-фазой, поэтому повисший свип нельзя снять до watchdog'а (та же находка, что в #3546). 4. **Сброс унаследованного чекпоинта** прогонов 7333/7344 при возврате, иначе resume пропустит бакеты `st` и `1`, по которым ничего не сохранено. ЕКБ-строка `domclick_city_sweep` **не трогается**: её выдача помещается в watchdog (run 7219 от 16.09 — 70 минут, 6372 seen / 237 new), дефект на ней не проявляется. ## Состояние прода Строки уже выключены вручную (`UPDATE 2`), чтобы прекратить расход узлов немедленно. Миграция делает это состояние воспроизводимым на чистой БД: 306 создаёт строки через `ON CONFLICT DO NOTHING` с `enabled = true`, и без 308 свежая база подняла бы их включёнными. `tests/test_migration_numbering.py` → 1 passed, 2 skipped. Номер сверен с `forgejo/main` (последняя — 307). 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01NQb6WeJtagZwZnUsSjDizs
lekss361 added 1 commit 2026-09-17 08:16:51 +00:00
fix(trade-in): выключить домклик-свипы 77/50 — они по построению не могут ничего собрать
All checks were successful
CI Trade-In / changes (pull_request) Successful in 19s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 23s
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 5m23s
ad27ed3ab0
Замер 17.09 одиночным прогоном, без соседей по сайдкару и пулу. run 7344
(Москва, прокси 13, старт 06:12:48) за два часа прошёл 2 бакета из 6: 'st' —
34.2 мин, '1' — 86+ мин и не закончился. Watchdog прогона 11100 с.

Это не одновременность и не блок площадки: прогон был единственным, узел не
банился, QRATOR-блока в логе нет. Причина структурная. ДомКлик режет offset на
2000, поэтому на больших выдачах скрейпер делит диапазон по цене бисекцией, и
каждый лист пагинируется отдельно. У Москвы около 23 690 лотов вторички против
6 300 у ЕКБ — листьев кратно больше. Формула watchdog'а считает число фетчей как
6 * pages и объём выдачи не учитывает: 11100 = 600 * (6 + 12) + 300. Она линейна
по pages, так что уменьшение pages_per_anchor урезает и сам watchdog.

Хуже, чем «не успевает». _domclick_phase — единственная фаза fetch_city + save:
лоты копятся в памяти и сохраняются одним save_listings после всех шести
бакетов, снятие по watchdog теряет всё собранное. А чекпоинт #3118 пишется ПОСЛЕ
этого, из живой ссылки на скрейпер — бакеты помечаются пройденными, хотя ни одна
их строка не сохранена, и следующий прогон пропускает их через skip_buckets. Два-
три прогона закрывают чекпоинт целиком: итоговый сбор по 77/50 равен нулю
навсегда.

Пока строки включены, вред не нулевой: каждые трое суток каждая забирает один из
двух узлов affinity='any' на три часа впустую. 17.09 из-за этого ЕКБ-свип run
7339 отбился 'banned' за 0 секунд, пока оба узла держали московские прогоны.

Условия возврата перечислены в шапке миграции: инкрементальное сохранение по
бакетам, watchdog от объёма выдачи, кооперативная отмена по бакетам и сброс
унаследованного чекпоинта прогонов 7333/7344.

ЕКБ-строка не трогается — её выдача помещается в watchdog (run 7219: 70 минут,
6372 seen / 237 new).

Claude-Session: https://claude.ai/code/session_01NQb6WeJtagZwZnUsSjDizs
lekss361 merged commit 9cc23c6698 into main 2026-09-17 08:23:06 +00:00
lekss361 deleted branch fix/domclick-msk-disable-until-incremental-save 2026-09-17 08:23:07 +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#3567
No description provided.