[P0] deactivate_stale для domklik/n1 + честный трекинг freshness domklik #2204

Closed
opened 2026-07-02 19:17:32 +00:00 by lekss361 · 5 comments
Owner

Эпик: #2200

Находка (Data/Scrapers, verified high): нет deactivate_stale джобы для domklik/n1 (scheduler.py:41-47 — только avito/yandex/cian). n1 уже доказал режим: 381 строка is_active=true, last_seen 16.06, floor NULL на всех. domklik: 6296 строк is_active, scraped_at заморожен 27-28.06, все делят один last_seen_at, двигаемый нетрекаемыми bulk-touch (нет записи в scrape_runs, расписание disabled). Без делистинга оба гниют активными вечно и отравляют пул аналогов; domklik также выпадет из эстиматора ~12.07 (scraped_at + 14д фильтр).

Acceptance:

  • deactivate_stale_domklik + deactivate_stale_n1 (разумный TTL) в scheduler + расписание.
  • Либо честно деактивировать n1 как источник, либо восстановить скрейпер (сейчас кода нет).
  • domklik: трекать freshness через scrape_runs (bulk-touch должен писать run) ИЛИ переключить last_seen на настоящий прогон.
  • Проверка: после прогона нет is_active строк старше TTL по domklik/n1.

Scope: tradein-mvp/backend/app/services/scheduler.py, scrape_pipeline.py.

Эпик: #2200 **Находка (Data/Scrapers, verified high):** нет `deactivate_stale` джобы для domklik/n1 (`scheduler.py:41-47` — только avito/yandex/cian). n1 уже доказал режим: 381 строка `is_active=true`, last_seen 16.06, floor NULL на всех. domklik: 6296 строк `is_active`, scraped_at заморожен 27-28.06, все делят один last_seen_at, двигаемый нетрекаемыми bulk-touch (нет записи в scrape_runs, расписание disabled). Без делистинга оба гниют активными вечно и отравляют пул аналогов; domklik также выпадет из эстиматора ~12.07 (scraped_at + 14д фильтр). **Acceptance:** - [ ] `deactivate_stale_domklik` + `deactivate_stale_n1` (разумный TTL) в scheduler + расписание. - [ ] Либо честно деактивировать n1 как источник, либо восстановить скрейпер (сейчас кода нет). - [ ] domklik: трекать freshness через scrape_runs (bulk-touch должен писать run) ИЛИ переключить `last_seen` на настоящий прогон. - [ ] Проверка: после прогона нет `is_active` строк старше TTL по domklik/n1. Scope: `tradein-mvp/backend/app/services/scheduler.py`, `scrape_pipeline.py`.
lekss361 added the
data
priority/p0
scope/backend
scrapers
tradein
labels 2026-07-02 19:20:15 +00:00
Author
Owner

Working on this (night shift), ветка fix/tradein-deactivate-stale-domklik-n1.

Верификация на проде (2026-07-02 ~19:50 UTC):

  • n1: 381 is_active, max(last_seen_at)=16.06, max(scraped_at)=15.06, 0 fresh — источник мёртв, кода скрейпера нет.
  • domklik: 6296 is_active, max(scraped_at)=28.06 (часы распада ~12.07 подтверждены), НО все 6296 строк имеют идентичный last_seen_at=2026-07-02 19:41:00.179444 — один нетрекаемый bulk UPDATE (ни одной строки в scrape_runs за 30ч по domclick; триггеров на listings, двигающих last_seen, нет; в коде main bulk-touch не найден — возможно ручной/из другого окна). Вывод аудита подтверждён: TTL по last_seen_at для domklik бесполезен, пока существует нетрекаемый тачер.

План (честная freshness без зависимости от last_seen):

  1. deactivate_stale_listings получает параметр staleness_column (whitelist: last_seen_at | scraped_at).
  2. Seed-миграция: deactivate_stale_domklik (TTL=14, staleness_column=scraped_at — двигается только реальным скрейпом) + deactivate_stale_n1 (TTL=14, last_seen_at). Wildcard-handler deactivate_stale_* уже диспатчит оба (kit + legacy).
  3. Regression-тесты на новый параметр.

