Vermeidet unnoetigen Platzbedarf beim Build (31 Pakete / 192 MB werden
sonst mitgezogen).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- .env / .env.example: TZ=Europe/Berlin und NTP_SERVER=ptbtime1.ptb.de
(offizielle deutsche Zeitreferenz, hohe Verfuegbarkeit)
- app/__init__.py setzt prozessweite Zeitzone frueh via os.environ+tzset
- Leichtgewichtiger SNTP-Client (pure socket, keine deps) prueft den
Uhr-Offset beim Start im Hintergrund-Thread und warnt bei Abweichung >5s
- Dockerfile installiert tzdata und ENV TZ=Europe/Berlin als Fallback
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Mit 2 Gunicorn-Workern laeuft der In-Memory-Broadcaster in zwei
voneinander getrennten Prozessen. Landet ein Lock-Request auf
Worker A und die SSE-Verbindung des Empfaengers auf Worker B, kommt
das Event nie beim Client an - genau deshalb klappte der Live-
Refresh bei freigegebenen Ordnern nicht zuverlaessig.
Jetzt: 1 Worker mit 32 Threads. Threads teilen Memory, der
Broadcaster ist fuer alle Verbindungen derselbe. Fuer mehr Durchsatz
waere Redis Pub/Sub noetig - hier reicht aber Single-Process-Modus.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Mit 4 synchronen Workern hielt jede SSE-Verbindung dauerhaft einen
ganzen Worker besetzt. 4 offene Browser-Tabs -> alle anderen
Requests blockiert -> "Dateien laden dauert ewig".
Loesung: gthread worker-class mit 2 Workern x 16 Threads = 32
gleichzeitige Slots. Lang laufende SSE-Streams belegen nur je
einen Thread, regulaere Requests laufen unbeeintraechtigt.
nginx.example.conf: separater Location-Block fuer /api/sync/events
mit proxy_buffering off und 24h Read-Timeout, damit die Events
sofort durchkommen und die Verbindung nicht abbricht.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>