gendesign/_wt-cadval/scripts/build_osrm.sh
bot-backend 542ff1c9ca docs(tradein/domclick): два комментария описывали пул, которого нет с миграции 253
Оба места утверждали, что у Домклика один выделенный резидентный прокси и
пула нет. Это перестало быть правдой ещё в #2800 (миграция 253 сняла
резервацию узла), но текст остался — и именно на него опирался тикет #3189,
поставленный под «калибровку» ограничения, которого не существует.
Свип к тому же ходит через пул давно (serp.py:359), а бэкфилл подключён к
нему в PR #3222.

Заодно докстринг называл не тот ограничитель: свип кладёт не счётчик
провалов lease, а break по первому DomClickBlockedError (#2854) — до
ротации дело не доходит ни при каком счётчике, отсюда buckets_completed=0.

Только комментарии, поведение не меняется. Миграция 175 уже применена, а
_schema_migrations трекает по имени файла без checksum — правка текста
её не перезапустит.
2026-08-29 18:57:25 +03:00

167 lines
9.2 KiB
Bash
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.

#!/usr/bin/env bash
# Build / refresh OSRM routing graph для site-finder (#39).
#
# Готовит .osrm-файлы (MLD pipeline) из OpenStreetMap-экстракта Свердловской
# области и кладёт их в ./data/osrm/, откуда их монтирует docker-compose.prod.yml
# (service `osrm`, volume ./data/osrm:/data → osrm-routed читает /data/<region>.osrm).
#
# === Где запускать ===
# На VPS из /opt/gendesign: bash scripts/build_osrm.sh
# (требует docker + ~5GB свободного диска + ~3GB свободной RAM на время extract).
#
# === ВАЖНО: это offline-задача, НЕ часть deploy.yml ===
# Download ~600MB-1.5GB + build 30-50 мин. Запускается ВРУЧНУЮ оркестратором,
# НЕ на каждом push. deploy.yml только поднимает уже готовый osrm-контейнер.
#
# === Idempotent / re-runnable ===
# Повторный запуск перекачивает свежий pbf и пересобирает граф (overwrite).
# Безопасно гонять ежемесячно (osm.pbf на Geofabrik обновляется ежедневно).
# # monthly refresh: cron на VPS, напр. 0 4 1 * * bash /opt/gendesign/scripts/build_osrm.sh >> /var/log/osrm-build.log 2>&1
# После refresh: docker compose -p gendesign -f docker-compose.prod.yml up -d --force-recreate --no-deps osrm
#
# === Регион / источник pbf ===
# Geofabrik НЕ публикует Свердловскую область отдельным extract'ом — только
# «Уральский ФО» (ural-fed-district). Два режима (CLIP=1 по умолчанию):
#
# CLIP=1 (default, РЕКОМЕНДОВАНО): качаем Ural-FO pbf и обрезаем по bbox
# Свердл. обл. через `osmium extract`. Результат легче → меньше RAM/диск
# в build и в runtime (osrm-routed warm ~0.8-1.2GB вместо ~1.5GB+ на
# весь Ural-FO). Минус: нужен extra-шаг osmium (запускаем в docker).
#
# CLIP=0: используем весь Ural-FO pbf как есть (zero-clip, проще, но тяжелее —
# граф Курган/Тюмень/ХМАО/ЯНАО грузится в RAM без пользы для Свердл).
# Бери, если RAM не жмёт и нужен запас на соседние регионы.
#
# bbox Свердловской обл (грубый, с запасом): lon 57.2..66.2, lat 56.0..62.0.
# Можно сузить до ЕКБ-агломерации если RAM критична (lon 59.0..62.5, lat 56.2..58.2)
# через EKB_TIGHT=1.
#
# === Профили ===
# Car (driving) — основной, строится всегда → <region>.osrm*.
# Foot (walking) — опциональный Phase-2, строится при WALK=1 → <region>-foot.osrm*.
# Для walking нужен второй compose-service (osrm-walk) — см. docs/osrm-routing.md.
# Этот PR car-first; walk выключен по умолчанию (issue хочет оба eventually).
#
# === Проверка после build ===
# docker compose -p gendesign -f docker-compose.prod.yml up -d osrm
# docker compose -p gendesign -f docker-compose.prod.yml exec osrm \
# sh -c 'echo OK' # контейнер жив
# # route-probe С ХОСТА (внутри образа нет curl) — временно прокинуть порт:
# docker run --rm --network gendesign_default curlimages/curl:8 -fsS \
# 'http://osrm:5000/route/v1/driving/60.6,56.84;60.65,56.86'
# ↑ ожидаем JSON {"code":"Ok","routes":[...]}.
set -euo pipefail
# --- Config (override через env) -------------------------------------------
OSRM_IMAGE="${OSRM_IMAGE:-osrm/osrm-backend:latest}"
OSMIUM_IMAGE="${OSMIUM_IMAGE:-stefda/osmium-tool:latest}"
REGION="${OSRM_REGION:-sverdlovsk}" # имя выходных .osrm* (= OSRM_REGION в compose)
PBF_URL="${PBF_URL:-https://download.geofabrik.de/russia/ural-fed-district-latest.osm.pbf}"
CLIP="${CLIP:-1}" # 1 = обрезать по bbox Свердл, 0 = весь Ural-FO
EKB_TIGHT="${EKB_TIGHT:-0}" # 1 = узкий bbox только ЕКБ-агломерация
WALK="${WALK:-0}" # 1 = ещё и пеший профиль <region>-foot.osrm*
CAR="${CAR:-1}" # 0 = пропустить car-граф (foot-only refresh, #39 A3)
CAR_PROFILE="${CAR_PROFILE:-/opt/car.lua}" # встроенные профили в osrm-backend образе
FOOT_PROFILE="${FOOT_PROFILE:-/opt/foot.lua}"
# bbox: left,bottom,right,top (lon_min,lat_min,lon_max,lat_max)
if [ "$EKB_TIGHT" = "1" ]; then
BBOX="${BBOX:-59.0,56.2,62.5,58.2}" # ЕКБ-агломерация (минимум RAM)
else
BBOX="${BBOX:-57.2,56.0,66.2,62.0}" # вся Свердловская обл (с запасом)
fi
# Каталог host (= ./data/osrm в compose). Скрипт зовём из /opt/gendesign.
DATA_DIR="${DATA_DIR:-$(pwd)/data/osrm}"
mkdir -p "$DATA_DIR"
RAW_PBF="$DATA_DIR/${REGION}-raw.osm.pbf" # сырой Ural-FO (или clip-источник)
WORK_PBF="$DATA_DIR/${REGION}.osm.pbf" # то, что реально пойдёт в osrm-extract
echo "=== OSRM build ==="
echo " region : $REGION"
echo " pbf source : $PBF_URL"
echo " clip to bbox : CLIP=$CLIP BBOX=$BBOX (EKB_TIGHT=$EKB_TIGHT)"
echo " walking profile : WALK=$WALK"
echo " data dir (host) : $DATA_DIR"
echo ""
# --- 1. Download ------------------------------------------------------------
# -N: качаем только если на сервере новее (idempotent monthly refresh).
echo "=== 1. Download pbf (Ural-FO ≈600MB) ==="
if command -v wget >/dev/null 2>&1; then
wget -N -O "$RAW_PBF" "$PBF_URL"
else
curl -fSL --time-cond "$RAW_PBF" -o "$RAW_PBF" "$PBF_URL"
fi
# --- 2. Clip (optional) -----------------------------------------------------
if [ "$CLIP" = "1" ]; then
echo "=== 2. Clip to Свердл bbox через osmium ($BBOX) ==="
docker run --rm -v "$DATA_DIR:/data" "$OSMIUM_IMAGE" \
osmium extract -b "$BBOX" "/data/$(basename "$RAW_PBF")" \
-o "/data/$(basename "$WORK_PBF")" --overwrite
else
echo "=== 2. No clip (CLIP=0) — используем Ural-FO целиком ==="
cp -f "$RAW_PBF" "$WORK_PBF"
fi
# --- helper: запуск osrm-backend образа на /data --------------------------
osrm() {
docker run --rm -v "$DATA_DIR:/data" "$OSRM_IMAGE" "$@"
}
# --- 3. MLD pipeline (car) --------------------------------------------------
# MLD = extract → partition → customize. НЕ osrm-contract (то CH-алгоритм,
# несовместим с --algorithm mld в compose).
#
# osrm-extract пишет <pbf-без-.osm.pbf>.osrm. Имя входного pbf специально равно
# целевому базовому имени (<region>.osm.pbf → <region>.osrm; <region>-foot.osm.pbf
# → <region>-foot.osrm), поэтому partition/customize работают по тому же базовому
# имени и переименование не требуется.
build_profile() {
local profile="$1" src_pbf="$2"
local base extracted
base="$(basename "${src_pbf%.osm.pbf}")"
extracted="/data/${base}.osrm"
echo "--- extract ($profile${base}.osrm) ---"
osrm osrm-extract -p "$profile" "/data/$(basename "$src_pbf")"
echo "--- partition (${base}.osrm) ---"
osrm osrm-partition "$extracted"
echo "--- customize (${base}.osrm) ---"
osrm osrm-customize "$extracted"
}
if [ "$CAR" = "1" ]; then
echo "=== 3. Build car profile → ${REGION}.osrm* ==="
build_profile "$CAR_PROFILE" "$WORK_PBF"
else
echo "=== 3. Skip car profile (CAR=0) — foot-only refresh, не трогаем живой ${REGION}.osrm ==="
fi
# --- 4. MLD pipeline (foot, optional) --------------------------------------
if [ "$WALK" = "1" ]; then
echo "=== 4. Build foot profile → ${REGION}-foot.osrm* ==="
# Отдельная копия pbf под пеший граф (osrm-extract overwrite'ит базу).
WALK_PBF="$DATA_DIR/${REGION}-foot.osm.pbf"
cp -f "$WORK_PBF" "$WALK_PBF"
build_profile "$FOOT_PROFILE" "$WALK_PBF"
else
echo "=== 4. Skip foot profile (WALK=0) — car-first, см. docs/osrm-routing.md ==="
fi
# --- 5. Cleanup heavy intermediates ----------------------------------------
echo "=== 5. Cleanup промежуточных .pbf (граф .osrm* уже собран) ==="
rm -f "$RAW_PBF" "$WORK_PBF" "${DATA_DIR}/${REGION}-foot.osm.pbf" 2>/dev/null || true
echo ""
echo "=== DONE ==="
echo "Артефакты в $DATA_DIR:"
ls -lh "$DATA_DIR"/*.osrm* 2>/dev/null | awk '{print " "$5"\t"$9}' || true
echo ""
echo "Дальше:"
echo " docker compose -p gendesign -f docker-compose.prod.yml up -d osrm"
echo " # verify (curl с хоста — внутри образа curl нет):"
echo " docker run --rm --network gendesign_default curlimages/curl:8 -fsS \\"
echo " 'http://osrm:5000/route/v1/driving/60.6,56.84;60.65,56.86'"