Примечание: с scraped_at-TTL при выключенном domclick-расписании (enabled=f сейчас) все 6296 строк честно деактивируются ~12.07 — для эстиматора они и так невидимы (фильтр 14д), а UI/подсчёты источников перестанут врать. Если #2206 (scraped_at bump в upsert) смержится и расписание включат — живые строки останутся активными. Re-enable расписания domclick — отдельное решение (не в этом PR).

Working on this (night shift), ветка `fix/tradein-deactivate-stale-domklik-n1`. Верификация на проде (2026-07-02 ~19:50 UTC): - n1: 381 is_active, max(last_seen_at)=16.06, max(scraped_at)=15.06, 0 fresh — источник мёртв, кода скрейпера нет. - domklik: 6296 is_active, max(scraped_at)=28.06 (часы распада ~12.07 подтверждены), НО **все 6296 строк имеют идентичный last_seen_at=2026-07-02 19:41:00.179444** — один нетрекаемый bulk UPDATE (ни одной строки в scrape_runs за 30ч по domclick; триггеров на listings, двигающих last_seen, нет; в коде main bulk-touch не найден — возможно ручной/из другого окна). Вывод аудита подтверждён: TTL по last_seen_at для domklik бесполезен, пока существует нетрекаемый тачер. План (честная freshness без зависимости от last_seen): 1. `deactivate_stale_listings` получает параметр `staleness_column` (whitelist: last_seen_at | scraped_at). 2. Seed-миграция: `deactivate_stale_domklik` (TTL=14, staleness_column=scraped_at — двигается только реальным скрейпом) + `deactivate_stale_n1` (TTL=14, last_seen_at). Wildcard-handler `deactivate_stale_*` уже диспатчит оба (kit + legacy). 3. Regression-тесты на новый параметр. Примечание: с scraped_at-TTL при выключенном domclick-расписании (enabled=f сейчас) все 6296 строк честно деактивируются ~12.07 — для эстиматора они и так невидимы (фильтр 14д), а UI/подсчёты источников перестанут врать. Если #2206 (scraped_at bump в upsert) смержится и расписание включат — живые строки останутся активными. Re-enable расписания domclick — отдельное решение (не в этом PR).
Author
Owner

PR #2221 смержен, deploy success. Верифицировано на проде: миграция 160 применена, оба расписания в scrape_schedules (enabled=t, next_run_at=2026-07-03 07:00 UTC, default_params с staleness_column=scraped_at для domklik), tradein-scraper пересоздан с новым кодом.

