Остальные семь чеков прошли за минуты, backend-tests стоял 1ч30м без
единого обновления статуса. Actions API на этом Forgejo недоступен
(/actions/tasks обрывает соединение), перезапуск — только новым
коммитом. Код не меняется.
Задача формулировала «импорт каждый день рапортует done с total_seen=0».
Проверка на проде показала другое: импорт исправен — ежедневно вычитывает
все 96 974 строки FDW-источника и честно их пропускает (rows_fetched =
rows_skipped = 96974), а `total_seen` — поле админ-витрины, не счётчик
импорта. Источник gendesign.rosreestr_deals стоял на Q1 2026 (загружен
30.04), хотя Q2 2026 опубликован Росреестром 10.07 и poll заметил его
14.08 (available=1). Оба сторожа — poll и deals_freshness_monitor —
сработали и семь событий ушли в GlitchTip, где 0 правил / 0 адресатов /
0 отправок.
Корень, которого в задаче не было: rosreestr_deals партиционирована по
period_start_date, партиции созданы списком в 01_schema «2024 Q3 — 2026
Q1», и ничто новые не создаёт. Загрузка Q2 21.08 упала:
ERROR: no partition of relation "rosreestr_deals" found for row
DETAIL: (period_start_date) = (2026-04-01)
То есть даже оператор, запустив загрузчик по подсказке poll, получил бы
отказ. Это и объясняет, почему poll сделан «только сообщить».
Что сделано:
• миграция 193 — партиции Q2, Q3, Q4 2026 с запасом, идемпотентно, с
lock_timeout; индексы наследуются от родителя (проверено: 4 на 2026q2);
• JOBS загрузчика — 2026Q2–Q4 (квартал без CSV честно SKIP);
• ловушка set -e в загрузчике: resolve_csv сигналит «файла нет» кодом 1,
и первый же квартал без CSV молча ронял ВЕСЬ прогон до строки SKIP — на
проде с одним Q2-файлом скрипт завершался rc=0, не напечатав ни строки.
`|| true` на вызове; после правки боевой прогон на VPS: 12 кварталов,
2026Q2 «уже загружен (741874 строк)», остальные SKIP, rc=0;
• тест-сторож горизонта: партиция обязана существовать на последний
публикуемый квартал (+20 дней лага после конца квартала; Q2 2026 вышел
10.07) и на следующий — чтобы предупреждение приходило за квартал до
отказа, а не в день публикации. Читает pg_inherits живого Postgres.
Красная сторона воспроизводима на проде, где миграция уже применена:
DETACH партиции в откатываемой транзакции → головная краснеет по
значению («нет партиции на квартал 2026-04-01»), откат возвращает
партицию (проверено: 12 партиций после теста). Без БД — skip с
причиной, в allowlist; календарный тест идёт везде.
Сам Q2 загружен на прод по штатному пути: 741 874 строки в
rosreestr_deals (ЕКБ-фильтр 13 654), import-rosreestr.sh → tradein.deals
+11 649 сделок, max(deal_date) 2026-01-01 → 2026-04-01.
deals_freshness_monitor на следующем тике: alert 0, latest_quarter 2.
pytest backend/tests/sql — 55 passed (через туннель к проду).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>