UNPKG

theater-client

Version:

TypeScript client library for Theater actor system TCP protocol

184 lines 5.54 kB
/** * Actor wrapper class - provides ergonomic interface around an actor ID */ import { TheaterConnectionError } from '../types/client.js'; import { encodeJson, decodeJson } from '../utils/serialization.js'; import { createLogger } from '../utils/logger.js'; const log = createLogger('Actor'); /** * Actor wrapper that provides a clean, object-oriented interface * around an actor ID, automatically filling in the ID for all operations */ export class Actor { id; client; // Separate connection just for event streaming eventConnection; callbacks; constructor(id, client, eventConnection, callbacks) { this.id = id; this.client = client; this.eventConnection = eventConnection || undefined; this.callbacks = callbacks || undefined; if (this.eventConnection && this.callbacks) { this.setupEventHandling(); } } // ===== ACTOR MANAGEMENT ===== /** * Get the current status of this actor */ async getStatus() { return this.client.getActorStatus(this.id); } /** * Restart this actor */ async restart() { return this.client.restartActor(this.id); } /** * Stop this actor */ async stop() { // Stop the actor via hygienic connection await this.client.stopActor(this.id); // Clean up event connection this.eventConnection?.close(); } /** * Get the manifest configuration of this actor */ async getManifest() { return this.client.getActorManifest(this.id); } /** * Get the current state of this actor */ async getState() { return this.client.getActorState(this.id); } /** * Get the event history for this actor */ async getEvents() { return this.client.getActorEvents(this.id); } /** * Get metrics for this actor */ async getMetrics() { return this.client.getActorMetrics(this.id); } // ===== MESSAGING ===== /** * Send raw bytes to this actor (fire-and-forget) */ async sendBytes(data) { return this.client.sendActorMessage(this.id, data); } /** * Send raw bytes to this actor and wait for response */ async requestBytes(data) { return this.client.requestActorMessage(this.id, data); } /** * Send a JSON object to this actor (fire-and-forget) */ async sendJson(obj) { return this.sendBytes(encodeJson(obj)); } /** * Send a JSON object to this actor and wait for JSON response */ async requestJson(obj) { const response = await this.requestBytes(encodeJson(obj)); return decodeJson(response); } /** * Send a string to this actor (fire-and-forget) */ async sendString(text) { return this.sendBytes(new TextEncoder().encode(text)); } /** * Send a string to this actor and wait for string response */ async requestString(text) { const response = await this.requestBytes(new TextEncoder().encode(text)); return new TextDecoder().decode(response); } // ===== REAL-TIME COMMUNICATION ===== /** * Open a communication channel with this actor */ async openChannel(initialMessage) { return this.client.openChannel({ Actor: this.id }, initialMessage); } /** * Subscribe to events from this actor */ async subscribe() { return this.client.subscribeToActor(this.id); } // ===== SUPERVISION ===== /** * Check if this actor has supervision (event stream connection) */ get isSupervised() { return !!this.eventConnection; } /** * Set up event handling for supervised actors */ setupEventHandling() { if (!this.eventConnection || !this.callbacks) return; log.info(`Setting up event handling for supervised actor: ${this.id}`); // Listen for events on the dedicated connection this.eventConnection.onMessage((response) => { if ('ActorEvent' in response && response.ActorEvent) { this.callbacks?.onEvent?.(response.ActorEvent.event); } else if ('ActorError' in response && response.ActorError) { this.callbacks?.onError?.(response.ActorError.error); } else if ('ActorResult' in response && response.ActorResult) { this.callbacks?.onActorResult?.(response.ActorResult); } }); this.eventConnection.onError((error) => { // Fail fast - let the application deal with it const connectionError = new TheaterConnectionError(`Event stream connection failed for actor ${this.id}: ${error.message}`, error); log.error(`Event stream connection failed for actor ${this.id}`, error); throw connectionError; }); } // ===== UTILITY METHODS ===== /** * String representation of this actor (returns the ID) */ toString() { return this.id; } /** * Check if this actor has the same ID as another actor */ equals(other) { return this.id === other.id; } /** * Get a JSON representation of this actor */ toJSON() { return { id: this.id }; } /** * Check if this actor represents the same ID as a string */ hasId(id) { return this.id === id; } } //# sourceMappingURL=Actor.js.map