Workstream 4: Geo & Eintreffzeit-Sortierung (Phase 3)
Selbstgehostete Geo-Dienste (OSRM + Nominatim auf Österreich-Extrakt),
Geokodierung beim Speichern und ETA-Sortierung der Suchtreffer mit
vollständigem Haversine-Luftlinie-Fallback.
- src/lib/geo/types.ts, config.ts: reine Typen + zentrale Konfiguration
(aus kanonischem env.ts; Defaults, kaputte URL wird weiterhin abgelehnt).
- haversine.ts: Luftlinie in Metern (rein). St. Pölten->Wien ~55 km verifiziert.
- nominatim.ts: kanonische, reine geocodeAddress(address) (countrycodes=at,
Timeout/Abort, status ok/not_found/error; KEIN geocodeBrigade-Zweitpfad).
- osrm.ts: etaTable via /table (sources=0, lng,lat), wirft bei Fehler.
- eintreffzeit.ts: orderByEintreffzeit (OSRM-first, kompletter Haversine-
Fallback bei Wurf, Kandidaten ohne Koordinaten ans Ende, stabile Sortierung;
OSRM-Funktion injizierbar fuer Tests).
- candidates.ts: searchHitsToGeoCandidates (Adapter, laedt brigades.lat/lng)
+ reine filterAndCapCandidates (Bounding-Box-Vorfilter 60 km, max 100).
- API: /api/geo/geocode (POST, auth-gated 401, Zod-Body, 404 bei not_found)
und /api/geo/health (GET, auth-gated; OSRM/Nominatim up/down) — beide
default-deny ueber apiAuth.
- Komponenten: standort-input.tsx (Client, Geolocation + Geocode-Fetch),
eta-badge.tsx (kennzeichnet Luftlinie-Fallback), optionale karte.tsx
via next/dynamic (ssr:false).
- Infra: docker-compose.geo.yml (internes Netz, Healthchecks), docker/osrm/
Dockerfile, scripts/prepare-osm-data.sh, infra/geo/{Makefile,README.md}.
WS4 legt KEINE Migration an (brigades-Geo-Spalten + brigades_latlng_idx
stammen aus WS2); drizzle-kit check bleibt sauber.
Offline verifiziert: tsc --noEmit (exit 0), next lint (0 Warnungen),
vitest run (54 passed / 7 skipped DB-roundtrip), next build (exit 0 mit
gesetzten env-Vars), drizzle-kit check ("Everything's fine").
Deferred (kein Postgres/Server im Sandbox): db:migrate, Live-OSRM/Nominatim,
Playwright-E2E.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
66
docker-compose.geo.yml
Normal file
66
docker-compose.geo.yml
Normal file
@@ -0,0 +1,66 @@
|
||||
# Geo-Dienste (OSRM + Nominatim) auf Österreich-OSM-Extrakt.
|
||||
# Zusammen mit der Basis verwenden:
|
||||
# docker compose -f docker-compose.yml -f docker-compose.geo.yml up -d osrm nominatim
|
||||
#
|
||||
# WICHTIG: Vor dem ersten Start das OSRM-Preprocessing laufen lassen
|
||||
# (scripts/prepare-osm-data.sh bzw. `make -C infra/geo data`) und den
|
||||
# Nominatim-Import einplanen (Stunden, mehrere GB RAM/Disk).
|
||||
|
||||
services:
|
||||
osrm:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: docker/osrm/Dockerfile
|
||||
command: osrm-routed --algorithm mld /data/austria-latest.osrm
|
||||
volumes:
|
||||
- osrm-data:/data
|
||||
networks:
|
||||
- geo-internal
|
||||
expose:
|
||||
- "5000"
|
||||
healthcheck:
|
||||
# /table mit zwei nahen NÖ-Punkten; erwartet HTTP 200.
|
||||
test:
|
||||
- CMD-SHELL
|
||||
- >-
|
||||
wget -q -O - 'http://localhost:5000/table/v1/driving/15.6229,48.2079;16.3738,48.2082?sources=0'
|
||||
| grep -q '"code":"Ok"'
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 60s
|
||||
restart: unless-stopped
|
||||
|
||||
nominatim:
|
||||
image: mediagis/nominatim:4.4
|
||||
environment:
|
||||
# Österreich-Extrakt (Geofabrik). Beim Erststart wird importiert.
|
||||
PBF_URL: https://download.geofabrik.de/europe/austria-latest.osm.pbf
|
||||
REPLICATION_URL: https://download.geofabrik.de/europe/austria-updates/
|
||||
IMPORT_STYLE: address
|
||||
NOMINATIM_PASSWORD: nominatim
|
||||
volumes:
|
||||
- nominatim-data:/var/lib/postgresql/14/main
|
||||
shm_size: 1g
|
||||
networks:
|
||||
- geo-internal
|
||||
expose:
|
||||
- "8080"
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD-SHELL
|
||||
- "wget -q -O - 'http://localhost:8080/status' | grep -q OK"
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 120s
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
osrm-data:
|
||||
nominatim-data:
|
||||
|
||||
networks:
|
||||
# Internes Netz: Geo-Dienste sind nur für die App erreichbar, nicht öffentlich.
|
||||
geo-internal:
|
||||
internal: true
|
||||
Reference in New Issue
Block a user