feat(tradein/scraper): чекпоинт по якорям для avito_city_sweep (#3074) #3112
No reviewers
Labels
No labels
Fable 5 ревью
GG-форсайт
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
feedback/max
generative
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#3112
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/3074-avito-anchor-checkpoint"
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?
Продолжение после yandex-свипа (#3098). Источник выбран по замеру, а не «доделать остальные»:
domclickисключён осознанно: прогоны по три минуты, деплоем не убит ни разу — чекпоинт там не окупается.Прод-факт, который решает дело
Типичный итог свипа Авито:
Прогон срывается блокировкой на первом из пяти якорей. Без чекпоинта следующий прогон снова идёт в первый якорь, упирается в ту же стену — и якоря 2–5 не собираются никогда. Для сравнения, у
cian_city_sweepв тех же countersanchors_done: 5из 5.Решения и их основания
Ключ чекпоинта — имя якоря, а не индекс. Состав списка зависит от
city_slug, позиция в нём между городами не устойчива.Гарда по числу якорей не нужна — в отличие от combo-чекпоинта яндекса, где
combo_labelякоря не содержал и пропуск был бы пропуском чужих якорей. Здесь якорь и есть ключ.Отдельный флаг
_anchor_ok. В чекпоинт попадает только якорь, пройденный до конца. Ветка блокировки делаетreturnи до записи не доходит, аexcept Exception— доходит: якорь упал, но цикл продолжается. Записать такой якорь пройденным значило бы, что следующий прогон пропустит его навсегда, причём молча — прогон завершится штатно, просто часть города не соберётся. Тот же инвариант, что уcombo_skippedв яндексе, и ровно он остался непокрытым тестом в #3098.Флаг сбрасывается на каждой итерации — иначе один упавший якорь заразил бы все последующие и чекпоинт перестал бы пополняться вовсе.
Пропущенный якорь двигает
anchors_done— чтобы счётчик продолжал означать «докуда дошли по списку», а не «сколько собрал именно этот прогон».Тесты
tradein-mvp/backend/tests/test_3074_avito_anchor_checkpoint.py, 4 поведенческих — с подменойAvitoScraper,AsyncSessionиsave_listings:Оговорка про фальсификацию, честно. На исходном коде все четыре падают с
TypeError: unexpected keyword argument 'resume_run_id', то есть доказывают отсутствие параметра, а не неверное поведение. Поведенческую часть держат сами утверждения внутри тестов — обойти их, добавив только параметр, не выйдет.Весь набор #3074 (этот + яндекс + claim) — 10 passed.
ruffчист, в коммите нет CR.Refs #3074, #3098
Продолжение после yandex-свипа. Выбор источника — по замеру, а не «для полноты»: за 60 дней avito_city_sweep дал 68 прогонов, 25 банов и 3 отмены деплоем при среднем времени 15 мин и максимуме 97. Прод-факт, который решает дело. Типичный итог свипа: {"anchors_done": 1, "anchors_total": 5, ..., "enrichment_abort_note": "detail enrichment aborted (Avito detail firewall/soft-block ...)"} Прогон срывается блокировкой на ПЕРВОМ из пяти якорей. Без чекпоинта следующий прогон снова идёт в первый якорь, упирается в ту же стену, и якоря 2-5 не собираются никогда. Ключ чекпоинта — ИМЯ якоря, а не индекс: состав списка зависит от city_slug, позиция в нём между городами не устойчива. По той же причине здесь не нужна гарда по числу якорей, которая есть у combo-чекпоинта яндекса: там ключ якоря не содержал, здесь якорь и есть ключ. Инвариант, ради которого отдельный флаг _anchor_ok: в чекпоинт попадает только якорь, пройденный до конца. Ветка блокировки делает return и до записи не доходит, а generic-except доходит — якорь упал, но цикл продолжается. Записать такой якорь пройденным значило бы, что следующий прогон пропустит его навсегда, причём молча: прогон завершится штатно, просто часть города не соберётся. Флаг сбрасывается на каждой итерации, иначе один упавший якорь заразил бы все последующие. Пропущенный якорь двигает anchors_done — чтобы счётчик продолжал означать «докуда дошли по списку», а не «сколько собрал именно этот прогон». domclick_city_sweep намеренно НЕ трогаю: 54 прогона, ноль отмен деплоем, среднее время 3 минуты — чекпоинт там не окупается. cian_city_sweep (среднее 35 мин, 2 отмены) — следующий шард. Тесты (4) поведенческие: якорь из чекпоинта не опрашивается вовсе; пройденный дописывается поверх унаследованных; без чекпоинта обходятся все; упавший в чекпоинт НЕ попадает. Оговорка: на исходном коде они падают по сигнатуре (unexpected keyword argument), то есть доказывают отсутствие параметра, а не поведение — поведенческую часть держат сами проверки. Весь набор #3074 — 10 passed.