Первый боевой прогон — 07:00 UTC. Ожидаемо: n1 деактивирует все 381 строку (last_seen 16.06 > TTL 14д); domklik пока 0 (scraped_at 28.06 < 14д — деактивация начнётся ~12.07, если реальные скрейпы не возобновятся; с #2206 живые строки останутся активными). Ручной триггер прогона не делаю (прод read-only). Acceptance-проверку «после прогона нет is_active старше TTL» — после первого прогона.

PR #2221 смержен, deploy success. Верифицировано на проде: миграция 160 применена, оба расписания в `scrape_schedules` (enabled=t, next_run_at=2026-07-03 07:00 UTC, default_params с staleness_column=scraped_at для domklik), tradein-scraper пересоздан с новым кодом. Первый боевой прогон — 07:00 UTC. Ожидаемо: n1 деактивирует все 381 строку (last_seen 16.06 > TTL 14д); domklik пока 0 (scraped_at 28.06 < 14д — деактивация начнётся ~12.07, если реальные скрейпы не возобновятся; с #2206 живые строки останутся активными). Ручной триггер прогона не делаю (прод read-only). Acceptance-проверку «после прогона нет is_active старше TTL» — после первого прогона.
Author
Owner

Корректировка по решению user (03.07): domklik ОСТАВЛЯЕМ активным — TTL-деактивация domklik отключается (PR #2253, миграция 163: enabled=false для deactivate_stale_domklik). Деактивация остаётся ТОЛЬКО для n1 (первый прогон 07:00 UTC уберёт 381 мёртвую строку). Механизм staleness_column в коде сохранён — при возобновлении domclick-свипов расписание включается одним UPDATE.

**Корректировка по решению user (03.07):** domklik ОСТАВЛЯЕМ активным — TTL-деактивация domklik отключается (PR #2253, миграция 163: enabled=false для `deactivate_stale_domklik`). Деактивация остаётся ТОЛЬКО для n1 (первый прогон 07:00 UTC уберёт 381 мёртвую строку). Механизм staleness_column в коде сохранён — при возобновлении domclick-свипов расписание включается одним UPDATE.
Author
Owner

Закрываю — оба acceptance-пункта верифицированы на проде (2026-07-03).

  • n1: TTL-джоба deactivate_stale_n1 отработала в 07:00 UTC — SELECT count(*) FROM listings WHERE source='n1' AND is_active = 0 (было 381, все с scraped_at 15.06).
  • domklik: остался активным — 6296 строк не тронуты. Его TTL-расписание отключено миграцией 163 (PR #2253, продуктовое решение user: domklik остаётся источником до возобновления свипов; механизм включается одним UPDATE).
  • Freshness-трекинг: deals_freshness_monitor заведён (миграция 162), scraped_at живёт честно с #2206.

Апдейт (решение user, утро 03.07): n1 выключаем полностью — готовится PR chore/tradein-remove-n1-source: миграция 165 (страховочная деактивация + удаление n1-строк из scrape_schedules/scraper_settings) + вычистка n1 из backend config/schemas/экспортера, ops-скриптов и frontend source-registry/UI, чтобы источник нигде не всплывал. Исторические строки БД остаются inactive.

**Закрываю — оба acceptance-пункта верифицированы на проде (2026-07-03).** - **n1:** TTL-джоба `deactivate_stale_n1` отработала в 07:00 UTC — `SELECT count(*) FROM listings WHERE source='n1' AND is_active` = **0** (было 381, все с scraped_at 15.06). - **domklik:** остался активным — 6296 строк не тронуты. Его TTL-расписание отключено миграцией 163 (PR #2253, продуктовое решение user: domklik остаётся источником до возобновления свипов; механизм включается одним UPDATE). - Freshness-трекинг: `deals_freshness_monitor` заведён (миграция 162), `scraped_at` живёт честно с #2206. **Апдейт (решение user, утро 03.07):** n1 выключаем полностью — готовится PR `chore/tradein-remove-n1-source`: миграция 165 (страховочная деактивация + удаление n1-строк из scrape_schedules/scraper_settings) + вычистка n1 из backend config/schemas/экспортера, ops-скриптов и frontend source-registry/UI, чтобы источник нигде не всплывал. Исторические строки БД остаются inactive.
Author
Owner

n1 выведен полностью — PR #2276 смержен, задеплоен и верифицирован на проде (2026-07-03 07:5x UTC):

  • scrape_schedules: n1-строк 0 (n1_city_sweep, deactivate_stale_n1 удалены миграцией 165);
  • scraper_settings: n1-строк 0;
  • listings: активных n1 0, история сохранена (382 строки, is_active=false);
  • backend health 200; n1 вычищен из SSRF-allowlist, search-Literal, PDF-экспортера, source-registry и всех UI-поверхностей (легаси-строки рендерятся с safe fallback, не падают).

Источник n1 больше нигде не всплывает. Issue остаётся закрытым.

**n1 выведен полностью — PR #2276 смержен, задеплоен и верифицирован на проде (2026-07-03 07:5x UTC):** - `scrape_schedules`: n1-строк **0** (`n1_city_sweep`, `deactivate_stale_n1` удалены миграцией 165); - `scraper_settings`: n1-строк **0**; - `listings`: активных n1 **0**, история сохранена (382 строки, `is_active=false`); - backend health 200; n1 вычищен из SSRF-allowlist, search-Literal, PDF-экспортера, source-registry и всех UI-поверхностей (легаси-строки рендерятся с safe fallback, не падают). Источник n1 больше нигде не всплывает. Issue остаётся закрытым.
Sign in to join this conversation.
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#2204
No description provided.