fix(scraper-kit): domclick city sweep — done_buckets во всех семи выходах, а не только в дрейне и одном бане #3372

Merged
bot-backend merged 2 commits from fix/3369-domclick-cancel-checkpoint into main 2026-09-05 20:19:45 +00:00
Collaborator

Closes #3369 (находка доводки #3363). Писатель counters у domclick — app-level с полной перезаписью, поэтому каждая запись без done_buckets = потерянный чекпоинт.

Что нашлось

Записи БЕЗ done_buckets до правки (статусы cancelled/banned/failed ∈ _RESUME_STATUSES): cancel-ветка update_heartbeat; финальный update_heartbeat после pages_fetched — затирал чекпоинт, записанный строкой выше; mark_banned QRATOR; mark_failed «оборван #2670»; mark_failed «0 listings»; mark_done; фатальный mark_failed в except. Чистыми были только дрейн (#3363) и mark_banned при NoProxyAvailable.

Фикс

Один _payload() + _checkpoint на функцию — все девять записей несут done_buckets = sorted(skip_buckets); правка в общей точке, не по веткам.

Тесты

test_3369_domclick_cancel_checkpoint.py; полный suite 5464 passed, 35 skipped (rc отдельно). Фальсификация (откат cancel-хунка): cancel: чекпоинт потерян (None вместо ['1:0:5000000', '2:0:5000000']), второй кейс None вместо [] — по значению.

Прод-приёмка

Первый cancelled/failed domclick-свип с унаследованным чекпоинтом → counters.done_buckets непуст; следующий claim → resume_reason='ok' (тот же SQL, что в #3355).

Closes #3369 (находка доводки #3363). Писатель counters у domclick — app-level с полной перезаписью, поэтому каждая запись без `done_buckets` = потерянный чекпоинт. ## Что нашлось Записи БЕЗ `done_buckets` до правки (статусы cancelled/banned/failed ∈ `_RESUME_STATUSES`): cancel-ветка `update_heartbeat`; **финальный `update_heartbeat` после `pages_fetched` — затирал чекпоинт, записанный строкой выше**; `mark_banned` QRATOR; `mark_failed` «оборван #2670»; `mark_failed` «0 listings»; `mark_done`; фатальный `mark_failed` в `except`. Чистыми были только дрейн (#3363) и `mark_banned` при `NoProxyAvailable`. ## Фикс Один `_payload()` + `_checkpoint` на функцию — все девять записей несут `done_buckets = sorted(skip_buckets)`; правка в общей точке, не по веткам. ## Тесты `test_3369_domclick_cancel_checkpoint.py`; **полный suite `5464 passed, 35 skipped`** (rc отдельно). Фальсификация (откат cancel-хунка): `cancel: чекпоинт потерян (None вместо ['1:0:5000000', '2:0:5000000'])`, второй кейс `None` вместо `[]` — по значению. ## Прод-приёмка Первый cancelled/failed domclick-свип с унаследованным чекпоинтом → `counters.done_buckets` непуст; следующий claim → `resume_reason='ok'` (тот же SQL, что в #3355).
bot-backend added 1 commit 2026-09-05 19:52:43 +00:00
fix(domclick): чекпоинт done_buckets во всех payload'ах свипа
All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 11s
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 5m5s
b796702d9a
cancel-ветка run_domclick_city_sweep писала голый counters.to_dict(); писатель —
app-level scrape_runs с полной перезаписью (CAST(:counters AS jsonb)), а
'cancelled' входит в _RESUME_STATUSES → отменённый прогон закрывался с пустым
чекпоинтом и резюм пересобирал все корзины. Те же потери были у финального
heartbeat и у mark_banned/mark_failed/mark_done (banned/failed тоже
резюмируемы): они затирали чекпоинт, записанный после SERP-фазы.

Один _payload() на функцию — done_buckets едет в каждой записи counters.

Refs #3355, PR #3363. Closes #3369
Light1YT added 1 commit 2026-09-05 20:13:24 +00:00
fix(domclick): честная мотивировка чекпоинта + один _payload() на все ветки
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 11s
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 5m3s
140caa4ddf
Правка ревью к PR #3372: комментарии и текст коммита обещали восстановление
потери, которой нет. Факт: pipeline.py импортирует scraper_kit.orchestration.runs,
и все четыре его писателя МЕРЖАТ jsonb (`counters = COALESCE(counters,'{}') ||
CAST(:counters AS jsonb)`, runs.py:708/776/817/880), а _pick_resume наследует
done_buckets при claim (scheduler.py:741-748, #3074) — чекпоинт domclick в БД не
терялся. Перезаписывающий двойник app/services/scrape_runs.py этой функцией не
вызывается.

Поэтому done_buckets в каждом payload — единообразие и защита от смены писателя
(если запись пойдёт через app-копию или kit-писатель станет перезаписывающим), а
не спасение данных. Комментарии переписаны под этот факт.

Дрейн-ветка и NoProxyAvailableError строили dict вручную — переведены на
{**_payload(), "interrupted": 1} и _payload(), чтобы «один _payload() на функцию»
было правдой.

Тест: к cancel добавлены ассерты на финальный heartbeat и mark_done — оба
payload'а несут унаследованное ∪ пройденное этим прогоном.

Refs #3355, PR #3363. Closes #3369
bot-backend merged commit 1c8035934d into main 2026-09-05 20:19:45 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
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#3372
No description provided.