Server-Sent Events
Der SSE-v2-Endpoint streamt alle Vorgangs-, Tour- und Activity-Ereignisse in Echtzeit über /api/v2/events/stream. Alle Events werden über eine einzige authentifizierte Server-Sent-Events-Verbindung mit Tenant-bewusster Filterung ausgeliefert.
Endpoint im Überblick
GET /api/v2/events/stream- Erfordert
Authorization: Bearer <JWT> - Response-Media-Type ist
text/event-stream - Optionaler Query-Parameter:
lastEventId– setzt den Stream ab einer im Cache befindlichen Event-ID fort (siehe Replay-Abschnitt) - Statuscodes:
200– Live-SSE-Stream (jedesevent:ist ein konkreterBaseEventDTO-Untertyp)401– nicht authentifiziert (ErrorDTO)429– mehr als die erlaubte Anzahl gleichzeitiger SSE-Verbindungen pro Benutzer (Standard5)500– allgemeiner Server-Fehler
Verbindung aufbauen
import { fetchEventSource } from '@microsoft/fetch-event-source';
await fetchEventSource('https://api.tourfold.com/api/v2/events/stream', {
headers: { Authorization: `Bearer ${token}` },
onmessage(event) {
console.log('event received', event.event, JSON.parse(event.data));
},
});
Wiederaufnahme mit lastEventId
Alle Events enthalten einen id:-Header, der eventId spiegelt. Speichern Sie die jeweils letzte ID clientseitig und senden Sie sie beim Reconnect mit, um verpasste Daten aus der In-Memory-History (ca. die letzten 10.000 Events pro Node) wiederzugeben. Wenn Sie die vorherige ID in lastEventId gespeichert haben:
await fetchEventSource(
`https://api.tourfold.com/api/v2/events/stream?lastEventId=${encodeURIComponent(lastEventId ?? '')}`,
{ headers: { Authorization: `Bearer ${token}` }, onmessage: handleEvent }
);
Es wird kein Fehler ausgegeben, wenn eine falsche lastEventId übergeben wird oder eine eventId so alt ist, dass sie nicht mehr im Speicher liegt.
Nur die letzten 100 Events bleiben erhalten und können wieder aufgenommen werden – als Schutz gegen kurze Netzwerkstörungen.
Diese API garantiert nicht, dass während einer Trennung keine Events verloren gehen.
Event-Format
Jede SSE-Nachricht sieht folgendermaßen aus:
event: CASE_CREATED:V1
id: 018fb1ba-15c1-7f2a-9f2d-2f2b0b8f3b1a
data: {"kind":"CASE_CREATED:V1","eventId":"018fb1ba-15c1-7f2a-9f2d-2f2b0b8f3b1a","timestamp":"2024-03-22T10:41:09.123Z","tenantId":"...","caseId":"...","caseData":{...}}
Häufige Envelope-Felder:
eventId/id:– serverseitig generierte UUIDv7 zur Reihenfolgenbildung.timestamp– Zeitpunkt, zu dem das Backend die Änderung aufgezeichnet hat (UTC).tenantId– stimmt stets mit dem Tenant des Abonnenten überein; Events anderer Tenants werden gefiltert.businessId– komfortabler String, abgeleitet auscaseId,tourId,vehicleIdusw.kind– Diskriminator und SSE-event:-Name.
Event-Arten
| Event-Art | Wann sie ausgelöst wird |
|---|---|
CASE_CREATED:V1 | Vorgang wird erstmals persistiert |
CASE_UPDATED:V1 | Beliebige Aktualisierung eines bestehenden Vorgangs |
CASE_ACTION:V1 <strong style={{color:'#c62828'}}>DEPRECATED | Veraltetes Workflow-Action-Event; verwenden Sie stattdessen andere Vorgangs-Events |
CASE_COMMENT_ADDED:V1 | Neuer Kommentar wurde an einem Vorgang erfasst |
CASE_EXTERNAL_ID_UPDATED:V1 | Externe Referenz (z. B. ERP/CRM) hat sich geändert |
TOUR_CREATED:V1 / TOUR_UPDATED:V1 / TOUR_DELETED:V1 | Tour-Lebenszyklus-Events |
VEHICLE_LOCATION_UPDATED:V1 <strong style={{color:'#c62828'}}>DEPRECATED | GPS-Position eines Fahrzeugs wurde aktualisiert |
AREA_WAITING_TIME_UPDATED:V1 | Operative Wartezeit für einen Bereich ändert sich |
HEARTBEAT:V1 | Synthetischer Heartbeat, ca. alle 30 s ausgegeben |
Verbindungs-Lebenszyklus, Limits und Fehler
- Timeouts – Alle SSE-Verbindungen werden serverseitig automatisch alle 90 Sekunden geschlossen, sodass der Client neu verbinden muss. Dieses kürzere Timeout sorgt dafür, dass tote Verbindungen (z. B. von Proxies oder Load Balancern getrennt) schnell erkannt und bereinigt werden. Der Client baut die Verbindung mit aktuellem JWT-Token automatisch wieder auf.
- Heartbeats – Werden ca. alle 30 Sekunden gesendet. Damit erkennen Sie inaktive Verbindungen ohne Anwendungsdaten. Ignorieren Sie sie, wenn Sie nur an fachlichen Events interessiert sind. Sendet das Backend keinen Heartbeat (Hinweis auf eine tote Verbindung), wird die Verbindung automatisch aufgeräumt.
- Bereinigung inaktiver Verbindungen – Der Server prüft periodisch Verbindungen, die keine Daten (einschließlich Heartbeats) erfolgreich gesendet haben, und räumt sie automatisch auf. Damit werden Ressourcenlecks durch Netzwerkfehler vermieden.
- Rate Limiting – Der Server erzwingt sowohl Durchsatz-Limits (gegen Überflutung) als auch eine pro Benutzer geltende Obergrenze gleichzeitiger Verbindungen (Standard 5). Schließen Sie ungenutzte Browser-Tabs oder EventSource-Instanzen, um unter dem Limit zu bleiben.
- Replay-Cache – Nur die jüngsten ca. 100 Events werden für
lastEventId-Aufholungen vorgehalten. Reconnects nach diesem Zeitfenster erfordern einen manuellen Re-Sync über die REST-APIs.
Fehler-Bodies folgen ErrorDTO. Siehe den Leitfaden zur Fehlerbehandlung.