Zum Inhalt springen
Deutsch

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:

WoMethode
Außerhalb eines Actorssystem.spawnTyped(behavior, name) / system.spawnTypedAnonymous(behavior)
Innerhalb eines untyped Actor.onReceivethis.context.spawnTyped(behavior, name) / this.context.spawnTypedAnonymous(behavior)
Innerhalb eines typed Behaviors.setup / Handlersctx.spawn(behavior, name)
Überall, wo Props<T> akzeptiert wirdtypedProps(behavior)

Die Methoden-Form spiegelt die Standard-OO-API — spawn vs. spawnAnonymous je nachdem, ob du einen Namen angibst.

import { ActorSystem, Behaviors, type Behavior, type ActorRef } from 'actor-ts';
type Cmd = { kind: 'inc' } | { kind: 'get'; replyTo: ActorRef<number> };
const counter = (n: number): Behavior<Cmd> => Behaviors.receive((ctx, cmd) => {
if (cmd.kind === 'inc') return counter(n + 1);
if (cmd.kind === 'get') { cmd.replyTo.tell(n); return Behaviors.same; }
return Behaviors.same;
});
const system = ActorSystem.create('demo');
const ref = system.spawnTyped(counter(0), 'counter');
// ^- ActorRef<Cmd>

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 Cmd-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<Cmd>
typedChild.tell({ kind: 'inc' });
}
}

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.

import { typedProps } from 'actor-ts';
const props = typedProps(counter(0))
.withMailboxCapacity(500)
.withDispatcher(myDispatcher);
const ref = system.spawn(props, 'counter');

Wenn du ein typisiertes Behavior willst, die API aber Props<T> nimmt (weil es ein älterer Einstiegspunkt ist oder weil du with…-Builder verketten willst), gibt typedProps(behavior) die richtigen Props<T> zurück.

Die Form:

function typedProps<T>(behavior: Behavior<T>): Props<T>;

Die zurückgegebenen Props können überall übergeben werden, wo Props<T> erwartet wird — system.spawn, context.spawn, Cluster.singletonProxy, der Entity-Props-Slot der Sharding-Region.

Innerhalb eines typisierten Handlers exponiert der Context sein eigenes spawn:

const parent: Behavior<ParentMsg> = Behaviors.setup((ctx) => {
const child = ctx.spawn(workerBehavior, 'worker');
// ^- ActorRef<WorkerMsg>
return Behaviors.receive((ctx, msg) => {
child.tell({ kind: 'do-it' });
return Behaviors.same;
});
});

Das ist der Standard-Weg für typed-Parents, typed-Children zu spawnen — durchgehend typisiert. ctx.spawn(behavior) kennt den Nachrichtentyp des Kindes aus dem Typ-Parameter des Behaviors.

Für die deterministischen Varianten (spawnTyped) ist der name-Parameter Pflicht und muss unter Geschwistern eindeutig sein. Für spawnTypedAnonymous generiert das Framework einen ('$1', '$2', …).

Der Pfad des resultierenden Actors folgt dem Standardformat:

  • system.spawnTyped(b, 'counter')actor-ts://my-app/user/counter
  • parentCtx.spawnTyped(b, 'worker')actor-ts://my-app/user/<parent>/worker
  • ctx.spawn(b, 'worker')actor-ts://my-app/user/<parent>/worker

Siehe Actor-Pfade für die Pfad-Semantik.

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:
→ ctx.spawn(b, name)
Du hast eine Funktion, die Props<T> nimmt, und willst ein Behavior verwenden:
→ typedProps(b)

Die Methoden sind absichtlich klein — jede handhabt einen häufigen Fall. typedProps ist die Notluke, wenn du ein Behavior in Props-förmige APIs stecken musst.

  • Behaviors — das DSL, das die Werte produziert, die du diesen Methoden übergibst.
  • Typed Actor — die Runtime, die die Spawn-Methoden wickeln.
  • Props — die untyped Konfiguration, die typedProps zurückgibt.
  • Actor-System — die spawn-API, die die Methoden letztlich aufrufen.