fix(scraper-kit): свежесть источника — по последнему прогону, принёсшему данные, а не по статусу done #3365
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#3365
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/3172-freshness-by-data"
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?
Closes #3172 (observability p2; породил ложный P1 #3118 «домклик мёртв с 05.08»).
_STALE_SOURCES_SQLсчитал свежесть поmax(finished_at)прогоновdone; прогон с блоками честно переводится вbanned(#2657) и при этом вставляет строки.Мера «прогон дал данные»
runs._RESULT_COUNTER_KEYS(total_seen/lots_fetched/unique_fetched/succeeded) — тот же словарь, которым уже судит сторож нулевого результата (#2703): одна мера на оба механизма, а не второй список, который разъедется. Неlots_inserted— это новизна, а не наличие данных: здоровый sweep с полностью дедуплицированной выдачей вставляет ноль и читался бы мёртвым (#3118 наизнанку). Результат не измерен (_run_result_count() is None— 28 источников без результатного ключа:refresh_search_matview,deactivate_stale_*, мониторы) → прежняя мера, статусdone: иначе «не измерено» схлопнулось бы с «ноль» и все они разом стали бы просроченными навсегда.never_ok— той же функцией.Отдельная колонка-отметка в финализаторе отвергнута: миграция + по построению не работает на исторических строках, а приёмка требует ретроспективу с 05.08.
Логика вынесена в Python (
run_brought_data/freshness_rows), SQL отдаёт завершённые прогоны — иначе нечем красить по значению (pg-фикстуры в репо нет).Тесты
test_freshness_by_data_3172.py+ перекодированныйtest_2670_stale_source_digest.py(пороговые тесты не тронуты):421 passed, 1 skipped(-k stale/fresh/scheduler). Фальсификация (откат scheduler.py):'domclick_city_sweep' not in {…age_days=21.08…},'yandex_city_sweep' in {},'avito_full_load' … never_ok=True— по значению.Прод-проверка (ретроспектива, сделаю комментарием)
SQL воркера:
old_since(по done) противnew_since(по данным) дляdomclick%— ожидание: старая мера ≈ 05.08, новая — свежая дата.Прод-проверка SQL воркера (05.09 19:03 UTC) — честно: сегодня неразличима. У
domclick_city_sweepиdomclick_detail_backfillесть свежиеdone-прогоны, поэтомуold_since(по статусу) =new_since(по данным) = 05.09. Ретроспектива «домклик перестаёт числиться мёртвым с 05.08» из приёмки #3172 воспроизводится только на срезе истории ДО первого done — сейчас такого окна нет.Что подтверждается тестами по значению (не продом): источник с последним прогоном
banned+ данные>0 → не stale;doneбез результата (измеримый источник) → stale; неизмеримые (28 источников без результатного ключа) — прежняя мера поdone.Датированный критерий (до 19.09): при первом эпизоде «серия
bannedс данными безdone≥ 7 суток» у любого источника — дайджест_STALE_SOURCESНЕ называет его протухшим (сравнить сold_since-формулой из SQL выше).Ревью ✅ (для записи), два minor — follow-up, не блокеры:
runs.py:187-201,_warn_source_has_no_result_metric) — дёрнуть тот же warn изrun_brought_data, одна строка.LEFT JOIN scrape_runs … finished_at IS NOT NULLбез окна → seq scan + jsonb на каждый исторический прогон при каждом рестарте планировщика (_last_stale_digest_atв памяти). На ~10k строк шум; окноfinished_at > now() - interval '365 days'не меняет смысла («не собирал за год» = просрочен по любой мере).Честный потолок меры (не дефект PR): «выдача отдала объявления» ≠ «строки легли в базу» — бан после первой страницы с
lots_fetched=17читается как живой источник; объём никто не сторожит.