Files
Florian-netz/infra/geo/README.md
Matthias Hochmeister e8bb75412b 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>
2026-06-09 09:37:39 +02:00

68 lines
2.5 KiB
Markdown
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.
# Geo-Dienste: OSRM (Routing) + Nominatim (Geocoding)
Selbstgehostete Geo-Dienste auf einem **Österreich-OSM-Extrakt** (Geofabrik).
Sie liefern die Eintreffzeit-Sortierung (`orderByEintreffzeit`) und die
Adress-Geokodierung (`geocodeAddress`). Beide Dienste laufen in einem
**internen** Compose-Netz und sind nur für den App-Container erreichbar.
## Komponenten
- **OSRM** (`ghcr.io/project-osrm/osrm-backend`, `--algorithm mld`) — `/table`
liefert die Fahrzeit-Matrix von EINER Quelle (`sources=0`) zu N Zielen.
Koordinaten in OSRM-Reihenfolge `lng,lat`.
- **Nominatim** (`mediagis/nominatim`) — `/search?countrycodes=at` geokodiert
österreichische Adressen.
## Erstinbetriebnahme
> Achtung: Import/Preprocessing brauchen Netzzugriff (Geofabrik, ~700 MB1 GB),
> mehrere GB RAM/Disk und Zeit (Minuten bis Stunden). Nicht in CI/Sandbox.
1. **OSRM-Daten vorbereiten** (extract → partition → customize):
```bash
make -C infra/geo data # oder: scripts/prepare-osm-data.sh
```
Erzeugt das `.osrm`-Set in `infra/geo/data` und füllt das OSRM-Volume.
2. **Dienste starten**:
```bash
make -C infra/geo up
# entspricht:
# docker compose -f docker-compose.yml -f docker-compose.geo.yml up -d osrm nominatim
```
Nominatim importiert beim ersten Start den PBF-Extrakt automatisch.
3. **Health prüfen** (intern, über die App):
```bash
make -C infra/geo health # ruft GET /api/geo/health (auth-gated)
```
## Konfiguration (kanonisch in `src/lib/env.ts`)
| Variable | Default | Zweck |
| -------------------- | ------------------------ | -------------------------------------- |
| `OSRM_URL` | `http://osrm:5000` | Basis-URL des OSRM-Dienstes |
| `NOMINATIM_URL` | `http://nominatim:8080` | Basis-URL des Nominatim-Dienstes |
| `GEO_HTTP_TIMEOUT_MS`| `4000` | Timeout/Abort für Geo-HTTP-Aufrufe |
| `HAVERSINE_KMH` | `50` | Durchschnittstempo der Luftlinie-Fallback-Schätzung |
## Fallback-Verhalten
Fällt OSRM aus, schaltet `orderByEintreffzeit` **vollständig** auf die
Haversine-Luftlinie um (`mode: "haversine"`, `isFallback: true`). Die UI
kennzeichnet diese Werte als „Luftlinie (geschätzt)" (`EtaBadge`). Wehren ohne
Koordinaten landen stets am Ende der Liste.
## Daten-Updates
Der Geofabrik-Extrakt veraltet. Aktualisierung ist ein manueller Lauf:
```bash
make -C infra/geo data && make -C infra/geo up
```