---
name: osm-pipeline-mini-failures
description: "Сборки geocoder.db и poi.db на mini падали молча месяц; osmium определяет формат по суффиксу имени, cron-safe убивает по таймауту без traceback"
metadata: 
  node_type: memory
  type: project
  originSessionId: d0c6c5aa-4d05-42e2-a1f9-034482b88603
  modified: 2026-07-31T11:02:24.866Z
---

**mac mini, OSM-конвейер `/Volumes/Ext/mac-mini/{geocoder,poi}` (разбор 2026-07-31).** Обе еженедельные сборки — `local.geocoder-refresh` (04:00) и `local.zemlya-poi-refresh` (06:00) — молча не работали: geocoder.db с PBF от 25 мая, poi.db от 5 июля, тайлы зелёные.

**1. osmium определяет формат ПО СУФФИКСУ ИМЕНИ.** `refresh_geocoder.sh` качал свежий PBF в `russia-latest.osm.pbf.new` и строил индекс прямо из него → `RuntimeError: Could not detect file format for filename '...pbf.new'`. Скачивалось всё исправно (файл валиден, replication timestamp читается), ломался только шаг сборки. Промежуточное имя обязано оканчиваться на `.osm.pbf` — исправлено на `russia-latest.new.osm.pbf`. **Грабля общая: любое временное имя для osmium/GDAL держать с правильным расширением, а не суффиксом `.new`/`.tmp`.**

**2. `cron-safe.py` убивает по таймауту SIGTERM→SIGKILL, и это выглядит как обрыв на ровном месте** — ни traceback, ни строки в логе, `set -euo pipefail` не спасает. Таймаут — 3-й аргумент в ProgramArguments plist. Стояло 3600 с у геокодера и 9000 с у poi при **замеренной** длительности сборки poi ~3 часа (pass1 438 с + заливка 8,8 ГБ mmap-кэша ~470 с + pass2 при 300–500 строк/с на 3,33 млн ways). Оба подняты до 18000 с. **Перед изменением расписания или логики — сначала замерить реальную длительность, лимиты выставлены наугад.**

**3. Периодическая launchd-задача не краснеет в ops_dashboard ни при каком коде возврата** — тайл отвечает «процесс запускался», а нужен ответ «данные свежие». Добавлена `_check_zemlya_poi_freshness` в `server.py`: смотрит mtime ВНУТРЕННЕЙ копии `data/poi_local/poi.db` (её реально читает бот), порог 10 суток, cooldown сутки; `refresh_poi.sh` через `trap on_failure EXIT` кладёт хвост лога в `ops_health.json` → дашборд подставляет причину в текст алерта. Тот же приём применим к любой периодической задаче с артефактом. См. [[deployed_is_not_running]], [[ops_dashboard_autorestart_kills_long_jobs]].

**Чего доказать не удалось:** конкретную причину обрывов poi 12 и 19 июля — системный лог macOS за июль не хранится. Версия со сном диска отпадает (`pmset`: disksleep 0, sleep 0, держит caffeinate). Осталось предположение про отвал Ext или kill по памяти на заливке mmap-кэша — см. [[mini_ext_disk_dropout_disksleep]].
