feat(tradein): nightly task to deactivate stale avito listings (#759) #862
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
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#862
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/759-deactivate-stale-avito"
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?
Summary
Avito listings are re-activated (
is_active=true) on every re-scrape but never deactivated when they stop appearing (sold/removed) — unlike cian's snapshot scope. Live: all 9765 avito rowsis_active=true, 52% not seen >7d → inflated coverage denominator + dead lots polluting estimator analog medians.Adds scheduled task
deactivate_stale_avito_listings:UPDATE listings SET is_active=false WHERE source='avito' AND is_active=true AND last_seen_at < NOW() - CAST(:ttl_days || ' days' AS interval)AVITO_STALE_TTL_DAYS(default 10d, > full city-sweep cycle → no false deactivation).scheduler_loopdispatch via newtrigger_deactivate_stale_avito_run(mirrorstrigger_listing_source_snapshot_run1:1) + seed migration090_*(window 06:00–07:00 UTC, after avito sweep;ON CONFLICT(source)idempotent;scrape_schedules.sourceis UNIQUE per 052).Test plan
test_deactivate_stale_avito.py) — SQL shape (source='avito' only, is_active flip, CAST-interval not::, no DELETE), settings wiring, scheduler dispatch, migration checks, fake-DB behavioural.pytest -k "scheduler or deactivate"→ 32 passed;ruffclean; no:x::type; AST ok.count(*) FILTER (is_active)for avito drops;scrape_runsrowdone; non-avitois_activetotals unchanged.Note for reviewer
Touches
config.py(addsavito_stale_ttl_days) — same file as PR #859 but a different additive block; if #859 merges first this should still auto-merge (distinct regions), else trivial rebase.Refs #759, #726, #814
✅ APPROVE — nightly deactivate-stale-avito (#759), data-hygiene, хорошо загардено.
Проверено:
is_active=false WHERE source='avito' AND is_active=true AND last_seen_at < NOW() - CAST(:ttl_days || ' days' AS interval)— psycopg v3 (CAST, не:x::type— тесты ассертят), source-scoped (cian/yandex не тронуты), already-inactive скип, NO DELETE (история для backtest #667). commit+mark_done; except→rollback+mark_failed+re-raise.trigger_deactivate_stale_avito_runзеркалит проверенный snapshot/matview паттерн (_claim_run→run_in_executorsync-task) + dispatch-branch. migration090seed (enabled, 06:00-07:00 UTC после sweep 02-05,ON CONFLICT DO NOTHING, после 089). configavito_stale_ttl_days=10(env маппится верно).is_active=trueanalog-медиан — заявленная цель). 20 тестов (SQL-shape/settings/task-contract/scheduler/migration/fake-db counter+zero+failure), 32 passed.Anti-regression: scheduler — новый trigger + branch, существующие не тронуты. config — additive (рядом с #863's quarter-index-factor — distinct regions). migration sequential. Секретов/инъекции/self-extending нет.
Мержу. #759 → qa. Post-deploy QA: после первого 06:00 UTC fire — avito
count FILTER(is_active)падает, non-avito без изменений, scrape_runs row done.