fix(tradein/scraper): detail-backfill с нулём обогащений перестаёт называться успехом (#2674) #2695
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#2695
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/2674-domclick-backfill-honesty"
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?
Проблема (числа с прода 2026-08-06)
domclick_detail_backfill: 30 прогонов, 494 попытки, 0 обогащено — и все 30 со статусомdone.Это не единичный случай, а общий дефект трёх detail-backfill'ов — все они финализировались одним
mark_done. Прогонов «попытки были, результата ноль» на проде 78 из 158:domclick_detail_backfillavito_detail_backfillyandex_detail_backfillПочему никто не заметил. Оба существующих алерта этот класс пропускают:
_alert_if_consecutive_failuresсчитает толькоfailed/banned— а тутdone;_alert_if_consecutive_zero_results(#2625) смотритtotal_seen, которого в counters backfill'ов нет вовсе → колонка всегда 0 → стрик не прерывается никогда → анти-спам молчит после первого срабатывания.Что сделано
Один общий финализатор
runs.mark_backfill_finishedна три задачи (правка в одной точке, а не в трёх копиях). Правила — по образцу #2657 дляdomclick_city_sweep:attempted=0→ done (честная пустота, кандидатов не было);gone(404 у avito) считается результатом наравне сenriched— прогон, подтвердивший снятие объявлений, работу сделал.В
scrape_runs.errorпишется причина с числами прогона, а не пустая строка. Побочный эффект честности: три подрядbanned/failedподнимают уже существующий Sentry-алерт — ровно тот сигнал, которого не хватало.Про корневую причину нуля у Домклика
Она внешняя и уже разобрана до этого PR: детект QRATOR-маркеров чинил #2645 (#2636), после чего 208-я миграция вернула расписание. Свежий прогон 3201 (2026-08-05) отработал ровно как задумано —
attempted=3 blocked=3за 49 с, брейкер оборвал. Второй фактор: куки test-аккаунта протухли 2026-08-03 (domclick_session_cookies.expires_at_estimate = 2026-08-03 20:10Z,last_used_at = 2026-08-01), обновление ручное черезPOST /scrape/domclick/upload-cookies.Расписание намеренно не трогаем: брейкер обрывает прогон после 3 блоков за ~150 с (цена вопроса ничтожна), а куки миграцией не перезальёшь. Теперь молчать это перестанет.
Test plan
tests/test_backfill_honest_status.py— 10 кейсов, каждый списан с фактического прод-прогона (16×attempted=3 blocked=3, 100 failed без блоков, avito 1500/1499, yandex 5/5, пустой снапшот, частичный, gone-only).aborted_by_blocks=True.test_search_cache_hit(он же deselect'ится в CI).docker logs tradein-scraper | grep backfill-honest-status(строка новая, до этого PR её не существовало) +SELECT status FROM scrape_runs WHERE source LIKE '%detail_backfill' ORDER BY id DESC.Refs #2674
bot-backend referenced this pull request2026-08-06 06:23:36 +00:00
Отложенная проверка закрыта: честный статус сработал на проде, и сразу вскрыл больше, чем чинил
При мерже поведенческая проверка была невозможна — ближайшие окна задач шли только через несколько часов. Прогоны состоялись:
Оба до правки назывались бы
done. Правило различает исходы верно:failedтам, где ноль результата без блокировок,bannedтам, где блокировки, и обе строки причины несут отличительный маркерbackfill-honest-status:.Что честный статус показал сверх того, ради чего писался
Задача заводилась по Домклику — 494 попытки, ноль обогащений, 30 прогонов подряд
done. Первые же прогоны после деплоя показывают, что на нуле стоят все три источника, а не один:Два последних до сегодняшнего дня были скрыты статусом
done— ровно тем механизмом, который эта задача и чинила. Разбор запущен отдельно.Показательно, что цена молчания оказалась выше заявленной в задаче: чинили видимость одного источника, а невидимыми были три.
Поправка: «на нуле все три источника» — неверно, и ошибок в моём выводе две
Разбор (PR #2738/#2739) опроверг обе половины. Перепроверил сам.
1. Авито обогащает детали каждый день — не через backfill-задачу, а через detail-фазу городского обхода:
На нуле стоит именно backfill-задача (последнее обогащение 12 июля, 25-й день), а не источник. Разница существенная: «источник не обогащается» и «одна из двух дорог к нему закрыта» требуют разных действий.
2. У Яндекса сломана не выдача, а голова очереди. Он обогащал 21 прогон из 53, всего 1409 объявлений, последний позавчера. Мои «5 отказов из 5» — один прогон, а не картина.
Корень найден и он не сетевой. Разбор возвращает
Noneдо всякого обращения к сети, если ссылка не похожа на карточку объявления:В очереди Яндекса 3 524 строки из 12 941 активных (27%) ведут на сайты застройщиков — так с выдачи уходят карточки новостроек. Обогащено из них за всю историю ноль. Идут они пачками, поэтому голова очереди на момент прогона оказалась пятью такими подряд.
3. И самое неприятное: «стена капчи» была нашим собственным сообщением. Код писал
ABORT -- 5 consecutive parse-None results (captcha wall?), и это уходило в мониторинг как признак противодействия площадки. Площадка тут ни при чём — пять подрядNoneдал наш же разбор на ссылках, которые он не умеет разбирать по построению.Это стоит запомнить отдельно: система поставила себе неверный диагноз, и неверный диагноз был принят на веру — в том числе мной, когда я формулировал задачу. Сегодня уже был симметричный случай (#2686: наш отказ записывался как бан площадки), но там метка была слишком широкой, а здесь — прямо выдуманной.
4. Мелочь, но моя: «окна avito 12:39, yandex 11:05 ежедневно» — это не окна, а случайные времена; у обеих задач окно 0–23. Следующие прогоны 07.08 в 01:54 и 07:54 UTC.
ban_kindпроставляется по умолчанию у 9 вызывающих из 12 — метка выглядит доказательством, не будучи им #2764done, причина в разборе а не в сети #2767