SSE (Server-Sent Events)
SseActor stellt einen Server-Sent-Events-Endpoint bereit. SSE
ist ein einseitiges Push-Protokoll vom Server zum Client über
einfaches HTTP — einfacher als WebSocket, mit browsernativem
Auto-Reconnect über die EventSource-API.
import { ActorSystem, Props, SseActor } from 'actor-ts';
const sse = system.spawn( Props.create(() => new SseActor({ host: '0.0.0.0', port: 8080, path: '/events', })), 'sse',);
// Irgendwo in der App — an alle verbundenen Clients pushen:sse.tell({ kind: 'broadcast', event: 'order-placed', data: JSON.stringify({ orderId: 'o-1' }),});
// An eine bestimmte Verbindung pushen:sse.tell({ kind: 'send', connectionId: 'conn-42', event: 'private', data: '...',});Browser-Clients konsumieren über:
const events = new EventSource('http://my-server/events');events.addEventListener('order-placed', (e) => { console.log(JSON.parse(e.data));});Settings
Abschnitt betitelt „Settings“interface SseActorSettings extends BrokerCommonSettings { host: string; port: number; path?: string; // Default '/events' keepaliveMs?: number; // Default 30_000 — sendet Kommentare, um Verbindungen am Leben zu halten}keepaliveMs steuert, wie oft der Server Kommentar-Frames
(: keepalive) sendet, damit zwischengeschaltete Proxies Idle-
Verbindungen nicht schließen. 30 Sekunden sind typisch.
Event-Format
Abschnitt betitelt „Event-Format“SSE hat ein spezifisches Wire-Format:
event: order-placeddata: {"orderId":"o-1"}id: 42
event: pingdata:Das Framework baut das für dich:
sse.tell({ kind: 'broadcast', event: 'order-placed', // Event-Name (Default 'message') data: JSON.stringify(o), // Payload id: String(Date.now()), // optional — vom Client für last-event-id-Reconnect genutzt});id ist wichtig: Wenn ein Client die Verbindung verliert und
wieder aufbaut (der Browser tut das automatisch), schickt er
Last-Event-ID — dein Actor kann ab dort wieder aufnehmen.
Last-Event-ID für resumable Streams
Abschnitt betitelt „Last-Event-ID für resumable Streams“class SseActor extends Actor<...> { override onReceive(msg) { if (msg.kind === 'connection-opened') { const lastId = msg.lastEventId; if (lastId) { // Events neuer als lastId an diesen Client wiedergeben this.replayFrom(msg.connectionId, lastId); } } }}Entscheidend für resumable Streams — ohne das verliert der Client Events während der Trennung. Kombiniert mit einem Event-Store (oder einer Journal-gestützten Projektion) kannst du At-least-once-Push-Zustellung bauen.
Wann SSE
Abschnitt betitelt „Wann SSE“Drei primäre Einsatzfälle:
- Einseitiges Push vom Server zum Browser — Live-Feeds, Benachrichtigungen, Echtzeit-Dashboards.
- Wenn WebSocket Overkill ist — einfacheres Protokoll, einfacheres Debugging (es ist ja nur HTTP).
- Freundlich zu HTTP-Infrastruktur — funktioniert durch Proxies, Load-Balancer, CDNs, die kein WS verstehen.
Für bidirektionale Kommunikation nimm WebSocket. Für Request/Response-RPC nimm einfaches HTTP.
Wohin als Nächstes
Abschnitt betitelt „Wohin als Nächstes“- I/O-Übersicht — das große Bild.
- Server-WebSocket — für Bidirektionales.
- BrokerActor-Basis — der gemeinsame Lifecycle.
- HTTP-Übersicht — für einfaches Request/Response.