import type { ActorSystem, SpawnOptions } from "./actor_system.js"; /** * Unique reference for a watch relationship. * Used to cancel a watch with unwatch(). */ export declare class WatchRef { readonly id: string; readonly watcherId: string; readonly watchedId: string; constructor(id: string, watcherId: string, watchedId: string); } /** * Unique reference for a timer. * Used to cancel a timer with cancelTimer(). */ export declare class TimerRef { readonly id: string; readonly actorId: string; readonly isInterval: boolean; constructor(id: string, actorId: string, isInterval: boolean); } /** * Unique reference for a link between two actors. * Used to unlink actors with unlink(). */ export declare class LinkRef { readonly id: string; readonly actor1Id: string; readonly actor2Id: string; constructor(id: string, actor1Id: string, actor2Id: string); } /** * Internal timer entry for tracking active timers. */ export interface TimerEntry { ref: TimerRef; handle: NodeJS.Timeout; message: any; } /** * Reason for actor termination. */ export type TerminationReason = { type: "normal"; } | { type: "error"; error: any; } | { type: "killed"; }; /** * Message sent to watchers when a watched actor terminates. */ export interface DownMessage { type: "down"; watchRef: WatchRef; actorRef: ActorRef; reason: TerminationReason; } /** * Message sent to linked actors when a linked actor terminates. * If trapExit is false, the actor will crash. If true, it receives this message via handleInfo(). */ export interface ExitMessage { type: "exit"; /** The link reference (present for link-based exits, undefined for explicit exit signals) */ linkRef?: LinkRef; /** The actor that terminated or sent the exit signal */ actorRef: ActorRef; /** The reason for the exit */ reason: TerminationReason; } /** * Message sent to an actor when it has been idle (no messages) for the configured timeout. * Delivered via handleInfo(). */ export interface TimeoutMessage { type: "timeout"; /** How long the actor was idle in milliseconds */ idleMs: number; } /** * Message sent to watchers/linked actors when an actor has been migrated to another node. * Unlike DownMessage/ExitMessage, this indicates the actor is still alive but at a new location. * Delivered via handleInfo(). * * Either watchRef or linkRef will be present, depending on whether this is a watch or link notification. */ export interface MovedMessage { type: "moved"; /** The watch reference (if this is a watch notification) */ watchRef?: WatchRef; /** The link reference (if this is a link notification) */ linkRef?: LinkRef; /** Reference to the actor that moved (points to new location) */ actorRef: ActorRef; /** The node the actor moved from */ oldNodeId: string; /** The node the actor moved to */ newNodeId: string; /** The new actor instance ID on the target node */ newActorId: string; } /** * System info messages delivered to actors via handleInfo(). */ export type InfoMessage = DownMessage | ExitMessage | TimeoutMessage | MovedMessage; /** * Strategy for supervising child actors. * - one-for-one: Only restart the crashed child * - one-for-all: Restart all children if one crashes * - rest-for-one: Restart the crashed child and all children spawned after it */ export type ChildSupervisionStrategy = "one-for-one" | "one-for-all" | "rest-for-one"; /** * Return type for init() that signals async continuation work. * @template T The type of data to pass to handleContinue() */ export interface InitContinue { continue: T; } /** * Type guard to check if init returned a continue signal. */ export declare function isInitContinue(value: any): value is InitContinue; /** * Options for child supervision. */ export interface ChildSupervisionOptions { /** Strategy for handling child crashes */ strategy: ChildSupervisionStrategy; /** Maximum restarts allowed within the period */ maxRestarts: number; /** Time period in ms for counting restarts */ periodMs: number; } /** * Default child supervision options. */ export declare const DEFAULT_CHILD_SUPERVISION: ChildSupervisionOptions; /** * Optional interface for actors that support migration between nodes. * Actors implementing this interface can have their state serialized, * transferred to another node, and restored. */ export interface Migratable { /** * Serialize actor state for transfer during migration. * The returned value must be JSON-serializable. * @returns The serialized state (can be async for complex state) */ getState(): unknown | Promise; /** * Restore actor state after migration. * Called on the target node after the actor instance is created. * @param state The serialized state from getState() */ setState(state: unknown): void | Promise; } /** * Type guard to check if an actor implements the Migratable interface. */ export declare function isMigratable(actor: Actor): actor is Actor & Migratable; /** * A unique identifier for an actor. * - `systemId`: The ID of the system/node it belongs to. * - `id`: The unique ID of this specific actor instance. * - `name`: The optional, logical name for registered actors. */ export declare class ActorId { readonly systemId: string; readonly id: string; readonly name?: string | undefined; constructor(systemId: string, id: string, name?: string | undefined); toString(): string; } /** * A reference to an actor, which can be used to send messages to it. * This is the public interface to an actor and is location-transparent. * * Optionally typed for compile-time message type checking. When type parameters * are not specified, defaults to `any` for backwards compatibility. * * @template TCast The type of cast (fire-and-forget) messages this actor accepts (default: any) * @template TCall The type of call (request-reply) messages this actor accepts (default: any) * @template TReply The type of replies this actor returns for call messages (default: any) * * @example * ```typescript * // Untyped (backwards compatible) * const ref: ActorRef = system.spawn(MyActor); * ref.cast({ anything: "goes" }); * * // Typed * const typedRef: ActorRef = system.spawn(MyTypedActor); * typedRef.cast({ type: "validMessage" }); // Type-checked! * ``` */ export declare class ActorRef { readonly id: ActorId; private readonly system; constructor(id: ActorId, system: ActorSystem); /** * Sends a 'call' message to the actor and waits for a reply. * @param message The message to send (type-checked if type parameters specified). * @param timeout The timeout in milliseconds. * @returns A promise that resolves with the reply from the actor. */ call(message: TCall, timeout?: number): Promise; /** * Sends a 'cast' message to the actor (fire-and-forget). * @param message The message to send (type-checked if type parameters specified). */ cast(message: TCast): void; } /** * A stashed message with its type information. */ export interface StashedMessage { type: "cast" | "call"; message: any; resolve?: (value: any) => void; reject?: (error: any) => void; timer?: ReturnType; } /** * Context provided to an actor, containing references to parent and children. */ export interface ActorContext { /** Reference to the parent actor, if any */ parent?: ActorRef; /** Set of child actor references */ children: Set; /** Ordered list of children (for rest-for-one strategy) */ childOrder: ActorRef[]; /** Reference to the actor system */ system: ActorSystem; /** Active watches this actor has on other actors */ watches: Map; /** Active links this actor has with other actors */ links: Map; /** Stashed messages waiting to be processed later */ stash: StashedMessage[]; /** Current message being processed (set by system during dispatch) */ currentMessage?: StashedMessage; /** Active timers owned by this actor */ timers: Map; /** Whether this actor traps exit signals from linked actors */ trapExit: boolean; /** Idle timeout in milliseconds (0 = disabled) */ idleTimeout: number; /** Timestamp of last activity (message received) */ lastActivityTime: number; /** Handle to the idle timeout timer */ idleTimeoutHandle?: NodeJS.Timeout; } /** * The base class for all actors. * Users should extend this class to create their own actors. * * Optionally typed for compile-time message type checking. When type parameters * are not specified, defaults to `any` for backwards compatibility. * * @template TCast The type of cast (fire-and-forget) messages this actor accepts (default: any) * @template TCall The type of call (request-reply) messages this actor accepts (default: any) * @template TReply The type of replies this actor returns for call messages (default: any) * * @example * ```typescript * // Untyped actor (backwards compatible) * class MyActor extends Actor { * handleCast(message: any) { ... } * handleCall(message: any) { return ...; } * } * * // Typed actor with compile-time message checking * type MyCast = { type: "doSomething" } | { type: "doOther"; value: number }; * type MyCall = { type: "query" }; * type MyReply = string; * * class MyTypedActor extends Actor { * handleCast(message: MyCast) { * switch (message.type) { * case "doSomething": ...; break; * case "doOther": console.log(message.value); break; * } * } * handleCall(message: MyCall): MyReply { * return "result"; * } * } * ``` */ export declare abstract class Actor { self: ActorRef; context: ActorContext; /** * Override this to define custom supervision options for child actors. * Defaults to one-for-one with 3 restarts in 5 seconds. */ childSupervision(): ChildSupervisionOptions; /** * Called when the actor is started. * This is a good place to initialize state. * * Can return `{ continue: data }` to trigger async post-initialization work. * The `handleContinue(data)` method will be called after init completes. * * @example * ```typescript * class MyActor extends Actor { * init() { * // Quick sync setup * this.cache = new Map(); * // Signal that expensive async work should happen * return { continue: { loadFromDb: true } }; * } * * async handleContinue(data: { loadFromDb: boolean }) { * // Expensive async initialization that doesn't block spawn * if (data.loadFromDb) { * await this.loadDataFromDatabase(); * } * } * } * ``` */ init(...args: any[]): void | InitContinue | Promise; /** * Called after init() when init returns `{ continue: data }`. * Use this for expensive async initialization that shouldn't block spawn. * * @param continueData The data passed via `{ continue: data }` from init() */ handleContinue(continueData: any): void | Promise; /** * Called when the actor is gracefully terminated. */ terminate(): void | Promise; /** * Handles 'call' messages, which require a reply. * @param message The incoming message (type-checked if type parameters specified). * @returns The reply. */ handleCall(message: TCall): TReply | Promise; /** * Handles 'cast' messages (fire-and-forget). * @param message The incoming message (type-checked if type parameters specified). */ handleCast(message: TCast): void | Promise; /** * Handles system info messages (e.g., DOWN messages from watched actors). * Override this to react to actor terminations. * @param message The info message (e.g., DownMessage). */ handleInfo(message: InfoMessage): void | Promise; /** * Start watching another actor for termination. * When the watched actor terminates, this actor will receive a DownMessage via handleInfo(). * @param actorRef The actor to watch * @returns A WatchRef that can be used to cancel the watch */ protected watch(actorRef: ActorRef): WatchRef; /** * Stop watching an actor. * @param watchRef The watch reference returned by watch() */ protected unwatch(watchRef: WatchRef): void; /** * Create a bidirectional link with another actor. * When either actor terminates abnormally, the other will also terminate * (unless trapExit is enabled, in which case it receives an ExitMessage). * * @param actorRef The actor to link with * @returns A LinkRef that can be used to unlink * * @example * ```typescript * class WorkerManager extends Actor { * init() { * const worker = this.spawn(WorkerActor); * this.link(worker); // If worker crashes, manager crashes too * } * } * ``` */ protected link(actorRef: ActorRef): LinkRef; /** * Remove a link with another actor. * @param linkRef The link reference returned by link() */ protected unlink(linkRef: LinkRef): void; /** * Enable or disable exit trapping. * When trapExit is true, exit signals from linked actors are delivered as * ExitMessage via handleInfo() instead of causing this actor to crash. * * @param trap Whether to trap exit signals * * @example * ```typescript * class Supervisor extends Actor { * init() { * this.setTrapExit(true); // Handle exits gracefully * const worker = this.spawn(WorkerActor); * this.link(worker); * } * * handleInfo(message: InfoMessage) { * if (message.type === "exit") { * console.log("Worker crashed, restarting..."); * // Handle the exit gracefully * } * } * } * ``` */ protected setTrapExit(trap: boolean): void; /** * Returns whether this actor is trapping exit signals. */ protected isTrapExit(): boolean; /** * 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 unless target is linked (normal termination) * - "kill": Always terminates the target, even if trapping exits * * @param actorRef The actor to send the exit signal to * @param reason The reason for the exit ("normal", "kill", or custom string) * * @example * ```typescript * class ManagerActor extends Actor { * handleCast(message: any) { * if (message.type === "shutdown_worker") { * // Gracefully request worker to exit * this.exit(message.workerRef, "shutdown"); * } else if (message.type === "kill_worker") { * // Force kill, ignores trapExit * this.exit(message.workerRef, "kill"); * } * } * } * ``` */ protected exit(actorRef: ActorRef, reason?: string): void; /** * Set an idle timeout for this actor. * When the actor hasn't received any messages for the specified duration, * it will receive a TimeoutMessage via handleInfo(). * * The timeout resets each time a message is processed. * Set to 0 to disable the idle timeout. * * @param timeoutMs Timeout in milliseconds (0 to disable) * * @example * ```typescript * class CacheActor extends Actor { * private cache = new Map(); * * init() { * // Expire cache entry after 30 seconds of inactivity * this.setIdleTimeout(30000); * } * * handleInfo(message: InfoMessage) { * if (message.type === "timeout") { * console.log(`Idle for ${message.idleMs}ms, clearing cache`); * this.cache.clear(); * } * } * } * ``` */ protected setIdleTimeout(timeoutMs: number): void; /** * Returns the current idle timeout in milliseconds (0 if disabled). */ protected getIdleTimeout(): number; /** * Stash the current message for later processing. * Call this when the actor is not ready to handle a message yet. * Use unstashAll() to process stashed messages when ready. */ protected stash(): void; /** * Unstash all stashed messages, prepending them to the mailbox. * Messages will be processed in the order they were originally received. */ protected unstashAll(): void; /** * Unstash just the oldest stashed message. */ protected unstash(): void; /** * Clear all stashed messages without processing them. */ protected clearStash(): void; /** * Spawns a child actor under this actor's supervision. * Returns a typed ActorRef if the child actor is typed. * * @param actorClass The actor class to spawn * @param options Spawn options (name, args, strategy) * @returns Reference to the spawned child actor (typed if actor class is typed) * * @example * ```typescript * // Spawning a typed child * const child = this.spawn(MyTypedActor); // Returns ActorRef * child.cast({ type: "validMessage" }); // Type-checked! * ``` */ protected spawn(actorClass: new () => T, options?: Omit): ActorRef; /** * Stops a child actor. * @param childRef Reference to the child actor to stop */ protected stopChild(childRef: ActorRef): Promise; /** * Gets all children of this actor. * Equivalent to Elixir's Supervisor.which_children/1. */ protected getChildren(): ActorRef[]; /** * Gets the count of children of this actor. * Equivalent to Elixir's Supervisor.count_children/1. */ protected countChildren(): number; /** * Schedules a message to be sent to this actor after a delay. * The message will be delivered via handleCast(). * * @param message The message to send * @param delayMs Delay in milliseconds * @returns A TimerRef that can be used to cancel the timer * * @example * ```typescript * class MyActor extends Actor { * init() { * // Send a tick message to self after 1 second * this.sendAfter({ type: "tick" }, 1000); * } * * handleCast(message: any) { * if (message.type === "tick") { * console.log("Timer fired!"); * } * } * } * ``` */ protected sendAfter(message: TCast, delayMs: number): TimerRef; /** * Schedules a message to be sent to this actor repeatedly at an interval. * The message will be delivered via handleCast(). * * @param message The message to send * @param intervalMs Interval in milliseconds * @returns A TimerRef that can be used to cancel the timer * * @example * ```typescript * class HeartbeatActor extends Actor { * private intervalRef?: TimerRef; * * init() { * // Send heartbeat every 5 seconds * this.intervalRef = this.sendInterval({ type: "heartbeat" }, 5000); * } * * handleCast(message: any) { * if (message.type === "heartbeat") { * console.log("Heartbeat!"); * } * } * } * ``` */ protected sendInterval(message: TCast, intervalMs: number): TimerRef; /** * Cancels a timer previously started with sendAfter() or sendInterval(). * * @param timerRef The timer reference returned by sendAfter() or sendInterval() * @returns true if the timer was cancelled, false if it wasn't found * * @example * ```typescript * class MyActor extends Actor { * private timerRef?: TimerRef; * * handleCast(message: any) { * if (message.type === "start") { * this.timerRef = this.sendAfter({ type: "timeout" }, 5000); * } else if (message.type === "cancel") { * if (this.timerRef) { * this.cancelTimer(this.timerRef); * } * } * } * } * ``` */ protected cancelTimer(timerRef: TimerRef): boolean; /** * Cancels all active timers for this actor. * Useful in terminate() or when resetting actor state. */ protected cancelAllTimers(): void; } //# sourceMappingURL=actor.d.ts.map