feat(tradein/scheduler): cooperative drain coverage for sweeps/full-loads (phase 3a) #2074
No reviewers
Labels
No labels
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
Fable 5 ревью
feedback/max
generative
GG-форсайт
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
вторичка
ИРД
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#2074
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/tradein-sweep-drain-coverage"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Зачем
Фаза 3a развязки scraper-деплоя (после #2065 ф.0+1, #2070 ф.2). Фаза 2 завела кооперативный SIGTERM-drain в
avito_detail_backfill+ rosreestr, но sweep'ы вscrape_pipeline.pyего не honor'или (толькоis_cancelled) → на SIGTERM упирались в 80с-таймаут_drain_inflight→ hard-cancel на середине anchor'а. Этот PR заводит drain во все long-sweep чек-пойнты → они дренятся чисто (коммит текущего anchor'а,mark_donepartial), а не убиваются.Изменения (
scrape_pipeline.py)13 сайтов: к каждому существующему
is_cancelled-чек-пойнту добавлен siblingelif shutdown_requested():→update_heartbeat+mark_done(partial) + чистый стоп (без дальнейших anchor'ов / без IMV/detail-фазы). Покрыты:run_avito/cian/yandex_city_sweep,run_avito/cian/yandex_full_load(через существующий raise-sentinelRuntimeError("shutdown")из_on_bucket),run_avito_newbuilding_sweep,run_domclick_city_sweep.mark_done(partial), НЕmark_cancelled(user-cancel семантика byte-for-byte не тронута).shutdown_requested()==False) — поведение идентично текущему.done(reap_zombies не пометит зомби). Нет double-mark (проверено по каждому пути).Review verdict
✅ APPROVE (code-reviewer).
drain≠cancelсверен сscrape_runs.py(is_cancelled==status уже 'cancelled' → mark_done no-op там; на SIGTERM status='running' → mark_done срабатывает). 3 judgment-call'а признаны корректными (domclick honest-status bypass byte-equivalent на pre-SERP; IMV-skip single-mark; sentinel"shutdown"≠"cancelled", реальный RuntimeError не глотается). Инфо: domclick — единый citywide-вызов, mid-fetch drain'а нет → fallback на Phase-2 safety-net (структурно).Тесты
tests/test_sweep_drain.py(new): return-style (avito/cian city_sweep) + sentinel-style (avito full_load) — shutdown после 1-й единицы → стоп на чек-пойнте,mark_done(partial),mark_cancelledНЕ вызван, дальнейшие anchor'ы/bucket'ы не обработаны. Локально: ruff-100 clean, 3 +-k "sweep or pipeline or cancel"166 passed + регрессия 73.Не входит:
resume_cursor/paused(фаза 3b, отложено). Refs #1182.Extend the cooperative shutdown-drain (Phase 2) to the long sweep and full-load loops in scrape_pipeline.py so they stop CLEANLY on SIGTERM instead of being hard-cancelled at the 80s _drain_inflight timeout. At every between-unit checkpoint that already polls scrape_runs.is_cancelled (user-cancel) we add an ALONGSIDE shutdown_requested() branch: - anchor-loop sweeps (avito/yandex/cian city) + avito newbuilding + domclick pre-SERP: update_heartbeat + mark_done(partial) + return; - full-load on_bucket callbacks (cian/yandex/avito): raise a distinct RuntimeError("shutdown") sentinel, handled next to the existing "cancelled" sentinel -> mark_done(partial), skipping the detail phase; - cian full-load detail loop: break -> existing post-loop mark_done. Drain finalizes as mark_done(partial), NOT mark_cancelled (that stays user-cancel only). is_cancelled -> user-cancel semantics are unchanged, and behaviour is identical when shutdown_requested() is False. No resume_cursor or paused status yet (Phase 3b, deferred): this is drain-coverage only. Tests: tests/test_sweep_drain.py covers both structural variants - run_avito_city_sweep / run_cian_city_sweep (anchor-loop) and run_avito_full_load (on_bucket sentinel): shutdown flips True after the first unit, asserting the sweep stops at the checkpoint, calls mark_done with partial counters, never calls mark_cancelled, and does not process later anchors/buckets/phases.