fix(tradein/deactivate): TTL не снимает объявления по порогу ниже собственного цикла обхода #2797
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
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#2797
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/2659-revisit-floor"
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?
Что происходит
Гейт здоровья #2710 отвечает на вопрос «источник вообще собирается?» и делает это
верно — Домклик на проде честно пропускается третьи сутки подряд. Но он не отвечает
на второй вопрос #2659: достаточно ли
ttl_days, чтобы молчание означало снятие?Пока свип возвращается к строке реже, чем раз в
ttl_days, TTL меряет НАШУ выборку,а не жизнь объявления, — и источник при этом полностью здоров, так что гейт молчит.
Замер до правки (прод, read-only, 2026-08-09)
С деплоя гейта 06.08 TTL снял 1 028 строк, 127 из них (12.4%) уже снова активны —
свип нашёл их живыми через 1-3 суток и вернул сам (upsert в
scraper_kit/base.pyставит
is_active = true). В разбивке по городам видно, что это не шум:В единственном городе с настоящим покрытием ложны все снятия. Возраст на момент
снятия у всех 127 — 29.9..30.3 суток при TTL=30: срабатывание ровно на границе, а
свип возвращался к строке на 31-34-е сутки.
Почему это не лечится новой константой
Разрывы переобхода против текущих TTL (
listing_source_snapshots, 40 суток, срезсовпадает со срезом TTL-джобы):
Домклик — контроль из своих же данных: при почти полном суточном обходе TTL лежит в
4.5 раза выше хвоста, и снятие у него действительно означает снятие. У остальных трёх
порог сидит вплотную к хвосту или внутри него. Руками подобранное число и есть корень
#2659 — чинить его вторым руками подобранным числом бессмысленно.
Что сделано
Вместо константы меряем факт: какой самый большой возраст, при котором свип за
последнее окно ДОКАЗАЛ строку живой (нашёл её на площадке). Если свип только что
вернул к жизни строку, молчавшую 40 суток, то 30 суток молчания не доказывают ничего.
эффективный TTL = max(ttl_days, пол)— пол только поднимает порог, никогда неопускает. Считается по ТОМУ ЖЕ срезу
source+segmentsи по ТОЙ ЖЕ колонке свежести,что и сам UPDATE, ДО любой записи. Нет истории снимков → пола нет, TTL как задан.
Побочный эффект намеренный: после провала сбора хвост разрывов распухает (свип
разгребает завал), пол растёт, деактивация замирает сама — ровно то, чего issue просил
от «гейта по банам», но выраженное через результат, а не через причину. Когда завал
разобран, хвост схлопывается и пол опускается обратно.
Миграции нет: новых пороговых констант не появилось, в этом и смысл правки. Квантиль
0.99 — калибровочная ручка в
default_paramsрасписания (revisit_floor_quantile,0 → пол выключен), подобран по требованию «пол обязан накрыть возраст 30.3 доказанно
ложных снятий».
Видимое пользователю изменение числа объявлений
Ближайший прогон Яндекса перестаёт снимать 43 активные строки vtorichka. На проде
это единственные строки, которых TTL сейчас вообще касается (avito, cian, domklik →
0 строк под ножом на сегодня). Дальше эффект идёт потоком: ~100-300 снятий в сутки,
из которых доказанно ложных 12.4%.
Test plan
test_effective_ttl_covers_every_proven_false_kill— проигрывает 127 доказанныхложных снятий на всех трёх прод-срезах; на старом коде 13 из 17 тестов красные
(эффективный TTL остаётся 30 и не накрывает возраст 30.3)
остальным трём нужен (0.24..1.13) — если это перестанет быть так, тест упадёт
колонка свежести, whitelist колонки, гейт здоровья выигрывает у пола
ruff check+ruff formatчисто; 105 тестов семейства deactivate_stale зелёныеcian/vtorichka 33.99, yandex/vtorichka 74.25, avito 69.67, domklik NULL; 235 мс
Прод-верификация (критерий записан ДО факта)
Прогон
deactivate_stale_yandexближайшим утром после деплоя должен датьcountersсttl_days_effective >= 34иdeactivated = 0вместо ожидаемых 43,а в логах — warning «TTL поднят с 30 до N сут». Если
deactivatedснова окажется43 — правка не доехала, а не «сработала тихо».
Refs #2659
Прод-верификация после мержа (read-only)
Код в живых контейнерах — проверено кодом, а не флагом релиза:
Решение, которое развёрнутый код примет на ближайшем прогоне (симуляция тем же
запросом, что зашит в задачу):
Критерий из описания PR выполнен: 43 активные строки yandex/vtorichka перестают
сниматься, это ровно те строки, которых TTL сегодня касается на всём проде.
Домклик остаётся под гейтом здоровья независимо от пола: подтверждений за 3 суток
0 при пороге 200 — пол у него NULL (переобходов нет вовсе, сбор стоит), и деактивация
не исполняется по-прежнему из-за #2710, а не из-за этой правки.