import { type WorkflowBackend } from "../backends/types.js"; import type { CheckpointOwnership } from "../executor/checkpoint-manager.js"; import type { ApprovalDecision, NodeState, WaitNodeConfig, WorkflowContext, WorkflowRun } from "../types.js"; import type { RunExecutionConfig } from "../worker/executors/types.js"; import type { DurableTimedWaitKind } from "../timed-wait-state.js"; export interface WorkflowRunControlExecuteResult { completed?: boolean; waiting?: boolean; waitingNode?: string; waitingConfig?: WaitNodeConfig; /** * Every node that suspended in the settled batch, when more than one did. * A batch of dependency-free waits parks them all at once, and each needs * its own durable record; announcing only the first would leave the others * parked with nothing able to wake them. `waitingNode` remains the first * entry for compatibility. */ waitingNodes?: ReadonlyArray<{ nodeId: string; waitConfig?: WaitNodeConfig; }>; /** * Reported with `error` when the graph found nothing to schedule and every * unfinished node is either this wait or blocked behind it. Whether that is a * stall or a run still parked depends on the durable approval or event-wait * record, which only this layer can read. */ stalledWaitNode?: string; /** Every running wait in a graph that found nothing left to schedule. */ stalledWaitNodes?: ReadonlyArray<{ nodeId: string; waitConfig: WaitNodeConfig; }>; context: WorkflowContext; nodeStates: Record; error?: string; } export interface WorkflowRunControlExecuteInput { backend: WorkflowBackend; run: WorkflowRun; expectedWorkerId?: string; enableLocking?: boolean; lockDuration: number; heartbeatInterval: number; waitForCancellationUpdate(runId: string): Promise; waitForCancellationGrace(operation: Promise): Promise; registerController?(runId: string, controller: AbortController): void; clearController?(runId: string, controller: AbortController): void; isCurrentExecution(runId: string, controller: AbortController): boolean; execute(input: { run: WorkflowRun; controller: AbortController; signal: AbortSignal; ownership?: CheckpointOwnership; }): Promise; onStart?(run: WorkflowRun): void | Promise; onComplete?(run: WorkflowRun): void | Promise; onError?(run: WorkflowRun, error: Error, context: WorkflowContext): void | Promise; /** Persist the durable wait record while the execution lock is still held. */ onWaitingPersist?(run: WorkflowRun, nodeId: string, waitConfig?: WaitNodeConfig): void | Promise; /** Notify observers after durable persistence and lock release. */ onWaiting?(run: WorkflowRun, nodeId: string, waitConfig?: WaitNodeConfig): void | Promise; /** Notify observers when resume observes an already-live wait record. */ onLiveWaiting?(run: WorkflowRun, nodeId: string, waitConfig?: WaitNodeConfig): void | Promise; onWaitingBatchComplete?(run: WorkflowRun): void | Promise; } export interface WorkflowRunControlExecuteOutcome { status: "completed" | "waiting" | "failed" | "cancelled" | "skipped" | "ownership-lost"; run?: WorkflowRun; } export interface WorkflowRunControlClaimInput { backend: WorkflowBackend; run: WorkflowRun; managerId: string; executionId: string; stalledThreshold: number; executionTimeout: number; env: Record; debug: boolean; createRunExecution(config: RunExecutionConfig): Promise; } export interface WorkflowRunControlClaimCreatedExecution { executionId: string; runId: string; status: "pending"; createdAt: Date; } export interface WorkflowRunControlClaimOutcome { status: "created" | "skipped-lock-held" | "skipped-status-changed" | "skipped-stalled-claim-lost" | "failed-before-claim" | "failed-after-claim"; execution?: WorkflowRunControlClaimCreatedExecution; error?: Error; } export interface WorkflowRunControlApprovalDecisionOperation { type: "approval-decision"; runId: string; approvalId: string; nodeId: string; decision: ApprovalDecision; decidedAt?: Date; maxAttempts?: number; resume?(runId: string, expectedWorkerId?: string): Promise; } export interface WorkflowRunControlEventDeliveryOperation { type: "event-delivery"; runId: string; waitId: string; nodeId: string; eventName: string; waitKind: DurableTimedWaitKind; /** Execution identity of the wait record being reconciled. */ waitInstanceId?: string; payload?: unknown; deliveredAt?: Date; maxAttempts?: number; resume?(runId: string, expectedWorkerId?: string): Promise; } export interface WorkflowRunControlHydrateEnvOperation { type: "hydrate-env"; run: WorkflowRun; env: Record; expectedWorkerId?: string; } export interface WorkflowRunControlFailExecutionOperation { type: "fail-execution"; runId: string; error: unknown; expectedWorkerId?: string; } export interface WorkflowRunControlReconcileInput { backend: WorkflowBackend; operation: WorkflowRunControlApprovalDecisionOperation | WorkflowRunControlEventDeliveryOperation | WorkflowRunControlHydrateEnvOperation | WorkflowRunControlFailExecutionOperation; } export interface WorkflowRunControlReconcileOutcome { status: "reconciled" | "unchanged" | "stale-wait" | "skipped-terminal" | "stale-owner" | "ownership-changing"; run?: WorkflowRun; } /** Consume the marker for an error raised after its run patch may have landed. */ export declare function consumeWorkflowRunControlOutcomeMayBeCommitted(error: unknown): boolean; export declare function reconcileWorkflowRunControl(input: WorkflowRunControlReconcileInput): Promise; export declare function claimWorkflowRunControl(input: WorkflowRunControlClaimInput): Promise; /** Refuse approval outcomes that a replacement-map backend cannot isolate. */ export declare function assertApprovalDecisionPatchIsolation(backend: WorkflowBackend, runId: string, approvalId: string): Promise; export declare function executeWorkflowRunControl(input: WorkflowRunControlExecuteInput): Promise; /** Remove request-only tenant authority before persisting workflow context. */ export declare function toPersistedWorkflowContext(context: WorkflowContext): WorkflowContext; //# sourceMappingURL=workflow-run-control.d.ts.map