gendesign/tradein-mvp/backend/app
bot-backend b64e824e17
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 9s
CI / frontend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 4m24s
fix(tradein/sber): сторож мерит отставание загрузки, а не календарь (#2846)
Порог свежести якоря был недостижим по построению. period_month — метка ПЕРВОГО
числа месяца, поэтому возрасту ≥30 уже на закрытии месяца; плюс лаг публикации
источника. За 31 сутки прямых наблюдений монитора (07-13…08-12, scrape_runs.counters)
возраст лежал в 46..76 и ни разу не опускался ниже 46 — при пороге оценщика 35.
Сторож был истинным 100% времени с рождения таблицы и нёс ноль бит: при живом
источнике и при мёртвом загрузчике он писал одно и то же.

Второй порог (монитор, 60 = 35 + запас 25) не лучше: он лежит ВНУТРИ рабочего
диапазона. Обещание миграции 212 («такт 7 ⇒ потолок возраста 53 < 60») прод
ОПРОВЕРГ — 2026-08-12 возраст 72 при полном прогоне загрузки 08-06; двенадцатые
сутки подряд ERROR при исправной загрузке. Потолок 53 держался бы, только если бы
источник публиковал строго помесячно.

Что теперь. Загрузчик тянет ВСЮ серию (limit=1000&offset=0), поэтому после прогона
с errors=0 AND upserted>0 наш max(period_month) равен максимуму источника ПО
ПОСТРОЕНИЮ. Значит вопрос «отстали ли мы» = «давно ли был последний ЗАВЕДОМО ПОЛНЫЙ
прогон», и он не зависит от возраста периода. Порог — 2 такта самой загрузки,
читается из scrape_schedules.default_params.interval_days, то есть из той же строки,
по которой планировщик считает next_run_at: разъехаться с тактом он не может.
status='done' за успех не считается — прогон id=37 имеет done при {errors: 9,
upserted: 0}. Табло спрашивается тем же порядком, что у оценщика
(SBER_COEFF_DASHBOARDS), потому что max() по таблице маскирует отставшее табло:
real_estate_deals 2026-06, dinamika-tsen-obyavlenii 2026-05.

Два порога сведены удалением: settings.sber_index_max_age_days и per-estimate
warning в estimator убраны, свежесть считает ровно одно место.

fetched_at больше не переписывается апсертом. Забор идёт всей серией, поэтому
fetched_at = now() в DO UPDATE ставил одну метку всем 639 строкам, включая период
2017-01 — как признак свежести колонка была пуста. Теперь она означает «когда
впервые увидели период», т.е. такт публикации источника станет измеримым.
Ретроспективу это не возвращает: у уже лежащих строк метка 2026-08-06 и останется.

Refs #2846
2026-08-13 00:25:53 +05:00
..
api fix(tradein/imv): «временная» ошибка снова временная — 1390 домов возвращаются в очередь (#2843) 2026-08-12 16:06:24 +00:00
core fix(tradein/sber): сторож мерит отставание загрузки, а не календарь (#2846) 2026-08-13 00:25:53 +05:00
observability chore(tradein): удалить мёртвые mobileproxy env-переменные и rotate-ip (#2616 шаги 2-3) (#2650) 2026-08-05 09:35:54 +00:00
schemas fix(tradein/dkp): «ФАКТИЧЕСКИЕ СДЕЛКИ» называют свой возраст, а не окно поиска (#2847) 2026-08-12 18:51:10 +00:00
services fix(tradein/sber): сторож мерит отставание загрузки, а не календарь (#2846) 2026-08-13 00:25:53 +05:00
tasks fix(tradein/sber): сторож мерит отставание загрузки, а не календарь (#2846) 2026-08-13 00:25:53 +05:00
__init__.py feat: add tradein-mvp subproject (Trade-In Estimator под /trade-in) 2026-05-21 00:25:39 +03:00
main.py feat(tradein): версионирование продукта — единый источник, подвал, PDF, /versions (#2824) 2026-08-10 16:00:54 +00:00
scheduler_main.py refactor(tradein/scheduler): удалить legacy scheduler_loop + scraper-scheduling, kit единственный путь (#2397 Part C) 2026-07-04 13:00:30 +03:00
tgbot_main.py feat(tradein/tgbot): Telegram support-мост @MERAsupport_bot 2026-07-16 16:58:53 +03:00