import { Actor, ActorId, ActorRef, WatchRef, LinkRef, TimerRef, TerminationReason, StashedMessage } from "./actor.js"; import { MigrationResult } from "./migration.js"; import { SupervisionOptions } from "./supervisor.js"; import { ChildSupervisor } from "./child_supervisor.js"; import { Transport } from "./transport.js"; import { Registry } from "./registry.js"; import { Cluster } from "./cluster.js"; import { PlacementStrategy } from "./placement.js"; import { HeartbeatConfig } from "./heartbeat.js"; import { HealthCheckable, ComponentHealth } from "./health.js"; import { type MailboxConfig } from "./mailbox.js"; import type { ActorDefinition } from "./types/functional.js"; import { TypedActorRef } from "./types/functional.js"; import { ProcessGroupManager } from "./process_group.js"; export interface SpawnOptions { name?: string; args?: any[]; strategy?: PlacementStrategy; role?: string; mailbox?: MailboxConfig; } export interface ShutdownOptions { /** Timeout in ms to wait for actors to terminate. Default: 5000 */ timeout?: number; /** Whether to wait for mailboxes to drain before stopping. Default: true */ drainMailboxes?: boolean; } export interface DrainOptions { /** Node ID to migrate actors to. If not provided, actors are not migrated — just drained. */ migrateTarget?: string; /** Max time in ms to wait for drain to complete. Default: 30000 */ timeout?: number; } export interface DrainResult { /** Number of actors successfully migrated */ migrated: number; /** Number of actors that drained naturally (mailbox emptied + terminated) */ drained: number; /** Actor names that failed migration */ failed: string[]; } export interface ActorInfo { /** Internal actor instance ID */ actorId: string; /** Registered name, if any */ name?: string; /** Actor class name */ className: string; /** Whether the actor implements Migratable */ migratable: boolean; /** Number of child actors */ childCount: number; } export interface SystemTimeouts { /** Timeout for remote watch/link setup requests. Default: 5000 */ remoteOperationTimeout?: number; /** Timeout for migration rollback requests. Default: 5000 */ migrationRollbackTimeout?: number; /** Default actor call timeout. Default: 5000 */ defaultCallTimeout?: number; } interface ActorMetadata { actorClass: new () => Actor; options: SpawnOptions; /** Reference to parent actor, if this actor was spawned as a child */ parent?: ActorRef; } /** * Information about a child actor spawned on a remote node. * Stored on the parent's node. */ interface RemoteChildEntry { childRef: ActorRef; childNodeId: string; parentRef: ActorRef; actorClass: new () => Actor; options: SpawnOptions; } /** * Manages the lifecycle of all actors on a single node. */ export declare class ActorSystem implements HealthCheckable { readonly id: string; private readonly actors; private readonly mailboxes; private readonly actorMetadata; private readonly actorClasses; /** Map from watchRef.id to WatchEntry */ private readonly watches; /** Map from watched actor ID to set of watchRef IDs */ private readonly watchedBy; /** Map from linkRef.id to LinkEntry */ private readonly links; /** Map from actor ID to set of linkRef IDs */ private readonly linkedWith; /** Map from local watched actor ID to set of remote watchers */ private readonly remoteWatchers; /** Map from watchRefId to RemoteWatchEntry (local actor watching remote actor) */ private readonly remoteWatches; /** Map from local actor ID to set of remote linkers (remote actors linked to this local actor) */ private readonly remoteLinkers; /** Map from linkRefId to RemoteLinkEntry (local actor linked to remote actor) */ private readonly remoteLinks; /** Map from child instance ID to RemoteChildEntry (child on remote node) */ private readonly remoteChildren; /** Map from local child instance ID to RemoteParentInfo (parent on remote node) */ private readonly remoteParents; private readonly supervisor; private readonly childSupervisor; private readonly transport; private readonly cluster; private readonly registry; private readonly placementEngine; private readonly heartbeatManager; private readonly timeouts; private readonly processGroups?; private readonly defaultMailboxConfig; private readonly log; private _isShuttingDown; private _isDraining; private _isRunning; private readonly pausedMailboxes; private readonly processingActors; private readonly mailboxScheduled; constructor(cluster: Cluster, transport: Transport, registry: Registry, supervisorOptions?: SupervisionOptions, heartbeatConfig?: Partial, defaultMailboxConfig?: MailboxConfig, timeouts?: SystemTimeouts, processGroups?: ProcessGroupManager); start(): Promise; /** * Returns true if the system is currently running. */ isRunning(): boolean; /** * Returns true if the system is in the process of shutting down. */ isShuttingDown(): boolean; /** * Returns true if the system is draining (not accepting new spawns but still processing). */ isDraining(): boolean; /** * Returns health status of the actor system. */ getHealth(): ComponentHealth; /** * Returns information about all actors in the system. */ getActors(): ActorInfo[]; /** * Gracefully shuts down the actor system. * 1. Stops accepting new spawns and messages * 2. Optionally drains all mailboxes * 3. Terminates all actors * 4. Unregisters all actor names * @param options Shutdown options */ shutdown(options?: ShutdownOptions): Promise; /** * Puts the system into drain mode: stops accepting new spawns * while allowing existing actors to continue processing. * Optionally migrates migratable actors to a target node. * @param options Drain configuration * @returns Result with migration/drain counts */ drain(options?: DrainOptions): Promise; /** * Exits drain mode, re-enabling spawn operations. */ undrain(): void; /** * Migrates all migratable actors to the target node. * Non-migratable actors and actors with children are skipped. * @param targetNodeId Node to migrate actors to * @param timeout Timeout per individual migration in ms. Default: 30000 * @returns Aggregate migration result */ migrateAll(targetNodeId: string, timeout?: number): Promise; migrate(actorName: string, targetNodeId: string, timeout?: number): Promise; private _cleanupActorForMigration; private _drainMailboxes; /** * Registers an actor class for remote spawning. * Must be called on all nodes that may receive remote spawn requests. * @param actorClass The actor class to register * @param name Optional name override (defaults to actorClass.name) */ registerActorClass(actorClass: new () => T, name?: string): void; /** * Registers multiple actor classes at once. * @param classes Array of actor classes to register */ registerActorClasses(classes: Array Actor>): void; /** * Resolves a registered actor class by name. * Returns undefined if no class is registered with that name. */ getActorClass(className: string): (new () => Actor) | undefined; /** * Spawns an actor and returns a reference to it. * Returns a typed ActorRef when spawning a typed actor class. * * @template TCast The type of cast messages the actor accepts (default: any) * @template TCall The type of call messages the actor accepts (default: any) * @template TReply The type of replies the actor returns (default: any) * @template T The actor class type * @param actorClass The actor class to spawn * @param options Spawn options (name, args, strategy) * @returns A reference to the spawned actor (typed if actor class is typed) * * @example * ```typescript * // Untyped spawn (backwards compatible) * const ref = system.spawn(MyActor); * ref.cast({ anything: "goes" }); * * // Typed spawn - type parameters inferred from actor class * const counter = system.spawn(CounterActor); * counter.cast({ type: "increment" }); // Type-checked! * const value = await counter.call({ type: "get" }); // Returns typed result * ``` */ spawn any>, TCasts extends Record void>>(actorClass: ActorDefinition, options?: SpawnOptions): TypedActorRef; spawn(actorClass: new () => T, options?: SpawnOptions): ActorRef; /** * Spawns a child actor under a parent actor's supervision. * The child will be automatically stopped when the parent is stopped. * @param parentRef Reference to the parent actor * @param actorClass The actor class to spawn * @param options Spawn options * @returns Reference to the spawned child actor */ spawnChild any>, TCasts extends Record void>>(parentRef: ActorRef, actorClass: ActorDefinition, options?: SpawnOptions): TypedActorRef; spawnChild(parentRef: ActorRef, actorClass: new () => T, options?: SpawnOptions): ActorRef; getRef(actorId: ActorId): ActorRef; /** * Gets an ActorRef by the actor's registered name. * This works for both local and remote actors - the registry is consulted * to find the actor's location. * * @param name The registered name of the actor * @returns An ActorRef that can be used to send messages, or null if not found * * @example * ```typescript * // On node1: spawn a named actor * node1.spawn(GreeterActor, { name: "greeter" }); * * // On node2: get a reference to the remote actor * const greeterRef = await node2.getActorByName("greeter"); * if (greeterRef) { * const reply = await greeterRef.call({ type: "greet", name: "World" }); * } * ``` */ getActorByName(name: string): Promise; joinGroup(group: string, ref: ActorRef): void; leaveGroup(group: string, ref: ActorRef): void; getGroup(group: string): ActorRef[]; broadcast(group: string, message: any): void; /** * Gets the actor instance by its ID (internal use). */ getActor(actorId: string): Actor | undefined; /** * Gets the metadata for an actor. */ getActorMetadata(actorId: string): ActorMetadata | undefined; /** * Gets the child supervisor for handling child actor crashes. */ getChildSupervisor(): ChildSupervisor; /** * Start watching an actor for termination. * When the watched actor terminates, the watcher will receive a DownMessage via handleInfo(). * Works for both local and remote actors. * @param watcherRef The actor that wants to watch * @param watchedRef The actor to watch * @returns A WatchRef that can be used to cancel the watch */ watch(watcherRef: ActorRef, watchedRef: ActorRef): WatchRef; /** * Sets up a watch on a remote actor. * Sends an RPC to the remote node to register the watch. */ private _setupRemoteWatch; /** * Stop watching an actor. * Works for both local and remote watches. * @param watchRef The watch reference returned by watch() */ unwatch(watchRef: WatchRef): void; /** * Removes a remote watch. */ private _unwatchRemote; /** * Create a bidirectional link between two actors. * When one actor terminates abnormally, the other will also terminate * (unless it has trapExit enabled, in which case it receives an ExitMessage). * Works for both local and remote actors. * @param actor1Ref First actor (must be local) * @param actor2Ref Second actor (can be local or remote) * @returns A LinkRef that can be used to unlink */ link(actor1Ref: ActorRef, actor2Ref: ActorRef): LinkRef; /** * Sets up a link to a remote actor. * Sends an RPC to the remote node to register the link. */ private _setupRemoteLink; /** * Remove a link between two actors. * Works for both local and remote links. * @param linkRef The link reference returned by link() */ unlink(linkRef: LinkRef): void; /** * Removes a remote link. */ private _unlinkRemote; /** * Notify all linked actors that an actor has terminated. * Called internally when an actor stops or crashes. * If the linked actor has trapExit=true, it receives an ExitMessage. * Otherwise, the linked actor is also terminated. * Works for both local and remote links. * @param actorRef The actor that terminated * @param reason The reason for termination */ notifyLinkedActors(actorRef: ActorRef, reason: TerminationReason): void; /** * Notify local actors linked to the terminated actor. */ private _notifyLocalLinkedActors; /** * Notify remote nodes that a local actor they linked to has terminated. */ private _notifyRemoteLinkers; /** * Send exit notification to a remote linker. */ private _notifyRemoteLinker; /** * Notify remote node that local actor linked to remote actor has exited. * Also cleans up local tracking. */ private _notifyRemoteLinkExit; /** * Send an EXIT message to a linked actor that is trapping exits. */ private sendExitMessage; /** * Send an exit signal to another actor. * * If the target actor is trapping exits (trapExit=true), it receives an * ExitMessage via handleInfo(). Otherwise, the target actor terminates. * * Special reasons: * - "normal": No effect (actor continues running) * - "kill": Always terminates the target, even if trapping exits * - Other strings: Treated as error reasons * * @param senderRef The actor sending the exit signal * @param targetRef The actor to send the exit signal to * @param reason The reason for the exit */ sendExit(senderRef: ActorRef, targetRef: ActorRef, reason: string): void; /** * Notify all watchers (local and remote) that an actor has terminated. * Called internally when an actor stops or crashes. * @param actorRef The actor that terminated * @param reason The reason for termination */ notifyWatchers(actorRef: ActorRef, reason: TerminationReason): void; /** * Sends a DOWN notification to a remote watcher. */ private _notifyRemoteWatcher; /** * Serializes a TerminationReason for transport (errors aren't serializable). */ private _serializeTerminationReason; /** * Send a DOWN message to a watcher. */ private sendDownMessage; notifyWatchersOfMigration(actorId: string, actorName: string | undefined, oldNodeId: string, newNodeId: string, newActorId: string): void; private _sendMovedMessageToWatcher; private _notifyRemoteWatcherOfMigration; private _handleRemoteWatcherMoved; notifyLinkedActorsOfMigration(actorId: string, actorName: string | undefined, oldNodeId: string, newNodeId: string, newActorId: string): void; private _notifyLocalLinkedActorsOfMigration; private _notifyRemoteLinkersOfMigration; private _notifyRemoteLinkExitForMigration; private _handleRemoteLinkMoved; /** * Starts a timer that sends a message to an actor after a delay. * Called internally by Actor.sendAfter() and Actor.sendInterval(). * @param actorRef The actor to send the message to * @param message The message to send * @param delayMs Delay in milliseconds * @param isInterval If true, repeats at the interval; if false, fires once * @returns A TimerRef that can be used to cancel the timer */ startActorTimer(actorRef: ActorRef, message: any, delayMs: number, isInterval: boolean): TimerRef; /** * Cancels a timer for an actor. * Called internally by Actor.cancelTimer(). * @param actorRef The actor that owns the timer * @param timerRef The timer to cancel * @returns true if the timer was cancelled, false if not found */ cancelActorTimer(actorRef: ActorRef, timerRef: TimerRef): boolean; /** * Cancels all timers for an actor. * Called internally by Actor.cancelAllTimers() and during actor termination. * @param actorRef The actor whose timers to cancel */ cancelAllActorTimers(actorRef: ActorRef): void; /** * Sets the idle timeout for an actor. * When the actor hasn't received any messages for the specified duration, * it will receive a TimeoutMessage via handleInfo(). * @param actorRef The actor to set the timeout for * @param timeoutMs Timeout in milliseconds (0 to disable) */ setActorIdleTimeout(actorRef: ActorRef, timeoutMs: number): void; /** * Schedules the idle timeout check for an actor. * Called internally after setting timeout or after processing a message. */ private _scheduleIdleTimeout; /** * Resets the idle timeout for an actor (called when a message is processed). * Called internally by the mailbox processor. */ private _resetIdleTimeout; /** * Clears the idle timeout for an actor (called during actor termination). */ private _clearIdleTimeout; /** * (For testing) Gets the instance IDs of all local actors. */ getLocalActorIds(): string[]; /** * Prepend stashed messages to the front of an actor's mailbox. * Called by Actor.unstashAll() to reprocess deferred messages. * @param actorRef The actor whose mailbox to prepend to * @param messages The stashed messages to prepend */ unstashAll(actorRef: ActorRef, messages: StashedMessage[]): void; stop(actorRef: ActorRef): Promise; /** * Restarts an actor using its stored metadata. * Called by the Supervisor when an actor crashes. * @param actorRef The actor to restart * @returns The new ActorRef, or null if restart failed */ restart(actorRef: ActorRef): Promise; /** * Stops a single actor without cascading to children. * Used internally during restarts. * @param notifyWatchers If true, notify watchers of termination (default: false for restarts) */ stopSingle(actorRef: ActorRef, notifyWatchers?: boolean): Promise; dispatchCall(actorId: ActorId, message: any, timeout: number): Promise; dispatchCast(actorId: ActorId, message: any): void; private _dispatchCastAsync; /** * Synchronously process a cast message on a local actor without going through * the mailbox/setImmediate cycle. Used by GenStage consumers to collapse the * demand → emit → process pipeline into a tight synchronous loop. * * Returns true if the message was processed synchronously. * Returns false if sync processing is not possible (actor not found, * already being processed, async handler, or paused). * * SAFETY: Only safe for local actors where the caller knows the handler * is synchronous. If the handler returns a Promise, this method returns * false and the caller must fall back to normal cast(). */ _syncLocalCast(actorId: string, message: any): boolean; /** * Synchronous fast path for local calls when the actor is idle. * Bypasses Promise + setTimeout + setImmediate (~14µs → ~1-2µs). * * SAFETY: Both processingActors and mailboxScheduled are locked to prevent * concurrent processMailbox execution. If the handler stashes the message, * we fall back to a deferred Promise that processMailbox will resolve. */ private _syncLocalCall; private _handleRpcCall; /** * Handles a remote watch registration request. * Called when another node wants to watch a local actor. */ private _handleRemoteWatchAdd; /** * Handles a remote watch removal request. * Called when another node cancels their watch on a local actor. */ private _handleRemoteWatchRemove; /** * Handles a DOWN notification from a remote node. * Called when a remote actor that we were watching has died. */ private _handleRemoteDown; /** * Deserializes a TerminationReason from transport. */ private _deserializeTerminationReason; /** * Handles a remote link registration request. * Called when another node wants to link to a local actor. */ private _handleRemoteLinkAdd; /** * Handles a remote link removal request. * Called when another node cancels their link to a local actor. */ private _handleRemoteLinkRemove; /** * Handles an exit notification from a remote node. * Called when a remote actor that we were linked to has exited. */ private _handleRemoteLinkExit; /** * Handles a remote child spawn request. * Called when another node wants to spawn a supervised child on this node. */ private _handleRemoteChildSpawn; /** * Handles a remote child restart request. * Called when parent's node requests a restart of a child on this node. */ private _handleRemoteChildRestart; /** * Handles a remote child stop request. * Called when parent's node requests stopping a child on this node. */ private _handleRemoteChildStop; /** * Handles a crash notification for a remote child. * Called when a child on a remote node has crashed and the parent is on this node. */ private _handleRemoteChildCrash; /** * Notifies the remote parent that a child has crashed. * Called from supervisor when a child with a remote parent crashes. */ notifyRemoteParentOfCrash(childInstanceId: string, reason: TerminationReason, errorMessage?: string): void; /** * Checks if a child has a remote parent. */ hasRemoteParent(childInstanceId: string): boolean; /** * Gets the remote child entry for a child instance ID. */ getRemoteChild(childInstanceId: string): RemoteChildEntry | undefined; /** * Spawns a child actor on a remote node. * @param parentRef Reference to the local parent actor * @param actorClass The actor class to spawn * @param targetNodeId The node where the child should be spawned * @param options Spawn options * @returns Reference to the spawned remote child, or null if spawn failed */ spawnChildRemote(parentRef: ActorRef, actorClass: new () => T, targetNodeId: string, options?: SpawnOptions): Promise; /** * Restarts a remote child actor. * Called by ChildSupervisor when applying supervision strategies. */ restartRemoteChild(remoteChild: RemoteChildEntry): Promise; /** * Stops a remote child actor. * Called by ChildSupervisor when applying supervision strategies. */ stopRemoteChild(childInstanceId: string): Promise; /** * Removes a remote child from tracking without sending stop request. * Used when child has exceeded max restarts. */ removeRemoteChild(childInstanceId: string, parentRef: ActorRef): void; /** * Called when a remote node has left the cluster (crashed or graceful shutdown). * Notifies all local actors that were watching actors on the dead node. * * This should be wired up to the membership layer's 'member_leave' event: * ```typescript * membership.on('member_leave', (nodeId) => system.handleNodeFailure(nodeId)); * ``` * * @param deadNodeId The ID of the node that has left the cluster */ handleNodeFailure(deadNodeId: string): void; /** * Handle node failure for remote watches. */ private _handleNodeFailureForWatches; /** * Handle node failure for remote links. */ private _handleNodeFailureForLinks; /** * Handle node failure for remote children. * When a node dies, all children hosted on that node are considered dead. */ private _handleNodeFailureForRemoteChildren; /** * Handle node failure for orphaned children. * When a parent's node dies, children on this node become orphaned. */ private _handleNodeFailureForOrphanedChildren; private _handleRpcCast; /** * Schedule mailbox processing for an actor if not already scheduled. * Uses setImmediate to avoid unbounded microtask queue growth * when actors cast to each other in tight loops. */ private scheduleProcessMailbox; /** * Maximum messages processed per setImmediate tick before yielding. * Batching dramatically reduces event-loop round-trip overhead. * Elixir's BEAM uses ~4000 reductions; 64 is conservative but safe. */ private static readonly MAILBOX_BATCH_SIZE; private processMailbox; pauseMailbox(actorId: string): boolean; resumeMailbox(actorId: string): boolean; isMailboxPaused(actorId: string): boolean; drainMailbox(actorId: string, timeout?: number): Promise; injectMessages(actorId: string, messages: StashedMessage[]): boolean; getPendingMessages(actorId: string): StashedMessage[]; private _getStateWithTimeout; private _rejectPendingCallsForMigration; private _handleMigratePrepare; private _handleMigrateExecute; private _handleMigrateRollback; } export {}; //# sourceMappingURL=actor_system.d.ts.map