/************************** * Workflow Executor * * Main orchestrator for executing durable workflows **************************/ import type { WaitNodeConfig, WorkflowDefinition, WorkflowRun, WorkflowStatus } from "../types.js"; import { type WorkflowBackend } from "../backends/types.js"; import { type StepExecutorConfig } from "./step-executor.js"; import type { BlobStorage } from "../blob/types.js"; /** * Workflow executor configuration */ export interface WorkflowExecutorConfig { /** Backend for persistence */ backend: WorkflowBackend; /** Blob storage for large data */ blobStorage?: BlobStorage; /** Step executor configuration */ stepExecutor?: StepExecutorConfig; /** Maximum concurrent parallel executions */ maxConcurrency?: number; /** Enable debug logging */ debug?: boolean; /** Lock duration in milliseconds for distributed execution (default: 30000) */ lockDuration?: number; /** Heartbeat and remote-cancellation poll interval in milliseconds (default: 10000) */ heartbeatInterval?: number; /** Enable distributed locking (default: true if backend supports it) */ enableLocking?: boolean; /** Max time result()/waitForResult waits for a terminal state (default: 300000) */ resultWaitTimeout?: number; /** Max milliseconds to wait for aborted execution to settle before detaching it (default: 1000) */ cancellationGracePeriod?: number; /** Callback when workflow starts */ onStart?: (run: WorkflowRun) => void; /** Callback when workflow completes */ onComplete?: (run: WorkflowRun) => void; /** Callback when workflow fails */ onError?: (run: WorkflowRun, error: Error) => void; /** Callback when workflow is waiting */ onWaitingPersist?: (run: WorkflowRun, nodeId: string, waitConfig?: WaitNodeConfig) => void | Promise; /** Callback when workflow is waiting */ onWaiting?: (run: WorkflowRun, nodeId: string, waitConfig?: WaitNodeConfig) => void | Promise; /** Callback when resume observes an already-live wait record. */ onLiveWaiting?: (run: WorkflowRun, nodeId: string, waitConfig?: WaitNodeConfig) => void | Promise; /** Callback after every wait in one settled DAG batch has been persisted. */ onWaitingBatchComplete?: (run: WorkflowRun) => void | Promise; /** Notify the owning wait manager after cancellation resolves a durable wait. */ onEventWaitResolved?: (runId: string, waitId: string) => void | Promise; } /** Controller for a running workflow. */ export interface WorkflowHandle { /** Run ID */ runId: string; /** Wait for background workflow execution and cleanup to finish */ settled(): Promise; /** Get current status */ status(): Promise; /** Wait for completion and get result */ result(): Promise; /** Cancel the workflow */ cancel(): Promise; } /** * Workflow Executor class * * Main entry point for executing workflows. Handles: * - Starting new workflow runs * - Resuming from checkpoints * - Coordinating DAG execution * - Managing workflow lifecycle */ export declare class WorkflowExecutor { private config; private stepExecutor; private checkpointManager; private dagExecutor; private workflows; private blobResolver?; private activeRunControllers; private cancellationUpdates; private cancelledWaitCleanupTimers; private cancelledWaitCleanupAttempts; /** Default lock duration: 30 seconds */ private static readonly DEFAULT_LOCK_DURATION; /** Heartbeat interval for long-running workflow liveness tracking */ private static readonly HEARTBEAT_INTERVAL_MS; constructor(config: WorkflowExecutorConfig); /** * Register a workflow definition */ register(workflow: WorkflowDefinition): void; /** * Get a registered workflow */ getWorkflow(id: string): WorkflowDefinition | undefined; /** * Start a new workflow run */ start(workflowId: string, input: TInput, options?: { runId?: string; }): Promise>; /** * Resume a paused/waiting workflow */ resume(runId: string, fromCheckpoint?: string, expectedWorkerId?: string): Promise; /** * Retry a failed workflow run from its failed node state. */ retry(runId: string): Promise; private finalizeTimedWaitClaimsBeforeRetry; private resumeRun; /** * Retire durable event waits created after an explicitly restored snapshot. * * Delivery and timeout claims are first returned to their durable pending * form so the same cancellation path can close them. Restoring a delivery * claim also puts its event back in the mailbox for the replayed wait rather * than consuming it on an execution the checkpoint discarded. */ private retireEventWaitsExcludedBySnapshot; /** * Execute a workflow run asynchronously * * Uses distributed locking (when backend supports it) to prevent * concurrent execution of the same workflow run. */ executeAsync(runId: string, startFromNode?: string, expectedWorkerId?: string): Promise; private executeRun; /** * Resolve workflow nodes from definition */ private resolveNodes; /** * Validate workflow nodes */ private validateNodes; /** * Execute with optional timeout * * Uses Promise.race() to properly handle timeout cleanup. * The timeout is always cleared in the finally block to prevent memory leaks. */ private executeWithTimeout; private waitForCancellationGrace; private isCurrentExecution; /** * Create a handle for a workflow run */ private createHandle; /** * Wait for workflow result */ private waitForResult; /** * Cancel a workflow run */ cancel(runId: string): Promise; private waitForCancellationUpdate; /** * Resolve the event waits of a run that was just cancelled. * * A cancelled run will never consume an event, so a wait left pending, * above all one without a deadline, would report the terminal run as * parked forever and be enumerated by every expiration sweep. Cleanup is * best-effort: the cancellation itself already committed. A bounded retry * keeps cleanup live even when the optional expiration sweep is disabled. */ private clearPendingEventWaits; private scheduleCancelledWaitCleanup; private clearCancelledWaitCleanupRetry; /** * Get workflow run status */ getStatus(runId: string): Promise; /** * List workflow runs */ listRuns(options?: { workflowId?: string; status?: WorkflowStatus | WorkflowStatus[]; limit?: number; }): Promise; } //# sourceMappingURL=workflow-executor.d.ts.map