The import hit a PK violation on (osm_type, osm_id, category): an OSM element that matches one category through two selectors on different keys (e.g. shelter = amenity=shelter OR tourism=wilderness_hut, both present) produced two rows for that category. Add DISTINCT ON (osm_type, osm_id, category) so classification is one row per (element, category), matching matchingCategoryIds semantics. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| backup-postgres.sh | ||
| gen-poi-selectors-sql.ts | ||
| poi-import.service | ||
| poi-import.sh | ||
| poi-import.timer | ||
| poi-selectors.sql | ||
| README.md | ||
Flagship operational scripts
Deployed to /opt/trails-cool/scripts/ by cd-infra.yml.
backup-postgres.sh
Daily pg_dump + retention sweep. Run via cron (see the header).
POI index import (poi-import.sh)
The "load where the database is" half of the poi-index
change. Pulls the artifact the BRouter host published, classifies each element
into planner.pois category rows, and swaps it in atomically.
poi-import.sh— fetch (vSwitch) → checksum → load → classify → guarded atomic rename swap.--bootstrapskips the 70% row-count guard for the first import (when the live table is legitimately empty).poi-selectors.sql— generated from@trails-cool/map-coreselectors; the classifier JOINs on it. Regenerate withnpx tsx infrastructure/scripts/gen-poi-selectors-sql.ts(CI sync test:packages/map-core/src/poi-selectors-sql.sync.test.ts).poi-import.service/.timer— monthly, offset a day after the extract.
First-time setup on the flagship
# 1. Create the empty live table from the Drizzle schema (idempotent).
# (Run from a checkout with DATABASE_URL pointed at production, or via the
# normal db:push deploy path.)
pnpm db:push
# 2. Install the timer.
cp /opt/trails-cool/scripts/poi-import.{service,timer} /etc/systemd/system/
systemctl daemon-reload
systemctl enable --now poi-import.timer
# 3. Bootstrap the first import (guard disabled — live table is empty).
BROUTER_AUTH_TOKEN=$(grep BROUTER_AUTH_TOKEN /opt/trails-cool/.env | cut -d= -f2-) \
/opt/trails-cool/scripts/poi-import.sh --bootstrap
Prometheus picks up import outcome from node_exporter's textfile collector
(poi_import_last_status, …_last_success_timestamp_seconds, …_last_rows)
when NODE_EXPORTER_TEXTFILE_DIR is set (the unit sets it). Index size and age
are additionally exposed by the planner at /metrics
(poi_index_rows{category}, poi_index_age_seconds).