Spawn Typed
Ein Behavior<T> ist ein Wert. Um ihn in die Runtime zu bringen
— um eine tatsächliche ActorRef<T> zu bekommen, der du
Nachrichten tellen kannst — verwende die Methode auf dem Host,
von dem aus du spawnst:
| Wo | Methode |
|---|---|
| Außerhalb eines Actors | system.spawnTyped(behavior, name) / system.spawnTypedAnonymous(behavior) |
Innerhalb eines untyped Actor.onReceive | this.context.spawnTyped(behavior, name) / this.context.spawnTypedAnonymous(behavior) |
Innerhalb eines typed Behaviors.setup / Handlers | context.spawn(behavior, name) |
| Überall, wo eine Actor-Klasse oder Factory akzeptiert wird | typedActor(behavior) |
Die Methoden-Form spiegelt die Standard-OO-API — spawn vs.
spawnAnonymous je nachdem, ob du einen Namen angibst.
system.spawnTyped — Top-Level
Abschnitt betitelt „system.spawnTyped — Top-Level“import { match } from 'ts-pattern';import { ActorSystem, Behaviors, type Behavior, type ActorRef } from 'actor-ts';
type IncrementCommand = { kind: 'increment' };type GetCommand = { kind: 'get'; replyTo: ActorRef<number> };type Command = IncrementCommand | GetCommand;
const counter = (n: number): Behavior<Command> => Behaviors.receive((context, command) => match(command) .with({ kind: 'increment' }, () => counter(n + 1)) .with({ kind: 'get' }, (c) => { c.replyTo.tell(n); return Behaviors.same; }) .exhaustive());
const system = ActorSystem.create('demo');const ref = system.spawnTyped(counter(0), 'counter');// ^- ActorRef<Command>Die Signaturen:
class ActorSystem { spawnTyped<T>(behavior: Behavior<T>, name: string): ActorRef<T>; spawnTypedAnonymous<T>(behavior: Behavior<T>): ActorRef<T>;}Gibt eine typisierte ActorRef<T> zurück — tell akzeptiert nur
Command-förmige Nachrichten, der Compiler erzwingt das.
ctx.spawnTyped — typed Child von einem untyped Parent
Abschnitt betitelt „ctx.spawnTyped — typed Child von einem untyped Parent“import { Actor, Behaviors } from 'actor-ts';
class UntypedParent extends Actor<...> { override preStart(): void { const typedChild = this.context.spawnTyped(counter(0), 'child'); // typedChild: ActorRef<Command> typedChild.tell({ kind: 'increment' }); }}Die Signaturen leben auf ActorContext:
interface ActorContext { spawnTyped<T>(behavior: Behavior<T>, name: string): ActorRef<T>; spawnTypedAnonymous<T>(behavior: Behavior<T>): ActorRef<T>;}Nützlich, wenn du einen bestehenden untyped-Supervisor hast, der typisierte Workers spawnen muss. Das Kind ist ein normaler Eintrag in der Children-Liste des Parents — Supervisor-Strategien gelten nach der Strategie des Parents, Death Watch funktioniert in beide Richtungen.
typedActor — Interop mit der Klassen-oder-Factory-API
Abschnitt betitelt „typedActor — Interop mit der Klassen-oder-Factory-API“import { ActorOptions, typedActor } from 'actor-ts';
const counterActor = typedActor(counter(0));const counterOptions = ActorOptions.create<Command>() .withMailboxCapacity(500) .withDispatcher(myDispatcher);
const ref = system.spawn(counterActor, 'counter', counterOptions);Wenn du ein typisiertes Behavior willst, die API aber einen Actor
nimmt — ein Einstiegspunkt, der älter ist als die typisierte
Schicht, oder ein Spawn, der eigene ActorOptions braucht —, gibt
typedActor(behavior) die ActorFactory<T> zurück, die diese
Stellen akzeptieren.
Die Form:
function typedActor<T>(behavior: Behavior<T>): ActorFactory<T>;Die zurückgegebene Factory kann überall übergeben werden, wo ein
Actor erwartet wird — system.spawn, context.spawn,
ClusterSingleton.start, der entityActor-Slot der
Sharding-Region.
Typed-Actor-zu-Typed-Child: ctx.spawn
Abschnitt betitelt „Typed-Actor-zu-Typed-Child: ctx.spawn“Innerhalb eines typisierten Handlers exponiert der Context sein
eigenes spawn:
const parent: Behavior<ParentMessage> = Behaviors.setup((context) => { const child = context.spawn(workerBehavior, 'worker'); // ^- ActorRef<WorkerMessage>
return Behaviors.receive((context, message) => { child.tell({ kind: 'do-it' }); return Behaviors.same; });});Das ist der Standard-Weg für typed-Parents, typed-Children zu
spawnen — durchgehend typisiert. context.spawn(behavior) kennt den
Nachrichtentyp des Kindes aus dem Typ-Parameter des Behaviors.
Naming + Pfade
Abschnitt betitelt „Naming + Pfade“Für die deterministischen Varianten (spawnTyped) ist der
name-Parameter Pflicht und muss unter Geschwistern eindeutig
sein. Für spawnTypedAnonymous generiert das Framework einen —
$anonymous-, einen Zähler pro Elternteil und zwölf zufällige
Hex-Zeichen, zum Beispiel '$anonymous-1-3f9c1a0d7b42'. Der Suffix
ist zufällig, der Pfad also über Läufe hinweg nicht stabil; nutze
spawnTyped, wenn du den Actor über den Pfad adressieren musst.
Der Pfad des resultierenden Actors folgt dem Standardformat:
system.spawnTyped(b, 'counter')→actor-ts://my-app/user/counterparentContext.spawnTyped(b, 'worker')→actor-ts://my-app/user/<parent>/workercontext.spawn(b, 'worker')→actor-ts://my-app/user/<parent>/worker
Siehe Actor-Pfade für die Pfad-Semantik.
Wann welches verwenden
Abschnitt betitelt „Wann welches verwenden“Aufrufer ist außerhalb eines Actors: → system.spawnTyped(b, name) // mit Namen → system.spawnTypedAnonymous(b) // wegwerf
Aufrufer ist innerhalb eines untyped Actor.onReceive: → this.context.spawnTyped(b, name) → this.context.spawnTypedAnonymous(b)
Aufrufer ist innerhalb eines typed Behaviors.setup oder Handlers: → context.spawn(b, name)
Du hast eine Funktion, die einen Actor nimmt, und willst ein Behavior verwenden: → typedActor(b)Die Methoden sind absichtlich klein — jede handhabt einen
häufigen Fall. typedActor ist die Notluke, wenn du ein Behavior
in Actor-förmige APIs stecken musst.
Wie es weitergeht
Abschnitt betitelt „Wie es weitergeht“- Behaviors — das DSL, das die Werte produziert, die du diesen Methoden übergibst.
- Typed Actor — die Runtime, die die Spawn-Methoden wickeln.
- Actors erzeugen — die untyped
Konfiguration, die
typedActorzurückgibt. - Actor-System — die
spawn-API, die die Methoden letztlich aufrufen.
