Initial: Mesh-Skills, Configs, Scripts
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
# 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).
|
||||
Reference in New Issue
Block a user