@gravito/flux 3.0.1 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +298 -0
  2. package/bin/flux.js +25 -1
  3. package/dev/viewer/app.js +4 -4
  4. package/dist/bun.cjs +2 -2
  5. package/dist/bun.cjs.map +1 -1
  6. package/dist/bun.d.cts +65 -26
  7. package/dist/bun.d.ts +65 -26
  8. package/dist/bun.js +1 -1
  9. package/dist/chunk-4DXCQ6CL.js +3486 -0
  10. package/dist/chunk-4DXCQ6CL.js.map +1 -0
  11. package/dist/chunk-6AZNHVEO.cjs +316 -0
  12. package/dist/chunk-6AZNHVEO.cjs.map +1 -0
  13. package/dist/{chunk-ZAMVC732.js → chunk-NAIVO7RR.js} +64 -15
  14. package/dist/chunk-NAIVO7RR.js.map +1 -0
  15. package/dist/chunk-WAPZDXSX.cjs +3486 -0
  16. package/dist/chunk-WAPZDXSX.cjs.map +1 -0
  17. package/dist/chunk-WGDTB6OC.js +316 -0
  18. package/dist/chunk-WGDTB6OC.js.map +1 -0
  19. package/dist/{chunk-SJSPR4ZU.cjs → chunk-YXBEYVGY.cjs} +66 -17
  20. package/dist/chunk-YXBEYVGY.cjs.map +1 -0
  21. package/dist/cli/flux-visualize.cjs +108 -0
  22. package/dist/cli/flux-visualize.cjs.map +1 -0
  23. package/dist/cli/flux-visualize.d.cts +1 -0
  24. package/dist/cli/flux-visualize.d.ts +1 -0
  25. package/dist/cli/flux-visualize.js +108 -0
  26. package/dist/cli/flux-visualize.js.map +1 -0
  27. package/dist/index.cjs +97 -9
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.cts +369 -13
  30. package/dist/index.d.ts +369 -13
  31. package/dist/index.js +96 -8
  32. package/dist/index.js.map +1 -1
  33. package/dist/index.node.cjs +11 -3
  34. package/dist/index.node.cjs.map +1 -1
  35. package/dist/index.node.d.cts +1110 -247
  36. package/dist/index.node.d.ts +1110 -247
  37. package/dist/index.node.js +10 -2
  38. package/dist/types-CRz5XdLd.d.cts +433 -0
  39. package/dist/types-CRz5XdLd.d.ts +433 -0
  40. package/package.json +17 -6
  41. package/dist/chunk-3JGQYHUN.js +0 -1006
  42. package/dist/chunk-3JGQYHUN.js.map +0 -1
  43. package/dist/chunk-5OXXH442.cjs +0 -1006
  44. package/dist/chunk-5OXXH442.cjs.map +0 -1
  45. package/dist/chunk-SJSPR4ZU.cjs.map +0 -1
  46. package/dist/chunk-ZAMVC732.js.map +0 -1
  47. package/dist/types-CZwYGpou.d.cts +0 -353
  48. package/dist/types-CZwYGpou.d.ts +0 -353
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors.ts","../src/builder/WorkflowBuilder.ts","../src/engine/BatchExecutor.ts","../src/core/ContextManager.ts","../src/core/StateMachine.ts","../src/orbit/CronTrigger.ts","../src/storage/MemoryStorage.ts","../src/core/executionUpdater.ts","../src/core/StepExecutor.ts","../src/core/DataOptimizer.ts","../src/engine/CompensationRetryPolicy.ts","../src/engine/stateUpdater.ts","../src/engine/FluxEngineHelpers.ts","../src/core/IdempotencyGuard.ts","../src/engine/RecoveryManager.ts","../src/engine/RollbackManager.ts","../src/engine/TraceEmitter.ts","../src/engine/ParallelExecutor.ts","../src/engine/WorkflowExecutor.ts","../src/engine/FluxEngine.ts","../src/storage/PostgreSQLStorage.ts","../src/trace/JsonFileTraceSink.ts","../src/core/LockProvider.ts","../src/core/RedisLockProvider.ts","../src/logger/FluxLogger.ts","../src/orbit/OrbitFlux.ts"],"sourcesContent":["/**\n * Standard error codes for FluxEngine operations.\n *\n * Used to programmatically identify the cause of a `FluxError`.\n */\nexport enum FluxErrorCode {\n /** The requested workflow instance could not be found in storage. */\n WORKFLOW_NOT_FOUND = 'WORKFLOW_NOT_FOUND',\n /** The input data provided to the workflow failed validation. */\n WORKFLOW_INVALID_INPUT = 'WORKFLOW_INVALID_INPUT',\n /** The workflow definition has changed since the instance was created, making it unsafe to resume. */\n WORKFLOW_DEFINITION_CHANGED = 'WORKFLOW_DEFINITION_CHANGED',\n /** The workflow name in the definition does not match the stored state. */\n WORKFLOW_NAME_MISMATCH = 'WORKFLOW_NAME_MISMATCH',\n /** An attempt was made to transition the workflow to an incompatible state. */\n INVALID_STATE_TRANSITION = 'INVALID_STATE_TRANSITION',\n /** An operation requiring a suspended state was attempted on a workflow that is not suspended. */\n WORKFLOW_NOT_SUSPENDED = 'WORKFLOW_NOT_SUSPENDED',\n /** The requested step index is out of bounds for the current workflow definition. */\n INVALID_STEP_INDEX = 'INVALID_STEP_INDEX',\n /** A workflow step exceeded its configured execution time limit. */\n STEP_TIMEOUT = 'STEP_TIMEOUT',\n /** The requested step could not be found in the workflow definition. */\n STEP_NOT_FOUND = 'STEP_NOT_FOUND',\n /** Multiple concurrent attempts to modify the same workflow instance were detected. */\n CONCURRENT_MODIFICATION = 'CONCURRENT_MODIFICATION',\n /** A workflow definition must contain at least one step to be executable. */\n EMPTY_WORKFLOW = 'EMPTY_WORKFLOW',\n /** No recovery action is registered for a step that requires recovery. */\n NO_RECOVERY_ACTION = 'NO_RECOVERY_ACTION',\n /** An invalid JSON Pointer was provided for state manipulation. */\n INVALID_JSON_POINTER = 'INVALID_JSON_POINTER',\n /** Cannot access a property on a non-object value in the state tree. */\n INVALID_PATH_TRAVERSAL = 'INVALID_PATH_TRAVERSAL',\n /** Cannot replace the root object of the workflow state. */\n CANNOT_REPLACE_ROOT = 'CANNOT_REPLACE_ROOT',\n /** Cannot remove the root object of the workflow state. */\n CANNOT_REMOVE_ROOT = 'CANNOT_REMOVE_ROOT',\n}\n\n/**\n * Base class for all errors thrown by the FluxEngine.\n *\n * Includes a machine-readable error code and optional context for debugging.\n *\n * @example\n * ```typescript\n * try {\n * await engine.execute(flow, input);\n * } catch (err) {\n * if (err instanceof FluxError && err.code === FluxErrorCode.STEP_TIMEOUT) {\n * console.error('Workflow timed out');\n * }\n * }\n * ```\n */\nexport class FluxError extends Error {\n /**\n * Creates a new FluxError.\n *\n * @param message - Human-readable error description.\n * @param code - Machine-readable error code.\n * @param context - Additional metadata related to the error.\n */\n constructor(\n message: string,\n public readonly code: FluxErrorCode,\n public readonly context?: Record<string, unknown>\n ) {\n super(message)\n this.name = 'FluxError'\n }\n}\n\n/**\n * Creates a FluxError for a missing workflow instance.\n *\n * @param id - The unique identifier of the missing workflow.\n * @returns A FluxError with the WORKFLOW_NOT_FOUND code.\n *\n * @example\n * ```typescript\n * throw workflowNotFound('wf-123');\n * ```\n */\nexport function workflowNotFound(id: string): FluxError {\n return new FluxError(`Workflow not found: ${id}`, FluxErrorCode.WORKFLOW_NOT_FOUND, {\n workflowId: id,\n })\n}\n\n/**\n * Creates a FluxError for an illegal state transition.\n *\n * @param from - The current state of the workflow.\n * @param to - The attempted target state.\n * @returns A FluxError with the INVALID_STATE_TRANSITION code.\n *\n * @example\n * ```typescript\n * throw invalidStateTransition('completed', 'running');\n * ```\n */\nexport function invalidStateTransition(from: string, to: string): FluxError {\n return new FluxError(\n `Invalid state transition: ${from} → ${to}`,\n FluxErrorCode.INVALID_STATE_TRANSITION,\n { from, to }\n )\n}\n\n/**\n * Creates a FluxError for invalid workflow input.\n *\n * @param workflowName - The name of the workflow definition.\n * @returns A FluxError with the WORKFLOW_INVALID_INPUT code.\n *\n * @example\n * ```typescript\n * throw invalidInput('order-process');\n * ```\n */\nexport function invalidInput(workflowName: string): FluxError {\n return new FluxError(\n `Invalid input for workflow \"${workflowName}\"`,\n FluxErrorCode.WORKFLOW_INVALID_INPUT,\n { workflowName }\n )\n}\n\n/**\n * Creates a FluxError for a workflow name mismatch.\n *\n * @param expected - The name expected by the definition.\n * @param received - The name found in the stored state.\n * @returns A FluxError with the WORKFLOW_NAME_MISMATCH code.\n */\nexport function workflowNameMismatch(expected: string, received: string): FluxError {\n return new FluxError(\n `Workflow name mismatch: ${received} !== ${expected}`,\n FluxErrorCode.WORKFLOW_NAME_MISMATCH,\n { expected, received }\n )\n}\n\n/**\n * Creates a FluxError when a workflow definition has changed incompatibly.\n *\n * @returns A FluxError with the WORKFLOW_DEFINITION_CHANGED code.\n */\nexport function workflowDefinitionChanged(): FluxError {\n return new FluxError(\n 'Workflow definition changed; operation is not safe',\n FluxErrorCode.WORKFLOW_DEFINITION_CHANGED\n )\n}\n\n/**\n * Creates a FluxError for a workflow version mismatch.\n *\n * @param stored - The version stored in the workflow instance.\n * @param current - The version in the current workflow definition.\n * @returns A FluxError with the WORKFLOW_DEFINITION_CHANGED code.\n *\n * @example\n * ```typescript\n * throw workflowVersionMismatch('1.0.0', '2.0.0');\n * ```\n */\nexport function workflowVersionMismatch(stored: string, current: string): FluxError {\n return new FluxError(\n `Workflow version mismatch: stored version \"${stored}\" does not match current \"${current}\"`,\n FluxErrorCode.WORKFLOW_DEFINITION_CHANGED,\n { storedVersion: stored, currentVersion: current }\n )\n}\n\n/**\n * Creates a FluxError when an operation requires a suspended workflow.\n *\n * @param status - The current status of the workflow.\n * @returns A FluxError with the WORKFLOW_NOT_SUSPENDED code.\n */\nexport function workflowNotSuspended(status: string): FluxError {\n return new FluxError(\n `Workflow is not suspended (status: ${status})`,\n FluxErrorCode.WORKFLOW_NOT_SUSPENDED,\n { status }\n )\n}\n\n/**\n * Creates a FluxError when a specific step cannot be found.\n *\n * @param step - The name or index of the missing step.\n * @returns A FluxError with the STEP_NOT_FOUND code.\n */\nexport function stepNotFound(step: string | number): FluxError {\n return new FluxError(`Step not found: ${step}`, FluxErrorCode.STEP_NOT_FOUND, { step })\n}\n\n/**\n * Creates a FluxError for an out-of-bounds step index.\n *\n * @param index - The invalid step index.\n * @returns A FluxError with the INVALID_STEP_INDEX code.\n */\nexport function invalidStepIndex(index: number): FluxError {\n return new FluxError(`Invalid step index: ${index}`, FluxErrorCode.INVALID_STEP_INDEX, { index })\n}\n\n/**\n * Creates a FluxError for an empty workflow (no steps defined).\n *\n * @param workflowName - The name of the workflow.\n * @returns A FluxError with the EMPTY_WORKFLOW code.\n */\nexport function emptyWorkflow(workflowName: string): FluxError {\n return new FluxError(`Workflow \"${workflowName}\" has no steps`, FluxErrorCode.EMPTY_WORKFLOW, {\n workflowName,\n })\n}\n\n/**\n * Creates a FluxError when no recovery action is registered for a step.\n *\n * @param stepName - The name of the step requiring recovery.\n * @returns A FluxError with the NO_RECOVERY_ACTION code.\n */\nexport function noRecoveryAction(stepName: string): FluxError {\n return new FluxError(\n `No recovery action registered for step: ${stepName}`,\n FluxErrorCode.NO_RECOVERY_ACTION,\n { stepName }\n )\n}\n\n/**\n * Creates a FluxError for invalid JSON Pointer syntax.\n *\n * @param path - The invalid JSON Pointer.\n * @returns A FluxError with the INVALID_JSON_POINTER code.\n */\nexport function invalidJsonPointer(path: string): FluxError {\n return new FluxError(`Invalid JSON Pointer: ${path}`, FluxErrorCode.INVALID_JSON_POINTER, {\n path,\n })\n}\n\n/**\n * Creates a FluxError when attempting to traverse a non-object value.\n *\n * @param segment - The property being accessed.\n * @param current - The current value type.\n * @returns A FluxError with the INVALID_PATH_TRAVERSAL code.\n */\nexport function invalidPathTraversal(segment: string, current: unknown): FluxError {\n return new FluxError(\n `Cannot access property '${segment}' on ${current}`,\n FluxErrorCode.INVALID_PATH_TRAVERSAL,\n { segment, currentType: typeof current }\n )\n}\n\n/**\n * Creates a FluxError when attempting to replace the root object.\n *\n * @returns A FluxError with the CANNOT_REPLACE_ROOT code.\n */\nexport function cannotReplaceRoot(): FluxError {\n return new FluxError('Cannot replace root object', FluxErrorCode.CANNOT_REPLACE_ROOT)\n}\n\n/**\n * Creates a FluxError when attempting to remove the root object.\n *\n * @returns A FluxError with the CANNOT_REMOVE_ROOT code.\n */\nexport function cannotRemoveRoot(): FluxError {\n return new FluxError('Cannot remove root object', FluxErrorCode.CANNOT_REMOVE_ROOT)\n}\n","import * as Errors from '../errors'\nimport type {\n StepDefinition,\n StepDescriptor,\n StepHandlerResult,\n WorkflowContext,\n WorkflowDefinition,\n WorkflowDescriptor,\n} from '../types'\n\n/**\n * Configuration options for a workflow step.\n * Allows fine-tuning of execution behavior such as retries, timeouts, and conditional logic.\n */\nexport interface StepOptions<TInput = unknown, TData = Record<string, any>> {\n /** Maximum number of retry attempts on failure. */\n retries?: number\n /** Execution time limit in milliseconds. */\n timeout?: number\n /** Predicate to determine if the step should execute based on current context. */\n when?: (ctx: WorkflowContext<TInput, TData>) => boolean\n /** Logic to execute for rolling back changes if a subsequent step fails. */\n compensate?: (ctx: WorkflowContext<TInput, TData>) => Promise<void> | void\n}\n\nexport interface ParallelStepConfig<TInput = unknown, TData = Record<string, any>> {\n name: string\n handler: (ctx: WorkflowContext<TInput, TData>) => StepHandlerResult\n options?: StepOptions<TInput, TData>\n /** Shorthand for options.compensate - rollback logic if subsequent steps fail */\n compensate?: (ctx: WorkflowContext<TInput, TData>) => Promise<void> | void\n /** Shorthand for options.retries */\n retries?: number\n /** Shorthand for options.timeout */\n timeout?: number\n /** Shorthand for options.when */\n when?: (ctx: WorkflowContext<TInput, TData>) => boolean\n}\n\n/**\n * A fluent API for defining workflows in a type-safe manner.\n * The builder pattern ensures that workflows are constructed with all necessary components\n * before being passed to the execution engine.\n *\n * @example\n * ```typescript\n * const flow = new WorkflowBuilder('order-process')\n * .input<{ id: string }>()\n * .step('validate', (ctx) => { ... })\n * .build();\n * ```\n */\nexport class WorkflowBuilder<TInput = unknown, TData = Record<string, any>> {\n private _name: string\n private _version?: string\n private _steps: StepDefinition[] = []\n private _validateInput?: (input: unknown) => input is TInput\n private _parallelGroupCounter = 0\n\n /**\n * Initializes a new workflow builder with a unique name.\n * @param name - The identifier for this workflow definition.\n */\n constructor(name: string) {\n this._name = name\n }\n\n /**\n * Defines the expected input type for the workflow.\n * This is a type-only operation that enables compile-time safety for subsequent steps.\n * @returns A builder instance with the specified input type.\n */\n input<T>(): WorkflowBuilder<T, TData> {\n return this as unknown as WorkflowBuilder<T, TData>\n }\n\n /**\n * Defines the structure of the shared data object used across steps.\n * @returns A builder instance with the specified data type.\n */\n data<T extends Record<string, any>>(): WorkflowBuilder<TInput, T> {\n return this as unknown as WorkflowBuilder<TInput, T>\n }\n\n /**\n * Sets the semantic version of this workflow definition.\n * @param v - A semantic version string (e.g., \"1.0.0\", \"2.1.0\").\n * @returns The builder instance for chaining.\n */\n version(v: string): this {\n this._version = v\n return this\n }\n\n /**\n * Attaches a runtime validator for the workflow input.\n * @param validator - A type guard function to verify input integrity.\n * @returns The builder instance for chaining.\n */\n validate(validator: (input: unknown) => input is TInput): this {\n this._validateInput = validator\n return this\n }\n\n /**\n * Adds a standard processing step to the workflow.\n * Standard steps are subject to compensation if the workflow fails later.\n *\n * @param name - Unique name for the step.\n * @param handler - The business logic to execute.\n * @param options - Optional execution configuration.\n * @returns The builder instance for chaining.\n */\n step(\n name: string,\n handler: (ctx: WorkflowContext<TInput, TData>) => StepHandlerResult,\n options?: StepOptions<TInput, TData>\n ): this {\n this._steps.push({\n name,\n handler: handler as (ctx: WorkflowContext) => StepHandlerResult,\n retries: options?.retries,\n timeout: options?.timeout,\n when: options?.when as ((ctx: WorkflowContext) => boolean) | undefined,\n compensate: options?.compensate as\n | ((ctx: WorkflowContext) => Promise<void> | void)\n | undefined,\n commit: false,\n })\n return this\n }\n\n /**\n * Adds multiple steps that execute in parallel.\n * All steps in a parallel group will run concurrently and must all succeed before proceeding.\n *\n * @param steps - Array of step configurations to execute in parallel.\n * @returns The builder instance for chaining.\n *\n * @example\n * ```typescript\n * workflow.stepParallel([\n * { name: 'fetch-user', handler: async (ctx) => { ctx.data.user = await getUser() } },\n * { name: 'fetch-orders', handler: async (ctx) => { ctx.data.orders = await getOrders() } },\n * { name: 'fetch-profile', handler: async (ctx) => { ctx.data.profile = await getProfile() } }\n * ])\n * ```\n */\n stepParallel(steps: ParallelStepConfig<TInput, TData>[]): this {\n if (steps.length === 0) {\n return this\n }\n\n const groupId = `parallel-${this._parallelGroupCounter++}`\n\n for (const stepConfig of steps) {\n this._steps.push({\n name: stepConfig.name,\n handler: stepConfig.handler as (ctx: WorkflowContext) => StepHandlerResult,\n retries: stepConfig.retries ?? stepConfig.options?.retries,\n timeout: stepConfig.timeout ?? stepConfig.options?.timeout,\n when: (stepConfig.when ?? stepConfig.options?.when) as\n | ((ctx: WorkflowContext) => boolean)\n | undefined,\n compensate: (stepConfig.compensate ?? stepConfig.options?.compensate) as\n | ((ctx: WorkflowContext) => Promise<void> | void)\n | undefined,\n commit: false,\n parallelGroup: groupId,\n })\n }\n\n return this\n }\n\n /**\n * Adds a \"commit\" step that represents a permanent side-effect.\n * Commit steps are intended for operations that should not be rolled back\n * or re-executed during certain replay scenarios.\n *\n * @param name - Unique name for the step.\n * @param handler - The side-effect logic to execute.\n * @param options - Optional execution configuration (compensation is not allowed).\n * @returns The builder instance for chaining.\n */\n commit(\n name: string,\n handler: (ctx: WorkflowContext<TInput, TData>) => Promise<void> | void,\n options?: Omit<StepOptions<TInput, TData>, 'compensate'>\n ): this {\n this._steps.push({\n name,\n handler: handler as (ctx: WorkflowContext) => StepHandlerResult,\n retries: options?.retries,\n timeout: options?.timeout,\n when: options?.when as ((ctx: WorkflowContext) => boolean) | undefined,\n commit: true,\n })\n return this\n }\n\n /**\n * Finalizes the workflow definition.\n * @returns A complete workflow blueprint ready for execution.\n * @throws Error if the workflow has no steps defined.\n */\n build(): WorkflowDefinition<TInput, TData> {\n if (this._steps.length === 0) {\n throw Errors.emptyWorkflow(this._name)\n }\n\n return {\n name: this._name,\n version: this._version,\n steps: [...this._steps] as StepDefinition<TInput, TData>[],\n validateInput: this._validateInput,\n }\n }\n\n /**\n * Generates a structural description of the workflow for introspection.\n * @returns A descriptor containing step metadata.\n */\n describe(): WorkflowDescriptor {\n const steps: StepDescriptor[] = this._steps.map((step) => ({\n name: step.name,\n commit: Boolean(step.commit),\n retries: step.retries,\n timeout: step.timeout,\n hasCondition: Boolean(step.when),\n }))\n\n return {\n name: this._name,\n version: this._version,\n steps,\n }\n }\n\n /** The name of the workflow being built. */\n get name(): string {\n return this._name\n }\n\n /** The number of steps currently defined in the workflow. */\n get stepCount(): number {\n return this._steps.length\n }\n}\n\n/**\n * Factory function to initiate a new workflow definition.\n *\n * @param name - The unique name for the workflow.\n * @returns A new WorkflowBuilder instance.\n *\n * @example\n * ```typescript\n * const flow = createWorkflow('my-flow')\n * .step('hello', () => console.log('world'))\n * .build();\n * ```\n */\nexport function createWorkflow(name: string): WorkflowBuilder {\n return new WorkflowBuilder(name)\n}\n","import type { WorkflowBuilder } from '../builder/WorkflowBuilder'\nimport type { FluxResult, WorkflowDefinition } from '../types'\nimport type { FluxEngine } from './FluxEngine'\n\n/**\n * Options for batch execution of workflows.\n */\nexport interface BatchExecutionOptions {\n /** Maximum concurrent workflow executions. @default 10 */\n concurrency?: number\n /** Whether to continue on individual workflow failures. @default true */\n continueOnError?: boolean\n /** Callback for progress updates */\n onProgress?: (completed: number, total: number, result: BatchItemResult) => void\n /** Abort signal for cancellation */\n signal?: AbortSignal\n}\n\n/**\n * Result of a single item in a batch execution.\n */\nexport interface BatchItemResult<TData = any> {\n /** Index in the batch */\n index: number\n /** Input provided to this workflow */\n input: unknown\n /** Execution result (null if failed before execution) */\n result: FluxResult<TData> | null\n /** Error if failed */\n error?: Error\n /** Whether this item succeeded */\n success: boolean\n}\n\n/**\n * Result of a batch execution containing all individual results.\n */\nexport interface BatchResult<TData = any> {\n /** Total items in batch */\n total: number\n /** Number of successful executions */\n succeeded: number\n /** Number of failed executions */\n failed: number\n /** Results for each item in order */\n results: BatchItemResult<TData>[]\n /** Total execution time in milliseconds */\n duration: number\n}\n\n/**\n * Semaphore for controlling concurrent execution.\n * Limits the number of concurrent operations to a specified maximum.\n */\nclass Semaphore {\n private current = 0\n private queue: Array<() => void> = []\n\n constructor(private max: number) {}\n\n async acquire(): Promise<void> {\n if (this.current < this.max) {\n this.current++\n return\n }\n await new Promise<void>((resolve) => {\n this.queue.push(() => {\n this.current++\n resolve()\n })\n })\n }\n\n release(): void {\n this.current--\n const next = this.queue.shift()\n if (next) {\n next()\n }\n }\n}\n\n/**\n * Executes workflows in batches with controlled concurrency.\n *\n * BatchExecutor provides efficient parallel execution of multiple workflow instances\n * while respecting concurrency limits, handling errors gracefully, and supporting\n * cancellation via AbortSignal.\n *\n * @example\n * ```typescript\n * const engine = new FluxEngine()\n * const executor = new BatchExecutor(engine)\n *\n * const results = await executor.execute(\n * myWorkflow,\n * [{ id: 1 }, { id: 2 }, { id: 3 }],\n * {\n * concurrency: 5,\n * onProgress: (completed, total) => console.log(`${completed}/${total}`)\n * }\n * )\n *\n * console.log(`Succeeded: ${results.succeeded}, Failed: ${results.failed}`)\n * ```\n */\nexport class BatchExecutor {\n constructor(private engine: FluxEngine) {}\n\n /**\n * Execute a workflow for multiple inputs with controlled concurrency.\n *\n * @param workflow - The workflow definition or builder to execute.\n * @param inputs - Array of inputs, one per workflow execution.\n * @param options - Execution options (concurrency, error handling, etc.).\n * @returns Batch result containing all individual execution results.\n */\n async execute<TInput, TData extends Record<string, any> = Record<string, any>>(\n workflow: WorkflowBuilder<TInput, TData> | WorkflowDefinition<TInput, TData>,\n inputs: TInput[],\n options?: BatchExecutionOptions\n ): Promise<BatchResult<TData>> {\n const startTime = Date.now()\n const concurrency = options?.concurrency ?? 10\n const continueOnError = options?.continueOnError ?? true\n const semaphore = new Semaphore(concurrency)\n\n const results: BatchItemResult<TData>[] = new Array(inputs.length)\n let succeeded = 0\n let failed = 0\n let completed = 0\n let shouldStop = false\n\n const executeOne = async (input: TInput, index: number): Promise<void> => {\n // Early exit check without acquiring semaphore\n if (options?.signal?.aborted || shouldStop) {\n results[index] = {\n index,\n input,\n result: null,\n error: new Error('Execution aborted'),\n success: false,\n }\n failed++\n completed++\n options?.onProgress?.(completed, inputs.length, results[index]!)\n return\n }\n\n // Acquire semaphore for actual execution\n await semaphore.acquire()\n\n try {\n // Check again after acquiring\n if (options?.signal?.aborted || shouldStop) {\n results[index] = {\n index,\n input,\n result: null,\n error: new Error('Execution aborted'),\n success: false,\n }\n failed++\n } else {\n const result = await this.engine.execute(\n workflow as\n | WorkflowBuilder<TInput, Record<string, any>>\n | WorkflowDefinition<TInput, Record<string, any>>,\n input\n )\n const success = result.status === 'completed'\n\n results[index] = {\n index,\n input,\n result: result as FluxResult<TData>,\n error: result.error,\n success,\n }\n\n if (success) {\n succeeded++\n } else {\n failed++\n if (!continueOnError) {\n shouldStop = true\n }\n }\n }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error))\n results[index] = {\n index,\n input,\n result: null,\n error: err,\n success: false,\n }\n failed++\n if (!continueOnError) {\n shouldStop = true\n }\n } finally {\n semaphore.release()\n completed++\n options?.onProgress?.(completed, inputs.length, results[index]!)\n }\n }\n\n await Promise.all(inputs.map((input, index) => executeOne(input, index)))\n\n return {\n total: inputs.length,\n succeeded,\n failed,\n results,\n duration: Date.now() - startTime,\n }\n }\n\n /**\n * Execute different workflows in a single batch.\n *\n * Unlike `execute()`, this method allows each item in the batch to use a different\n * workflow definition, enabling heterogeneous batch processing.\n *\n * @param items - Array of workflow/input pairs to execute.\n * @param options - Execution options (concurrency, error handling, etc.).\n * @returns Batch result containing all individual execution results.\n */\n async executeMany<TData = any>(\n items: Array<{ workflow: WorkflowDefinition<any, any>; input: any }>,\n options?: BatchExecutionOptions\n ): Promise<BatchResult<TData>> {\n const startTime = Date.now()\n const concurrency = options?.concurrency ?? 10\n const continueOnError = options?.continueOnError ?? true\n const semaphore = new Semaphore(concurrency)\n\n const results: BatchItemResult<TData>[] = new Array(items.length)\n let succeeded = 0\n let failed = 0\n let completed = 0\n let shouldStop = false\n\n const executeOne = async (\n item: { workflow: WorkflowDefinition<any, any>; input: any },\n index: number\n ): Promise<void> => {\n // Early exit check without acquiring semaphore\n if (options?.signal?.aborted || shouldStop) {\n results[index] = {\n index,\n input: item.input,\n result: null,\n error: new Error('Execution aborted'),\n success: false,\n }\n failed++\n completed++\n options?.onProgress?.(completed, items.length, results[index]!)\n return\n }\n\n // Acquire semaphore for actual execution\n await semaphore.acquire()\n\n try {\n // Check again after acquiring\n if (options?.signal?.aborted || shouldStop) {\n results[index] = {\n index,\n input: item.input,\n result: null,\n error: new Error('Execution aborted'),\n success: false,\n }\n failed++\n } else {\n const result = await this.engine.execute(item.workflow, item.input)\n const success = result.status === 'completed'\n\n results[index] = {\n index,\n input: item.input,\n result,\n error: result.error,\n success,\n }\n\n if (success) {\n succeeded++\n } else {\n failed++\n if (!continueOnError) {\n shouldStop = true\n }\n }\n }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error))\n results[index] = {\n index,\n input: item.input,\n result: null,\n error: err,\n success: false,\n }\n failed++\n if (!continueOnError) {\n shouldStop = true\n }\n } finally {\n semaphore.release()\n completed++\n options?.onProgress?.(completed, items.length, results[index]!)\n }\n }\n\n await Promise.all(items.map((item, index) => executeOne(item, index)))\n\n return {\n total: items.length,\n succeeded,\n failed,\n results,\n duration: Date.now() - startTime,\n }\n }\n}\n","import type { StepExecution, WorkflowContext, WorkflowState, WorkflowStatus } from '../types'\n\n/**\n * Generates a unique identifier for workflow instances.\n *\n * @returns A cryptographically secure UUID string.\n */\nfunction generateId(): string {\n return crypto.randomUUID()\n}\n\n/**\n * Orchestrates the lifecycle and state transformations of a workflow context.\n *\n * The ContextManager is responsible for initializing new contexts, restoring them from\n * persisted states, and performing immutable updates during execution.\n *\n * @example\n * ```typescript\n * const manager = new ContextManager();\n * const ctx = manager.create('order-flow', { id: '123' }, 5);\n * ```\n */\nexport class ContextManager {\n /**\n * Initializes a fresh workflow context with a pending status and empty history.\n *\n * @param name - The human-readable identifier for the workflow type.\n * @param input - The initial data required to start the workflow.\n * @param stepCount - Total number of steps defined in the workflow for history pre-allocation.\n * @returns A new WorkflowContext instance.\n *\n * @example\n * ```typescript\n * const ctx = manager.create('signup', { email: 'user@example.com' }, 3);\n * ```\n */\n create<TInput, TData extends Record<string, any> = Record<string, any>>(\n name: string,\n input: TInput,\n stepCount: number\n ): WorkflowContext<TInput, TData> {\n const history: StepExecution[] = Array.from({ length: stepCount }, (_, _i) => ({\n name: '',\n status: 'pending',\n retries: 0,\n }))\n\n return {\n id: generateId(),\n name,\n input,\n data: {} as TData,\n status: 'pending',\n currentStep: 0,\n history,\n version: 1,\n }\n }\n\n /**\n * Reconstructs a workflow context from a previously persisted state.\n *\n * Used for resuming suspended workflows or replaying failed ones from a specific point.\n *\n * @param state - The persisted state object.\n * @returns A hydrated WorkflowContext ready for execution.\n *\n * @example\n * ```typescript\n * const state = await storage.load(id);\n * const ctx = manager.restore(state);\n * ```\n */\n restore<TInput, TData extends Record<string, any> = Record<string, any>>(\n state: WorkflowState<TInput, TData>\n ): WorkflowContext<TInput, TData> {\n return {\n id: state.id,\n name: state.name,\n input: state.input as TInput,\n data: { ...state.data } as unknown as TData,\n status: state.status,\n currentStep: state.currentStep,\n history: state.history.map((h) => ({ ...h })),\n version: state.version || 1,\n }\n }\n\n /**\n * Converts a runtime context into a serializable state for persistence.\n *\n * Captures the current progress, data, and execution history.\n *\n * @param ctx - The active workflow context.\n * @returns A serializable WorkflowState object.\n *\n * @example\n * ```typescript\n * const state = manager.toState(ctx);\n * await storage.save(state);\n * ```\n */\n toState<TInput, TData extends Record<string, any>>(\n ctx: WorkflowContext<TInput, TData>\n ): WorkflowState<TInput, TData> {\n return {\n id: ctx.id,\n name: ctx.name,\n status: ctx.status,\n input: ctx.input,\n data: { ...ctx.data },\n currentStep: ctx.currentStep,\n history: ctx.history.map((h) => ({ ...h })),\n createdAt: new Date(),\n updatedAt: new Date(),\n version: ctx.version,\n }\n }\n\n /**\n * Updates the overall status of the workflow.\n *\n * @param ctx - The current context.\n * @param status - The new status to apply.\n * @returns A new context instance with the updated status.\n *\n * @example\n * ```typescript\n * const runningCtx = manager.updateStatus(ctx, 'running');\n * ```\n */\n updateStatus<TInput, TData extends Record<string, any>>(\n ctx: WorkflowContext<TInput, TData>,\n status: WorkflowStatus\n ): WorkflowContext<TInput, TData> {\n return {\n ...ctx,\n status,\n }\n }\n\n /**\n * Increments the current step pointer.\n *\n * @param ctx - The current context.\n * @returns A new context instance pointing to the next step.\n *\n * @example\n * ```typescript\n * const nextStepCtx = manager.advanceStep(ctx);\n * console.log(nextStepCtx.currentStep); // ctx.currentStep + 1\n * ```\n */\n advanceStep<TInput, TData extends Record<string, any>>(\n ctx: WorkflowContext<TInput, TData>\n ): WorkflowContext<TInput, TData> {\n return {\n ...ctx,\n currentStep: ctx.currentStep + 1,\n }\n }\n\n /**\n * Assigns a name to a specific step in the execution history.\n *\n * Useful for tracking which step is currently being executed or has been completed.\n *\n * @param ctx - The current context.\n * @param index - The index of the step in the history array.\n * @param name - The name to assign to the step.\n * @returns A new context instance with the updated history.\n *\n * @example\n * ```typescript\n * const namedCtx = manager.setStepName(ctx, 0, 'validate-user');\n * console.log(namedCtx.history[0].name); // 'validate-user'\n * ```\n */\n setStepName<TInput, TData extends Record<string, any>>(\n ctx: WorkflowContext<TInput, TData>,\n index: number,\n name: string\n ): WorkflowContext<TInput, TData> {\n if (!ctx.history[index]) {\n return ctx\n }\n const history = [...ctx.history]\n history[index] = { ...history[index], name }\n return {\n ...ctx,\n history,\n }\n }\n}\n","/**\n * @fileoverview State Machine for workflow status transitions\n *\n * Pure state machine with no runtime dependencies.\n *\n * @module @gravito/flux/core\n */\n\nimport * as Errors from '../errors'\nimport type { WorkflowStatus } from '../types'\n\n/**\n * Defines the authoritative set of allowed status transitions for a workflow.\n *\n * This map ensures that workflows follow a logical progression and prevents\n * illegal state jumps (e.g., from 'completed' back to 'running').\n */\nconst TRANSITIONS: Record<WorkflowStatus, WorkflowStatus[]> = {\n pending: ['running', 'failed'],\n running: ['paused', 'completed', 'failed', 'suspended', 'rolling_back'],\n paused: ['running', 'failed'],\n suspended: ['running', 'failed'],\n rolling_back: ['rolled_back', 'failed', 'compensation_failed'],\n rolled_back: ['pending'], // allow retry from scratch\n completed: [], // terminal state\n failed: ['pending'], // allow retry\n compensation_failed: ['pending'], // allow retry even if compensation failed\n}\n\n/**\n * Manages the lifecycle states of a workflow instance.\n *\n * The StateMachine enforces transition rules and notifies listeners of state changes.\n * It is designed to be the single source of truth for a workflow's current progress.\n *\n * @example\n * ```typescript\n * const sm = new StateMachine();\n * sm.addEventListener('transition', (e) => console.log(e.detail));\n * sm.transition('running');\n * ```\n */\nexport class StateMachine extends EventTarget {\n private _status: WorkflowStatus = 'pending'\n\n /**\n * The current operational status of the workflow.\n */\n get status(): WorkflowStatus {\n return this._status\n }\n\n /**\n * Evaluates if a transition to the specified status is valid from the current state.\n *\n * @param to - The target status to check.\n * @returns True if the transition is permitted by the transition map.\n *\n * @example\n * ```typescript\n * if (sm.canTransition('completed')) {\n * sm.transition('completed');\n * }\n * ```\n */\n canTransition(to: WorkflowStatus): boolean {\n return TRANSITIONS[this._status].includes(to)\n }\n\n /**\n * Moves the workflow to a new status if the transition is valid.\n *\n * @param to - The target status.\n * @throws {Error} If the transition is illegal according to the defined rules.\n *\n * @example\n * ```typescript\n * try {\n * sm.transition('completed');\n * } catch (e) {\n * // Handle invalid transition\n * }\n * ```\n */\n transition(to: WorkflowStatus): void {\n if (!this.canTransition(to)) {\n throw Errors.invalidStateTransition(this._status, to)\n }\n\n const from = this._status\n this._status = to\n\n // Emit transition event\n this.dispatchEvent(\n new CustomEvent('transition', {\n detail: { from, to },\n })\n )\n }\n\n /**\n * Overrides the current status without validation.\n *\n * This should only be used during workflow restoration from persisted storage\n * or when replaying history where the state is already known to be valid.\n *\n * @param status - The status to force set.\n *\n * @example\n * ```typescript\n * // Restore state from database\n * sm.forceStatus(storedState.status);\n * ```\n */\n forceStatus(status: WorkflowStatus): void {\n this._status = status\n }\n\n /**\n * Determines if the workflow has reached a state where no further execution is possible.\n *\n * @returns True if the status is 'completed', 'failed', or 'rolled_back'.\n *\n * @example\n * ```typescript\n * if (sm.isTerminal()) {\n * console.log('Workflow finished');\n * }\n * ```\n */\n isTerminal(): boolean {\n return (\n this._status === 'completed' ||\n this._status === 'failed' ||\n this._status === 'rolled_back' ||\n this._status === 'compensation_failed'\n )\n }\n\n /**\n * Checks if the workflow is in a state that allows for execution or resumption.\n *\n * @returns True if the workflow can be started or resumed.\n *\n * @example\n * ```typescript\n * if (sm.canExecute()) {\n * await engine.run();\n * }\n * ```\n */\n canExecute(): boolean {\n return this._status === 'pending' || this._status === 'paused' || this._status === 'suspended'\n }\n}\n","import { CronExpressionParser } from 'cron-parser'\nimport type { FluxEngine } from '../engine/FluxEngine'\nimport type { CronScheduleOptions } from '../types'\n\n/**\n * Built-in scheduler for Flux workflows.\n *\n * Manages multiple cron-based schedules and triggers workflow execution\n * at the specified intervals.\n */\nexport class CronTrigger {\n private schedules = new Map<string, CronScheduleOptions>()\n private timers = new Map<string, Timer>()\n private running = false\n\n /**\n * Creates a new CronTrigger instance.\n *\n * @param engine - The Flux engine to use for executing scheduled workflows.\n */\n constructor(private engine: FluxEngine) {}\n\n /**\n * Starts the scheduler.\n */\n start(): void {\n if (this.running) {\n return\n }\n this.running = true\n this.refreshAll()\n }\n\n /**\n * Stops the scheduler and clears all timers.\n */\n stop(): void {\n this.running = false\n for (const timer of this.timers.values()) {\n clearTimeout(timer)\n }\n this.timers.clear()\n }\n\n /**\n * Adds a new schedule or updates an existing one.\n *\n * @param options - The schedule configuration.\n */\n addSchedule(options: CronScheduleOptions): void {\n this.schedules.set(options.id, options)\n if (this.running) {\n this.refreshSchedule(options.id)\n }\n }\n\n /**\n * Removes a schedule.\n *\n * @param id - The ID of the schedule to remove.\n */\n removeSchedule(id: string): void {\n this.schedules.delete(id)\n const timer = this.timers.get(id)\n if (timer) {\n clearTimeout(timer)\n this.timers.delete(id)\n }\n }\n\n /**\n * Refreshes all active schedules.\n * @private\n */\n private refreshAll(): void {\n for (const id of this.schedules.keys()) {\n this.refreshSchedule(id)\n }\n }\n\n /**\n * Calculates the next execution time and sets a timer for a specific schedule.\n *\n * @param id - The ID of the schedule to refresh.\n * @private\n */\n private refreshSchedule(id: string): void {\n const schedule = this.schedules.get(id)\n if (!schedule || schedule.enabled === false) {\n return\n }\n\n // Clear existing timer if any\n const existingTimer = this.timers.get(id)\n if (existingTimer) {\n clearTimeout(existingTimer)\n }\n\n try {\n const interval = CronExpressionParser.parse(schedule.cron)\n const nextDate = interval.next().toDate()\n const delay = nextDate.getTime() - Date.now()\n\n if (delay <= 0) {\n // If the date is in the past (shouldn't happen with next()),\n // try again in a short while\n const timer = setTimeout(() => this.refreshSchedule(id), 1000)\n this.timers.set(id, timer)\n return\n }\n\n const timer = setTimeout(async () => {\n if (!this.running) {\n return\n }\n\n try {\n // Trigger the workflow\n await this.engine.execute(schedule.workflow as any, schedule.input)\n } catch (error) {\n console.error(`[CronTrigger] Failed to execute scheduled workflow \"${id}\":`, error)\n } finally {\n // Schedule the next run\n if (this.running && this.schedules.has(id)) {\n this.refreshSchedule(id)\n }\n }\n }, delay)\n\n this.timers.set(id, timer)\n } catch (error) {\n console.error(`[CronTrigger] Invalid cron expression for schedule \"${id}\":`, error)\n }\n }\n\n /**\n * Lists all registered schedules.\n * @returns An array of schedule configurations.\n */\n listSchedules(): CronScheduleOptions[] {\n return Array.from(this.schedules.values())\n }\n}\n","/**\n * @fileoverview In-memory storage adapter\n *\n * Simple storage for development and testing.\n *\n * @module @gravito/flux/storage\n */\n\nimport type { WorkflowFilter, WorkflowState, WorkflowStorage } from '../types'\n\n/**\n * MemoryStorage provides a volatile, in-memory storage backend for Flux workflows.\n *\n * It is primarily intended for development, testing, and ephemeral workloads where persistence\n * across process restarts is not required.\n *\n * @example\n * ```typescript\n * const storage = new MemoryStorage();\n * await storage.save(workflowState);\n * const state = await storage.load('workflow-id');\n * ```\n */\nexport class MemoryStorage implements WorkflowStorage {\n private store = new Map<string, WorkflowState>()\n\n /**\n * Stores a workflow state in the internal Map.\n *\n * Automatically updates the `updatedAt` timestamp to reflect the current time.\n *\n * @param state - The workflow state to persist.\n * @throws {Error} If the state object is invalid or cannot be stored.\n */\n async save(state: WorkflowState): Promise<void> {\n this.store.set(state.id, {\n ...state,\n updatedAt: new Date(),\n })\n }\n\n /**\n * Retrieves a workflow state by its ID from the internal Map.\n *\n * @param id - The unique identifier of the workflow.\n * @returns The workflow state if found, otherwise null.\n */\n async load(id: string): Promise<WorkflowState | null> {\n return this.store.get(id) ?? null\n }\n\n /**\n * Filters and returns workflow states stored in memory.\n *\n * Supports filtering by name and status, and provides basic pagination.\n * Results are sorted by creation date in descending order.\n *\n * @param filter - Criteria for filtering and paginating results.\n * @returns An array of matching workflow states.\n */\n async list(filter?: WorkflowFilter): Promise<WorkflowState[]> {\n let results = Array.from(this.store.values())\n\n if (filter?.name) {\n results = results.filter((s) => s.name === filter.name)\n }\n\n if (filter?.status) {\n const statuses = Array.isArray(filter.status) ? filter.status : [filter.status]\n results = results.filter((s) => statuses.includes(s.status))\n }\n\n if (filter?.version) {\n results = results.filter((s) => s.definitionVersion === filter.version)\n }\n\n // Sort by createdAt desc\n results.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime())\n\n // Apply pagination\n if (filter?.offset) {\n results = results.slice(filter.offset)\n }\n if (filter?.limit) {\n results = results.slice(0, filter.limit)\n }\n\n return results\n }\n\n /**\n * Removes a workflow state from the internal Map.\n *\n * @param id - The unique identifier of the workflow to delete.\n */\n async delete(id: string): Promise<void> {\n this.store.delete(id)\n }\n\n /**\n * Initializes the memory storage.\n *\n * This is a no-op for MemoryStorage but satisfies the WorkflowStorage interface.\n */\n async init(): Promise<void> {\n // No-op for memory storage\n }\n\n /**\n * Clears all stored workflow states and resets the storage.\n */\n async close(): Promise<void> {\n this.store.clear()\n }\n\n /**\n * Returns the total number of workflow states currently stored in memory.\n *\n * Useful for assertions in test environments.\n *\n * @returns The number of entries in the store.\n */\n size(): number {\n return this.store.size\n }\n}\n","import type { StepExecution } from '../types'\n\n/**\n * Performs an immutable update on a step execution record.\n *\n * This utility ensures that execution history remains consistent by returning\n * a new object with the merged updates, preserving the original record.\n *\n * @param execution - The current execution record to update.\n * @param updates - A partial object containing the fields to be modified.\n * @returns A new StepExecution instance with the applied changes.\n *\n * @example\n * ```typescript\n * const updated = updateStepExecution(record, { status: 'completed', duration: 150 });\n * ```\n */\nexport function updateStepExecution(\n execution: StepExecution,\n updates: Partial<StepExecution>\n): StepExecution {\n return {\n ...execution,\n ...updates,\n }\n}\n","/**\n * @fileoverview Step Executor for workflow steps\n *\n * Handles step execution with retry and timeout support.\n *\n * @module @gravito/flux/core\n */\n\nimport type { StepDefinition, StepExecution, StepResult, WorkflowContext } from '../types'\nimport { updateStepExecution } from './executionUpdater'\n\n/**\n * Handles the isolated execution of a single workflow step.\n *\n * The StepExecutor manages the operational aspects of step execution, including\n * condition checking, retry logic with exponential backoff, and timeout enforcement.\n *\n * @example\n * ```typescript\n * const executor = new StepExecutor({ defaultRetries: 3 });\n * const { result } = await executor.execute(stepDef, ctx, executionRecord);\n * ```\n */\nexport class StepExecutor {\n private defaultRetries: number\n private defaultTimeout: number\n private onRetry?: (\n step: StepDefinition<any, any>,\n ctx: WorkflowContext<any, any>,\n error: Error,\n attempt: number,\n maxRetries: number\n ) => void | Promise<void>\n\n /**\n * Creates a new StepExecutor with global defaults.\n *\n * @param options - Configuration for default behavior and lifecycle hooks.\n */\n constructor(\n options: {\n defaultRetries?: number\n defaultTimeout?: number\n onRetry?: (\n step: StepDefinition<any, any>,\n ctx: WorkflowContext<any, any>,\n error: Error,\n attempt: number,\n maxRetries: number\n ) => void | Promise<void>\n } = {}\n ) {\n this.defaultRetries = options.defaultRetries ?? 3\n this.defaultTimeout = options.defaultTimeout ?? 30000\n this.onRetry = options.onRetry\n }\n\n /**\n * Executes a step definition against a workflow context.\n *\n * This method performs the following sequence:\n * 1. Evaluates the `when` condition (if present).\n * 2. Initiates the execution loop with retries.\n * 3. Enforces timeouts for each attempt.\n * 4. Handles suspension signals (`flux_wait`).\n * 5. Updates the execution history record.\n *\n * @param step - The definition of the step to execute.\n * @param ctx - The current workflow context.\n * @param execution - The current execution record for this step.\n * @returns The result of the execution and the updated execution record.\n *\n * @throws {Error} If the step handler throws an unrecoverable error or times out.\n *\n * @example\n * ```typescript\n * const { result, execution } = await executor.execute(\n * stepDefinition,\n * currentContext,\n * currentExecution\n * );\n *\n * if (!result.success) {\n * console.error(result.error);\n * }\n * ```\n */\n async execute<TInput, TData extends Record<string, any>>(\n step: StepDefinition<TInput, TData>,\n ctx: WorkflowContext<TInput, TData>,\n execution: StepExecution\n ): Promise<{ result: StepResult; execution: StepExecution }> {\n const maxRetries = step.retries ?? this.defaultRetries\n const timeout = step.timeout ?? this.defaultTimeout\n const startTime = Date.now()\n let currentExecution = execution\n\n // Check condition\n if (step.when && !step.when(ctx)) {\n currentExecution = updateStepExecution(currentExecution, { status: 'skipped' })\n return {\n result: {\n success: true,\n duration: 0,\n },\n execution: currentExecution,\n }\n }\n\n currentExecution = updateStepExecution(currentExecution, {\n status: 'running',\n startedAt: new Date(),\n })\n\n let lastError: Error | undefined\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n currentExecution = updateStepExecution(currentExecution, { retries: attempt })\n\n try {\n // Execute with timeout\n const result = await this.executeWithTimeout(step.handler, ctx, timeout)\n\n if (\n result &&\n typeof result === 'object' &&\n '__kind' in result &&\n result.__kind === 'flux_wait'\n ) {\n const duration = Date.now() - startTime\n currentExecution = updateStepExecution(currentExecution, {\n status: 'suspended',\n waitingFor: result.signal,\n suspendedAt: new Date(),\n duration,\n })\n\n return {\n result: {\n success: true,\n suspended: true,\n waitingFor: result.signal,\n duration,\n },\n execution: currentExecution,\n }\n }\n\n const duration = Date.now() - startTime\n currentExecution = updateStepExecution(currentExecution, {\n status: 'completed',\n completedAt: new Date(),\n duration,\n })\n\n return {\n result: {\n success: true,\n duration,\n },\n execution: currentExecution,\n }\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error))\n\n // If not last retry, continue\n if (attempt < maxRetries) {\n await this.onRetry?.(step, ctx, lastError, attempt + 1, maxRetries)\n // Exponential backoff\n await this.sleep(Math.min(1000 * 2 ** attempt, 10000))\n }\n }\n }\n\n // All retries failed\n const duration = Date.now() - startTime\n currentExecution = updateStepExecution(currentExecution, {\n status: 'failed',\n completedAt: new Date(),\n duration,\n error: lastError?.message,\n })\n\n return {\n result: {\n success: false,\n error: lastError,\n duration,\n },\n execution: currentExecution,\n }\n }\n\n /**\n * Wraps the step handler in a timeout race.\n *\n * @param handler - The user-defined step handler.\n * @param ctx - The workflow context.\n * @param timeout - Maximum time allowed for execution in milliseconds.\n * @returns The handler result or a suspension signal.\n * @throws {Error} If the timeout is reached before the handler completes.\n * @private\n */\n private async executeWithTimeout<TInput, TData extends Record<string, any>>(\n handler: StepDefinition<TInput, TData>['handler'],\n ctx: WorkflowContext<TInput, TData>,\n timeout: number\n ): Promise<import('../types').StepHandlerResult> {\n let timer: ReturnType<typeof setTimeout> | null = null\n try {\n const timeoutPromise = new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(new Error('Step timeout')), timeout)\n })\n\n return await Promise.race([Promise.resolve(handler(ctx)), timeoutPromise])\n } finally {\n if (timer) {\n clearTimeout(timer)\n }\n }\n }\n\n /**\n * Pauses execution for a specified duration.\n *\n * @param ms - Milliseconds to sleep.\n * @private\n */\n private async sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n }\n}\n","/**\n * @fileoverview Data Optimizer for workflow state persistence\n *\n * Optimizes workflow data storage by detecting large objects and converting them to references.\n * This reduces serialization overhead and I/O costs during state persistence.\n *\n * @module @gravito/flux/core\n */\n\n/**\n * Represents a reference to external data stored in an external system.\n * The actual data can be loaded lazily when needed.\n */\nexport interface DataReference<T = unknown> {\n /** Marker to identify this as a reference object. */\n __ref: true\n /** Unique identifier for retrieving the data. */\n id: string\n /** The storage location of the actual data. */\n location: 's3' | 'redis' | 'database' | 'memory'\n /** Size of the original data in bytes. */\n size: number\n /** Optional lazy loader function to retrieve the actual data. */\n load?: () => Promise<T>\n}\n\n/**\n * Configuration options for DataOptimizer.\n */\nexport interface DataOptimizerConfig {\n /** Threshold in bytes above which data is converted to a reference. Default: 10KB */\n threshold?: number\n /** Default storage location for large objects. Default: 'database' */\n defaultLocation?: DataReference['location']\n}\n\n/**\n * Utility for optimizing workflow data storage.\n *\n * Automatically detects large objects in workflow data and converts them to references,\n * reducing serialization overhead during persistence.\n *\n * @example\n * ```typescript\n * const optimizer = new DataOptimizer({ threshold: 10 * 1024 }); // 10KB threshold\n *\n * const data = {\n * small: 'hello',\n * large: Buffer.alloc(100 * 1024) // 100KB buffer\n * };\n *\n * const optimized = optimizer.optimizeForStorage(data);\n * // optimized.small === 'hello'\n * // optimized.large.__ref === true (converted to reference)\n * ```\n */\nexport class DataOptimizer {\n private threshold: number\n private defaultLocation: DataReference['location']\n\n /**\n * Creates a new DataOptimizer instance.\n *\n * @param config - Configuration options for the optimizer.\n */\n constructor(config: DataOptimizerConfig = {}) {\n this.threshold = config.threshold ?? 10 * 1024 // 10KB default\n this.defaultLocation = config.defaultLocation ?? 'database'\n }\n\n /**\n * Estimates the size of a data object in bytes.\n *\n * This uses JSON.stringify to calculate the approximate size,\n * which may not be exact for all types but provides a reasonable estimate.\n *\n * @param data - The data to measure.\n * @returns The estimated size in bytes.\n *\n * @example\n * ```typescript\n * const size = DataOptimizer.estimateSize({ key: 'value' });\n * console.log(size); // 15 (approximate)\n * ```\n */\n static estimateSize(data: unknown): number {\n try {\n return JSON.stringify(data).length\n } catch {\n // If serialization fails, return a large number to trigger reference conversion\n return Number.MAX_SAFE_INTEGER\n }\n }\n\n /**\n * Optimizes a data object for storage by replacing large values with references.\n *\n * Iterates through the object's properties and converts any value exceeding the\n * threshold to a DataReference object.\n *\n * @param data - The data object to optimize.\n * @param customThreshold - Optional custom threshold for this optimization.\n * @returns A new object with large values replaced by references.\n *\n * @example\n * ```typescript\n * const optimizer = new DataOptimizer({ threshold: 1024 });\n * const result = optimizer.optimizeForStorage({\n * small: 'text',\n * large: Buffer.alloc(10 * 1024)\n * });\n * // result.small === 'text'\n * // result.large.__ref === true\n * ```\n */\n optimizeForStorage<T extends Record<string, any>>(\n data: T,\n customThreshold?: number\n ): Record<string, any> {\n const threshold = customThreshold ?? this.threshold\n const result: Record<string, any> = {}\n\n for (const [key, value] of Object.entries(data)) {\n // Skip null/undefined\n if (value === null || value === undefined) {\n result[key] = value\n continue\n }\n\n // Skip if already a reference\n if (this.isReference(value)) {\n result[key] = value\n continue\n }\n\n const size = DataOptimizer.estimateSize(value)\n\n if (size > threshold) {\n // Convert to reference\n result[key] = this.createReference(value, size)\n } else {\n result[key] = value\n }\n }\n\n return result\n }\n\n /**\n * Checks if a value is a DataReference.\n *\n * @param value - The value to check.\n * @returns True if the value is a DataReference.\n */\n isReference(value: unknown): value is DataReference {\n return typeof value === 'object' && value !== null && '__ref' in value && value.__ref === true\n }\n\n /**\n * Creates a DataReference from a value.\n *\n * @param value - The original value to create a reference for.\n * @param size - The size of the original value in bytes.\n * @returns A DataReference object.\n * @private\n */\n private createReference(_value: unknown, size: number): DataReference {\n return {\n __ref: true,\n id: this.generateReferenceId(),\n location: this.defaultLocation,\n size,\n // Note: The actual storage and load implementation\n // should be handled by the storage adapter\n }\n }\n\n /**\n * Generates a unique identifier for a data reference.\n *\n * @returns A unique reference ID.\n * @private\n */\n private generateReferenceId(): string {\n return `ref_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`\n }\n\n /**\n * Resolves references in a data object by loading the actual values.\n *\n * This is the inverse operation of optimizeForStorage.\n *\n * @param data - The data object containing references.\n * @returns A promise resolving to the data with references replaced by actual values.\n *\n * @example\n * ```typescript\n * const optimizer = new DataOptimizer();\n * const resolved = await optimizer.resolveReferences({\n * small: 'text',\n * large: { __ref: true, id: 'ref_123', location: 'database', size: 1024 }\n * });\n * // resolved.large contains the actual loaded data\n * ```\n */\n async resolveReferences<T extends Record<string, any>>(data: T): Promise<Record<string, any>> {\n const result: Record<string, any> = {}\n\n for (const [key, value] of Object.entries(data)) {\n if (this.isReference(value)) {\n // Load the actual data if a loader is provided\n if (value.load) {\n result[key] = await value.load()\n } else {\n // If no loader, keep the reference\n result[key] = value\n }\n } else {\n result[key] = value\n }\n }\n\n return result\n }\n\n /**\n * Calculates the total size reduction achieved by optimization.\n *\n * @param original - The original data object.\n * @param optimized - The optimized data object.\n * @returns An object containing size statistics.\n *\n * @example\n * ```typescript\n * const optimizer = new DataOptimizer();\n * const original = { large: Buffer.alloc(100 * 1024) };\n * const optimized = optimizer.optimizeForStorage(original);\n * const stats = optimizer.getOptimizationStats(original, optimized);\n * console.log(stats); // { originalSize: 102400, optimizedSize: 100, reduction: 99.9 }\n * ```\n */\n getOptimizationStats(\n original: Record<string, any>,\n optimized: Record<string, any>\n ): {\n originalSize: number\n optimizedSize: number\n reduction: number\n referencesCreated: number\n } {\n const originalSize = DataOptimizer.estimateSize(original)\n const optimizedSize = DataOptimizer.estimateSize(optimized)\n const referencesCreated = Object.values(optimized).filter((v) => this.isReference(v)).length\n\n return {\n originalSize,\n optimizedSize,\n reduction: ((originalSize - optimizedSize) / originalSize) * 100,\n referencesCreated,\n }\n }\n}\n","/**\n * Configuration for compensation retry behavior.\n */\nexport interface CompensationRetryConfig {\n /** Maximum number of retry attempts. Default: 3 */\n maxAttempts?: number\n /** Initial delay in milliseconds. Default: 1000ms (1s) */\n initialDelay?: number\n /** Backoff coefficient multiplier. Default: 2 (exponential) */\n backoffCoefficient?: number\n /** Maximum delay cap in milliseconds. Default: 30000ms (30s) */\n maxDelay?: number\n /** Jitter factor (0-1) to add randomness. Default: 0.1 (10%) */\n jitter?: number\n}\n\n/**\n * Result of a retry attempt.\n */\nexport interface RetryResult<T = void> {\n /** Whether the operation succeeded. */\n success: boolean\n /** The result value if successful. */\n value?: T\n /** The error if failed. */\n error?: Error\n /** Number of attempts made. */\n attempts: number\n /** Total time spent in milliseconds. */\n duration: number\n}\n\n/**\n * Manages retry logic for failed compensation actions with exponential backoff.\n *\n * Implements a robust retry strategy to handle transient failures during\n * workflow rollback, ensuring eventual consistency in distributed transactions.\n *\n * @example\n * ```typescript\n * const policy = new CompensationRetryPolicy({\n * maxAttempts: 5,\n * initialDelay: 2000,\n * backoffCoefficient: 2,\n * });\n *\n * const result = await policy.execute(async () => {\n * await externalAPI.cancelReservation(reservationId);\n * });\n *\n * if (!result.success) {\n * console.error(`Failed after ${result.attempts} attempts`);\n * }\n * ```\n */\nexport class CompensationRetryPolicy {\n private config: Required<CompensationRetryConfig>\n\n constructor(config: CompensationRetryConfig = {}) {\n this.config = {\n maxAttempts: config.maxAttempts ?? 3,\n initialDelay: config.initialDelay ?? 1000,\n backoffCoefficient: config.backoffCoefficient ?? 2,\n maxDelay: config.maxDelay ?? 30000,\n jitter: config.jitter ?? 0.1,\n }\n }\n\n /**\n * Executes an operation with automatic retry on failure.\n *\n * Uses exponential backoff with jitter to avoid thundering herd problems.\n *\n * @param operation - The async operation to execute.\n * @returns A promise resolving to the retry result.\n *\n * @example\n * ```typescript\n * const policy = new CompensationRetryPolicy();\n *\n * const result = await policy.execute(async () => {\n * await paymentGateway.refund(transactionId);\n * });\n *\n * if (result.success) {\n * console.log(`Refund succeeded after ${result.attempts} attempts`);\n * }\n * ```\n */\n async execute<T = void>(operation: () => Promise<T>): Promise<RetryResult<T>> {\n const startTime = Date.now()\n let lastError: Error | undefined\n let attempts = 0\n\n while (attempts < this.config.maxAttempts) {\n attempts++\n\n try {\n const value = await operation()\n return {\n success: true,\n value,\n attempts,\n duration: Date.now() - startTime,\n }\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err))\n\n if (attempts < this.config.maxAttempts) {\n const delay = this.calculateDelay(attempts)\n await this.sleep(delay)\n }\n }\n }\n\n return {\n success: false,\n error: lastError,\n attempts,\n duration: Date.now() - startTime,\n }\n }\n\n /**\n * Calculates the delay for a given retry attempt using exponential backoff.\n *\n * @param attempt - The current attempt number (1-indexed).\n * @returns The delay in milliseconds.\n * @private\n */\n private calculateDelay(attempt: number): number {\n const exponentialDelay =\n this.config.initialDelay * this.config.backoffCoefficient ** (attempt - 1)\n\n const cappedDelay = Math.min(exponentialDelay, this.config.maxDelay)\n\n const jitterAmount = cappedDelay * this.config.jitter\n const jitter = (Math.random() - 0.5) * 2 * jitterAmount\n\n return Math.max(0, cappedDelay + jitter)\n }\n\n /**\n * Sleeps for the specified duration.\n *\n * @param ms - Duration in milliseconds.\n * @private\n */\n private async sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n }\n\n /**\n * Checks if an error is retryable.\n *\n * By default, all errors are retryable. Override this method or provide\n * a custom predicate to implement selective retry logic.\n *\n * @param error - The error to check.\n * @returns True if the error is retryable.\n *\n * @example\n * ```typescript\n * class CustomRetryPolicy extends CompensationRetryPolicy {\n * isRetryable(error: Error): boolean {\n * return error.message.includes('TRANSIENT');\n * }\n * }\n * ```\n */\n isRetryable(_error: Error): boolean {\n return true\n }\n\n /**\n * Executes an operation with selective retry based on error type.\n *\n * @param operation - The async operation to execute.\n * @param isRetryable - Predicate to determine if an error should trigger retry.\n * @returns A promise resolving to the retry result.\n *\n * @example\n * ```typescript\n * const policy = new CompensationRetryPolicy();\n *\n * const result = await policy.executeWithPredicate(\n * async () => await api.call(),\n * (err) => err.message.includes('timeout')\n * );\n * ```\n */\n async executeWithPredicate<T = void>(\n operation: () => Promise<T>,\n isRetryable: (error: Error) => boolean\n ): Promise<RetryResult<T>> {\n const startTime = Date.now()\n let lastError: Error | undefined\n let attempts = 0\n\n while (attempts < this.config.maxAttempts) {\n attempts++\n\n try {\n const value = await operation()\n return {\n success: true,\n value,\n attempts,\n duration: Date.now() - startTime,\n }\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err))\n\n if (!isRetryable(lastError)) {\n break\n }\n\n if (attempts < this.config.maxAttempts) {\n const delay = this.calculateDelay(attempts)\n await this.sleep(delay)\n }\n }\n }\n\n return {\n success: false,\n error: lastError,\n attempts,\n duration: Date.now() - startTime,\n }\n }\n\n /**\n * Gets the current retry configuration.\n *\n * @returns A copy of the current configuration.\n */\n getConfig(): Readonly<Required<CompensationRetryConfig>> {\n return { ...this.config }\n }\n}\n","import type { WorkflowContext } from '../types'\n\n/**\n * Pure function to update the workflow context.\n *\n * This utility ensures that context updates are performed immutably,\n * which is critical for maintaining consistent state across the engine.\n *\n * @param ctx - The current workflow context to update.\n * @param updates - The partial updates to apply to the context.\n * @returns A new workflow context instance with the updates applied.\n *\n * @example\n * ```typescript\n * const nextCtx = updateWorkflowContext(ctx, { status: 'completed' });\n * ```\n */\nexport function updateWorkflowContext<TInput, TData extends Record<string, any>>(\n ctx: WorkflowContext<TInput, TData>,\n updates: Partial<WorkflowContext<TInput, TData>>\n): WorkflowContext<TInput, TData> {\n return {\n ...ctx,\n ...updates,\n }\n}\n","import { WorkflowBuilder } from '../builder/WorkflowBuilder'\nimport type { ContextManager } from '../core/ContextManager'\nimport { StepExecutor } from '../core/StepExecutor'\nimport * as Errors from '../errors'\nimport type {\n FluxConfig,\n FluxResult,\n WorkflowContext,\n WorkflowDefinition,\n WorkflowStorage,\n} from '../types'\nimport type { RollbackManager } from './RollbackManager'\nimport { updateWorkflowContext } from './stateUpdater'\nimport type { TraceEmitter } from './TraceEmitter'\n\n/**\n * Creates and configures a StepExecutor with tracing support.\n *\n * This helper initializes the executor with retry policies and connects it to the trace emitter\n * to record retry attempts.\n *\n * @param config - The engine configuration containing default retry/timeout settings.\n * @param traceEmitter - The emitter for sending trace events.\n * @returns A fully configured StepExecutor instance.\n *\n * @example\n * ```typescript\n * const executor = createStepExecutor(config, traceEmitter);\n * ```\n */\nexport function createStepExecutor(config: FluxConfig, traceEmitter: TraceEmitter): StepExecutor {\n return new StepExecutor({\n defaultRetries: config.defaultRetries,\n defaultTimeout: config.defaultTimeout,\n onRetry: async (step, ctx, error, attempt, maxRetries) => {\n await traceEmitter.emit({\n type: 'step:retry',\n timestamp: Date.now(),\n workflowId: ctx.id,\n workflowName: ctx.name,\n stepName: step.name,\n stepIndex: ctx.currentStep,\n commit: Boolean(step.commit),\n retries: attempt,\n maxRetries,\n error: error.message,\n status: 'running',\n })\n },\n })\n}\n\n/**\n * Resolves a workflow definition from a builder or a raw definition.\n *\n * Allows the engine to accept both `WorkflowBuilder` instances and plain `WorkflowDefinition` objects.\n *\n * @param workflow - The workflow builder or definition object.\n * @returns The compiled WorkflowDefinition.\n *\n * @example\n * ```typescript\n * const def = resolveDefinition(myWorkflowBuilder);\n * ```\n */\nexport function resolveDefinition<TInput, TData>(\n workflow: WorkflowBuilder<TInput, TData> | WorkflowDefinition<TInput, TData>\n): WorkflowDefinition<TInput, TData> {\n return workflow instanceof WorkflowBuilder ? workflow.build() : workflow\n}\n\n/**\n * Resolves the starting index for workflow execution.\n *\n * Handles various ways of specifying the start step: by index, by name, or using a fallback.\n *\n * @param definition - The workflow definition containing the steps.\n * @param fromStep - The requested start step (index or name).\n * @param fallback - The fallback index if `fromStep` is undefined.\n * @returns The zero-based index of the step to start from.\n * @throws {FluxError} If the step index is out of bounds or the step name is not found.\n *\n * @example\n * ```typescript\n * const index = resolveStartIndex(def, 'payment-step', 0);\n * ```\n */\nexport function resolveStartIndex<TInput, TData>(\n definition: WorkflowDefinition<TInput, TData>,\n fromStep: number | string | undefined,\n fallback: number\n): number {\n if (typeof fromStep === 'number') {\n if (fromStep < 0 || fromStep >= definition.steps.length) {\n throw Errors.invalidStepIndex(fromStep)\n }\n return fromStep\n }\n if (typeof fromStep === 'string') {\n const index = definition.steps.findIndex((step) => step.name === fromStep)\n if (index === -1) {\n throw Errors.stepNotFound(fromStep)\n }\n return index\n }\n return Math.max(0, Math.min(fallback, definition.steps.length - 1))\n}\n\n/**\n * Resets the execution history from a given step index.\n *\n * Clears the status and results of steps from the start index onwards, effectively\n * \"rewinding\" the workflow history for a retry or resume operation.\n *\n * @param ctx - The workflow context to modify.\n * @param startIndex - The index from which to reset history.\n *\n * @example\n * ```typescript\n * resetHistoryFrom(ctx, 2);\n * // Steps 2, 3, ... are now 'pending'\n * ```\n */\nexport function resetHistoryFrom<TInput, TData>(\n ctx: WorkflowContext<TInput, TData>,\n startIndex: number\n): void {\n for (let i = startIndex; i < ctx.history.length; i++) {\n const entry = ctx.history[i]\n if (!entry) {\n continue\n }\n entry.status = 'pending'\n entry.startedAt = undefined\n entry.completedAt = undefined\n entry.duration = undefined\n entry.error = undefined\n entry.retries = 0\n }\n}\n\n/**\n * Handles the final result of a workflow execution, triggering rollback if necessary.\n *\n * Checks if the workflow failed and initiates the compensation process via the RollbackManager.\n *\n * @param definition - The workflow definition.\n * @param ctx - The workflow context at the end of execution.\n * @param result - The raw result from the executor.\n * @param contextManager - The context manager for state restoration.\n * @param rollbackManager - The manager responsible for compensation logic.\n * @param storage - Storage adapter to fetch the latest version for optimistic locking.\n * @returns The final processed result, potentially reflecting a 'rolled_back' status.\n *\n * @example\n * ```typescript\n * const finalResult = await handleExecutionResult(def, ctx, rawResult, cm, rm, storage);\n * ```\n */\nexport async function handleExecutionResult<TInput, TData extends Record<string, any>>(\n definition: WorkflowDefinition<TInput, TData>,\n ctx: WorkflowContext<TInput, TData>,\n result: FluxResult<TData>,\n contextManager: ContextManager,\n rollbackManager: RollbackManager,\n storage: WorkflowStorage\n): Promise<FluxResult<TData>> {\n if (result.status === 'failed' && result.error) {\n const failedIndex = result.history.findIndex((h) => h.status === 'failed')\n if (failedIndex !== -1) {\n // Load the latest state from storage to get the correct version\n const latestState = await storage.load(ctx.id)\n const restoredCtx = contextManager.restore({\n ...contextManager.toState(ctx),\n history: result.history,\n data: result.data,\n status: 'failed',\n version: latestState?.version ?? result.version,\n })\n const rolledBackCtx = await rollbackManager.rollback(\n definition,\n restoredCtx,\n failedIndex,\n result.error\n )\n\n return {\n ...result,\n status: rolledBackCtx.status,\n history: rolledBackCtx.history,\n data: rolledBackCtx.data as TData,\n }\n }\n }\n\n return result\n}\n\n/**\n * Persists a workflow context to storage with optimistic concurrency control.\n *\n * Converts the context to a state object, checks for version conflicts, and saves it.\n *\n * @param ctx - The workflow context to save.\n * @param storage - The storage adapter.\n * @param contextManager - The context manager for serialization.\n * @returns A promise resolving to the updated context with incremented version.\n * @throws {FluxError} If a concurrent modification is detected.\n *\n * @example\n * ```typescript\n * ctx = await persistContext(ctx, storage, cm);\n * ```\n */\nexport async function persistContext<TInput, TData extends Record<string, any>>(\n ctx: WorkflowContext<TInput, TData>,\n storage: WorkflowStorage,\n contextManager: ContextManager,\n definitionVersion?: string\n): Promise<WorkflowContext<TInput, TData>> {\n const state = contextManager.toState(ctx)\n const stored = await storage.load(state.id)\n if (stored && stored.version !== state.version) {\n throw new Errors.FluxError(\n 'Concurrent modification detected',\n Errors.FluxErrorCode.CONCURRENT_MODIFICATION\n )\n }\n // Preserve definitionVersion: use explicit value, or keep existing from storage\n if (definitionVersion !== undefined) {\n state.definitionVersion = definitionVersion\n } else if (stored?.definitionVersion) {\n state.definitionVersion = stored.definitionVersion\n }\n const nextVersion = state.version + 1\n await storage.save({ ...state, version: nextVersion })\n const result = updateWorkflowContext(ctx, { version: nextVersion })\n return result\n}\n\nexport async function acquireEngineLock(config: FluxConfig, workflowId: string) {\n if (!config.lockProvider) {\n return null\n }\n const owner = `node_${Math.random().toString(36).substring(7)}`\n return await config.lockProvider.acquire(workflowId, owner, 30000)\n}\n","import type { StepExecution, WorkflowContext } from '../types'\n\n/**\n * Guards against duplicate compensation execution.\n *\n * Ensures compensation actions are idempotent by checking execution history\n * before allowing re-execution. Prevents duplicate side effects when rollback\n * is retried after a partial failure.\n *\n * @example\n * ```typescript\n * const guard = new IdempotencyGuard();\n *\n * if (guard.canCompensate(ctx, 'payment-step')) {\n * await compensate();\n * guard.recordCompensation(ctx, 'payment-step');\n * }\n * ```\n */\nexport class IdempotencyGuard {\n /**\n * Checks if a step can be compensated based on its execution history.\n *\n * A step can be compensated if:\n * - It has completed successfully\n * - It has NOT already been compensated\n * - It is not currently being compensated\n *\n * @param ctx - The current workflow context.\n * @param stepName - The name of the step to check.\n * @returns True if the step can be safely compensated.\n *\n * @example\n * ```typescript\n * const guard = new IdempotencyGuard();\n *\n * if (guard.canCompensate(ctx, 'reserve-inventory')) {\n * await inventoryService.release(ctx.data.reservationId);\n * }\n * ```\n */\n canCompensate<TInput, TData>(ctx: WorkflowContext<TInput, TData>, stepName: string): boolean {\n const execution = this.findExecution(ctx, stepName)\n\n if (!execution) {\n return false\n }\n\n return execution.status === 'completed'\n }\n\n /**\n * Checks if a step has already been compensated.\n *\n * @param ctx - The current workflow context.\n * @param stepName - The name of the step to check.\n * @returns True if the step has already been compensated.\n *\n * @example\n * ```typescript\n * if (guard.isCompensated(ctx, 'book-flight')) {\n * console.log('Flight booking already cancelled');\n * }\n * ```\n */\n isCompensated<TInput, TData>(ctx: WorkflowContext<TInput, TData>, stepName: string): boolean {\n const execution = this.findExecution(ctx, stepName)\n return execution?.status === 'compensated'\n }\n\n /**\n * Checks if a step is currently being compensated.\n *\n * @param ctx - The current workflow context.\n * @param stepName - The name of the step to check.\n * @returns True if the step is currently in the compensating state.\n */\n isCompensating<TInput, TData>(ctx: WorkflowContext<TInput, TData>, stepName: string): boolean {\n const execution = this.findExecution(ctx, stepName)\n return execution?.status === 'compensating'\n }\n\n /**\n * Retrieves the compensation timestamp for a step.\n *\n * @param ctx - The current workflow context.\n * @param stepName - The name of the step.\n * @returns The compensation timestamp if available, otherwise undefined.\n */\n getCompensationTimestamp<TInput, TData>(\n ctx: WorkflowContext<TInput, TData>,\n stepName: string\n ): Date | undefined {\n const execution = this.findExecution(ctx, stepName)\n return execution?.compensatedAt\n }\n\n /**\n * Counts how many times compensation has been attempted for a step.\n *\n * This is useful for implementing retry limits or circuit breakers.\n *\n * @param ctx - The current workflow context.\n * @param stepName - The name of the step.\n * @returns The number of compensation attempts (0 if never attempted).\n */\n getCompensationAttempts<TInput, TData>(\n ctx: WorkflowContext<TInput, TData>,\n stepName: string\n ): number {\n const executions = ctx.history.filter((h) => h.name === stepName)\n\n return executions.filter((e) => e.status === 'compensated' || e.status === 'compensating')\n .length\n }\n\n /**\n * Finds the most recent execution record for a given step.\n *\n * @param ctx - The current workflow context.\n * @param stepName - The name of the step to find.\n * @returns The step execution record, or undefined if not found.\n * @private\n */\n private findExecution<TInput, TData>(\n ctx: WorkflowContext<TInput, TData>,\n stepName: string\n ): StepExecution | undefined {\n for (let i = ctx.history.length - 1; i >= 0; i--) {\n if (ctx.history[i].name === stepName) {\n return ctx.history[i]\n }\n }\n return undefined\n }\n\n /**\n * Verifies that all completed steps have been compensated.\n *\n * Used to ensure rollback has fully completed.\n *\n * @param ctx - The current workflow context.\n * @param stepNames - Array of step names that should be compensated.\n * @returns True if all specified steps are compensated.\n *\n * @example\n * ```typescript\n * const guard = new IdempotencyGuard();\n * const completedSteps = ['reserve', 'charge', 'notify'];\n *\n * if (guard.allCompensated(ctx, completedSteps)) {\n * console.log('Rollback complete');\n * }\n * ```\n */\n allCompensated<TInput, TData>(ctx: WorkflowContext<TInput, TData>, stepNames: string[]): boolean {\n return stepNames.every((name) => this.isCompensated(ctx, name))\n }\n\n /**\n * Finds all steps that need compensation but haven't been compensated yet.\n *\n * @param ctx - The current workflow context.\n * @param stepNames - Array of step names to check.\n * @returns Array of step names that still need compensation.\n *\n * @example\n * ```typescript\n * const guard = new IdempotencyGuard();\n * const pending = guard.getPendingCompensations(ctx, ['step1', 'step2', 'step3']);\n * console.log(`Still need to compensate: ${pending.join(', ')}`);\n * ```\n */\n getPendingCompensations<TInput, TData>(\n ctx: WorkflowContext<TInput, TData>,\n stepNames: string[]\n ): string[] {\n return stepNames.filter((name) => {\n const execution = this.findExecution(ctx, name)\n return execution?.status === 'completed'\n })\n }\n}\n","import * as Errors from '../errors'\nimport type { WorkflowContext } from '../types'\n\n/**\n * Callback for handling recovery needed events.\n */\nexport type RecoveryCallback<TInput = unknown, TData = Record<string, any>> = (\n ctx: WorkflowContext<TInput, TData>,\n stepName: string,\n error: Error\n) => Promise<void> | void\n\n/**\n * Recovery action types for manual intervention.\n */\nexport type RecoveryAction =\n | { type: 'retry'; maxAttempts?: number }\n | { type: 'skip' }\n | { type: 'manual'; handler: () => Promise<void> }\n | { type: 'abort' }\n\n/**\n * Manages recovery from failed compensation actions through human intervention.\n *\n * When automatic retry fails, this manager allows workflows to wait for\n * manual recovery actions before proceeding with rollback.\n *\n * @example\n * ```typescript\n * const manager = new RecoveryManager();\n *\n * manager.onRecoveryNeeded(async (ctx, stepName, error) => {\n * await notificationService.alert(\n * 'CRITICAL: Manual recovery needed',\n * { workflow: ctx.id, step: stepName, error: error.message }\n * );\n * });\n *\n * manager.registerAction('refund-payment', {\n * type: 'manual',\n * handler: async () => {\n * await finance.manualRefund(ctx.data.transactionId);\n * }\n * });\n * ```\n */\nexport class RecoveryManager<TInput = unknown, TData = Record<string, any>> {\n private recoveryCallbacks: RecoveryCallback<TInput, TData>[] = []\n private actions: Map<string, RecoveryAction> = new Map()\n private pendingRecoveries: Map<string, { stepName: string; error: Error }> = new Map()\n\n /**\n * Registers a callback to be invoked when recovery is needed.\n *\n * @param callback - Function to call when a recovery event occurs.\n *\n * @example\n * ```typescript\n * manager.onRecoveryNeeded(async (ctx, stepName, error) => {\n * await slack.send(`#alerts`, `Workflow ${ctx.id} needs recovery at ${stepName}`);\n * });\n * ```\n */\n onRecoveryNeeded(callback: RecoveryCallback<TInput, TData>): void {\n this.recoveryCallbacks.push(callback)\n }\n\n /**\n * Emits a recovery needed event.\n *\n * @param ctx - The workflow context.\n * @param stepName - The step that failed compensation.\n * @param error - The error that occurred.\n */\n async notifyRecoveryNeeded(\n ctx: WorkflowContext<TInput, TData>,\n stepName: string,\n error: Error\n ): Promise<void> {\n this.pendingRecoveries.set(ctx.id, { stepName, error })\n\n for (const callback of this.recoveryCallbacks) {\n await callback(ctx, stepName, error)\n }\n }\n\n /**\n * Registers a recovery action for a specific step.\n *\n * @param stepName - The step name to associate the action with.\n * @param action - The recovery action to perform.\n *\n * @example\n * ```typescript\n * manager.registerAction('book-flight', {\n * type: 'retry',\n * maxAttempts: 5\n * });\n *\n * manager.registerAction('charge-card', {\n * type: 'manual',\n * handler: async () => {\n * await accountingSystem.manualRefund(transactionId);\n * }\n * });\n * ```\n */\n registerAction(stepName: string, action: RecoveryAction): void {\n this.actions.set(stepName, action)\n }\n\n /**\n * Gets the registered recovery action for a step.\n *\n * @param stepName - The step name.\n * @returns The recovery action if registered, otherwise undefined.\n */\n getAction(stepName: string): RecoveryAction | undefined {\n return this.actions.get(stepName)\n }\n\n /**\n * Checks if a workflow has a pending recovery.\n *\n * @param workflowId - The workflow ID.\n * @returns True if recovery is pending.\n */\n hasPendingRecovery(workflowId: string): boolean {\n return this.pendingRecoveries.has(workflowId)\n }\n\n /**\n * Gets the pending recovery details for a workflow.\n *\n * @param workflowId - The workflow ID.\n * @returns The pending recovery details if any.\n */\n getPendingRecovery(workflowId: string): { stepName: string; error: Error } | undefined {\n return this.pendingRecoveries.get(workflowId)\n }\n\n /**\n * Marks a recovery as resolved.\n *\n * @param workflowId - The workflow ID.\n */\n resolveRecovery(workflowId: string): void {\n this.pendingRecoveries.delete(workflowId)\n }\n\n /**\n * Executes the registered recovery action for a step.\n *\n * @param stepName - The step name.\n * @returns The recovery action result.\n *\n * @example\n * ```typescript\n * const action = manager.getAction('failed-step');\n * if (action && action.type === 'manual') {\n * await manager.executeRecovery('failed-step');\n * }\n * ```\n */\n async executeRecovery(stepName: string): Promise<void> {\n const action = this.actions.get(stepName)\n\n if (!action) {\n throw Errors.noRecoveryAction(stepName)\n }\n\n if (action.type === 'manual') {\n await action.handler()\n }\n }\n\n /**\n * Clears all registered actions.\n */\n clearActions(): void {\n this.actions.clear()\n }\n\n /**\n * Clears all recovery callbacks.\n */\n clearCallbacks(): void {\n this.recoveryCallbacks = []\n }\n\n /**\n * Gets all pending recoveries.\n *\n * @returns A map of workflow IDs to pending recovery details.\n */\n getAllPendingRecoveries(): Map<string, { stepName: string; error: Error }> {\n return new Map(this.pendingRecoveries)\n }\n\n /**\n * Clears all pending recoveries.\n */\n clearPendingRecoveries(): void {\n this.pendingRecoveries.clear()\n }\n\n /**\n * Gets the count of registered callbacks.\n * @internal For testing purposes.\n */\n getCallbackCount(): number {\n return this.recoveryCallbacks.length\n }\n}\n","import type { ContextManager } from '../core/ContextManager'\nimport { IdempotencyGuard } from '../core/IdempotencyGuard'\nimport { CompensationRetryPolicy } from '../engine/CompensationRetryPolicy'\nimport { RecoveryManager } from '../engine/RecoveryManager'\nimport type { WorkflowContext, WorkflowDefinition, WorkflowStorage } from '../types'\nimport { updateWorkflowContext } from './stateUpdater'\nimport type { TraceEmitter } from './TraceEmitter'\n\n/**\n * Configuration options for the RollbackManager.\n */\nexport interface RollbackManagerConfig {\n /** Policy for retrying failed compensation steps. */\n retryPolicy?: CompensationRetryPolicy\n /** Guard for preventing duplicate compensations. */\n idempotencyGuard?: IdempotencyGuard\n /** Manager for handling manual recovery interventions. */\n recoveryManager?: RecoveryManager\n}\n\n/**\n * Manages the compensation (rollback) logic for failed workflows.\n *\n * The RollbackManager is responsible for executing `compensate` handlers defined\n * in workflow steps in reverse order when a workflow fails. This ensures eventual\n * consistency in distributed transactions (Saga pattern).\n *\n * Enhanced with:\n * - Automatic retry with exponential backoff\n * - Idempotency checks to prevent duplicate compensation\n * - Human-in-the-loop recovery for failed compensations\n *\n * @example\n * ```typescript\n * const rollbackManager = new RollbackManager(\n * storage,\n * contextManager,\n * traceEmitter\n * );\n * ```\n */\nexport class RollbackManager {\n private retryPolicy: CompensationRetryPolicy\n private idempotencyGuard: IdempotencyGuard\n private recoveryManager: RecoveryManager\n\n /**\n * Initializes the RollbackManager.\n *\n * @param storage - The storage adapter for persisting rollback progress.\n * @param contextManager - Manager for workflow context operations.\n * @param traceEmitter - Emitter for rollback-related trace events.\n * @param onPersist - Optional callback to handle custom persistence logic.\n * @param config - Optional configuration for retry, idempotency, and recovery.\n */\n constructor(\n private storage: WorkflowStorage,\n private contextManager: ContextManager,\n private traceEmitter: TraceEmitter,\n private onPersist?: (ctx: WorkflowContext<any, any>) => Promise<WorkflowContext<any, any>>,\n config?: RollbackManagerConfig\n ) {\n this.retryPolicy = config?.retryPolicy ?? new CompensationRetryPolicy()\n this.idempotencyGuard = config?.idempotencyGuard ?? new IdempotencyGuard()\n this.recoveryManager = config?.recoveryManager ?? new RecoveryManager()\n }\n\n /**\n * Executes the rollback process for a failed workflow.\n *\n * Iterates backwards from the failed step and executes the `compensate` handler\n * for each completed step that has one defined.\n *\n * @param definition - The definition of the workflow being rolled back.\n * @param ctx - The current workflow context.\n * @param failedAtIndex - The index of the step where the failure occurred.\n * @param originalError - The error that triggered the rollback.\n * @returns A promise resolving to the updated workflow context after rollback.\n * @throws {Error} If compensation logic itself fails and recovery options are exhausted.\n *\n * @example\n * ```typescript\n * const rolledBackCtx = await rollbackManager.rollback(\n * definition,\n * ctx,\n * failedIndex,\n * error\n * );\n * ```\n */\n async rollback<TInput, TData extends Record<string, any> = Record<string, any>>(\n definition: WorkflowDefinition<TInput, TData>,\n ctx: WorkflowContext<TInput, TData>,\n failedAtIndex: number,\n originalError: Error\n ): Promise<WorkflowContext<TInput, TData>> {\n let currentCtx = updateWorkflowContext(ctx, { status: 'rolling_back' })\n\n await this.traceEmitter.emit({\n type: 'workflow:rollback_start',\n timestamp: Date.now(),\n workflowId: currentCtx.id,\n workflowName: currentCtx.name,\n status: 'rolling_back',\n error: originalError.message,\n })\n\n let compensatedCount = 0\n\n for (let i = failedAtIndex - 1; i >= 0; i--) {\n const step = definition.steps[i]\n let execution = currentCtx.history[i]\n\n if (!step || !step.compensate || !execution || execution.status !== 'completed') {\n continue\n }\n\n if (this.idempotencyGuard.isCompensated(currentCtx, step.name)) {\n continue\n }\n\n try {\n execution = { ...execution, status: 'compensating' }\n currentCtx = updateWorkflowContext(currentCtx, {\n history: currentCtx.history.map((h, idx) => (idx === i ? execution : h)),\n })\n currentCtx = await this.persist(currentCtx)\n\n if (this.retryPolicy.getConfig().maxAttempts === 0) {\n await step.compensate?.(currentCtx)\n } else {\n const result = await this.retryPolicy.execute(async () => {\n await step.compensate?.(currentCtx)\n })\n\n if (!result.success) {\n throw result.error ?? new Error('Compensation failed')\n }\n }\n\n execution = { ...execution, status: 'compensated', compensatedAt: new Date() }\n currentCtx = updateWorkflowContext(currentCtx, {\n history: currentCtx.history.map((h, idx) => (idx === i ? execution : h)),\n })\n compensatedCount++\n\n await this.traceEmitter.stepCompensate(currentCtx, step.name, i)\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n\n const action = this.recoveryManager.getAction(step.name)\n\n if (action?.type === 'skip') {\n continue\n }\n\n if (action?.type === 'abort') {\n currentCtx = updateWorkflowContext(currentCtx, { status: 'compensation_failed' })\n await this.traceEmitter.emit({\n type: 'workflow:error',\n timestamp: Date.now(),\n workflowId: currentCtx.id,\n workflowName: currentCtx.name,\n status: 'compensation_failed',\n error: `Compensation aborted at step \"${step.name}\": ${error.message}`,\n })\n return currentCtx\n }\n\n await this.recoveryManager.notifyRecoveryNeeded(currentCtx, step.name, error)\n currentCtx = updateWorkflowContext(currentCtx, { status: 'compensation_failed' })\n await this.traceEmitter.emit({\n type: 'workflow:error',\n timestamp: Date.now(),\n workflowId: currentCtx.id,\n workflowName: currentCtx.name,\n status: 'compensation_failed',\n error: `Compensation failed at step \"${step.name}\": ${error.message}`,\n })\n return currentCtx\n }\n\n currentCtx = await this.persist(currentCtx)\n }\n\n if (compensatedCount > 0) {\n currentCtx = updateWorkflowContext(currentCtx, { status: 'rolled_back' })\n await this.traceEmitter.emit({\n type: 'workflow:rollback_complete',\n timestamp: Date.now(),\n workflowId: currentCtx.id,\n workflowName: currentCtx.name,\n status: 'rolled_back',\n })\n } else {\n currentCtx = updateWorkflowContext(currentCtx, { status: 'failed' })\n }\n\n return currentCtx\n }\n\n /**\n * Persists the current context using the configured mechanism.\n * @private\n */\n private async persist<TInput, TData extends Record<string, any>>(\n ctx: WorkflowContext<TInput, TData>\n ): Promise<WorkflowContext<TInput, TData>> {\n if (this.onPersist) {\n return await this.onPersist(ctx)\n } else {\n await this.storage.save(this.contextManager.toState(ctx))\n return ctx\n }\n }\n\n /**\n * Gets the retry policy instance used by this manager.\n * @returns The CompensationRetryPolicy instance.\n */\n getRetryPolicy(): CompensationRetryPolicy {\n return this.retryPolicy\n }\n\n /**\n * Gets the idempotency guard instance used by this manager.\n * @returns The IdempotencyGuard instance.\n */\n getIdempotencyGuard(): IdempotencyGuard {\n return this.idempotencyGuard\n }\n\n /**\n * Gets the recovery manager instance used by this manager.\n * @returns The RecoveryManager instance.\n */\n getRecoveryManager(): RecoveryManager {\n return this.recoveryManager\n }\n}\n","import type { FluxTraceEvent, FluxTraceSink, StepResult, WorkflowContext } from '../types'\n\n/**\n * Responsible for emitting observability events throughout the workflow lifecycle.\n *\n * TraceEmitter abstracts the underlying trace sink and provides semantic methods\n * for logging workflow and step-level events such as starts, completions, and errors.\n */\nexport class TraceEmitter {\n /**\n * Initializes the TraceEmitter.\n *\n * @param traceSink - The destination for trace events.\n */\n constructor(private traceSink?: FluxTraceSink) {}\n\n /**\n * Emits a raw trace event to the configured sink.\n *\n * @param event - The trace event to emit.\n */\n async emit(event: FluxTraceEvent): Promise<void> {\n try {\n await this.traceSink?.emit(event)\n } catch {}\n }\n\n /**\n * Emits an event indicating that a workflow has started.\n *\n * @param ctx - The workflow context at the start.\n */\n async workflowStart(ctx: WorkflowContext): Promise<void> {\n await this.emit({\n type: 'workflow:start',\n timestamp: Date.now(),\n workflowId: ctx.id,\n workflowName: ctx.name,\n status: 'running',\n input: ctx.input,\n })\n }\n\n /**\n * Emits an event indicating that a workflow has completed successfully.\n *\n * @param ctx - The final workflow context.\n * @param duration - The total execution time in milliseconds.\n */\n async workflowComplete(ctx: WorkflowContext, duration: number): Promise<void> {\n await this.emit({\n type: 'workflow:complete',\n timestamp: Date.now(),\n workflowId: ctx.id,\n workflowName: ctx.name,\n status: 'completed',\n duration,\n data: ctx.data as Record<string, unknown>,\n })\n }\n\n /**\n * Emits an event indicating that a workflow has failed.\n *\n * @param ctx - The workflow context at the time of failure.\n * @param error - The error that caused the failure.\n * @param duration - The execution time until failure in milliseconds.\n */\n async workflowError(ctx: WorkflowContext, error: Error, duration: number): Promise<void> {\n await this.emit({\n type: 'workflow:error',\n timestamp: Date.now(),\n workflowId: ctx.id,\n workflowName: ctx.name,\n status: 'failed',\n duration,\n error: error.message,\n })\n }\n\n /**\n * Emits an event indicating that a specific step has started.\n *\n * @param ctx - The current workflow context.\n * @param stepName - The name of the step.\n * @param stepIndex - The index of the step in the workflow.\n * @param commit - Whether the step is a commit step.\n */\n async stepStart(\n ctx: WorkflowContext,\n stepName: string,\n stepIndex: number,\n commit: boolean\n ): Promise<void> {\n await this.emit({\n type: 'step:start',\n timestamp: Date.now(),\n workflowId: ctx.id,\n workflowName: ctx.name,\n stepName,\n stepIndex,\n commit,\n status: 'running',\n })\n }\n\n /**\n * Emits an event indicating that a step has completed successfully.\n *\n * @param ctx - The current workflow context.\n * @param stepName - The name of the step.\n * @param stepIndex - The index of the step.\n * @param result - The result of the step execution.\n */\n async stepComplete(\n ctx: WorkflowContext,\n stepName: string,\n stepIndex: number,\n result: StepResult\n ): Promise<void> {\n await this.emit({\n type: 'step:complete',\n timestamp: Date.now(),\n workflowId: ctx.id,\n workflowName: ctx.name,\n stepName,\n stepIndex,\n duration: result.duration,\n status: 'completed',\n })\n }\n\n /**\n * Emits an event indicating that a step has failed.\n *\n * @param ctx - The current workflow context.\n * @param stepName - The name of the step.\n * @param stepIndex - The index of the step.\n * @param result - The result containing the error.\n */\n async stepError(\n ctx: WorkflowContext,\n stepName: string,\n stepIndex: number,\n result: StepResult\n ): Promise<void> {\n await this.emit({\n type: 'step:error',\n timestamp: Date.now(),\n workflowId: ctx.id,\n workflowName: ctx.name,\n stepName,\n stepIndex,\n duration: result.duration,\n error: result.error?.message,\n status: 'failed',\n })\n }\n\n /**\n * Emits an event indicating that a step has been suspended.\n *\n * @param ctx - The current workflow context.\n * @param stepName - The name of the step.\n * @param stepIndex - The index of the step.\n * @param signal - The name of the signal the step is waiting for.\n */\n async stepSuspended(\n ctx: WorkflowContext,\n stepName: string,\n stepIndex: number,\n signal: string\n ): Promise<void> {\n await this.emit({\n type: 'step:suspend',\n timestamp: Date.now(),\n workflowId: ctx.id,\n workflowName: ctx.name,\n stepName,\n stepIndex,\n meta: { signal },\n })\n }\n\n /**\n * Emits an event indicating that a step's compensation logic has been executed.\n *\n * @param ctx - The current workflow context.\n * @param stepName - The name of the step being compensated.\n * @param stepIndex - The index of the step.\n */\n async stepCompensate(ctx: WorkflowContext, stepName: string, stepIndex: number): Promise<void> {\n await this.emit({\n type: 'step:compensate',\n timestamp: Date.now(),\n workflowId: ctx.id,\n workflowName: ctx.name,\n stepName,\n stepIndex,\n status: 'compensated',\n })\n }\n}\n","import type { StepDefinition, StepExecution, WorkflowContext } from '../types'\n\n/**\n * Result of a parallel group execution.\n *\n * Contains categorized lists of successful and failed step executions.\n */\nexport interface ParallelExecutionResult<\n TInput = unknown,\n TData extends Record<string, any> = Record<string, any>,\n> {\n /** List of execution records for steps that completed successfully. */\n successes: StepExecution[]\n /** List of failures containing the step definition, the error, and the partial execution record. */\n failures: Array<{ step: StepDefinition<TInput, TData>; error: Error; execution: StepExecution }>\n}\n\n/**\n * Orchestrates the concurrent execution of multiple workflow steps.\n *\n * The ParallelExecutor manages the simultaneous execution of a group of steps,\n * collecting results and aggregating success/failure states. It uses `Promise.allSettled`\n * to ensure all steps are attempted even if some fail.\n *\n * @example\n * ```typescript\n * const parallelExecutor = new ParallelExecutor();\n * const { successes, failures } = await parallelExecutor.executeGroup(steps, ctx, runStepFn);\n * ```\n */\nexport class ParallelExecutor {\n /**\n * Executes a list of steps concurrently.\n *\n * @param steps - The definitions of the steps to run in parallel.\n * @param ctx - The shared workflow context.\n * @param executeStep - A callback function to execute a single step.\n * @returns A promise resolving to the aggregated execution results.\n */\n async executeGroup<TInput = unknown, TData extends Record<string, any> = Record<string, any>>(\n steps: StepDefinition<TInput, TData>[],\n ctx: WorkflowContext<TInput, TData>,\n executeStep: (\n step: StepDefinition<TInput, TData>,\n ctx: WorkflowContext<TInput, TData>\n ) => Promise<{ ctx: WorkflowContext<TInput, TData>; execution: StepExecution }>\n ): Promise<ParallelExecutionResult<TInput, TData>> {\n const results = await Promise.allSettled(\n steps.map(async (step, index) => {\n try {\n const result = await executeStep(step, ctx)\n return { step, result, index, success: true as const }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error))\n return { step, error: err, index, success: false as const }\n }\n })\n )\n\n const successes: StepExecution[] = []\n const failures: Array<{\n step: StepDefinition<TInput, TData>\n error: Error\n execution: StepExecution\n }> = []\n\n for (const promiseResult of results) {\n if (promiseResult.status === 'fulfilled') {\n const value = promiseResult.value\n if (value.success) {\n successes.push(value.result.execution)\n } else {\n const failedExecution: StepExecution = {\n name: value.step.name,\n status: 'failed',\n startedAt: new Date(),\n error: value.error.message,\n retries: 0,\n }\n failures.push({\n step: value.step,\n error: value.error,\n execution: failedExecution,\n })\n }\n } else {\n const error =\n promiseResult.reason instanceof Error\n ? promiseResult.reason\n : new Error(String(promiseResult.reason))\n\n const failedExecution: StepExecution = {\n name: 'unknown-step',\n status: 'failed',\n startedAt: new Date(),\n error: error.message,\n retries: 0,\n }\n\n failures.push({\n step: steps[0]!,\n error,\n execution: failedExecution,\n })\n }\n }\n\n return { successes, failures }\n }\n}\n","import type { ContextManager } from '../core/ContextManager'\nimport type { DataOptimizer } from '../core/DataOptimizer'\nimport type { StateMachine } from '../core/StateMachine'\nimport type { StepExecutor } from '../core/StepExecutor'\nimport type {\n FluxConfig,\n FluxResult,\n StepDefinition,\n WorkflowContext,\n WorkflowDefinition,\n WorkflowStorage,\n} from '../types'\nimport { ParallelExecutor } from './ParallelExecutor'\nimport { updateWorkflowContext } from './stateUpdater'\nimport type { TraceEmitter } from './TraceEmitter'\n\n/**\n * Internal component responsible for the sequential execution of workflow steps.\n *\n * WorkflowExecutor handles the iteration over steps, interaction with the StepExecutor,\n * state machine transitions, and persistence between steps. It also coordinates\n * parallel execution groups.\n *\n * @example\n * ```typescript\n * const executor = new WorkflowExecutor(\n * storage,\n * contextManager,\n * stepExecutor,\n * traceEmitter\n * );\n * ```\n */\nexport class WorkflowExecutor {\n private parallelExecutor: ParallelExecutor\n\n /**\n * Initializes the WorkflowExecutor.\n *\n * @param storage - The storage adapter for persistence.\n * @param contextManager - Manager for workflow context operations.\n * @param stepExecutor - Executor for individual steps.\n * @param traceEmitter - Emitter for execution-related trace events.\n * @param config - Global engine configuration.\n * @param onPersist - Optional callback for custom persistence logic.\n */\n constructor(\n private storage: WorkflowStorage,\n private contextManager: ContextManager,\n private stepExecutor: StepExecutor,\n private traceEmitter: TraceEmitter,\n private config: FluxConfig = {},\n private onPersist?: (ctx: WorkflowContext<any, any>) => Promise<WorkflowContext<any, any>>,\n private optimizer?: DataOptimizer\n ) {\n this.parallelExecutor = new ParallelExecutor()\n }\n\n /**\n * Executes the steps of a workflow definition.\n *\n * This method manages the loop over workflow steps, handling suspensions,\n * failures, and successful completions. It delegates parallel step groups\n * to the ParallelExecutor.\n *\n * @param definition - The workflow definition to execute.\n * @param ctx - The current workflow context.\n * @param stateMachine - The state machine governing the workflow status.\n * @param startTime - The timestamp when the workflow execution originally started.\n * @param startIndex - The index of the step to start execution from.\n * @param meta - Metadata about the execution (e.g., if it's a resume or retry).\n * @returns A promise resolving to the result of the workflow execution.\n * @throws {Error} If execution fails and no rollback/recovery was successful (handled internally but re-thrown if critical).\n *\n * @example\n * ```typescript\n * const result = await executor.execute(definition, ctx, stateMachine, Date.now(), 0);\n * ```\n */\n async execute<TInput, TData extends Record<string, any> = Record<string, any>>(\n definition: WorkflowDefinition<TInput, TData>,\n ctx: WorkflowContext<TInput, TData>,\n stateMachine: StateMachine,\n startTime: number,\n startIndex: number,\n meta?: { resume?: boolean; retry?: boolean; fromStep?: number }\n ): Promise<FluxResult<TData>> {\n let currentCtx = ctx\n try {\n if (stateMachine.canExecute()) {\n stateMachine.transition('running')\n currentCtx = updateWorkflowContext(currentCtx, { status: 'running' })\n }\n\n if (!meta?.resume && !meta?.retry) {\n await this.traceEmitter.workflowStart(currentCtx)\n }\n\n for (let i = startIndex; i < definition.steps.length; ) {\n const step = definition.steps[i]!\n\n if (step.parallelGroup) {\n const { lastIndex, updatedCtx, result } = await this.executeParallelGroup(\n definition,\n currentCtx,\n i,\n startTime\n )\n currentCtx = updatedCtx\n currentCtx = await this.persist(currentCtx)\n if (result) {\n return result\n }\n i = lastIndex + 1\n } else {\n const { updatedCtx, shouldReturn, result } = await this.executeSequentialStep(\n definition,\n currentCtx,\n i,\n startTime,\n stateMachine\n )\n currentCtx = updatedCtx\n currentCtx = await this.persist(currentCtx)\n if (shouldReturn && result) {\n return result\n }\n i++\n }\n }\n\n stateMachine.transition('completed')\n currentCtx = updateWorkflowContext(currentCtx, { status: 'completed' })\n\n currentCtx = await this.persist(currentCtx)\n\n this.config.on?.workflowComplete?.(currentCtx)\n await this.traceEmitter.workflowComplete(currentCtx, Date.now() - startTime)\n\n return {\n id: currentCtx.id,\n status: 'completed',\n data: currentCtx.data as TData,\n history: currentCtx.history,\n duration: Date.now() - startTime,\n version: currentCtx.version,\n }\n } catch (error) {\n console.log(\n 'In catch block, history:',\n currentCtx.history.map((h) => ({ name: h.name, status: h.status }))\n )\n const err = error instanceof Error ? error : new Error(String(error))\n stateMachine.forceStatus('failed')\n currentCtx = updateWorkflowContext(currentCtx, { status: 'failed' })\n\n currentCtx = await this.persist(currentCtx)\n\n this.config.on?.workflowError?.(currentCtx, err)\n await this.traceEmitter.workflowError(currentCtx, err, Date.now() - startTime)\n\n return {\n id: currentCtx.id,\n status: 'failed',\n data: currentCtx.data as TData,\n history: currentCtx.history,\n duration: Date.now() - startTime,\n error: err,\n version: currentCtx.version,\n }\n }\n }\n\n /**\n * Executes a single sequential step.\n * @private\n */\n private async executeSequentialStep<TInput, TData extends Record<string, any>>(\n definition: WorkflowDefinition<TInput, TData>,\n ctx: WorkflowContext<TInput, TData>,\n index: number,\n startTime: number,\n stateMachine: StateMachine\n ): Promise<{\n updatedCtx: WorkflowContext<TInput, TData>\n shouldReturn: boolean\n result?: FluxResult<TData>\n }> {\n const step = definition.steps[index]!\n let execution = ctx.history[index]!\n let currentCtx = ctx\n\n currentCtx = this.contextManager.setStepName(currentCtx, index, step.name)\n execution = currentCtx.history[index]!\n currentCtx = updateWorkflowContext(currentCtx, { currentStep: index })\n\n this.config.on?.stepStart?.(step.name, currentCtx)\n await this.traceEmitter.stepStart(currentCtx, step.name, index, Boolean(step.commit))\n\n const { result, execution: updatedExecution } = await this.stepExecutor.execute(\n step,\n currentCtx,\n execution\n )\n execution = updatedExecution\n currentCtx = updateWorkflowContext(currentCtx, {\n history: currentCtx.history.map((h, idx) => (idx === index ? execution : h)),\n })\n\n if (result.success) {\n if (result.suspended) {\n stateMachine.transition('suspended')\n currentCtx = updateWorkflowContext(currentCtx, { status: 'suspended' })\n await this.traceEmitter.stepSuspended(currentCtx, step.name, index, result.waitingFor!)\n\n const suspendedResult: FluxResult<TData> = {\n id: currentCtx.id,\n status: 'suspended',\n data: currentCtx.data as TData,\n history: currentCtx.history,\n duration: Date.now() - startTime,\n version: currentCtx.version,\n }\n return { updatedCtx: currentCtx, shouldReturn: true, result: suspendedResult }\n }\n\n this.config.on?.stepComplete?.(step.name, currentCtx, result)\n await this.traceEmitter.stepComplete(currentCtx, step.name, index, result)\n } else {\n await this.traceEmitter.stepError(currentCtx, step.name, index, result)\n const failedResult: FluxResult<TData> = {\n id: currentCtx.id,\n status: 'failed',\n data: currentCtx.data as TData,\n history: currentCtx.history,\n duration: Date.now() - startTime,\n error: result.error,\n version: currentCtx.version,\n }\n return { updatedCtx: currentCtx, shouldReturn: true, result: failedResult }\n }\n\n return { updatedCtx: currentCtx, shouldReturn: false }\n }\n\n /**\n * Executes a group of parallel steps.\n * @private\n */\n private async executeParallelGroup<TInput, TData extends Record<string, any>>(\n definition: WorkflowDefinition<TInput, TData>,\n ctx: WorkflowContext<TInput, TData>,\n startIndex: number,\n startTime: number\n ): Promise<{\n lastIndex: number\n updatedCtx: WorkflowContext<TInput, TData>\n result?: FluxResult<TData>\n }> {\n const firstStep = definition.steps[startIndex]!\n const groupId = firstStep.parallelGroup!\n const groupSteps: Array<{ step: StepDefinition<TInput, TData>; index: number }> = []\n\n for (let i = startIndex; i < definition.steps.length; i++) {\n const step = definition.steps[i]!\n if (step.parallelGroup === groupId) {\n groupSteps.push({ step, index: i })\n } else {\n break\n }\n }\n\n const lastIndex = groupSteps[groupSteps.length - 1]?.index\n let currentCtx = ctx\n\n const executeStepWrapper = async (\n step: StepDefinition<TInput, TData>,\n stepCtx: WorkflowContext<TInput, TData>\n ) => {\n const stepIndex = groupSteps.find((gs) => gs.step === step)?.index\n let execution = stepCtx.history[stepIndex!]!\n\n const localCtx = this.contextManager.setStepName(stepCtx, stepIndex!, step.name)\n execution = localCtx.history[stepIndex!]!\n\n this.config.on?.stepStart?.(step.name, localCtx)\n await this.traceEmitter.stepStart(localCtx, step.name, stepIndex!, Boolean(step.commit))\n\n const { result, execution: updatedExecution } = await this.stepExecutor.execute(\n step,\n localCtx,\n execution\n )\n\n if (result.success) {\n this.config.on?.stepComplete?.(step.name, localCtx, result)\n await this.traceEmitter.stepComplete(localCtx, step.name, stepIndex!, result)\n } else {\n await this.traceEmitter.stepError(localCtx, step.name, stepIndex!, result)\n throw result.error || new Error(`Step ${step.name} failed`)\n }\n\n return { ctx: localCtx, execution: updatedExecution }\n }\n\n try {\n const parallelResult = await this.parallelExecutor.executeGroup(\n groupSteps.map((gs) => gs.step),\n currentCtx,\n executeStepWrapper\n )\n\n for (const execution of parallelResult.successes) {\n const stepIndex = groupSteps.find((gs) => gs.step.name === execution.name)?.index\n currentCtx = updateWorkflowContext(currentCtx, {\n history: currentCtx.history.map((h, idx) => (idx === stepIndex ? execution : h)),\n })\n }\n\n for (const failure of parallelResult.failures) {\n const stepIndex = groupSteps.find((gs) => gs.step.name === failure.step.name)?.index\n currentCtx = updateWorkflowContext(currentCtx, {\n history: currentCtx.history.map((h, idx) => (idx === stepIndex ? failure.execution : h)),\n })\n }\n\n if (parallelResult.failures.length > 0) {\n const firstFailure = parallelResult.failures[0]!\n const failedResult: FluxResult<TData> = {\n id: currentCtx.id,\n status: 'failed',\n data: currentCtx.data as TData,\n history: currentCtx.history,\n duration: Date.now() - startTime,\n error: firstFailure.error,\n version: currentCtx.version,\n }\n return { lastIndex, updatedCtx: currentCtx, result: failedResult }\n }\n\n return { lastIndex, updatedCtx: currentCtx }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error))\n const failedResult: FluxResult<TData> = {\n id: currentCtx.id,\n status: 'failed',\n data: currentCtx.data as TData,\n history: currentCtx.history,\n duration: Date.now() - startTime,\n error: err,\n version: currentCtx.version,\n }\n return { lastIndex, updatedCtx: currentCtx, result: failedResult }\n }\n }\n\n /**\n * Persists the context to storage.\n * @private\n */\n private async persist<TInput, TData extends Record<string, any>>(\n ctx: WorkflowContext<TInput, TData>\n ): Promise<WorkflowContext<TInput, TData>> {\n let currentCtx = ctx\n if (this.optimizer) {\n const optimizedData = this.optimizer.optimizeForStorage(ctx.data) as TData\n currentCtx = updateWorkflowContext(ctx, { data: optimizedData })\n }\n\n if (this.onPersist) {\n return await this.onPersist(currentCtx)\n } else {\n await this.storage.save(this.contextManager.toState(currentCtx))\n return currentCtx\n }\n }\n}\n","import type { WorkflowBuilder } from '../builder/WorkflowBuilder'\nimport { ContextManager } from '../core/ContextManager'\nimport { DataOptimizer } from '../core/DataOptimizer'\nimport { StateMachine } from '../core/StateMachine'\nimport { CompensationRetryPolicy } from '../engine/CompensationRetryPolicy'\nimport * as Errors from '../errors'\nimport { CronTrigger } from '../orbit/CronTrigger'\nimport { MemoryStorage } from '../storage/MemoryStorage'\nimport type {\n CronScheduleOptions,\n FluxConfig,\n FluxResult,\n WorkflowContext,\n WorkflowDefinition,\n WorkflowState,\n WorkflowStorage,\n} from '../types'\nimport { type BatchExecutionOptions, BatchExecutor, type BatchResult } from './BatchExecutor'\nimport {\n acquireEngineLock,\n createStepExecutor,\n handleExecutionResult,\n persistContext,\n resetHistoryFrom,\n resolveDefinition,\n resolveStartIndex,\n} from './FluxEngineHelpers'\nimport { RollbackManager } from './RollbackManager'\nimport { updateWorkflowContext } from './stateUpdater'\nimport { TraceEmitter } from './TraceEmitter'\nimport { WorkflowExecutor } from './WorkflowExecutor'\n\n/**\n * The core execution engine for Flux workflows.\n *\n * FluxEngine manages the lifecycle of workflow execution, including persistence,\n * state transitions, retries, and compensation (rollback) logic. It acts as the\n * primary entry point for interacting with the workflow system.\n *\n * @example\n * ```typescript\n * const engine = new FluxEngine({\n * storage: new MemoryStorage(),\n * defaultRetries: 3\n * });\n * await engine.init();\n * const result = await engine.execute(myWorkflow, { userId: '123' });\n * ```\n */\nexport class FluxEngine {\n private storage: WorkflowStorage\n private contextManager: ContextManager\n private traceEmitter: TraceEmitter\n private executor: WorkflowExecutor\n private rollbackManager: RollbackManager\n private cronTrigger: CronTrigger\n private dataOptimizer?: DataOptimizer\n\n constructor(config: FluxConfig = {}) {\n this.storage = config.storage ?? new MemoryStorage()\n this.contextManager = new ContextManager()\n this.traceEmitter = new TraceEmitter(config.trace)\n\n if (config.optimizer?.enabled) {\n this.dataOptimizer = new DataOptimizer({\n threshold: config.optimizer.threshold,\n defaultLocation: config.optimizer.defaultLocation,\n })\n }\n\n const stepExecutor = createStepExecutor(config, this.traceEmitter)\n const persist = (ctx: WorkflowContext<any, any>) => this.persist(ctx)\n\n this.executor = new WorkflowExecutor(\n this.storage,\n this.contextManager,\n stepExecutor,\n this.traceEmitter,\n config,\n persist,\n this.dataOptimizer\n )\n\n this.rollbackManager = new RollbackManager(\n this.storage,\n this.contextManager,\n this.traceEmitter,\n persist,\n {\n retryPolicy: new CompensationRetryPolicy({\n maxAttempts: config.defaultRetries !== undefined ? config.defaultRetries : 3,\n }),\n }\n )\n\n this.cronTrigger = new CronTrigger(this)\n this.config = config\n }\n\n private config: FluxConfig\n\n async execute<TInput, TData extends Record<string, any> = Record<string, any>>(\n workflow: WorkflowBuilder<TInput, TData> | WorkflowDefinition<TInput, TData>,\n input: TInput\n ): Promise<FluxResult<TData>> {\n const definition = resolveDefinition(workflow)\n if (definition.validateInput && !definition.validateInput(input)) {\n throw Errors.invalidInput(definition.name)\n }\n\n let ctx = this.contextManager.create<TInput, TData>(\n definition.name,\n input,\n definition.steps.length\n ) as WorkflowContext<TInput, TData>\n\n ctx = await this.persist(ctx, definition.version)\n return this.executeWithLock(definition, ctx, 0, {}, Date.now())\n }\n\n async executeBatch<TInput, TData extends Record<string, any> = Record<string, any>>(\n workflow: WorkflowBuilder<TInput, TData> | WorkflowDefinition<TInput, TData>,\n inputs: TInput[],\n options?: BatchExecutionOptions\n ): Promise<BatchResult<TData>> {\n const executor = new BatchExecutor(this)\n return executor.execute(workflow, inputs, options)\n }\n\n private async executeWithLock<TInput, TData extends Record<string, any>>(\n definition: WorkflowDefinition<TInput, TData>,\n ctx: WorkflowContext<TInput, TData>,\n startIndex: number,\n options: any,\n startTime?: number\n ): Promise<FluxResult<TData>> {\n const lock = await acquireEngineLock(this.config, ctx.id)\n try {\n const result = await this.executor.execute(\n definition,\n ctx,\n new StateMachine(),\n startTime ?? Date.now(),\n startIndex,\n options\n )\n return handleExecutionResult(\n definition,\n ctx,\n result,\n this.contextManager,\n this.rollbackManager,\n this.storage\n )\n } finally {\n await lock?.release()\n }\n }\n\n async resume<TInput, TData extends Record<string, any> = Record<string, any>>(\n workflow: WorkflowBuilder<TInput, TData> | WorkflowDefinition<TInput, TData>,\n workflowId: string,\n options?: { fromStep?: number | string }\n ): Promise<FluxResult<TData> | null> {\n const definition = resolveDefinition(workflow)\n const state = await this.storage.load(workflowId)\n if (!state || state.name !== definition.name) {\n if (!state) {\n return null\n }\n throw Errors.workflowNameMismatch(definition.name, state.name)\n }\n if (state.history.length !== definition.steps.length) {\n throw Errors.workflowDefinitionChanged()\n }\n\n if (\n state.definitionVersion &&\n definition.version &&\n state.definitionVersion !== definition.version\n ) {\n this.config.logger?.warn(\n `Workflow version mismatch: instance was created with v${state.definitionVersion}, ` +\n `but current definition is v${definition.version}. Continuing execution.`\n )\n }\n\n let ctx = this.contextManager.restore<TInput, TData>(\n state as unknown as WorkflowState<TInput, TData>\n )\n const startIndex = resolveStartIndex(definition, options?.fromStep, ctx.currentStep)\n resetHistoryFrom(ctx, startIndex)\n ctx = updateWorkflowContext(ctx, { status: 'pending', currentStep: startIndex })\n ctx = await this.persist(ctx)\n\n return this.executeWithLock(definition, ctx, startIndex, { resume: true, fromStep: startIndex })\n }\n\n async signal<TInput, TData extends Record<string, any> = Record<string, any>>(\n workflow: WorkflowBuilder<TInput, TData> | WorkflowDefinition<TInput, TData>,\n workflowId: string,\n signalName: string,\n payload?: any\n ): Promise<FluxResult<TData>> {\n const definition = resolveDefinition(workflow)\n const state = await this.storage.load(workflowId)\n if (!state) {\n throw Errors.workflowNotFound(workflowId)\n }\n if (state.status !== 'suspended') {\n throw Errors.workflowNotSuspended(state.status)\n }\n\n let ctx = this.contextManager.restore<TInput, TData>(\n state as unknown as WorkflowState<TInput, TData>\n )\n const idx = ctx.currentStep\n const exec = ctx.history[idx]\n\n if (!exec || exec.status !== 'suspended' || exec.waitingFor !== signalName) {\n const isSuspended = exec?.status === 'suspended'\n throw new Errors.FluxError(\n isSuspended\n ? `Workflow waiting for signal \"${exec.waitingFor}\", received \"${signalName}\"`\n : 'Workflow state invalid: no suspended step found',\n isSuspended\n ? Errors.FluxErrorCode.INVALID_STATE_TRANSITION\n : Errors.FluxErrorCode.STEP_NOT_FOUND\n )\n }\n\n ctx = updateWorkflowContext(ctx, {\n history: ctx.history.map((h, i) =>\n i === idx\n ? { ...h, status: 'completed' as const, completedAt: new Date(), output: payload }\n : h\n ),\n })\n\n await this.traceEmitter.emit({\n type: 'signal:received',\n timestamp: Date.now(),\n workflowId: ctx.id,\n workflowName: ctx.name,\n status: 'suspended',\n input: payload,\n })\n\n return this.executeWithLock(definition, ctx, idx + 1, { resume: true, fromStep: idx + 1 })\n }\n\n async retryStep<TInput, TData extends Record<string, any> = Record<string, any>>(\n workflow: WorkflowBuilder<TInput, TData> | WorkflowDefinition<TInput, TData>,\n workflowId: string,\n stepName: string\n ): Promise<FluxResult<TData> | null> {\n const definition = resolveDefinition(workflow)\n const state = await this.storage.load(workflowId)\n if (!state || state.name !== definition.name) {\n if (!state) {\n return null\n }\n throw Errors.workflowNameMismatch(definition.name, state.name)\n }\n if (state.history.length !== definition.steps.length) {\n throw Errors.workflowDefinitionChanged()\n }\n\n let ctx = this.contextManager.restore<TInput, TData>(\n state as unknown as WorkflowState<TInput, TData>\n )\n const idx = resolveStartIndex(definition, stepName, ctx.currentStep)\n resetHistoryFrom(ctx, idx)\n ctx = updateWorkflowContext(ctx, { status: 'pending', currentStep: idx })\n ctx = await this.persist(ctx)\n\n return this.executeWithLock(definition, ctx, idx, { retry: true, fromStep: idx })\n }\n\n /**\n * Retrieves the current state of a workflow instance from storage.\n *\n * @param workflowId - The unique identifier of the workflow.\n * @returns A promise resolving to the workflow state or null if not found.\n */\n async get<TInput = any, TData = any>(\n workflowId: string\n ): Promise<WorkflowState<TInput, TData> | null> {\n return this.storage.load(workflowId) as Promise<WorkflowState<TInput, TData> | null>\n }\n\n async saveState<TInput, TData extends Record<string, any>>(\n state: WorkflowState<TInput, TData>\n ): Promise<void> {\n const stored = await this.storage.load(state.id)\n if (stored && stored.version !== state.version) {\n throw new Errors.FluxError(\n 'Concurrent modification detected',\n Errors.FluxErrorCode.CONCURRENT_MODIFICATION\n )\n }\n return this.storage.save({ ...state, version: state.version + 1 } as WorkflowState)\n }\n\n async list(filter?: Parameters<WorkflowStorage['list']>[0]) {\n return this.storage.list(filter)\n }\n\n schedule<TInput, TData extends Record<string, any>>(\n cron: string,\n workflow: WorkflowBuilder<TInput, TData> | WorkflowDefinition<TInput, TData>,\n input: TInput,\n id = `schedule_${Date.now()}`\n ): string {\n this.cronTrigger.addSchedule({\n id,\n cron,\n workflow: resolveDefinition(workflow) as any,\n input,\n enabled: true,\n })\n return id\n }\n\n unschedule(id: string): void {\n this.cronTrigger.removeSchedule(id)\n }\n\n /**\n * Lists all active workflow schedules.\n */\n listSchedules(): CronScheduleOptions[] {\n return this.cronTrigger.listSchedules()\n }\n\n /**\n * Gets the recovery manager for handling manual intervention.\n */\n getRecoveryManager() {\n return this.rollbackManager.getRecoveryManager()\n }\n\n /**\n * Gets the lock provider used for cluster mode.\n */\n getLockProvider() {\n return this.config.lockProvider\n }\n\n /**\n * Initializes the engine and its underlying storage, and starts the scheduler.\n */\n async init(): Promise<void> {\n await this.storage.init?.()\n this.cronTrigger.start()\n }\n\n /**\n * Closes the engine and releases storage resources.\n */\n async close(): Promise<void> {\n this.cronTrigger.stop()\n await this.storage.close?.()\n }\n\n private async persist<TInput, TData extends Record<string, any>>(\n ctx: WorkflowContext<TInput, TData>,\n definitionVersion?: string\n ): Promise<WorkflowContext<TInput, TData>> {\n return persistContext(ctx, this.storage, this.contextManager, definitionVersion)\n }\n}\n","import type { WorkflowFilter, WorkflowState, WorkflowStorage } from '../types'\n\n/**\n * Configuration options for the PostgreSQL storage adapter.\n *\n * Defines connection parameters and database schema settings.\n */\nexport interface PostgreSQLStorageOptions {\n /** Connection string URL (e.g. \"postgres://user:pass@host:5432/db\"). */\n connectionString?: string\n /** Database host address. */\n host?: string\n /** Database port number. @default 5432 */\n port?: number\n /** Database name. @default \"postgres\" */\n database?: string\n /** Database user. */\n user?: string\n /** Database password. */\n password?: string\n /** Name of the table to store workflows. @default \"flux_workflows\" */\n tableName?: string\n /** SSL configuration for secure connections. */\n ssl?: boolean | { rejectUnauthorized?: boolean }\n}\n\n/**\n * PostgreSQL storage adapter for Flux workflows.\n *\n * Provides persistent, reliable storage using a PostgreSQL database.\n * Supports JSONB for efficient storage of workflow state and history.\n *\n * @example\n * ```typescript\n * const storage = new PostgreSQLStorage({\n * connectionString: process.env.DATABASE_URL,\n * tableName: 'my_workflows'\n * });\n * await storage.init();\n * ```\n */\nexport class PostgreSQLStorage implements WorkflowStorage {\n private pool: any\n private tableName: string\n private initialized = false\n private options: PostgreSQLStorageOptions\n\n /**\n * Creates a new PostgreSQL storage instance.\n *\n * @param options - Connection and configuration options.\n */\n constructor(options: PostgreSQLStorageOptions = {}) {\n this.options = options\n this.tableName = options.tableName ?? 'flux_workflows'\n }\n\n /**\n * Initializes the database connection pool and schema.\n *\n * Creates the workflow table and indexes if they do not exist.\n * This method is idempotent.\n *\n * @throws {Error} If connection fails or schema creation fails.\n */\n async init(): Promise<void> {\n if (this.initialized) {\n return\n }\n\n const { Pool } = await import('pg')\n\n const config: any = this.options.connectionString\n ? { connectionString: this.options.connectionString }\n : {\n host: this.options.host ?? 'localhost',\n port: this.options.port ?? 5432,\n database: this.options.database ?? 'postgres',\n user: this.options.user,\n password: this.options.password,\n }\n\n if (this.options.ssl !== undefined) {\n config.ssl = this.options.ssl\n }\n\n this.pool = new Pool(config)\n\n await this.pool.query(`\n CREATE TABLE IF NOT EXISTS ${this.tableName} (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n status TEXT NOT NULL,\n input JSONB NOT NULL,\n data JSONB NOT NULL,\n current_step INTEGER NOT NULL,\n history JSONB NOT NULL,\n error TEXT,\n created_at TIMESTAMPTZ NOT NULL,\n updated_at TIMESTAMPTZ NOT NULL,\n completed_at TIMESTAMPTZ,\n version INTEGER NOT NULL DEFAULT 1,\n definition_version TEXT\n )\n `)\n\n await this.pool.query(`\n CREATE INDEX IF NOT EXISTS idx_${this.tableName}_name \n ON ${this.tableName}(name)\n `)\n await this.pool.query(`\n CREATE INDEX IF NOT EXISTS idx_${this.tableName}_status \n ON ${this.tableName}(status)\n `)\n await this.pool.query(`\n CREATE INDEX IF NOT EXISTS idx_${this.tableName}_created \n ON ${this.tableName}(created_at DESC)\n `)\n\n this.initialized = true\n }\n\n /**\n * Persists the current state of a workflow.\n *\n * Uses upsert (INSERT ... ON CONFLICT) to save or update the workflow state.\n *\n * @param state - The workflow state to save.\n * @throws {Error} If the database operation fails.\n */\n async save(state: WorkflowState): Promise<void> {\n await this.init()\n\n await this.pool.query(\n `\n INSERT INTO ${this.tableName} \n (id, name, status, input, data, current_step, history, error, created_at, updated_at, completed_at, version, definition_version)\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)\n ON CONFLICT (id) DO UPDATE SET\n name = EXCLUDED.name,\n status = EXCLUDED.status,\n input = EXCLUDED.input,\n data = EXCLUDED.data,\n current_step = EXCLUDED.current_step,\n history = EXCLUDED.history,\n error = EXCLUDED.error,\n updated_at = EXCLUDED.updated_at,\n completed_at = EXCLUDED.completed_at,\n version = EXCLUDED.version,\n definition_version = EXCLUDED.definition_version\n `,\n [\n state.id,\n state.name,\n state.status,\n JSON.stringify(state.input),\n JSON.stringify(state.data),\n state.currentStep,\n JSON.stringify(state.history),\n state.error ?? null,\n state.createdAt,\n new Date(),\n state.completedAt ?? null,\n state.version,\n state.definitionVersion ?? null,\n ]\n )\n }\n\n /**\n * Loads a workflow state by its ID.\n *\n * @param id - The unique identifier of the workflow.\n * @returns The workflow state, or null if not found.\n * @throws {Error} If the database query fails.\n */\n async load(id: string): Promise<WorkflowState | null> {\n await this.init()\n\n const result = await this.pool.query(`SELECT * FROM ${this.tableName} WHERE id = $1`, [id])\n\n if (result.rows.length === 0) {\n return null\n }\n\n return this.rowToState(result.rows[0])\n }\n\n /**\n * Lists workflows matching the given filter.\n *\n * @param filter - Criteria to filter the results.\n * @returns A list of matching workflow states.\n * @throws {Error} If the database query fails.\n */\n async list(filter?: WorkflowFilter): Promise<WorkflowState[]> {\n await this.init()\n\n let query = `SELECT * FROM ${this.tableName} WHERE 1=1`\n const params: unknown[] = []\n let paramIndex = 1\n\n if (filter?.name) {\n query += ` AND name = $${paramIndex++}`\n params.push(filter.name)\n }\n\n if (filter?.status) {\n if (Array.isArray(filter.status)) {\n const placeholders = filter.status.map(() => `$${paramIndex++}`).join(', ')\n query += ` AND status IN (${placeholders})`\n params.push(...filter.status)\n } else {\n query += ` AND status = $${paramIndex++}`\n params.push(filter.status)\n }\n }\n\n if (filter?.version) {\n query += ` AND definition_version = $${paramIndex++}`\n params.push(filter.version)\n }\n\n query += ' ORDER BY created_at DESC'\n\n if (filter?.limit) {\n query += ` LIMIT $${paramIndex++}`\n params.push(filter.limit)\n }\n\n if (filter?.offset) {\n query += ` OFFSET $${paramIndex++}`\n params.push(filter.offset)\n }\n\n const result = await this.pool.query(query, params)\n\n return result.rows.map((row: PostgreSQLRow) => this.rowToState(row))\n }\n\n /**\n * Deletes a workflow state by its ID.\n *\n * @param id - The unique identifier of the workflow to delete.\n * @throws {Error} If the database operation fails.\n */\n async delete(id: string): Promise<void> {\n await this.init()\n\n await this.pool.query(`DELETE FROM ${this.tableName} WHERE id = $1`, [id])\n }\n\n /**\n * Closes the database connection pool.\n *\n * Should be called when shutting down the application.\n */\n async close(): Promise<void> {\n if (this.pool) {\n await this.pool.end()\n this.initialized = false\n }\n }\n\n /**\n * Converts a database row to a WorkflowState object.\n *\n * @param row - The raw database row.\n * @returns The parsed workflow state.\n */\n private rowToState(row: PostgreSQLRow): WorkflowState {\n return {\n id: row.id,\n name: row.name,\n status: row.status as WorkflowState['status'],\n input: typeof row.input === 'string' ? JSON.parse(row.input) : row.input,\n data: typeof row.data === 'string' ? JSON.parse(row.data) : row.data,\n currentStep: row.current_step,\n history: typeof row.history === 'string' ? JSON.parse(row.history) : row.history,\n error: row.error ?? undefined,\n createdAt: new Date(row.created_at),\n updatedAt: new Date(row.updated_at),\n completedAt: row.completed_at ? new Date(row.completed_at) : undefined,\n version: row.version,\n definitionVersion: row.definition_version ?? undefined,\n }\n }\n\n /**\n * Returns the underlying pg.Pool instance.\n *\n * Useful for testing or advanced database operations.\n *\n * @returns The PostgreSQL connection pool.\n */\n getPool(): any {\n return this.pool\n }\n\n /**\n * Optimizes the database table by reclaiming storage and updating statistics.\n *\n * Runs VACUUM ANALYZE on the workflow table.\n *\n * @throws {Error} If the maintenance operation fails.\n */\n async vacuum(): Promise<void> {\n await this.init()\n await this.pool.query('VACUUM ANALYZE')\n }\n}\n\n/**\n * Internal interface for PostgreSQL row structure.\n */\ninterface PostgreSQLRow {\n id: string\n name: string\n status: string\n input: string | object\n data: string | object\n current_step: number\n history: string | object\n error: string | null\n created_at: string | Date\n updated_at: string | Date\n completed_at: string | Date | null\n version: number\n definition_version: string | null\n}\n","/**\n * @fileoverview JSON file trace sink (NDJSON)\n *\n * Writes trace events to a newline-delimited JSON file.\n */\n\nimport { appendFile, mkdir, writeFile } from 'node:fs/promises'\nimport { dirname } from 'node:path'\nimport type { FluxTraceEvent, FluxTraceSink } from '../types'\n\n/**\n * Options for configuring the `JsonFileTraceSink`.\n *\n * @public\n */\nexport interface JsonFileTraceSinkOptions {\n /** Absolute path where the trace file should be stored. */\n path: string\n /** Whether to reset (clear) the file on initialization. @default true */\n reset?: boolean\n}\n\n/**\n * A trace sink that writes events to a newline-delimited JSON (NDJSON) file.\n *\n * This sink is ideal for local development and debugging as it produces\n * a human-readable and easily machine-parsable log of workflow events.\n *\n * @example\n * ```typescript\n * const sink = new JsonFileTraceSink({\n * path: './traces/workflow.jsonl',\n * reset: true\n * });\n * ```\n *\n * @public\n */\nexport class JsonFileTraceSink implements FluxTraceSink {\n private path: string\n private ready: Promise<void>\n\n /**\n * Creates a new JSON file trace sink.\n *\n * @param options - Configuration options for the sink.\n */\n constructor(options: JsonFileTraceSinkOptions) {\n this.path = options.path\n this.ready = this.init(options.reset ?? true)\n }\n\n /**\n * Ensures the target directory exists and optionally resets the file.\n *\n * @param reset - Whether to truncate the file if it already exists.\n * @throws {Error} If directory creation or file writing fails.\n */\n private async init(reset: boolean): Promise<void> {\n await mkdir(dirname(this.path), { recursive: true })\n if (reset) {\n await writeFile(this.path, '', 'utf8')\n }\n }\n\n /**\n * Appends a trace event to the file in NDJSON format.\n *\n * Waits for initialization to complete before writing.\n *\n * @param event - The trace event to record.\n * @throws {Error} If writing to the file fails.\n *\n * @example\n * ```typescript\n * await sink.emit({\n * type: 'step_start',\n * workflowId: 'wf-1',\n * timestamp: Date.now(),\n * data: { step: 'validate' }\n * });\n * ```\n */\n async emit(event: FluxTraceEvent): Promise<void> {\n await this.ready\n await appendFile(this.path, `${JSON.stringify(event)}\\n`, 'utf8')\n }\n}\n","/**\n * @fileoverview Lock Provider interface for distributed execution\n *\n * Provides a mechanism for coordinating workflow execution across multiple\n * nodes by ensuring only one node executes a specific workflow instance at a time.\n *\n * @module @gravito/flux/core\n */\n\n/**\n * Represents a distributed lock for a specific resource.\n */\nexport interface Lock {\n /** The unique identifier for the locked resource. */\n id: string\n /** The owner of the lock (e.g., node identifier). */\n owner: string\n /** Unix timestamp when the lock expires. */\n expiresAt: number\n /** Releases the lock manually. */\n release(): Promise<void>\n}\n\n/**\n * Interface for implementing distributed locking mechanisms.\n * Required for Cluster Mode to prevent race conditions in multi-node environments.\n */\nexport interface LockProvider {\n /**\n * Attempts to acquire a lock for a specific resource.\n *\n * @param resourceId - The unique ID of the resource to lock (e.g., workflowId).\n * @param owner - The identifier of the node/process requesting the lock.\n * @param ttl - Time-to-live for the lock in milliseconds.\n * @returns A Lock object if successful, otherwise null.\n */\n acquire(resourceId: string, owner: string, ttl: number): Promise<Lock | null>\n\n /**\n * Refreshes an existing lock to extend its lifetime.\n *\n * @param resourceId - The ID of the resource.\n * @param owner - The current owner of the lock.\n * @param ttl - The new time-to-live from the current moment.\n * @returns True if the lock was successfully refreshed.\n */\n refresh(resourceId: string, owner: string, ttl: number): Promise<boolean>\n\n /**\n * Forcefully releases a lock, regardless of the owner.\n *\n * @param resourceId - The ID of the resource to unlock.\n */\n release(resourceId: string): Promise<void>\n}\n\n/**\n * In-memory implementation of LockProvider for local development and testing.\n * Does NOT support multiple processes or nodes.\n */\nexport class MemoryLockProvider implements LockProvider {\n private locks = new Map<string, { owner: string; expiresAt: number }>()\n\n async acquire(resourceId: string, owner: string, ttl: number): Promise<Lock | null> {\n const now = Date.now()\n const existing = this.locks.get(resourceId)\n\n if (existing && existing.expiresAt > now) {\n if (existing.owner === owner) {\n // Same owner, refresh\n existing.expiresAt = now + ttl\n return this.createLock(resourceId, owner, existing.expiresAt)\n }\n return null\n }\n\n const expiresAt = now + ttl\n this.locks.set(resourceId, { owner, expiresAt })\n return this.createLock(resourceId, owner, expiresAt)\n }\n\n async refresh(resourceId: string, owner: string, ttl: number): Promise<boolean> {\n const now = Date.now()\n const existing = this.locks.get(resourceId)\n\n if (existing && existing.owner === owner && existing.expiresAt > now) {\n existing.expiresAt = now + ttl\n return true\n }\n\n return false\n }\n\n async release(resourceId: string): Promise<void> {\n this.locks.delete(resourceId)\n }\n\n private createLock(id: string, owner: string, expiresAt: number): Lock {\n return {\n id,\n owner,\n expiresAt,\n release: () => this.release(id),\n }\n }\n}\n","/**\n * @fileoverview Redis-based Lock Provider for distributed workflow execution\n *\n * Provides a Redis-backed distributed locking mechanism for coordinating\n * workflow execution across multiple nodes in a cluster.\n *\n * @module @gravito/flux/core\n */\n\nimport type { Lock, LockProvider } from './LockProvider'\n\n/**\n * Minimal Redis client interface for compatibility with ioredis/redis libraries.\n * Consumers should provide a client that implements these methods.\n */\nexport interface RedisClient {\n /**\n * SET command with optional NX and PX options.\n * @param key - The key to set\n * @param value - The value to set\n * @param options - SET options (NX for only-if-not-exists, PX for expiry in ms)\n * @returns 'OK' if set, null if key exists (with NX)\n */\n set(key: string, value: string, options?: { NX?: boolean; PX?: number }): Promise<'OK' | null>\n\n /**\n * GET command to retrieve a value.\n * @param key - The key to get\n * @returns The value or null if not found\n */\n get(key: string): Promise<string | null>\n\n /**\n * DEL command to delete a key.\n * @param key - The key to delete\n * @returns Number of keys deleted\n */\n del(key: string): Promise<number>\n\n /**\n * EVAL command to execute Lua scripts atomically.\n * @param script - The Lua script\n * @param keys - Array of keys\n * @param args - Array of arguments\n * @returns Script result\n */\n eval(script: string, keys: string[], args: (string | number)[]): Promise<unknown>\n}\n\n/**\n * Configuration options for RedisLockProvider.\n */\nexport interface RedisLockProviderOptions {\n /** Redis client instance (must implement RedisClient interface) */\n client: RedisClient\n /** Prefix for all lock keys (default: 'flux:lock:') */\n keyPrefix?: string\n /** Default TTL for locks in milliseconds (default: 30000) */\n defaultTtl?: number\n /** Delay between retry attempts in milliseconds (default: 100) */\n retryDelay?: number\n /** Maximum number of retry attempts (default: 0, no retries) */\n maxRetries?: number\n}\n\n/**\n * Lua script for safe lock release.\n * Only releases the lock if the owner matches.\n */\nconst RELEASE_LOCK_SCRIPT = `\nif redis.call(\"get\", KEYS[1]) == ARGV[1] then\n return redis.call(\"del\", KEYS[1])\nelse\n return 0\nend\n`\n\n/**\n * Lua script for safe lock refresh.\n * Only refreshes the TTL if the owner matches.\n */\nconst REFRESH_LOCK_SCRIPT = `\nif redis.call(\"get\", KEYS[1]) == ARGV[1] then\n return redis.call(\"pexpire\", KEYS[1], ARGV[2])\nelse\n return 0\nend\n`\n\n/**\n * Redis-based implementation of LockProvider for distributed locking.\n *\n * Uses Redis SET NX PX for atomic lock acquisition and Lua scripts\n * for safe release and refresh operations.\n *\n * @example\n * ```typescript\n * import Redis from 'ioredis'\n * import { RedisLockProvider } from '@gravito/flux'\n *\n * const redis = new Redis()\n * const lockProvider = new RedisLockProvider({\n * client: redis,\n * keyPrefix: 'myapp:locks:',\n * defaultTtl: 30000,\n * })\n *\n * const lock = await lockProvider.acquire('workflow-123', 'node-1', 30000)\n * if (lock) {\n * try {\n * // Do work with the lock\n * } finally {\n * await lock.release()\n * }\n * }\n * ```\n */\nexport class RedisLockProvider implements LockProvider {\n private readonly client: RedisClient\n private readonly keyPrefix: string\n private readonly defaultTtl: number\n private readonly retryDelay: number\n private readonly maxRetries: number\n\n constructor(options: RedisLockProviderOptions) {\n this.client = options.client\n this.keyPrefix = options.keyPrefix ?? 'flux:lock:'\n this.defaultTtl = options.defaultTtl ?? 30000\n this.retryDelay = options.retryDelay ?? 100\n this.maxRetries = options.maxRetries ?? 0\n }\n\n /**\n * Attempts to acquire a lock for a specific resource.\n *\n * Uses Redis SET with NX (only if not exists) and PX (expire in ms)\n * for atomic lock acquisition. Supports retry with configurable delay.\n *\n * @param resourceId - The unique ID of the resource to lock\n * @param owner - The identifier of the node/process requesting the lock\n * @param ttl - Time-to-live for the lock in milliseconds\n * @returns A Lock object if successful, otherwise null\n */\n async acquire(resourceId: string, owner: string, ttl: number): Promise<Lock | null> {\n const key = this.getKey(resourceId)\n const effectiveTtl = ttl || this.defaultTtl\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n const result = await this.client.set(key, owner, {\n NX: true,\n PX: effectiveTtl,\n })\n\n if (result === 'OK') {\n const expiresAt = Date.now() + effectiveTtl\n return this.createLock(resourceId, owner, expiresAt)\n }\n\n const currentOwner = await this.client.get(key)\n if (currentOwner === owner) {\n const refreshed = await this.refresh(resourceId, owner, effectiveTtl)\n if (refreshed) {\n const expiresAt = Date.now() + effectiveTtl\n return this.createLock(resourceId, owner, expiresAt)\n }\n }\n\n if (attempt < this.maxRetries) {\n await this.sleep(this.retryDelay)\n }\n }\n\n return null\n }\n\n /**\n * Refreshes an existing lock to extend its lifetime.\n *\n * Uses a Lua script to atomically check ownership and extend TTL.\n *\n * @param resourceId - The ID of the resource\n * @param owner - The current owner of the lock\n * @param ttl - The new time-to-live from the current moment\n * @returns True if the lock was successfully refreshed\n */\n async refresh(resourceId: string, owner: string, ttl: number): Promise<boolean> {\n const key = this.getKey(resourceId)\n const effectiveTtl = ttl || this.defaultTtl\n\n const result = await this.client.eval(REFRESH_LOCK_SCRIPT, [key], [owner, effectiveTtl])\n\n return result === 1\n }\n\n /**\n * Forcefully releases a lock, regardless of the owner.\n *\n * @param resourceId - The ID of the resource to unlock\n */\n async release(resourceId: string): Promise<void> {\n const key = this.getKey(resourceId)\n await this.client.del(key)\n }\n\n /**\n * Safely releases a lock only if owned by the specified owner.\n *\n * Uses a Lua script to atomically check ownership and delete.\n *\n * @param resourceId - The ID of the resource to unlock\n * @param owner - The owner that should release the lock\n * @returns True if the lock was released, false if not owned\n */\n async releaseIfOwned(resourceId: string, owner: string): Promise<boolean> {\n const key = this.getKey(resourceId)\n const result = await this.client.eval(RELEASE_LOCK_SCRIPT, [key], [owner])\n return result === 1\n }\n\n /**\n * Generates the Redis key for a resource.\n */\n private getKey(resourceId: string): string {\n return `${this.keyPrefix}${resourceId}`\n }\n\n /**\n * Creates a Lock object with a release method.\n */\n private createLock(id: string, owner: string, expiresAt: number): Lock {\n return {\n id,\n owner,\n expiresAt,\n release: async () => {\n await this.releaseIfOwned(id, owner)\n },\n }\n }\n\n /**\n * Sleeps for the specified duration.\n */\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n }\n}\n","/**\n * @fileoverview Console Logger for FluxEngine\n *\n * Default logger implementation using console.\n *\n * @module @gravito/flux\n */\n\nimport type { FluxLogger } from '../types'\n\n/**\n * Console Logger implementation for FluxEngine.\n *\n * Provides a standard way to output workflow execution logs to the system console\n * with a configurable prefix for easy filtering.\n *\n * @example\n * ```typescript\n * const logger = new FluxConsoleLogger('[OrderFlow]');\n * logger.info('Workflow started', { orderId: '123' });\n * ```\n */\nexport class FluxConsoleLogger implements FluxLogger {\n private prefix: string\n\n /**\n * Creates a new console logger instance.\n *\n * @param prefix - String prepended to every log message for identification.\n */\n constructor(prefix = '[Flux]') {\n this.prefix = prefix\n }\n\n /**\n * Logs fine-grained informational events that are most useful to debug an application.\n *\n * @param message - The primary log message.\n * @param args - Additional metadata or objects to include in the log output.\n */\n debug(message: string, ...args: unknown[]): void {\n console.debug(`${this.prefix} ${message}`, ...args)\n }\n\n /**\n * Logs informational messages that highlight the progress of the application at coarse-grained level.\n *\n * @param message - The primary log message.\n * @param args - Additional metadata or objects to include in the log output.\n */\n info(message: string, ...args: unknown[]): void {\n console.info(`${this.prefix} ${message}`, ...args)\n }\n\n /**\n * Logs potentially harmful situations that should be noted but don't stop execution.\n *\n * @param message - The primary log message.\n * @param args - Additional metadata or objects to include in the log output.\n */\n warn(message: string, ...args: unknown[]): void {\n console.warn(`${this.prefix} ${message}`, ...args)\n }\n\n /**\n * Logs error events that might still allow the application to continue running.\n *\n * @param message - The primary log message.\n * @param args - Additional metadata or objects to include in the log output.\n */\n error(message: string, ...args: unknown[]): void {\n console.error(`${this.prefix} ${message}`, ...args)\n }\n}\n\n/**\n * Silent Logger implementation that discards all log entries.\n *\n * Useful for production environments where logging is handled externally,\n * or for unit tests where console output should be suppressed.\n *\n * @example\n * ```typescript\n * const engine = new FluxEngine({\n * logger: new FluxSilentLogger()\n * });\n * ```\n */\nexport class FluxSilentLogger implements FluxLogger {\n /** Discards debug logs. */\n debug(): void {}\n /** Discards info logs. */\n info(): void {}\n /** Discards warning logs. */\n warn(): void {}\n /** Discards error logs. */\n error(): void {}\n}\n","import type { GravitoOrbit, PlanetCore } from '@gravito/core'\nimport { FluxEngine } from '../engine/FluxEngine'\nimport { BunSQLiteStorage } from '../storage/BunSQLiteStorage'\nimport { MemoryStorage } from '../storage/MemoryStorage'\nimport type { FluxConfig, FluxLogger, WorkflowStorage } from '../types'\n\n/**\n * Configuration options for the OrbitFlux extension.\n *\n * Defines how the workflow engine should be initialized and integrated into the Gravito core.\n */\nexport interface OrbitFluxOptions {\n /**\n * Specifies the storage driver to use for persisting workflow states.\n *\n * - 'memory': Volatile in-memory storage (default).\n * - 'sqlite': Persistent SQLite storage (Bun only).\n * - WorkflowStorage: A custom implementation of the storage interface.\n */\n storage?: 'memory' | 'sqlite' | WorkflowStorage\n\n /**\n * The file system path for the SQLite database.\n *\n * Only applicable when `storage` is set to 'sqlite'.\n */\n dbPath?: string\n\n /**\n * The key under which the FluxEngine will be registered in the core service container.\n */\n exposeAs?: string\n\n /**\n * A custom logger implementation for the workflow engine.\n *\n * If not provided, the engine will use a wrapper around the core logger.\n */\n logger?: FluxLogger\n\n /**\n * The default number of times a workflow step should be retried upon failure.\n */\n defaultRetries?: number\n\n /**\n * The default timeout in milliseconds for workflow steps.\n */\n defaultTimeout?: number\n}\n\n/**\n * OrbitFlux integrates the Flux workflow engine into the Gravito Galaxy Architecture.\n *\n * It acts as an \"Orbit\" (infrastructure extension) that provides a managed `FluxEngine`\n * instance to the core application and other satellites. It also bridges engine events\n * to the core hook system.\n *\n * @example\n * ```typescript\n * import { OrbitFlux } from '@gravito/flux'\n *\n * const core = await PlanetCore.boot({\n * orbits: [\n * new OrbitFlux({\n * storage: 'sqlite',\n * dbPath: './data/workflows.db'\n * })\n * ]\n * })\n *\n * // Access the engine from the container\n * const flux = core.container.make<FluxEngine>('flux')\n * ```\n */\nexport class OrbitFlux implements GravitoOrbit {\n private options: OrbitFluxOptions\n private engine?: FluxEngine\n\n /**\n * Initializes a new OrbitFlux instance with the given options.\n *\n * @param options - Configuration for the workflow engine integration.\n */\n constructor(options: OrbitFluxOptions = {}) {\n this.options = {\n storage: 'memory',\n exposeAs: 'flux',\n defaultRetries: 3,\n defaultTimeout: 30000,\n ...options,\n }\n }\n\n /**\n * Static factory method to create and configure an OrbitFlux instance.\n *\n * @param options - Configuration for the workflow engine integration.\n * @returns A configured OrbitFlux instance.\n */\n static configure(options: OrbitFluxOptions = {}): OrbitFlux {\n return new OrbitFlux(options)\n }\n\n /**\n * Installs the Flux workflow engine into the Gravito core.\n *\n * This method resolves the storage adapter, initializes it, configures the engine\n * with core-integrated logging and hooks, and registers the engine in the IoC container.\n *\n * @param core - The PlanetCore instance being booted.\n * @throws {Error} If storage initialization fails or engine registration conflicts occur.\n */\n async install(core: PlanetCore): Promise<void> {\n const { storage, dbPath, exposeAs, defaultRetries, defaultTimeout, logger } = this.options\n\n // Resolve storage adapter\n let storageAdapter: WorkflowStorage\n\n if (typeof storage === 'string') {\n switch (storage) {\n case 'sqlite':\n storageAdapter = new BunSQLiteStorage({ path: dbPath })\n break\n default:\n storageAdapter = new MemoryStorage()\n }\n } else {\n storageAdapter = storage!\n }\n\n // Initialize storage\n await storageAdapter.init?.()\n\n // Create engine configuration\n const engineConfig: FluxConfig = {\n storage: storageAdapter,\n defaultRetries,\n defaultTimeout,\n logger: logger ?? {\n debug: (msg) => core.logger.debug(`[Flux] ${msg}`),\n info: (msg) => core.logger.info(`[Flux] ${msg}`),\n warn: (msg) => core.logger.warn(`[Flux] ${msg}`),\n error: (msg) => core.logger.error(`[Flux] ${msg}`),\n },\n on: {\n stepStart: (step) => {\n core.hooks.doAction('flux:step:start', { step })\n },\n stepComplete: (step, ctx, result) => {\n core.hooks.doAction('flux:step:complete', { step, ctx, result })\n },\n stepError: (step, ctx, error) => {\n core.hooks.doAction('flux:step:error', { step, ctx, error })\n },\n workflowComplete: (ctx) => {\n core.hooks.doAction('flux:workflow:complete', { ctx })\n },\n workflowError: (ctx, error) => {\n core.hooks.doAction('flux:workflow:error', { ctx, error })\n },\n },\n }\n\n // Create engine\n this.engine = new FluxEngine(engineConfig)\n\n // Register in core container\n core.container.instance(exposeAs!, this.engine)\n\n core.logger.info(\n `[OrbitFlux] Initialized (Storage: ${typeof storage === 'string' ? storage : 'custom'})`\n )\n }\n\n /**\n * Retrieves the managed FluxEngine instance.\n *\n * @returns The FluxEngine instance, or undefined if the orbit has not been installed.\n */\n getEngine(): FluxEngine | undefined {\n return this.engine\n }\n\n /**\n * Performs cleanup operations when the core is shutting down.\n *\n * Closes the underlying workflow engine and its storage connections.\n *\n * @throws {Error} If the engine fails to close cleanly.\n */\n async cleanup(): Promise<void> {\n if (this.engine) {\n await this.engine.close()\n }\n }\n}\n"],"mappings":"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","names":["FluxErrorCode","timer","duration"]}