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
Ревью 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
68 lines
5.7 KiB
PL/PgSQL
68 lines
5.7 KiB
PL/PgSQL
-- 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;
|