fix(tradein): single-run guard на avito-city-sweep admin-endpoint #874
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#874
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/avito-sweep-single-run-guard"
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-sweep'ы делят один прокси-IP → удвоенный rate → Avito бан.
Incident 2026-05-31 (verified по scrape_runs): runs #26 (08:31:29–08:42:50) и #27 (08:38:09–08:43:40) шли ОДНОВРЕМЕННО → оба
banned. Это и скомпрометировало delay-эксперимент (казалось «5s банится», а на деле дубль).Scheduler уже защищён (
has_running_run+ advisory lock в_claim_run), но ручной admin-endpointPOST /scrape/avito-city-sweepguard'а НЕ имел → два ручных триггера проходили.admin.py:has_running_run('avito_city_sweep')→HTTPException 409передcreate_run(до background task — run-row не создаётся).has_running_run→True → 409.Test plan
pytest tests/test_api_avito_stage4a.py→ 6 passedNoted follow-ups (не блокируют): TOCTOU на ручном endpoint (sub-second двойной POST) — при необходимости переиспользовать advisory-lock из
_claim_run; опц. включить blocking run_id в 409-detail.✅ APPROVE — single-run guard на ручном avito-city-sweep endpoint.
Cruxes проверены:
has_running_run(db: Session, source: str) -> boolсуществует (scheduler.py:87) — сигнатура совпадает с вызовомhas_running_run(db, "avito_city_sweep").admin/app.api(admin→scheduler односторонний). Подтверждает «import-граф ацикличен».runs_mod.create_run→ при 409 orphan run-row не создаётся. ✓admin_module.has_running_run— корректно перекрывает имя изfrom ... importв неймспейсе admin.Incident-grounded: runs #26+#27 параллельно → оба
banned(делят прокси-IP). Scheduler уже защищён (has_running_run+ advisory lock в_claim_run); этот guard закрывает ручной admin-триггер. TOCTOU (sub-second двойной POST) честно вынесен в non-blocking follow-up — практический gap (раны 11 мин врозь) закрыт.6 тестов pass, own code-reviewer ✅. admin.py + test, SQL/секретов/self-extending нет.
Мержу. (Incident hotfix, без linked issue.)