53 lines
2.9 KiB
Markdown
53 lines
2.9 KiB
Markdown
# #033 M20 – Live-Aktualisierung per SSE statt Polling
|
||
|
||
**Status:** offen
|
||
**Im Tracker:** [#53](https://git.wilde-server.de/florian.wilde/Laufzettel/issues/53)
|
||
**Meilenstein:** v0.2.0
|
||
**Labels:** phase-2, backend, frontend
|
||
**Geschätzt:** 6 h **Tatsächlich:** –
|
||
|
||
## Ziel
|
||
|
||
Die Abarbeitungsansicht fragt alle zehn Sekunden nach dem Zustand. Das reicht für zwei Techniker an
|
||
einem Lauf, kostet aber bei zwanzig offenen Tabs zwanzig Abfragen je zehn Sekunden — und zehn
|
||
Sekunden sind lang, wenn zwei Leute dieselbe Liste abhaken.
|
||
|
||
Die Vorleistung steht: das Polling liegt in genau einem Route Handler
|
||
(`/api/laeufe/[id]/zustand`) und lässt sich tauschen.
|
||
|
||
## Zu entscheiden
|
||
|
||
- [ ] **`LISTEN`/`NOTIFY` in Postgres als Signal** — Empfehlung. Ein Trigger auf `Schrittergebnis`
|
||
und `Lauf` schickt `NOTIFY lauf_geaendert, '<laufId>'`; der Route Handler hält eine Verbindung
|
||
und schiebt weiter. Damit funktioniert es auch mit mehreren Instanzen der Anwendung, ohne
|
||
einen zweiten Dienst. Die Alternative — der Server fragt selbst alle zwei Sekunden — wäre
|
||
dasselbe Polling, nur an anderer Stelle.
|
||
- [ ] **Polling bleibt als Rückfall**, nicht als zweite Wahrheit: derselbe Handler antwortet weiter
|
||
auf eine gewöhnliche Anfrage. Wer kein `EventSource` hat oder hinter einem Proxy sitzt, der
|
||
Ströme puffert, bekommt den alten Weg. Ein Rückfall, der nie geprüft wird, ist keiner —
|
||
deshalb ein Test je Weg.
|
||
|
||
## Aufgaben
|
||
|
||
- [ ] Trigger und `NOTIFY` in einer handgeschriebenen Migration, mit dem üblichen Vermerk (Prisma
|
||
kennt Trigger nicht und will sie löschen)
|
||
- [ ] Route Handler liefert `text/event-stream`, schickt alle 25 s einen Kommentar als Herzschlag
|
||
(sonst schließen Proxys die Verbindung) und beendet sauber bei `abort`
|
||
- [ ] **Der Handler prüft Recht und Mandant selbst** — ein offener Strom ist ein Leseweg wie jeder
|
||
andere (CLAUDE.md: Route Handler deckt die Hülle nicht ab)
|
||
- [ ] Client: `EventSource` mit Wiederverbindung; bei versteckter Lasche pausieren wie heute; bei
|
||
`error` auf Polling zurückfallen und das **einmal** melden, nicht bei jedem Versuch
|
||
- [ ] `docs/betrieb/reverse-proxy.md`: `proxy_buffering off` für nginx, `flush_interval -1` für
|
||
Caddy — ohne das kommt kein Ereignis an, und die Seite sieht aus, als sei sie hängen geblieben
|
||
- [ ] Obergrenze für gleichzeitige Ströme je Instanz, damit ein Browser mit vierzig Tabs die
|
||
Verbindungen nicht aufbraucht
|
||
|
||
## Akzeptanzkriterien
|
||
|
||
- [ ] Test: zwei Sitzungen am selben Lauf — hakt die eine ab, sieht die andere es in unter einer
|
||
Sekunde, ohne neu zu laden
|
||
- [ ] Test: ohne Recht wird der Strom abgewiesen, bevor das erste Ereignis fließt
|
||
- [ ] Test: ein Lauf eines fremden Kunden liefert keinen Strom
|
||
- [ ] Test: der Rückfall auf Polling funktioniert — gefahren mit abgeschaltetem `EventSource`
|
||
- [ ] Der Herzschlag kommt an: eine Verbindung überlebt 60 s ohne Änderung
|