gendesign/tradein-mvp/backend/data/sql/212_sber_index_pull_weekly.sql
bot-backend 3e1b9a8b0d
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 7s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 2m59s
fix(tradein): чинит такт загрузки СберИндекса — иначе новый ERROR стал бы ложной тревогой (#2674)
Ревью PR #2681 опровергло исходную посылку по СберИндексу, и это подтвердилось
на моих же числах (все 24 прогона монитора, read-only):

  13-16.07  alert=1  age 73..76  latest=май
  17.07     alert=0  age 46      latest=июнь  ← день загрузки
  18-31.07  alert=0  age 47..60
  01-05.08  alert=1  age 61..65

Загрузка ходила раз в 28 дней и приносила период на месяц новее, возраст
считается от первого числа покрытого месяца → пол 46, потолок 74, порог 60
ВНУТРИ диапазона. Тревога срабатывала 14 суток из 28 без всякого застоя
источника: девять срабатываний были замером нашего собственного такта. Поднятие
до ERROR без этой правки завело бы ежедневное ложное событие две недели в месяц.

Миграция 212 переводит sber_index_pull на недельный такт (потолок ≈53 при пороге
60, запас 7 суток) вместо поднятия порога до 75 (запас 1 сутки — ломается от
любого сдвига окна). Цена: 9 запросов в неделю вместо 9 в 28 дней к публичному
sberindex.ru/api/sowa; прогон 4 секунды, 0 ошибок за всю историю.

Дополнительно по ревью:
- поллер Росреестра: ветка «файл найден в листинге, но HEAD не отдал zip» →
  ERROR (ровно поведение старой Bitrix-заглушки) + вписана в таблицу уровней;
- тестовый харнесс закрывает клиент событий (фоновый поток на каждый тест).

Refs #2674
2026-08-06 02:53:26 +05:00

68 lines
5.7 KiB
PL/PgSQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- 212_sber_index_pull_weekly.sql
-- sber_index_pull: такт 28 дней → 7. Ревью PR #2681 (#2674).
--
-- ПОЧЕМУ. Монитор sber_freshness_monitor алертил при age > 60д
-- (sber_index_max_age_days 35 + lag_allowance 25). Прод-разбор всех 24 прогонов
-- монитора (read-only, 2026-08-06, scrape_runs.counters) показал ПИЛУ, а не застой:
--
-- 13-16.07 alert=1 age 73,74,75,76 latest_month=5 (май)
-- 17.07 alert=0 age 46 latest_month=6 ← день загрузки
-- 18-31.07 alert=0 age 47..60 latest_month=6
-- 01-05.08 alert=1 age 61..65 latest_month=6
--
-- Механика: загрузка ходила раз в 28 дней и приносила период на месяц новее, а
-- возраст считается от ПЕРВОГО ЧИСЛА покрытого месяца. Значит в момент самой
-- свежей загрузки возраст уже ~46 (07-17 минус 06-01), к следующей дорастает до
-- 46+28=74, и порог 60 лежит ВНУТРИ [46, 74] — тревога пересекала его каждый
-- цикл, 14 суток из 28. Девять срабатываний, поданных в #2674 как улика застоя
-- бенчмарка, — это замер НАШЕГО СОБСТВЕННОГО ТАКТА. После #2681 (WARNING → ERROR)
-- это стало бы ежедневным событием две недели в месяц, гаснущим само собой —
-- ровно та ложная тревога, которая приучает не читать алерты.
--
-- ПОЧЕМУ ТАКТ, А НЕ ПОРОГ. Рассматривались два варианта:
-- (A) поднять lag_allowance 25 → 40 (порог 75 против потолка 74). Запас ОДИН
-- день: любой сдвиг окна/пропуск прогона на сутки — и ложная тревога
-- возвращается. Порог при этом продолжает кодировать наш такт, а не
-- поведение источника. Отклонено.
-- (B) ЭТА миграция: такт 28 → 7. Потолок возраста становится floor+7 ≈ 53 при
-- том же пороге 60 — запас 7 суток, т.е. один пропущенный недельный цикл
-- поглощается, два подряд дают тревогу (и это уже осмысленная тревога).
-- Порог 60 начинает означать ИМЕННО «Сбер перестал публиковать / загрузка
-- сломалась», а не «мы давно не ходили».
--
-- ЦЕНА. pull_sber_indices делает SBER_REF_AREAS (3: 643/66/77) × SBER_DASHBOARDS
-- (3) = 9 GET-запросов к публичному неавторизованному sberindex.ru/api/sowa, без
-- пауз в цикле; прод-прогон 2026-07-17 занял 4 секунды (counters.duration_sec=4,
-- errors=0, upserted=639). Было 9 запросов / 28 дней, стало 9 / 7 дней = 36 в
-- месяц. Это тот же эндпоинт, который дёргают сами дашборды Сбера при каждом
-- открытии страницы; лимитов/бана на нём за всю историю прогонов не наблюдалось
-- (0 ошибок в 6 прогонах). Риск нагрузки считаем отсутствующим.
--
-- ПОБОЧНО. Оценщик имеет СВОЙ per-estimate guard свежести с порогом
-- settings.sber_index_max_age_days=35. Он пробивается всегда, потому что возраст
-- стартует с ~46. Недельный такт сокращает НАШУ задержку обнаружения с ≤28 суток
-- до ≤7, то есть возраст = (лаг публикации Сбера) + ≤7 вместо + ≤28. Уйдёт ли он
-- под 35 — зависит от того, когда Сбер реально публикует месяц (по нашим данным
-- лаг публикации ≤46 и ≥31 суток, точнее по имеющимся прогонам не определить),
-- поэтому НЕ обещаем починку этого guard'а, только снятие нашей части задержки.
--
-- next_run_at подтягиваем на ближайшее окно (05:00-06:00 UTC): без этого правка
-- default_params начнёт действовать только после уже запланированного прогона
-- 2026-08-14, а до тех пор ложная тревога продолжала бы идти каждый день.
-- LEAST() — чтобы повторное применение НИКОГДА не отодвигало прогон дальше.
--
-- Идемпотентно: jsonb-конкатенация + LEAST, повторный прогон безопасен.
-- Кода не меняет: interval_days читается kit-планировщиком из default_params
-- (orchestration/scheduler.py::_defer_next_run_at, params.get("interval_days", 1)).
BEGIN;
UPDATE scrape_schedules
SET default_params = COALESCE(default_params, '{}'::jsonb) || '{"interval_days": 7}'::jsonb,
next_run_at = LEAST(
next_run_at,
((CURRENT_DATE + INTERVAL '1 day') + make_interval(hours => 5)) AT TIME ZONE 'UTC'
)
WHERE source = 'sber_index_pull';
COMMIT;