Receptionist
Der Receptionist ist ein cluster-weites Service-Registry. Jeder Node hostet einen Receptionist-Actor unter einem wohldefinierten Pfad; Registrierungen sind lokal autoritativ (du vertraust den Registrierungen deines eigenen Nodes); Peers erfahren über Gossip von fremden Registrierungen.
import { ReceptionistId, ServiceKey } from 'actor-ts';
const receptionist = system.extension(ReceptionistId).start(cluster);
// 1. Einen getypten Key für diesen Service definierenconst apiKey = ServiceKey.of<ApiMsg>('api-service');
// 2. Einen Actor unter dem Key registrierenconst api = system.spawn(Props.create(() => new ApiActor()), 'api');receptionist.register(apiKey, api);
// 3. Von jedem Node — jeden registrierten Actor findenconst refs = await receptionist.find(apiKey);console.log(`${refs.length} API-Actors im Cluster`);
// 4. Auf Änderungen subscribenreceptionist.subscribe(apiKey, (listing) => { console.log(`aktuelles Listing: ${listing.refs.length} Actors`);});Der Receptionist ist pro Cluster — jeder Node sieht dasselbe Listing (mit Gossip-Lag, siehe unten).
Service Keys
Abschnitt betitelt „Service Keys“const key = ServiceKey.of<ApiMsg>('api-service');// ^^^^^^^// getypter Payload — Consumer wissen, was sie senden müssenEin ServiceKey<T> trägt:
- Einen String-Identifier — der menschenlesbare Key-Name.
- Einen Typ-Parameter — der Nachrichtentyp, den der registrierte Actor akzeptiert.
Typsicheres Lookup: await receptionist.find(apiKey) gibt
ActorRef<ApiMsg>[] zurück.
Keys sind Werte — einmal definieren, überall importieren.
Konvention: in einem geteilten Keys.ts-Modul pro App.
Registrieren
Abschnitt betitelt „Registrieren“receptionist.register(key, actorRef);Sagt dem lokalen Receptionist: “Dieser Actor auf diesem Node liefert den Service.” Der Receptionist:
- Fügt die Ref seiner lokalen Map unter
keyhinzu. - Watcht die Ref, damit sie bei Stop automatisch deregistriert wird.
- Gossipt das Hinzufügen an Peers (nächste Gossip-Runde).
receptionist.deregister(key, actorRef);Freiwilliges Entfernen. Nützlich, wenn ein Actor einen Service “verlässt”, ohne zu stoppen (vorübergehender Statuswechsel).
Wenn der Actor einfach normal stoppt, sieht der Receptionist
Terminated und deregistriert automatisch — kein manuelles
Aufräumen nötig.
const refs = await receptionist.find(key);// ^^^^^^^^// Array jedes Actors, der unter diesem Key im Cluster registriert istDas Find:
- Liest lokale Registrierungen unter
key. - Fügt bekannte Remote-Registrierungen aus Gossip hinzu.
- Gibt die kombinierte Liste zurück.
Kehrt sofort mit der aktuellen lokalen Sicht zurück — keine synchrone Cluster-Abfrage. Bedeutet: Registrierungen auf anderen Nodes, die noch nicht gegossipt wurden, fehlen.
Innerhalb einer Gossip-Runde oder zwei (1-2 Sekunden Default) konvergiert jeder Node auf dieselbe Sicht.
Subscriben
Abschnitt betitelt „Subscriben“const unsubscribe = receptionist.subscribe(key, (listing) => { console.log(`aktualisiertes Listing für ${key.id}: ${listing.refs.length} Refs`);});
// Später: unsubscribe();Der Handler feuert, wann immer sich das Listing für key
ändert — lokal (register/deregister/stop) oder via eingehendem
Gossip.
Nutze es für dynamisches Routing: ein Actor, der auf einen Key subscribet und seine Routing-Entscheidungen anpasst, wenn Refs auftauchen / verschwinden.
Cluster-aware vs. Single-Node
Abschnitt betitelt „Cluster-aware vs. Single-Node“// In einem Cluster:const receptionist = system.extension(ReceptionistId).start(cluster);
// Ohne Cluster (Single Node):const receptionist = system.extension(ReceptionistId).start(null);Ohne Cluster funktioniert der Receptionist nur lokal — nützlich für Tests oder Single-Node-Apps, die trotzdem die ServiceKey-basierte Lookup-API wollen.
Für Cluster-Setups immer den Cluster übergeben — sonst sind Remote-Registrierungen unsichtbar.
Auto-Bereinigung beim Verlassen eines Nodes
Abschnitt betitelt „Auto-Bereinigung beim Verlassen eines Nodes“Wenn MemberRemoved für einen Peer feuert:
- Vergisst der Receptionist jede Registrierung, die dieser Node beigesteuert hat.
- Subscriber feuern mit dem aktualisierten (kleineren) Listing.
Das deckt den Fall “Node ist abgestürzt, hatte keine Chance zu deregistrieren” ab — Gossip + Cluster-Membership erledigen die Bereinigung.
Mehrere Actors pro Key
Abschnitt betitelt „Mehrere Actors pro Key“receptionist.register(apiKey, instance1);receptionist.register(apiKey, instance2);receptionist.register(apiKey, instance3); // alle drei unter demselben Key
await receptionist.find(apiKey); // → [instance1, instance2, instance3]Ein häufiges Muster: N Worker registrieren sich alle unter demselben Key. Consumer sehen den ganzen Pool und können routen, wie sie wollen — Round-Robin, Broadcast, Zufallsauswahl.
Ein Actor pro Key (Konvention)
Abschnitt betitelt „Ein Actor pro Key (Konvention)“// Ein Singleton für den Cluster registriertreceptionist.register(coordinatorKey, theCoordinator);await receptionist.find(coordinatorKey); // → [theCoordinator]Für Singleton-artige Services hat der Key eine Ref. Consumer
nehmen refs[0] (mit Fallback für den leeren Fall).
Der Receptionist erzwingt keine einzelne Instanz — das ist die Aufgabe des Singleton Managers. Aber einen Singleton unter einem Key zu registrieren gibt Consumern einen Discovery-Pfad, der Leadership-Wechsel überlebt.
Wann verwenden vs. Alternativen
Abschnitt betitelt „Wann verwenden vs. Alternativen“| Bedarf | Werkzeug |
|---|---|
| Feste Routees pro Node, jeder Node hat sie | ClusterRouter mit einem wohldefinierten Pfad |
| Dynamische Registrierungen, Lookup per Service-Name | Receptionist |
| Genau ein Actor cluster-weit | ClusterSingleton (bei Bedarf zum Lookup im Receptionist registriert) |
| Per-Key-Actors mit Auto-Spawn | ClusterSharding |
Der Receptionist ist die flexibelste Discovery — du zahlst aber Gossip-Kosten für die Dynamik. Für statisches Routing ist der Cluster Router günstiger.
Wohin als Nächstes
Abschnitt betitelt „Wohin als Nächstes“- Discovery im Überblick — das Gesamtbild.
- Cluster im Überblick — das Membership-Modell darunter.
- Cluster Router — Static-Path-Alternative für “wohldefinierten Service”-Routing.
- Singleton im Überblick — oft im Receptionist für Discovery registriert.
Die Receptionist-API-Referenz
deckt die vollständige Oberfläche ab.