Files

53 lines
2.6 KiB
Markdown
Raw Permalink 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.
# GTFS-Verbindungs-PDF: Offline-Precompute statt Live-Routing (2026-08-19)
Bewährt für `urlaub.perfekt-ohne-en.de` (Flask + SQLite + GTFS-Zugdaten). Wenn eine
Einzel-Verbindungs-PDF eine **komplette Fahrplan-Verbindung inkl. Haltestellenliste**
zeigen soll, darf die Flask-Route den Router/RAPTOR/Dijkstra **nicht bei jedem Request**
ausführen.
## Symptom
`wkhtmltopdf` + RAPTOR auf großen Knoten (Köln, Berlin) lief 40–200 s je Aufruf →
**nginx 504 Gateway Timeout** (Gateway-Zeitlimit überschritten). Nutzer meldete
„Wenn ich die PDF anklicke … keine Haltestellenliste".
## Fix: einmaliger Offline-Backfill → JSON-Cache → schneller Cache-Read
1. **Precompute-Skript** (`gtfs_pfade_cache.py`): iteriert `SELECT DISTINCT von,nach`
aus `urlaub.db`, ruft für jedes Paar `router.path(von,nach)` (liefert Segmentliste
der Zwischenhalte), schreibt `pfade_cache.json`:
```json
{"<von>|<nach>": {"seg": [["Halt1","Halt2",...]], "dauer_h": 1.5}}
```
2. **Flask-Route** liest NUR `json.load(open('/opt/<app>/pfade_cache.json'))` mit
Key `f"{start}|{ziel}"` → Antwort < 1 s, kein Timeout. **Nie** den Router zur
Laufzeit importieren/rechnen.
3. Skript als **Hintergrund-Job** (background=true, notify_on_complete) laufen lassen,
nicht foreground.
## Teilmenge wählen, sonst quadratische Backfill-Zeit
Eindeutige `von|nach` über ALLE Ebenen waren **10 510 Paare** → ~2,4 s/Paar = **~7 h**.
Auf die **Ebenen 1+2** (`WHERE ebene IN (1,2)`, ~1 979 Paare) beschränkt = **~35 min**.
Ebene-3 (Kleinstädte) = reine Verzweigung ohne eigene PDFs → weglassen.
- Trefferquote ist KEINE 100 % (Radevormwald/Kleinstädte ohne Bahnhof im Feed).
Template ehrlich auf „Keine GTFS-Haltestellenliste verfügbar" zurückfallen, nie erfinden.
## Pfad-Rekonstruktion muss dasselbe Abfahrtsprofil wie die Dauer nutzen
Ein Precompute mit **fester Abfahrtszeit (09:00)** rekonstruierte nur ~34 % der Pfade,
weil viele Verbindungen erst zu späteren Tageszeiten existieren. Die Dauer-Profile-Suche
(06–22 Uhr) liefert mehr Treffer — die Pfad-Rekonstruktion muss **dasselbe Profil**
durchlaufen statt fest 09:00, sonst bleibt die Trefferquote konsistent niedrig.
## Verifikation
```bash
# Service nach Template-/Code-Änderung neu starten, dann:
curl -sk -o /dev/null -w "PDF: %{http_code} (%{time_total}s)\n" \
"https://<sub>/pdf/<von>/<nach>"
# Erwartung: 200 in <1 s (nicht 504), Haltestellenliste enthalten sobald Cache da.
```
Flask läuft mit `debug=False` (systemd) → **nach Änderung IMMER `systemctl restart`**
(wg. Template-/Code-Reload-Pitfall, siehe Haupt-SKILL).