feat(tradein): schedule cian_full_load (exhaustive secondary) + anchor sweep NB-only #1752

Merged
lekss361 merged 1 commit from feat/cian-schedule-fullload-nb-only into main 2026-06-18 10:38:32 +00:00
Owner

Проблема

run_cian_full_load (exhaustive room×price-бисекция вторички, secondary-only, incremental save, checkpoint/resume) построен, протестирован и прод-проверен (#926/#929/#930/#938) — run #46 от 2026-05-31 собрал 29511 уникальных вторичных листингов за 25 мин. Но запускается ТОЛЬКО вручную через admin API, в scheduler НЕ зарегистрирован → 18 дней не запускался → набор протух, deactivate_stale_cian выкосил неподтверждённые. Recurring cian_city_sweep гоняет anchor-овскую стратегию (5 гео-точек × pagination-cap), которая теряет хвост: cian vtorichka просел до 5520/7748 active (71%) против эталона yandex (бисекция) 4442/4598 (97%).

Решение

  1. Подключить готовый run_cian_full_load в in-app scheduler как recurring-источник cian_full_load (окно 20-22 UTC — не конфликтует на shared kf-прокси с cian_city_sweep/cian_history_backfill в 2-5). Логику загрузки НЕ трогал.
  2. run_cian_city_sweep → newbuilding-only (newbuilding_only: bool = True): SERP-лоты фильтруются до listing_segment == "novostroyki" перед save_listings, т.к. full_load теперь авторитетно владеет вторичкой. DETAIL/HOUSES-фазы не изменены. Убирает дубль secondary SERP-сейва и двойной расход прокси.

Изменения

  • scheduler.py — import run_cian_full_load; trigger_cian_full_load_run (по образцу trigger_cian_city_sweep_run); dispatch elif source == "cian_full_load"; trigger_cian_city_sweep_run прокидывает newbuilding_only; обновлён docstring-registry.
  • scrape_pipeline.pyrun_cian_city_sweep(newbuilding_only=True) + counter lots_dropped_secondary.
  • data/sql/126_scrape_schedules_seed_cian_full_load.sql — idempotent seed (enabled=true, 20-22 UTC, ON CONFLICT DO UPDATE без затирания enabled).
  • tests/test_scheduler.py (+3), tests/test_cian_city_sweep.py (+2).

Тесты

Full suite: 1844 passed, 2 deselected (per test-gate). 2 yandex test_scraper_proxy падения — pre-existing, от незакоммиченного WIP другого окна в shared worktree; в diff этого PR yandex-файлов НЕТ (5 файлов, подтверждено git diff main...HEAD --stat); на чистом дереве зелёные. Targeted: test_scheduler.py test_cian_city_sweep.py test_scheduler_main.py → 36 passed. Ruff clean.

Прод-смоук после merge

Сравнить cian vtorichka active ДО/ПОСЛЕ первого cian_full_load (ручной trigger или дождаться окна 20-22 UTC): ожидается рост 5520 → ~25-29k. Подтвердить что run_cian_city_sweep больше не сейвит вторичку (lots_dropped_secondary > 0 в counters).

## Проблема `run_cian_full_load` (exhaustive room×price-бисекция вторички, secondary-only, incremental save, checkpoint/resume) **построен, протестирован и прод-проверен** (#926/#929/#930/#938) — run #46 от 2026-05-31 собрал **29511 уникальных** вторичных листингов за 25 мин. Но запускается ТОЛЬКО вручную через admin API, в scheduler НЕ зарегистрирован → 18 дней не запускался → набор протух, `deactivate_stale_cian` выкосил неподтверждённые. Recurring `cian_city_sweep` гоняет anchor-овскую стратегию (5 гео-точек × pagination-cap), которая теряет хвост: cian vtorichka просел до **5520/7748 active (71%)** против эталона yandex (бисекция) **4442/4598 (97%)**. ## Решение 1. **Подключить готовый `run_cian_full_load` в in-app scheduler** как recurring-источник `cian_full_load` (окно 20-22 UTC — не конфликтует на shared kf-прокси с `cian_city_sweep`/`cian_history_backfill` в 2-5). Логику загрузки НЕ трогал. 2. **`run_cian_city_sweep` → newbuilding-only** (`newbuilding_only: bool = True`): SERP-лоты фильтруются до `listing_segment == "novostroyki"` перед `save_listings`, т.к. full_load теперь авторитетно владеет вторичкой. DETAIL/HOUSES-фазы не изменены. Убирает дубль secondary SERP-сейва и двойной расход прокси. ## Изменения - `scheduler.py` — import `run_cian_full_load`; `trigger_cian_full_load_run` (по образцу `trigger_cian_city_sweep_run`); dispatch `elif source == "cian_full_load"`; `trigger_cian_city_sweep_run` прокидывает `newbuilding_only`; обновлён docstring-registry. - `scrape_pipeline.py` — `run_cian_city_sweep(newbuilding_only=True)` + counter `lots_dropped_secondary`. - `data/sql/126_scrape_schedules_seed_cian_full_load.sql` — idempotent seed (enabled=true, 20-22 UTC, `ON CONFLICT DO UPDATE` без затирания enabled). - `tests/test_scheduler.py` (+3), `tests/test_cian_city_sweep.py` (+2). ## Тесты Full suite: **1844 passed**, 2 deselected (per test-gate). 2 yandex `test_scraper_proxy` падения — pre-existing, от незакоммиченного WIP другого окна в shared worktree; в diff этого PR yandex-файлов НЕТ (5 файлов, подтверждено `git diff main...HEAD --stat`); на чистом дереве зелёные. Targeted: `test_scheduler.py test_cian_city_sweep.py test_scheduler_main.py` → 36 passed. Ruff clean. ## Прод-смоук после merge Сравнить cian vtorichka active ДО/ПОСЛЕ первого `cian_full_load` (ручной trigger или дождаться окна 20-22 UTC): ожидается рост 5520 → ~25-29k. Подтвердить что `run_cian_city_sweep` больше не сейвит вторичку (`lots_dropped_secondary` > 0 в counters).
lekss361 added 1 commit 2026-06-18 10:26:52 +00:00
feat(tradein): schedule cian_full_load (exhaustive secondary) + anchor sweep NB-only
All checks were successful
CI / changes (pull_request) Successful in 6s
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
158a24c25b
Подключает prod-проверенный run_cian_full_load (exhaustive региональный сбор
Cian ЕКБ вторички, room×price партиционирование, incremental on_bucket save) в
in-app scheduler как recurring-источник cian_full_load (окно 20-22 UTC — отделено
от cian_city_sweep/history_backfill на 2-5 чтобы не конкурировать на shared
kf-прокси).

run_cian_city_sweep теперь NB-only (newbuilding_only=True default): SERP-фаза
сохраняет только novostroyki-лоты, вторичку отбрасывает — ею авторитетно владеет
full_load. Убирает дубль secondary SERP-сейва. DETAIL/HOUSES-фазы не затронуты.
lekss361 added the
enhancement
priority/p1
scope/backend
scope/db
scrapers
status/review
labels 2026-06-18 10:27:00 +00:00
bot-reviewer approved these changes 2026-06-18 10:38:26 +00:00
bot-reviewer left a comment
Collaborator

APPROVE — reviewed on clean worktree at head 158a24c2.

Проверено (4 концерна):

  1. newbuilding_only-фильтр — отсекает ТОЛЬКО вторичку (listing_segment != "novostroyki") в SERP-фазе перед save_listings. DETAIL-фаза не тронута: query WHERE source='cian' AND detail_enriched_at IS NULL AND scraped_at > NOW()-2h сегмент-агностична → обогащает любой cian-листинг, регресса нет. HOUSES-фаза ключуется на house_source=="cian_newbuilding" лотах, переживающих фильтр.
  2. scheduler dispatch — elif source == "cian_full_load" корректен; trigger_cian_full_load_run прокидывает все 5 параметров + resume_run_id=None. _claim_run использует pg_try_advisory_xact_lock с double-check (#750) → дубль-ран исключён.
  3. SQL 126 — номер свободен (на main максимум 125); idempotent ON CONFLICT DO UPDATE НЕ затирает enabled. Окно 20-22 UTC отделено от city_sweep/history_backfill (2-5). deactivate_stale cian = vtorichka TTL=30d против daily-каденса → преждевременной деактивации нет.
  4. Сигнатура run_cian_city_sweep — newbuilding_only default True; все вызовы (scheduler прокидывает, admin/tests на дефолте) проходят.

Тесты на чистом дереве: 1945 passed, 1 skipped, 0 failed (2 cache-теста deselected per gate). test_scraper_proxy зелёный — подтверждает что 2 падения в shared worktree = несвязанный yandex WIP. Ruff clean.

Информационно (не блокер): ручной admin-эндпоинт /scrape/cian-city-sweep не прокидывает newbuilding_only → теперь по дефолту тоже NB-only. Согласуется с архитектурой «full_load владеет вторичкой».

Merge (merge style).

✅ APPROVE — reviewed on clean worktree at head 158a24c2. Проверено (4 концерна): 1. newbuilding_only-фильтр — отсекает ТОЛЬКО вторичку (listing_segment != "novostroyki") в SERP-фазе перед save_listings. DETAIL-фаза не тронута: query WHERE source='cian' AND detail_enriched_at IS NULL AND scraped_at > NOW()-2h сегмент-агностична → обогащает любой cian-листинг, регресса нет. HOUSES-фаза ключуется на house_source=="cian_newbuilding" лотах, переживающих фильтр. 2. scheduler dispatch — elif source == "cian_full_load" корректен; trigger_cian_full_load_run прокидывает все 5 параметров + resume_run_id=None. _claim_run использует pg_try_advisory_xact_lock с double-check (#750) → дубль-ран исключён. 3. SQL 126 — номер свободен (на main максимум 125); idempotent ON CONFLICT DO UPDATE НЕ затирает enabled. Окно 20-22 UTC отделено от city_sweep/history_backfill (2-5). deactivate_stale cian = vtorichka TTL=30d против daily-каденса → преждевременной деактивации нет. 4. Сигнатура run_cian_city_sweep — newbuilding_only default True; все вызовы (scheduler прокидывает, admin/tests на дефолте) проходят. Тесты на чистом дереве: 1945 passed, 1 skipped, 0 failed (2 cache-теста deselected per gate). test_scraper_proxy зелёный — подтверждает что 2 падения в shared worktree = несвязанный yandex WIP. Ruff clean. Информационно (не блокер): ручной admin-эндпоинт /scrape/cian-city-sweep не прокидывает newbuilding_only → теперь по дефолту тоже NB-only. Согласуется с архитектурой «full_load владеет вторичкой». Merge (merge style).
lekss361 merged commit 10b93011a3 into main 2026-06-18 10:38:32 +00:00
lekss361 deleted branch feat/cian-schedule-fullload-nb-only 2026-06-18 10:38:32 +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#1752
No description provided.