@sonamu-kit/tasks 0.1.1 → 0.1.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.
package/dist/client.d.ts CHANGED
@@ -99,7 +99,6 @@ export declare class OpenWorkflow {
99
99
  * Declare a workflow without providing its implementation (which is provided
100
100
  * separately via `implementWorkflow`). Returns a lightweight WorkflowSpec
101
101
  * that can be used to schedule workflow runs.
102
- * @param config - Workflow config
103
102
  * @param spec - Workflow spec
104
103
  * @returns Workflow spec
105
104
  * @example
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/dist/client.js CHANGED
@@ -129,7 +129,6 @@ const DEFAULT_RESULT_TIMEOUT_MS = 5 * 60 * 1000; // 5m
129
129
  * Declare a workflow without providing its implementation (which is provided
130
130
  * separately via `implementWorkflow`). Returns a lightweight WorkflowSpec
131
131
  * that can be used to schedule workflow runs.
132
- * @param config - Workflow config
133
132
  * @param spec - Workflow spec
134
133
  * @returns Workflow spec
135
134
  * @example
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client.ts"],"sourcesContent":["import type { Backend } from \"./backend\";\nimport type { StandardSchemaV1 } from \"./core/schema\";\nimport type { SchemaInput, SchemaOutput, WorkflowRun } from \"./core/workflow\";\nimport { validateInput } from \"./core/workflow\";\nimport type { WorkflowFunction } from \"./execution\";\nimport { WorkflowRegistry } from \"./registry\";\nimport { Worker, type WorkerOptions } from \"./worker\";\nimport { defineWorkflow, defineWorkflowSpec, type Workflow, type WorkflowSpec } from \"./workflow\";\n\nconst DEFAULT_RESULT_POLL_INTERVAL_MS = 1000; // 1s\nconst DEFAULT_RESULT_TIMEOUT_MS = 5 * 60 * 1000; // 5m\n\n/* The data the worker function receives (after transformation). */\ntype WorkflowHandlerInput<TSchema, Input> = SchemaOutput<TSchema, Input>;\n\n/* The data the client sends (before transformation) */\ntype WorkflowRunInput<TSchema, Input> = SchemaInput<TSchema, Input>;\n\n/**\n * Options for the OpenWorkflow client.\n */\nexport interface OpenWorkflowOptions {\n backend: Backend;\n}\n\n/**\n * Client used to register workflows and start runs.\n */\nexport class OpenWorkflow {\n private backend: Backend;\n private registry = new WorkflowRegistry();\n\n constructor(options: OpenWorkflowOptions) {\n this.backend = options.backend;\n }\n\n /**\n * Create a new Worker with this client's backend and workflows.\n * @param options - Worker options\n * @param options.concurrency - Max concurrent workflow runs\n * @returns Worker instance\n */\n newWorker(options?: {\n concurrency?: number | undefined;\n usePubSub?: boolean;\n listenDelay?: number;\n }): Worker {\n return new Worker({\n backend: this.backend,\n registry: this.registry,\n concurrency: options?.concurrency,\n usePubSub: options?.usePubSub,\n listenDelay: options?.listenDelay,\n } satisfies WorkerOptions);\n }\n\n /**\n * Provide the implementation for a declared workflow. This links the workflow\n * specification to its execution logic and registers it with this\n * OpenWorkflow instance for worker execution.\n * @param spec - Workflow spec\n * @param fn - Workflow implementation\n */\n implementWorkflow<Input, Output, RunInput = Input>(\n spec: WorkflowSpec<Input, Output, RunInput>,\n fn: WorkflowFunction<Input, Output>,\n ): void {\n const workflow: Workflow<Input, Output, RunInput> = { spec, fn };\n this.registry.register(workflow as Workflow<unknown, unknown, unknown>);\n }\n\n /**\n * Run a workflow from its specification. This is the primary way to schedule\n * a workflow using only its WorkflowSpec.\n * @param spec - Workflow spec\n * @param input - Workflow input\n * @param options - Run options\n * @returns Handle for awaiting the result\n * @example\n * ```ts\n * const handle = await ow.runWorkflow(emailWorkflow, { to: 'user@example.com' });\n * const result = await handle.result();\n * ```\n */\n async runWorkflow<Input, Output, RunInput = Input>(\n spec: WorkflowSpec<Input, Output, RunInput>,\n input?: RunInput,\n options?: WorkflowRunOptions,\n ): Promise<WorkflowRunHandle<Output>> {\n const validationResult = await validateInput(spec.schema, input);\n if (!validationResult.success) {\n throw new Error(validationResult.error);\n }\n const parsedInput = validationResult.value;\n const workflowRun = await this.backend.createWorkflowRun({\n workflowName: spec.name,\n version: spec.version ?? null,\n idempotencyKey: null,\n config: {},\n context: null,\n input: parsedInput ?? null,\n availableAt: null,\n deadlineAt: options?.deadlineAt ?? null,\n });\n\n if (options?.publishToChannel) {\n await this.backend.publish(workflowRun.id);\n }\n\n return new WorkflowRunHandle<Output>({\n backend: this.backend,\n workflowRun: workflowRun,\n resultPollIntervalMs: DEFAULT_RESULT_POLL_INTERVAL_MS,\n resultTimeoutMs: DEFAULT_RESULT_TIMEOUT_MS,\n });\n }\n\n /**\n * Define and register a new workflow.\n *\n * This is a convenience method that combines `declareWorkflow` and\n * `implementWorkflow` into a single call. For better code splitting and to\n * separate declaration from implementation, consider using those methods\n * separately.\n * @param config - Workflow config\n * @param fn - Workflow implementation\n * @returns Runnable workflow\n * @example\n * ```ts\n * const workflow = ow.defineWorkflow(\n * { name: 'my-workflow' },\n * async ({ input, step }) => {\n * // workflow implementation\n * },\n * );\n * ```\n */\n defineWorkflow<Input, Output, TSchema extends StandardSchemaV1 | undefined = undefined>(\n spec: WorkflowSpec<\n WorkflowHandlerInput<TSchema, Input>,\n Output,\n WorkflowRunInput<TSchema, Input>\n >,\n fn: WorkflowFunction<WorkflowHandlerInput<TSchema, Input>, Output>,\n ): RunnableWorkflow<\n WorkflowHandlerInput<TSchema, Input>,\n Output,\n WorkflowRunInput<TSchema, Input>\n > {\n const workflow = defineWorkflow(spec, fn);\n this.registry.register(workflow as Workflow<unknown, unknown, unknown>);\n return new RunnableWorkflow(this, workflow);\n }\n\n /**\n * Unregister a workflow from the registry.\n * @param name - The workflow name\n * @param version - The workflow version (null for unversioned)\n * @example\n * ```ts\n * ow.unregisterWorkflow(\"my-workflow\", \"v1\");\n * ```\n */\n unregisterWorkflow(name: string, version: string | null): void {\n this.registry.remove(name, version);\n }\n\n /**\n * Check if a workflow is registered in the registry.\n * @param name - The workflow name\n * @param version - The workflow version (null for unversioned)\n * @returns True if the workflow is registered, false otherwise\n * @example\n * ```ts\n * ow.isWorkflowRegistered(\"my-workflow\", \"v1\");\n * ```\n */\n isWorkflowRegistered(name: string, version: string | null): boolean {\n return this.registry.has(name, version);\n }\n}\n\n/**\n * Declare a workflow without providing its implementation (which is provided\n * separately via `implementWorkflow`). Returns a lightweight WorkflowSpec\n * that can be used to schedule workflow runs.\n * @param config - Workflow config\n * @param spec - Workflow spec\n * @returns Workflow spec\n * @example\n * ```ts\n * export const emailWorkflow = declareWorkflow({\n * name: 'send-email',\n * schema: z.object({ to: z.string().email() }),\n * });\n * ```\n */\n// kept for backwards compatibility, to be deprecated\n// eslint-disable-next-line unicorn/prefer-export-from\nexport const declareWorkflow = defineWorkflowSpec;\n\n//\n// --- Workflow Definition\n//\n\n/**\n * A fully defined workflow with its implementation. This class is returned by\n * `defineWorkflow` and provides the `.run()` method for scheduling workflow\n * runs.\n */\nexport class RunnableWorkflow<Input, Output, RunInput = Input> {\n private readonly ow: OpenWorkflow;\n readonly workflow: Workflow<Input, Output, RunInput>;\n\n constructor(ow: OpenWorkflow, workflow: Workflow<Input, Output, RunInput>) {\n this.ow = ow;\n this.workflow = workflow;\n }\n\n /**\n * Starts a new workflow run.\n * @param input - Workflow input\n * @param options - Run options\n * @returns Workflow run handle\n */\n async run(input?: RunInput, options?: WorkflowRunOptions): Promise<WorkflowRunHandle<Output>> {\n return this.ow.runWorkflow(this.workflow.spec, input, options);\n }\n}\n\n//\n// --- Workflow Run\n//\n\n/**\n * Options for creating a new workflow run from a runnable workflow when calling\n * `workflow.run()`.\n */\nexport interface WorkflowRunOptions {\n /**\n * Set a deadline for the workflow run. If the workflow exceeds this deadline,\n * it will be marked as failed.\n */\n deadlineAt?: Date;\n\n /**\n * Publish when the workflow run is created to the channel.\n * Default: true\n */\n publishToChannel?: boolean;\n}\n\n/**\n * Options for WorkflowHandle.\n */\nexport interface WorkflowHandleOptions {\n backend: Backend;\n workflowRun: WorkflowRun;\n resultPollIntervalMs: number;\n resultTimeoutMs: number;\n}\n\n/**\n * Represents a started workflow run and provides methods to await its result.\n * Returned from `workflowDef.run()`.\n */\nexport class WorkflowRunHandle<Output> {\n private backend: Backend;\n readonly workflowRun: WorkflowRun;\n private resultPollIntervalMs: number;\n private resultTimeoutMs: number;\n\n constructor(options: WorkflowHandleOptions) {\n this.backend = options.backend;\n this.workflowRun = options.workflowRun;\n this.resultPollIntervalMs = options.resultPollIntervalMs;\n this.resultTimeoutMs = options.resultTimeoutMs;\n }\n\n /**\n * Waits for the workflow run to complete and returns the result.\n * @returns Workflow output\n */\n async result(): Promise<Output> {\n const start = Date.now();\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n while (true) {\n const latest = await this.backend.getWorkflowRun({\n workflowRunId: this.workflowRun.id,\n });\n\n if (!latest) {\n throw new Error(`Workflow run ${this.workflowRun.id} no longer exists`);\n }\n\n // 'succeeded' status is deprecated\n if (latest.status === \"succeeded\" || latest.status === \"completed\") {\n return latest.output as Output;\n }\n\n if (latest.status === \"failed\") {\n throw new Error(\n `Workflow ${this.workflowRun.workflowName} failed: ${JSON.stringify(latest.error)}`,\n );\n }\n\n if (latest.status === \"canceled\") {\n throw new Error(`Workflow ${this.workflowRun.workflowName} was canceled`);\n }\n\n if (Date.now() - start > this.resultTimeoutMs) {\n throw new Error(`Timed out waiting for workflow run ${this.workflowRun.id} to finish`);\n }\n\n await new Promise((resolve) => {\n setTimeout(resolve, this.resultPollIntervalMs);\n });\n }\n }\n\n /**\n * Cancels the workflow run. Only workflows in pending, running, or sleeping\n * status can be canceled.\n */\n async cancel(): Promise<void> {\n await this.backend.cancelWorkflowRun({\n workflowRunId: this.workflowRun.id,\n });\n }\n}\n"],"names":["validateInput","WorkflowRegistry","Worker","defineWorkflow","defineWorkflowSpec","DEFAULT_RESULT_POLL_INTERVAL_MS","DEFAULT_RESULT_TIMEOUT_MS","OpenWorkflow","backend","registry","options","newWorker","concurrency","usePubSub","listenDelay","implementWorkflow","spec","fn","workflow","register","runWorkflow","input","validationResult","schema","success","Error","error","parsedInput","value","workflowRun","createWorkflowRun","workflowName","name","version","idempotencyKey","config","context","availableAt","deadlineAt","publishToChannel","publish","id","WorkflowRunHandle","resultPollIntervalMs","resultTimeoutMs","RunnableWorkflow","unregisterWorkflow","remove","isWorkflowRegistered","has","declareWorkflow","ow","run","result","start","Date","now","latest","getWorkflowRun","workflowRunId","status","output","JSON","stringify","Promise","resolve","setTimeout","cancel","cancelWorkflowRun"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/client.ts"],"sourcesContent":["import type { Backend } from \"./backend\";\nimport type { StandardSchemaV1 } from \"./core/schema\";\nimport type { SchemaInput, SchemaOutput, WorkflowRun } from \"./core/workflow\";\nimport { validateInput } from \"./core/workflow\";\nimport type { WorkflowFunction } from \"./execution\";\nimport { WorkflowRegistry } from \"./registry\";\nimport { Worker, type WorkerOptions } from \"./worker\";\nimport { defineWorkflow, defineWorkflowSpec, type Workflow, type WorkflowSpec } from \"./workflow\";\n\nconst DEFAULT_RESULT_POLL_INTERVAL_MS = 1000; // 1s\nconst DEFAULT_RESULT_TIMEOUT_MS = 5 * 60 * 1000; // 5m\n\n/* The data the worker function receives (after transformation). */\ntype WorkflowHandlerInput<TSchema, Input> = SchemaOutput<TSchema, Input>;\n\n/* The data the client sends (before transformation) */\ntype WorkflowRunInput<TSchema, Input> = SchemaInput<TSchema, Input>;\n\n/**\n * Options for the OpenWorkflow client.\n */\nexport interface OpenWorkflowOptions {\n backend: Backend;\n}\n\n/**\n * Client used to register workflows and start runs.\n */\nexport class OpenWorkflow {\n private backend: Backend;\n private registry = new WorkflowRegistry();\n\n constructor(options: OpenWorkflowOptions) {\n this.backend = options.backend;\n }\n\n /**\n * Create a new Worker with this client's backend and workflows.\n * @param options - Worker options\n * @param options.concurrency - Max concurrent workflow runs\n * @returns Worker instance\n */\n newWorker(options?: {\n concurrency?: number | undefined;\n usePubSub?: boolean;\n listenDelay?: number;\n }): Worker {\n return new Worker({\n backend: this.backend,\n registry: this.registry,\n concurrency: options?.concurrency,\n usePubSub: options?.usePubSub,\n listenDelay: options?.listenDelay,\n } satisfies WorkerOptions);\n }\n\n /**\n * Provide the implementation for a declared workflow. This links the workflow\n * specification to its execution logic and registers it with this\n * OpenWorkflow instance for worker execution.\n * @param spec - Workflow spec\n * @param fn - Workflow implementation\n */\n implementWorkflow<Input, Output, RunInput = Input>(\n spec: WorkflowSpec<Input, Output, RunInput>,\n fn: WorkflowFunction<Input, Output>,\n ): void {\n const workflow: Workflow<Input, Output, RunInput> = { spec, fn };\n this.registry.register(workflow as Workflow<unknown, unknown, unknown>);\n }\n\n /**\n * Run a workflow from its specification. This is the primary way to schedule\n * a workflow using only its WorkflowSpec.\n * @param spec - Workflow spec\n * @param input - Workflow input\n * @param options - Run options\n * @returns Handle for awaiting the result\n * @example\n * ```ts\n * const handle = await ow.runWorkflow(emailWorkflow, { to: 'user@example.com' });\n * const result = await handle.result();\n * ```\n */\n async runWorkflow<Input, Output, RunInput = Input>(\n spec: WorkflowSpec<Input, Output, RunInput>,\n input?: RunInput,\n options?: WorkflowRunOptions,\n ): Promise<WorkflowRunHandle<Output>> {\n const validationResult = await validateInput(spec.schema, input);\n if (!validationResult.success) {\n throw new Error(validationResult.error);\n }\n const parsedInput = validationResult.value;\n const workflowRun = await this.backend.createWorkflowRun({\n workflowName: spec.name,\n version: spec.version ?? null,\n idempotencyKey: null,\n config: {},\n context: null,\n input: parsedInput ?? null,\n availableAt: null,\n deadlineAt: options?.deadlineAt ?? null,\n });\n\n if (options?.publishToChannel) {\n await this.backend.publish(workflowRun.id);\n }\n\n return new WorkflowRunHandle<Output>({\n backend: this.backend,\n workflowRun: workflowRun,\n resultPollIntervalMs: DEFAULT_RESULT_POLL_INTERVAL_MS,\n resultTimeoutMs: DEFAULT_RESULT_TIMEOUT_MS,\n });\n }\n\n /**\n * Define and register a new workflow.\n *\n * This is a convenience method that combines `declareWorkflow` and\n * `implementWorkflow` into a single call. For better code splitting and to\n * separate declaration from implementation, consider using those methods\n * separately.\n * @param config - Workflow config\n * @param fn - Workflow implementation\n * @returns Runnable workflow\n * @example\n * ```ts\n * const workflow = ow.defineWorkflow(\n * { name: 'my-workflow' },\n * async ({ input, step }) => {\n * // workflow implementation\n * },\n * );\n * ```\n */\n defineWorkflow<Input, Output, TSchema extends StandardSchemaV1 | undefined = undefined>(\n spec: WorkflowSpec<\n WorkflowHandlerInput<TSchema, Input>,\n Output,\n WorkflowRunInput<TSchema, Input>\n >,\n fn: WorkflowFunction<WorkflowHandlerInput<TSchema, Input>, Output>,\n ): RunnableWorkflow<\n WorkflowHandlerInput<TSchema, Input>,\n Output,\n WorkflowRunInput<TSchema, Input>\n > {\n const workflow = defineWorkflow(spec, fn);\n this.registry.register(workflow as Workflow<unknown, unknown, unknown>);\n return new RunnableWorkflow(this, workflow);\n }\n\n /**\n * Unregister a workflow from the registry.\n * @param name - The workflow name\n * @param version - The workflow version (null for unversioned)\n * @example\n * ```ts\n * ow.unregisterWorkflow(\"my-workflow\", \"v1\");\n * ```\n */\n unregisterWorkflow(name: string, version: string | null): void {\n this.registry.remove(name, version);\n }\n\n /**\n * Check if a workflow is registered in the registry.\n * @param name - The workflow name\n * @param version - The workflow version (null for unversioned)\n * @returns True if the workflow is registered, false otherwise\n * @example\n * ```ts\n * ow.isWorkflowRegistered(\"my-workflow\", \"v1\");\n * ```\n */\n isWorkflowRegistered(name: string, version: string | null): boolean {\n return this.registry.has(name, version);\n }\n}\n\n/**\n * Declare a workflow without providing its implementation (which is provided\n * separately via `implementWorkflow`). Returns a lightweight WorkflowSpec\n * that can be used to schedule workflow runs.\n * @param spec - Workflow spec\n * @returns Workflow spec\n * @example\n * ```ts\n * export const emailWorkflow = declareWorkflow({\n * name: 'send-email',\n * schema: z.object({ to: z.string().email() }),\n * });\n * ```\n */\n// kept for backwards compatibility, to be deprecated\n// eslint-disable-next-line unicorn/prefer-export-from\nexport const declareWorkflow = defineWorkflowSpec;\n\n//\n// --- Workflow Definition\n//\n\n/**\n * A fully defined workflow with its implementation. This class is returned by\n * `defineWorkflow` and provides the `.run()` method for scheduling workflow\n * runs.\n */\nexport class RunnableWorkflow<Input, Output, RunInput = Input> {\n private readonly ow: OpenWorkflow;\n readonly workflow: Workflow<Input, Output, RunInput>;\n\n constructor(ow: OpenWorkflow, workflow: Workflow<Input, Output, RunInput>) {\n this.ow = ow;\n this.workflow = workflow;\n }\n\n /**\n * Starts a new workflow run.\n * @param input - Workflow input\n * @param options - Run options\n * @returns Workflow run handle\n */\n async run(input?: RunInput, options?: WorkflowRunOptions): Promise<WorkflowRunHandle<Output>> {\n return this.ow.runWorkflow(this.workflow.spec, input, options);\n }\n}\n\n//\n// --- Workflow Run\n//\n\n/**\n * Options for creating a new workflow run from a runnable workflow when calling\n * `workflow.run()`.\n */\nexport interface WorkflowRunOptions {\n /**\n * Set a deadline for the workflow run. If the workflow exceeds this deadline,\n * it will be marked as failed.\n */\n deadlineAt?: Date;\n\n /**\n * Publish when the workflow run is created to the channel.\n * Default: true\n */\n publishToChannel?: boolean;\n}\n\n/**\n * Options for WorkflowHandle.\n */\nexport interface WorkflowHandleOptions {\n backend: Backend;\n workflowRun: WorkflowRun;\n resultPollIntervalMs: number;\n resultTimeoutMs: number;\n}\n\n/**\n * Represents a started workflow run and provides methods to await its result.\n * Returned from `workflowDef.run()`.\n */\nexport class WorkflowRunHandle<Output> {\n private backend: Backend;\n readonly workflowRun: WorkflowRun;\n private resultPollIntervalMs: number;\n private resultTimeoutMs: number;\n\n constructor(options: WorkflowHandleOptions) {\n this.backend = options.backend;\n this.workflowRun = options.workflowRun;\n this.resultPollIntervalMs = options.resultPollIntervalMs;\n this.resultTimeoutMs = options.resultTimeoutMs;\n }\n\n /**\n * Waits for the workflow run to complete and returns the result.\n * @returns Workflow output\n */\n async result(): Promise<Output> {\n const start = Date.now();\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n while (true) {\n const latest = await this.backend.getWorkflowRun({\n workflowRunId: this.workflowRun.id,\n });\n\n if (!latest) {\n throw new Error(`Workflow run ${this.workflowRun.id} no longer exists`);\n }\n\n // 'succeeded' status is deprecated\n if (latest.status === \"succeeded\" || latest.status === \"completed\") {\n return latest.output as Output;\n }\n\n if (latest.status === \"failed\") {\n throw new Error(\n `Workflow ${this.workflowRun.workflowName} failed: ${JSON.stringify(latest.error)}`,\n );\n }\n\n if (latest.status === \"canceled\") {\n throw new Error(`Workflow ${this.workflowRun.workflowName} was canceled`);\n }\n\n if (Date.now() - start > this.resultTimeoutMs) {\n throw new Error(`Timed out waiting for workflow run ${this.workflowRun.id} to finish`);\n }\n\n await new Promise((resolve) => {\n setTimeout(resolve, this.resultPollIntervalMs);\n });\n }\n }\n\n /**\n * Cancels the workflow run. Only workflows in pending, running, or sleeping\n * status can be canceled.\n */\n async cancel(): Promise<void> {\n await this.backend.cancelWorkflowRun({\n workflowRunId: this.workflowRun.id,\n });\n }\n}\n"],"names":["validateInput","WorkflowRegistry","Worker","defineWorkflow","defineWorkflowSpec","DEFAULT_RESULT_POLL_INTERVAL_MS","DEFAULT_RESULT_TIMEOUT_MS","OpenWorkflow","backend","registry","options","newWorker","concurrency","usePubSub","listenDelay","implementWorkflow","spec","fn","workflow","register","runWorkflow","input","validationResult","schema","success","Error","error","parsedInput","value","workflowRun","createWorkflowRun","workflowName","name","version","idempotencyKey","config","context","availableAt","deadlineAt","publishToChannel","publish","id","WorkflowRunHandle","resultPollIntervalMs","resultTimeoutMs","RunnableWorkflow","unregisterWorkflow","remove","isWorkflowRegistered","has","declareWorkflow","ow","run","result","start","Date","now","latest","getWorkflowRun","workflowRunId","status","output","JSON","stringify","Promise","resolve","setTimeout","cancel","cancelWorkflowRun"],"mappings":"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"}
@@ -11,7 +11,7 @@ type Unit = Years | Months | Weeks | Days | Hours | Minutes | Seconds | Millisec
11
11
  type UnitAnyCase = Capitalize<Unit> | Uppercase<Unit> | Lowercase<Unit>;
12
12
  export type DurationString = `${number}` | `${number}${UnitAnyCase}` | `${number} ${UnitAnyCase}`;
13
13
  /**
14
- * Parse a duration string into milliseconds. Exmaples:
14
+ * Parse a duration string into milliseconds. Examples:
15
15
  * - short units: "1ms", "5s", "30m", "2h", "7d", "3w", "1y"
16
16
  * - long units: "1 millisecond", "5 seconds", "30 minutes", "2 hours", "7 days", "3 weeks", "1 year"
17
17
  * @param str - Duration string
@@ -1,6 +1,6 @@
1
1
  import { err, ok } from "./result.js";
2
2
  /**
3
- * Parse a duration string into milliseconds. Exmaples:
3
+ * Parse a duration string into milliseconds. Examples:
4
4
  * - short units: "1ms", "5s", "30m", "2h", "7d", "3w", "1y"
5
5
  * - long units: "1 millisecond", "5 seconds", "30 minutes", "2 hours", "7 days", "3 weeks", "1 year"
6
6
  * @param str - Duration string
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/duration.ts"],"sourcesContent":["import type { Result } from \"./result\";\nimport { err, ok } from \"./result\";\n\ntype Years = \"years\" | \"year\" | \"yrs\" | \"yr\" | \"y\";\ntype Months = \"months\" | \"month\" | \"mo\";\ntype Weeks = \"weeks\" | \"week\" | \"w\";\ntype Days = \"days\" | \"day\" | \"d\";\ntype Hours = \"hours\" | \"hour\" | \"hrs\" | \"hr\" | \"h\";\ntype Minutes = \"minutes\" | \"minute\" | \"mins\" | \"min\" | \"m\";\ntype Seconds = \"seconds\" | \"second\" | \"secs\" | \"sec\" | \"s\";\ntype Milliseconds = \"milliseconds\" | \"millisecond\" | \"msecs\" | \"msec\" | \"ms\";\ntype Unit = Years | Months | Weeks | Days | Hours | Minutes | Seconds | Milliseconds;\ntype UnitAnyCase = Capitalize<Unit> | Uppercase<Unit> | Lowercase<Unit>;\nexport type DurationString = `${number}` | `${number}${UnitAnyCase}` | `${number} ${UnitAnyCase}`;\n\n/**\n * Parse a duration string into milliseconds. Exmaples:\n * - short units: \"1ms\", \"5s\", \"30m\", \"2h\", \"7d\", \"3w\", \"1y\"\n * - long units: \"1 millisecond\", \"5 seconds\", \"30 minutes\", \"2 hours\", \"7 days\", \"3 weeks\", \"1 year\"\n * @param str - Duration string\n * @returns Milliseconds\n */\nexport function parseDuration(str: DurationString): Result<number> {\n if (typeof str !== \"string\") {\n return err(\n new TypeError(`Invalid duration format: expected a string but received ${typeof str}`),\n );\n }\n\n if (str.length === 0) {\n return err(new Error('Invalid duration format: \"\"'));\n }\n\n const match = /^(-?\\.?\\d+(?:\\.\\d+)?)\\s*([a-z]+)?$/i.exec(str);\n\n if (!match?.[1]) {\n return err(new Error(`Invalid duration format: \"${str}\"`));\n }\n\n const numValue = Number.parseFloat(match[1]);\n const unit = match[2]?.toLowerCase() ?? \"ms\"; // default to ms if not provided\n\n const multipliers: Record<string, number> = {\n millisecond: 1,\n milliseconds: 1,\n msec: 1,\n msecs: 1,\n ms: 1,\n second: 1000,\n seconds: 1000,\n sec: 1000,\n secs: 1000,\n s: 1000,\n minute: 60 * 1000,\n minutes: 60 * 1000,\n min: 60 * 1000,\n mins: 60 * 1000,\n m: 60 * 1000,\n hour: 60 * 60 * 1000,\n hours: 60 * 60 * 1000,\n hr: 60 * 60 * 1000,\n hrs: 60 * 60 * 1000,\n h: 60 * 60 * 1000,\n day: 24 * 60 * 60 * 1000,\n days: 24 * 60 * 60 * 1000,\n d: 24 * 60 * 60 * 1000,\n week: 7 * 24 * 60 * 60 * 1000,\n weeks: 7 * 24 * 60 * 60 * 1000,\n w: 7 * 24 * 60 * 60 * 1000,\n month: 2_629_800_000,\n months: 2_629_800_000,\n mo: 2_629_800_000,\n year: 31_557_600_000,\n years: 31_557_600_000,\n yr: 31_557_600_000,\n yrs: 31_557_600_000,\n y: 31_557_600_000,\n };\n\n const multiplier = multipliers[unit];\n if (multiplier === undefined) {\n return err(new Error(`Invalid duration format: \"${str}\"`));\n }\n\n return ok(numValue * multiplier);\n}\n"],"names":["err","ok","parseDuration","str","TypeError","length","Error","match","exec","numValue","Number","parseFloat","unit","toLowerCase","multipliers","millisecond","milliseconds","msec","msecs","ms","second","seconds","sec","secs","s","minute","minutes","min","mins","m","hour","hours","hr","hrs","h","day","days","d","week","weeks","w","month","months","mo","year","years","yr","yrs","y","multiplier","undefined"],"mappings":"AACA,SAASA,GAAG,EAAEC,EAAE,QAAQ,cAAW;AAcnC;;;;;;CAMC,GACD,OAAO,SAASC,cAAcC,GAAmB;IAC/C,IAAI,OAAOA,QAAQ,UAAU;QAC3B,OAAOH,IACL,IAAII,UAAU,CAAC,wDAAwD,EAAE,OAAOD,KAAK;IAEzF;IAEA,IAAIA,IAAIE,MAAM,KAAK,GAAG;QACpB,OAAOL,IAAI,IAAIM,MAAM;IACvB;IAEA,MAAMC,QAAQ,sCAAsCC,IAAI,CAACL;IAEzD,IAAI,CAACI,OAAO,CAAC,EAAE,EAAE;QACf,OAAOP,IAAI,IAAIM,MAAM,CAAC,0BAA0B,EAAEH,IAAI,CAAC,CAAC;IAC1D;IAEA,MAAMM,WAAWC,OAAOC,UAAU,CAACJ,KAAK,CAAC,EAAE;IAC3C,MAAMK,OAAOL,KAAK,CAAC,EAAE,EAAEM,iBAAiB,MAAM,gCAAgC;IAE9E,MAAMC,cAAsC;QAC1CC,aAAa;QACbC,cAAc;QACdC,MAAM;QACNC,OAAO;QACPC,IAAI;QACJC,QAAQ;QACRC,SAAS;QACTC,KAAK;QACLC,MAAM;QACNC,GAAG;QACHC,QAAQ,KAAK;QACbC,SAAS,KAAK;QACdC,KAAK,KAAK;QACVC,MAAM,KAAK;QACXC,GAAG,KAAK;QACRC,MAAM,KAAK,KAAK;QAChBC,OAAO,KAAK,KAAK;QACjBC,IAAI,KAAK,KAAK;QACdC,KAAK,KAAK,KAAK;QACfC,GAAG,KAAK,KAAK;QACbC,KAAK,KAAK,KAAK,KAAK;QACpBC,MAAM,KAAK,KAAK,KAAK;QACrBC,GAAG,KAAK,KAAK,KAAK;QAClBC,MAAM,IAAI,KAAK,KAAK,KAAK;QACzBC,OAAO,IAAI,KAAK,KAAK,KAAK;QAC1BC,GAAG,IAAI,KAAK,KAAK,KAAK;QACtBC,OAAO;QACPC,QAAQ;QACRC,IAAI;QACJC,MAAM;QACNC,OAAO;QACPC,IAAI;QACJC,KAAK;QACLC,GAAG;IACL;IAEA,MAAMC,aAAanC,WAAW,CAACF,KAAK;IACpC,IAAIqC,eAAeC,WAAW;QAC5B,OAAOlD,IAAI,IAAIM,MAAM,CAAC,0BAA0B,EAAEH,IAAI,CAAC,CAAC;IAC1D;IAEA,OAAOF,GAAGQ,WAAWwC;AACvB"}
1
+ {"version":3,"sources":["../../src/core/duration.ts"],"sourcesContent":["import type { Result } from \"./result\";\nimport { err, ok } from \"./result\";\n\ntype Years = \"years\" | \"year\" | \"yrs\" | \"yr\" | \"y\";\ntype Months = \"months\" | \"month\" | \"mo\";\ntype Weeks = \"weeks\" | \"week\" | \"w\";\ntype Days = \"days\" | \"day\" | \"d\";\ntype Hours = \"hours\" | \"hour\" | \"hrs\" | \"hr\" | \"h\";\ntype Minutes = \"minutes\" | \"minute\" | \"mins\" | \"min\" | \"m\";\ntype Seconds = \"seconds\" | \"second\" | \"secs\" | \"sec\" | \"s\";\ntype Milliseconds = \"milliseconds\" | \"millisecond\" | \"msecs\" | \"msec\" | \"ms\";\ntype Unit = Years | Months | Weeks | Days | Hours | Minutes | Seconds | Milliseconds;\ntype UnitAnyCase = Capitalize<Unit> | Uppercase<Unit> | Lowercase<Unit>;\nexport type DurationString = `${number}` | `${number}${UnitAnyCase}` | `${number} ${UnitAnyCase}`;\n\n/**\n * Parse a duration string into milliseconds. Examples:\n * - short units: \"1ms\", \"5s\", \"30m\", \"2h\", \"7d\", \"3w\", \"1y\"\n * - long units: \"1 millisecond\", \"5 seconds\", \"30 minutes\", \"2 hours\", \"7 days\", \"3 weeks\", \"1 year\"\n * @param str - Duration string\n * @returns Milliseconds\n */\nexport function parseDuration(str: DurationString): Result<number> {\n if (typeof str !== \"string\") {\n return err(\n new TypeError(`Invalid duration format: expected a string but received ${typeof str}`),\n );\n }\n\n if (str.length === 0) {\n return err(new Error('Invalid duration format: \"\"'));\n }\n\n const match = /^(-?\\.?\\d+(?:\\.\\d+)?)\\s*([a-z]+)?$/i.exec(str);\n\n if (!match?.[1]) {\n return err(new Error(`Invalid duration format: \"${str}\"`));\n }\n\n const numValue = Number.parseFloat(match[1]);\n const unit = match[2]?.toLowerCase() ?? \"ms\"; // default to ms if not provided\n\n const multipliers: Record<string, number> = {\n millisecond: 1,\n milliseconds: 1,\n msec: 1,\n msecs: 1,\n ms: 1,\n second: 1000,\n seconds: 1000,\n sec: 1000,\n secs: 1000,\n s: 1000,\n minute: 60 * 1000,\n minutes: 60 * 1000,\n min: 60 * 1000,\n mins: 60 * 1000,\n m: 60 * 1000,\n hour: 60 * 60 * 1000,\n hours: 60 * 60 * 1000,\n hr: 60 * 60 * 1000,\n hrs: 60 * 60 * 1000,\n h: 60 * 60 * 1000,\n day: 24 * 60 * 60 * 1000,\n days: 24 * 60 * 60 * 1000,\n d: 24 * 60 * 60 * 1000,\n week: 7 * 24 * 60 * 60 * 1000,\n weeks: 7 * 24 * 60 * 60 * 1000,\n w: 7 * 24 * 60 * 60 * 1000,\n month: 2_629_800_000,\n months: 2_629_800_000,\n mo: 2_629_800_000,\n year: 31_557_600_000,\n years: 31_557_600_000,\n yr: 31_557_600_000,\n yrs: 31_557_600_000,\n y: 31_557_600_000,\n };\n\n const multiplier = multipliers[unit];\n if (multiplier === undefined) {\n return err(new Error(`Invalid duration format: \"${str}\"`));\n }\n\n return ok(numValue * multiplier);\n}\n"],"names":["err","ok","parseDuration","str","TypeError","length","Error","match","exec","numValue","Number","parseFloat","unit","toLowerCase","multipliers","millisecond","milliseconds","msec","msecs","ms","second","seconds","sec","secs","s","minute","minutes","min","mins","m","hour","hours","hr","hrs","h","day","days","d","week","weeks","w","month","months","mo","year","years","yr","yrs","y","multiplier","undefined"],"mappings":"AACA,SAASA,GAAG,EAAEC,EAAE,QAAQ,cAAW;AAcnC;;;;;;CAMC,GACD,OAAO,SAASC,cAAcC,GAAmB;IAC/C,IAAI,OAAOA,QAAQ,UAAU;QAC3B,OAAOH,IACL,IAAII,UAAU,CAAC,wDAAwD,EAAE,OAAOD,KAAK;IAEzF;IAEA,IAAIA,IAAIE,MAAM,KAAK,GAAG;QACpB,OAAOL,IAAI,IAAIM,MAAM;IACvB;IAEA,MAAMC,QAAQ,sCAAsCC,IAAI,CAACL;IAEzD,IAAI,CAACI,OAAO,CAAC,EAAE,EAAE;QACf,OAAOP,IAAI,IAAIM,MAAM,CAAC,0BAA0B,EAAEH,IAAI,CAAC,CAAC;IAC1D;IAEA,MAAMM,WAAWC,OAAOC,UAAU,CAACJ,KAAK,CAAC,EAAE;IAC3C,MAAMK,OAAOL,KAAK,CAAC,EAAE,EAAEM,iBAAiB,MAAM,gCAAgC;IAE9E,MAAMC,cAAsC;QAC1CC,aAAa;QACbC,cAAc;QACdC,MAAM;QACNC,OAAO;QACPC,IAAI;QACJC,QAAQ;QACRC,SAAS;QACTC,KAAK;QACLC,MAAM;QACNC,GAAG;QACHC,QAAQ,KAAK;QACbC,SAAS,KAAK;QACdC,KAAK,KAAK;QACVC,MAAM,KAAK;QACXC,GAAG,KAAK;QACRC,MAAM,KAAK,KAAK;QAChBC,OAAO,KAAK,KAAK;QACjBC,IAAI,KAAK,KAAK;QACdC,KAAK,KAAK,KAAK;QACfC,GAAG,KAAK,KAAK;QACbC,KAAK,KAAK,KAAK,KAAK;QACpBC,MAAM,KAAK,KAAK,KAAK;QACrBC,GAAG,KAAK,KAAK,KAAK;QAClBC,MAAM,IAAI,KAAK,KAAK,KAAK;QACzBC,OAAO,IAAI,KAAK,KAAK,KAAK;QAC1BC,GAAG,IAAI,KAAK,KAAK,KAAK;QACtBC,OAAO;QACPC,QAAQ;QACRC,IAAI;QACJC,MAAM;QACNC,OAAO;QACPC,IAAI;QACJC,KAAK;QACLC,GAAG;IACL;IAEA,MAAMC,aAAanC,WAAW,CAACF,KAAK;IACpC,IAAIqC,eAAeC,WAAW;QAC5B,OAAOlD,IAAI,IAAIM,MAAM,CAAC,0BAA0B,EAAEH,IAAI,CAAC,CAAC;IAC1D;IAEA,OAAOF,GAAGQ,WAAWwC;AACvB"}
@@ -72,7 +72,8 @@ export declare function validateInput<RunInput, Input>(schema: StandardSchemaV1<
72
72
  /**
73
73
  * Check if a workflow run status represents a terminal state.
74
74
  * @param status - The workflow run status
75
- * @returns True if the status is terminal (completed, failed, or canceled)
75
+ * @returns True if the status is terminal (succeeded, completed, failed, or canceled).
76
+ * Note: 'succeeded' is deprecated in favor of 'completed'.
76
77
  */
77
78
  export declare function isTerminalStatus(status: string): status is "succeeded" | "completed" | "failed" | "canceled";
78
79
  //# sourceMappingURL=workflow.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../../src/core/workflow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEjD;;GAEG;AACH,MAAM,MAAM,iBAAiB,GACzB,SAAS,GACT,SAAS,GACT,UAAU,GACV,WAAW,GACX,WAAW,GACX,QAAQ,GACR,UAAU,CAAC;AAEf;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,MAAM,EAAE,SAAS,CAAC;IAClB,OAAO,EAAE,SAAS,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,SAAS,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,4BAA4B,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,CAAC,OAAO,EAAE,QAAQ,IAAI,OAAO,SAAS,gBAAgB,GACzE,gBAAgB,CAAC,UAAU,CAAC,OAAO,CAAC,GACpC,QAAQ,CAAC;AAEb;;GAEG;AACH,MAAM,MAAM,YAAY,CAAC,OAAO,EAAE,QAAQ,IAAI,OAAO,SAAS,gBAAgB,GAC1E,gBAAgB,CAAC,WAAW,CAAC,OAAO,CAAC,GACrC,QAAQ,CAAC;AAEb;;;GAGG;AACH,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAElG;;GAEG;AACH,eAAO,MAAM,8BAA8B;IACzC,kDAAkD;;IAElD,0CAA0C;;CAElC,CAAC;AAEX;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,KAAK,EACjD,MAAM,EAAE,gBAAgB,CAAC,QAAQ,EAAE,KAAK,CAAC,GAAG,IAAI,GAAG,SAAS,EAC5D,KAAK,EAAE,QAAQ,GAAG,SAAS,GAC1B,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CA4BlC;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,GACb,MAAM,IAAI,WAAW,GAAG,WAAW,GAAG,QAAQ,GAAG,UAAU,CAI7D"}
1
+ {"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../../src/core/workflow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEjD;;GAEG;AACH,MAAM,MAAM,iBAAiB,GACzB,SAAS,GACT,SAAS,GACT,UAAU,GACV,WAAW,GACX,WAAW,GACX,QAAQ,GACR,UAAU,CAAC;AAEf;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,MAAM,EAAE,SAAS,CAAC;IAClB,OAAO,EAAE,SAAS,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,SAAS,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,4BAA4B,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,CAAC,OAAO,EAAE,QAAQ,IAAI,OAAO,SAAS,gBAAgB,GACzE,gBAAgB,CAAC,UAAU,CAAC,OAAO,CAAC,GACpC,QAAQ,CAAC;AAEb;;GAEG;AACH,MAAM,MAAM,YAAY,CAAC,OAAO,EAAE,QAAQ,IAAI,OAAO,SAAS,gBAAgB,GAC1E,gBAAgB,CAAC,WAAW,CAAC,OAAO,CAAC,GACrC,QAAQ,CAAC;AAEb;;;GAGG;AACH,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAElG;;GAEG;AACH,eAAO,MAAM,8BAA8B;IACzC,kDAAkD;;IAElD,0CAA0C;;CAElC,CAAC;AAEX;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,KAAK,EACjD,MAAM,EAAE,gBAAgB,CAAC,QAAQ,EAAE,KAAK,CAAC,GAAG,IAAI,GAAG,SAAS,EAC5D,KAAK,EAAE,QAAQ,GAAG,SAAS,GAC1B,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CA4BlC;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,GACb,MAAM,IAAI,WAAW,GAAG,WAAW,GAAG,QAAQ,GAAG,UAAU,CAI7D"}
@@ -38,7 +38,8 @@
38
38
  /**
39
39
  * Check if a workflow run status represents a terminal state.
40
40
  * @param status - The workflow run status
41
- * @returns True if the status is terminal (completed, failed, or canceled)
41
+ * @returns True if the status is terminal (succeeded, completed, failed, or canceled).
42
+ * Note: 'succeeded' is deprecated in favor of 'completed'.
42
43
  */ export function isTerminalStatus(status) {
43
44
  return status === "succeeded" || status === "completed" || status === "failed" || status === "canceled";
44
45
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/workflow.ts"],"sourcesContent":["import type { SerializedError } from \"./error\";\nimport type { JsonValue } from \"./json\";\nimport type { StandardSchemaV1 } from \"./schema\";\n\n/**\n * Status of a workflow run through its lifecycle.\n */\nexport type WorkflowRunStatus =\n | \"pending\"\n | \"running\"\n | \"sleeping\"\n | \"succeeded\" // deprecated in favor of 'completed'\n | \"completed\"\n | \"failed\"\n | \"canceled\";\n\n/**\n * WorkflowRun represents a single execution instance of a workflow.\n */\nexport interface WorkflowRun {\n namespaceId: string;\n id: string;\n workflowName: string;\n version: string | null;\n status: WorkflowRunStatus;\n idempotencyKey: string | null;\n config: JsonValue; // user-defined config\n context: JsonValue | null; // runtime execution metadata\n input: JsonValue | null;\n output: JsonValue | null;\n error: SerializedError | null;\n attempts: number;\n parentStepAttemptNamespaceId: string | null;\n parentStepAttemptId: string | null;\n workerId: string | null;\n availableAt: Date | null;\n deadlineAt: Date | null;\n startedAt: Date | null;\n finishedAt: Date | null;\n createdAt: Date;\n updatedAt: Date;\n}\n\n/**\n * Infers the input type from a Standard Schema.\n */\nexport type SchemaInput<TSchema, Fallback> = TSchema extends StandardSchemaV1\n ? StandardSchemaV1.InferInput<TSchema>\n : Fallback;\n\n/**\n * Infers the output type from a Standard Schema.\n */\nexport type SchemaOutput<TSchema, Fallback> = TSchema extends StandardSchemaV1\n ? StandardSchemaV1.InferOutput<TSchema>\n : Fallback;\n\n/**\n * Result of input validation - either success with a value or failure with an\n * error message.\n */\nexport type ValidationResult<T> = { success: true; value: T } | { success: false; error: string };\n\n/**\n * Default configuration for result polling when awaiting workflow completion.\n */\nexport const DEFAULT_WORKFLOW_RESULT_CONFIG = {\n /** Polling interval in milliseconds (1 second) */\n pollIntervalMs: 1000,\n /** Timeout in milliseconds (5 minutes) */\n timeoutMs: 5 * 60 * 1000,\n} as const;\n\n/**\n * Validate input against a Standard Schema. Pure async function that validates\n * input and returns a ValidationResult.\n * @param schema - The Standard Schema to validate against (or null/undefined\n * for no validation)\n * @param input - The input value to validate\n * @returns A ValidationResult containing either the validated value or an error\n * message\n */\nexport async function validateInput<RunInput, Input>(\n schema: StandardSchemaV1<RunInput, Input> | null | undefined,\n input: RunInput | undefined,\n): Promise<ValidationResult<Input>> {\n // No schema means no validation - pass through as-is\n if (!schema) {\n return {\n success: true,\n value: input as unknown as Input,\n };\n }\n\n // Validate using Standard Schema v1 protocol https://standardschema.dev\n const result = schema[\"~standard\"].validate(input);\n const resolved = await Promise.resolve(result);\n\n if (resolved.issues) {\n const messages =\n resolved.issues.length > 0\n ? resolved.issues.map((issue) => issue.message).join(\"; \")\n : \"Validation failed\";\n return {\n success: false,\n error: messages,\n };\n }\n\n return {\n success: true,\n value: resolved.value,\n };\n}\n\n/**\n * Check if a workflow run status represents a terminal state.\n * @param status - The workflow run status\n * @returns True if the status is terminal (completed, failed, or canceled)\n */\nexport function isTerminalStatus(\n status: string,\n): status is \"succeeded\" | \"completed\" | \"failed\" | \"canceled\" {\n return (\n status === \"succeeded\" || status === \"completed\" || status === \"failed\" || status === \"canceled\"\n );\n}\n"],"names":["DEFAULT_WORKFLOW_RESULT_CONFIG","pollIntervalMs","timeoutMs","validateInput","schema","input","success","value","result","validate","resolved","Promise","resolve","issues","messages","length","map","issue","message","join","error","isTerminalStatus","status"],"mappings":"AA+DA;;CAEC,GACD,OAAO,MAAMA,iCAAiC;IAC5C,gDAAgD,GAChDC,gBAAgB;IAChB,wCAAwC,GACxCC,WAAW,IAAI,KAAK;AACtB,EAAW;AAEX;;;;;;;;CAQC,GACD,OAAO,eAAeC,cACpBC,MAA4D,EAC5DC,KAA2B;IAE3B,qDAAqD;IACrD,IAAI,CAACD,QAAQ;QACX,OAAO;YACLE,SAAS;YACTC,OAAOF;QACT;IACF;IAEA,wEAAwE;IACxE,MAAMG,SAASJ,MAAM,CAAC,YAAY,CAACK,QAAQ,CAACJ;IAC5C,MAAMK,WAAW,MAAMC,QAAQC,OAAO,CAACJ;IAEvC,IAAIE,SAASG,MAAM,EAAE;QACnB,MAAMC,WACJJ,SAASG,MAAM,CAACE,MAAM,GAAG,IACrBL,SAASG,MAAM,CAACG,GAAG,CAAC,CAACC,QAAUA,MAAMC,OAAO,EAAEC,IAAI,CAAC,QACnD;QACN,OAAO;YACLb,SAAS;YACTc,OAAON;QACT;IACF;IAEA,OAAO;QACLR,SAAS;QACTC,OAAOG,SAASH,KAAK;IACvB;AACF;AAEA;;;;CAIC,GACD,OAAO,SAASc,iBACdC,MAAc;IAEd,OACEA,WAAW,eAAeA,WAAW,eAAeA,WAAW,YAAYA,WAAW;AAE1F"}
1
+ {"version":3,"sources":["../../src/core/workflow.ts"],"sourcesContent":["import type { SerializedError } from \"./error\";\nimport type { JsonValue } from \"./json\";\nimport type { StandardSchemaV1 } from \"./schema\";\n\n/**\n * Status of a workflow run through its lifecycle.\n */\nexport type WorkflowRunStatus =\n | \"pending\"\n | \"running\"\n | \"sleeping\"\n | \"succeeded\" // deprecated in favor of 'completed'\n | \"completed\"\n | \"failed\"\n | \"canceled\";\n\n/**\n * WorkflowRun represents a single execution instance of a workflow.\n */\nexport interface WorkflowRun {\n namespaceId: string;\n id: string;\n workflowName: string;\n version: string | null;\n status: WorkflowRunStatus;\n idempotencyKey: string | null;\n config: JsonValue; // user-defined config\n context: JsonValue | null; // runtime execution metadata\n input: JsonValue | null;\n output: JsonValue | null;\n error: SerializedError | null;\n attempts: number;\n parentStepAttemptNamespaceId: string | null;\n parentStepAttemptId: string | null;\n workerId: string | null;\n availableAt: Date | null;\n deadlineAt: Date | null;\n startedAt: Date | null;\n finishedAt: Date | null;\n createdAt: Date;\n updatedAt: Date;\n}\n\n/**\n * Infers the input type from a Standard Schema.\n */\nexport type SchemaInput<TSchema, Fallback> = TSchema extends StandardSchemaV1\n ? StandardSchemaV1.InferInput<TSchema>\n : Fallback;\n\n/**\n * Infers the output type from a Standard Schema.\n */\nexport type SchemaOutput<TSchema, Fallback> = TSchema extends StandardSchemaV1\n ? StandardSchemaV1.InferOutput<TSchema>\n : Fallback;\n\n/**\n * Result of input validation - either success with a value or failure with an\n * error message.\n */\nexport type ValidationResult<T> = { success: true; value: T } | { success: false; error: string };\n\n/**\n * Default configuration for result polling when awaiting workflow completion.\n */\nexport const DEFAULT_WORKFLOW_RESULT_CONFIG = {\n /** Polling interval in milliseconds (1 second) */\n pollIntervalMs: 1000,\n /** Timeout in milliseconds (5 minutes) */\n timeoutMs: 5 * 60 * 1000,\n} as const;\n\n/**\n * Validate input against a Standard Schema. Pure async function that validates\n * input and returns a ValidationResult.\n * @param schema - The Standard Schema to validate against (or null/undefined\n * for no validation)\n * @param input - The input value to validate\n * @returns A ValidationResult containing either the validated value or an error\n * message\n */\nexport async function validateInput<RunInput, Input>(\n schema: StandardSchemaV1<RunInput, Input> | null | undefined,\n input: RunInput | undefined,\n): Promise<ValidationResult<Input>> {\n // No schema means no validation - pass through as-is\n if (!schema) {\n return {\n success: true,\n value: input as unknown as Input,\n };\n }\n\n // Validate using Standard Schema v1 protocol https://standardschema.dev\n const result = schema[\"~standard\"].validate(input);\n const resolved = await Promise.resolve(result);\n\n if (resolved.issues) {\n const messages =\n resolved.issues.length > 0\n ? resolved.issues.map((issue) => issue.message).join(\"; \")\n : \"Validation failed\";\n return {\n success: false,\n error: messages,\n };\n }\n\n return {\n success: true,\n value: resolved.value,\n };\n}\n\n/**\n * Check if a workflow run status represents a terminal state.\n * @param status - The workflow run status\n * @returns True if the status is terminal (succeeded, completed, failed, or canceled).\n * Note: 'succeeded' is deprecated in favor of 'completed'.\n */\nexport function isTerminalStatus(\n status: string,\n): status is \"succeeded\" | \"completed\" | \"failed\" | \"canceled\" {\n return (\n status === \"succeeded\" || status === \"completed\" || status === \"failed\" || status === \"canceled\"\n );\n}\n"],"names":["DEFAULT_WORKFLOW_RESULT_CONFIG","pollIntervalMs","timeoutMs","validateInput","schema","input","success","value","result","validate","resolved","Promise","resolve","issues","messages","length","map","issue","message","join","error","isTerminalStatus","status"],"mappings":"AA+DA;;CAEC,GACD,OAAO,MAAMA,iCAAiC;IAC5C,gDAAgD,GAChDC,gBAAgB;IAChB,wCAAwC,GACxCC,WAAW,IAAI,KAAK;AACtB,EAAW;AAEX;;;;;;;;CAQC,GACD,OAAO,eAAeC,cACpBC,MAA4D,EAC5DC,KAA2B;IAE3B,qDAAqD;IACrD,IAAI,CAACD,QAAQ;QACX,OAAO;YACLE,SAAS;YACTC,OAAOF;QACT;IACF;IAEA,wEAAwE;IACxE,MAAMG,SAASJ,MAAM,CAAC,YAAY,CAACK,QAAQ,CAACJ;IAC5C,MAAMK,WAAW,MAAMC,QAAQC,OAAO,CAACJ;IAEvC,IAAIE,SAASG,MAAM,EAAE;QACnB,MAAMC,WACJJ,SAASG,MAAM,CAACE,MAAM,GAAG,IACrBL,SAASG,MAAM,CAACG,GAAG,CAAC,CAACC,QAAUA,MAAMC,OAAO,EAAEC,IAAI,CAAC,QACnD;QACN,OAAO;YACLb,SAAS;YACTc,OAAON;QACT;IACF;IAEA,OAAO;QACLR,SAAS;QACTC,OAAOG,SAASH,KAAK;IACvB;AACF;AAEA;;;;;CAKC,GACD,OAAO,SAASc,iBACdC,MAAc;IAEd,OACEA,WAAW,eAAeA,WAAW,eAAeA,WAAW,YAAYA,WAAW;AAE1F"}
@@ -1 +1 @@
1
- {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/database/backend.ts"],"names":[],"mappings":"AACA,OAAa,EAAE,KAAK,IAAI,EAAE,MAAM,MAAM,CAAC;AACvC,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EAC9B,KAAK,yBAAyB,EAC9B,KAAK,uBAAuB,EAC5B,KAAK,uBAAuB,EAE5B,KAAK,4BAA4B,EACjC,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,EAC5B,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,OAAO,EAAE,KAAK,YAAY,EAAkB,MAAM,UAAU,CAAC;AAE7D,eAAO,MAAM,sBAAsB,EAAG,WAAoB,CAAC;AAG3D,UAAU,sBAAsB;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IAGxB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;GAEG;AACH,qBAAa,eAAgB,YAAW,OAAO;IAC7C,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,SAAS,CAAU;IAC3B,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,aAAa,CAAU;IAE/B,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,KAAK,IAAI,GAMf;gBAEW,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,sBAAsB;IAqC3D,UAAU;IAYV,SAAS,CAAC,QAAQ,EAAE,YAAY;IAgBhC,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBxC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAUrB,iBAAiB,CAAC,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAAC,WAAW,CAAC;IAkCxE,cAAc,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAsCzE,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;IA6B/F,OAAO,CAAC,0BAA0B;IAkB5B,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IA4D7E,sBAAsB,CAAC,MAAM,EAAE,4BAA4B,GAAG,OAAO,CAAC,WAAW,CAAC;IAyBlF,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,WAAW,CAAC;IA4BtE,mBAAmB,CAAC,MAAM,EAAE,yBAAyB,GAAG,OAAO,CAAC,WAAW,CAAC;IA8B5E,eAAe,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,WAAW,CAAC;IAgDpE,iBAAiB,CAAC,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAAC,WAAW,CAAC;IAgDxE,iBAAiB,CAAC,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAAC,WAAW,CAAC;IA8BxE,cAAc,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAezE,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;IA6B/F,OAAO,CAAC,0BAA0B;IAmBlC,OAAO,CAAC,wBAAwB;IAyC1B,mBAAmB,CAAC,MAAM,EAAE,yBAAyB,GAAG,OAAO,CAAC,WAAW,CAAC;IAiC5E,eAAe,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,WAAW,CAAC;CAgC3E;AAED;;;;;GAKG;AACH,UAAU,MAAM;IACd,SAAS,EAAE,IAAI,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;CACZ;AASD,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAOnD"}
1
+ {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/database/backend.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { getLogger } from "@logtape/logtape";
1
2
  import { camelize } from "inflection";
2
3
  import knex from "knex";
3
4
  import { DEFAULT_NAMESPACE_ID } from "../backend.js";
@@ -6,6 +7,11 @@ import { DEFAULT_SCHEMA, migrate } from "./base.js";
6
7
  import { PostgresPubSub } from "./pubsub.js";
7
8
  export const DEFAULT_LISTEN_CHANNEL = "new_tasks";
8
9
  const DEFAULT_PAGINATION_PAGE_SIZE = 100;
10
+ const logger = getLogger([
11
+ "sonamu",
12
+ "internal",
13
+ "tasks"
14
+ ]);
9
15
  /**
10
16
  * Manages a connection to a Postgres database for workflow operations.
11
17
  */ export class BackendPostgres {
@@ -112,6 +118,9 @@ const DEFAULT_PAGINATION_PAGE_SIZE = 100;
112
118
  }).returning("*");
113
119
  const workflowRun = await qb;
114
120
  if (!workflowRun[0]) {
121
+ logger.error("Failed to create workflow run: {params}", {
122
+ params
123
+ });
115
124
  throw new Error("Failed to create workflow run");
116
125
  }
117
126
  return workflowRun[0];
@@ -193,6 +202,9 @@ const DEFAULT_PAGINATION_PAGE_SIZE = 100;
193
202
  updated_at: this.knex.fn.now()
194
203
  }).returning("*");
195
204
  if (!updated) {
205
+ logger.error("Failed to extend lease for workflow run: {params}", {
206
+ params
207
+ });
196
208
  throw new Error("Failed to extend lease for workflow run");
197
209
  }
198
210
  return updated;
@@ -214,6 +226,9 @@ const DEFAULT_PAGINATION_PAGE_SIZE = 100;
214
226
  updated_at: this.knex.fn.now()
215
227
  }).returning("*");
216
228
  if (!updated) {
229
+ logger.error("Failed to sleep workflow run: {params}", {
230
+ params
231
+ });
217
232
  throw new Error("Failed to sleep workflow run");
218
233
  }
219
234
  return updated;
@@ -232,6 +247,9 @@ const DEFAULT_PAGINATION_PAGE_SIZE = 100;
232
247
  updated_at: this.knex.fn.now()
233
248
  }).returning("*");
234
249
  if (!updated) {
250
+ logger.error("Failed to complete workflow run: {params}", {
251
+ params
252
+ });
235
253
  throw new Error("Failed to complete workflow run");
236
254
  }
237
255
  return updated;
@@ -260,6 +278,9 @@ const DEFAULT_PAGINATION_PAGE_SIZE = 100;
260
278
  updated_at: this.knex.fn.now()
261
279
  }).returning("*");
262
280
  if (!updated) {
281
+ logger.error("Failed to mark workflow run failed: {params}", {
282
+ params
283
+ });
263
284
  throw new Error("Failed to mark workflow run failed");
264
285
  }
265
286
  return updated;
@@ -298,8 +319,15 @@ const DEFAULT_PAGINATION_PAGE_SIZE = 100;
298
319
  "completed",
299
320
  "failed"
300
321
  ].includes(existing.status)) {
322
+ logger.error("Cannot cancel workflow run: {params} with status {status}", {
323
+ params,
324
+ status: existing.status
325
+ });
301
326
  throw new Error(`Cannot cancel workflow run ${params.workflowRunId} with status ${existing.status}`);
302
327
  }
328
+ logger.error("Failed to cancel workflow run: {params}", {
329
+ params
330
+ });
303
331
  throw new Error("Failed to cancel workflow run");
304
332
  }
305
333
  return updated;
@@ -322,6 +350,9 @@ const DEFAULT_PAGINATION_PAGE_SIZE = 100;
322
350
  updated_at: this.knex.fn.now()
323
351
  }).returning("*");
324
352
  if (!stepAttempt) {
353
+ logger.error("Failed to create step attempt: {params}", {
354
+ params
355
+ });
325
356
  throw new Error("Failed to create step attempt");
326
357
  }
327
358
  return stepAttempt;
@@ -405,6 +436,9 @@ const DEFAULT_PAGINATION_PAGE_SIZE = 100;
405
436
  updated_at: this.knex.fn.now()
406
437
  }).updateFrom(`${DEFAULT_SCHEMA}.workflow_runs as wr`).where("sa.namespace_id", this.namespaceId).where("sa.workflow_run_id", params.workflowRunId).where("sa.id", params.stepAttemptId).where("sa.status", "running").where("wr.namespace_id", this.knex.ref("sa.namespace_id")).where("wr.id", this.knex.ref("sa.workflow_run_id")).where("wr.status", "running").where("wr.worker_id", params.workerId).returning("sa.*");
407
438
  if (!updated) {
439
+ logger.error("Failed to mark step attempt completed: {params}", {
440
+ params
441
+ });
408
442
  throw new Error("Failed to mark step attempt completed");
409
443
  }
410
444
  return updated;
@@ -421,6 +455,9 @@ const DEFAULT_PAGINATION_PAGE_SIZE = 100;
421
455
  updated_at: this.knex.fn.now()
422
456
  }).updateFrom(`${DEFAULT_SCHEMA}.workflow_runs as wr`).where("sa.namespace_id", this.namespaceId).where("sa.workflow_run_id", params.workflowRunId).where("sa.id", params.stepAttemptId).where("sa.status", "running").where("wr.namespace_id", this.knex.ref("sa.namespace_id")).where("wr.id", this.knex.ref("sa.workflow_run_id")).where("wr.status", "running").where("wr.worker_id", params.workerId).returning("sa.*");
423
457
  if (!updated) {
458
+ logger.error("Failed to mark step attempt failed: {params}", {
459
+ params
460
+ });
424
461
  throw new Error("Failed to mark step attempt failed");
425
462
  }
426
463
  return updated;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/database/backend.ts"],"sourcesContent":["import { camelize } from \"inflection\";\nimport knex, { type Knex } from \"knex\";\nimport {\n type Backend,\n type CancelWorkflowRunParams,\n type ClaimWorkflowRunParams,\n type CompleteStepAttemptParams,\n type CompleteWorkflowRunParams,\n type CreateStepAttemptParams,\n type CreateWorkflowRunParams,\n DEFAULT_NAMESPACE_ID,\n type ExtendWorkflowRunLeaseParams,\n type FailStepAttemptParams,\n type FailWorkflowRunParams,\n type GetStepAttemptParams,\n type GetWorkflowRunParams,\n type ListStepAttemptsParams,\n type ListWorkflowRunsParams,\n type PaginatedResponse,\n type SleepWorkflowRunParams,\n} from \"../backend\";\nimport { DEFAULT_RETRY_POLICY } from \"../core/retry\";\nimport type { StepAttempt } from \"../core/step\";\nimport type { WorkflowRun } from \"../core/workflow\";\nimport { DEFAULT_SCHEMA, migrate } from \"./base\";\nimport { type OnSubscribed, PostgresPubSub } from \"./pubsub\";\n\nexport const DEFAULT_LISTEN_CHANNEL = \"new_tasks\" as const;\nconst DEFAULT_PAGINATION_PAGE_SIZE = 100 as const;\n\ninterface BackendPostgresOptions {\n namespaceId?: string;\n runMigrations?: boolean;\n\n // default: true\n usePubSub?: boolean;\n}\n\n/**\n * Manages a connection to a Postgres database for workflow operations.\n */\nexport class BackendPostgres implements Backend {\n private config: Knex.Config;\n private namespaceId: string;\n private usePubSub: boolean;\n private pubsub: PostgresPubSub | null = null;\n private initialized: boolean = false;\n private runMigrations: boolean;\n\n private _knex: Knex | null = null;\n private get knex(): Knex {\n if (!this._knex) {\n this._knex = knex(this.config);\n }\n\n return this._knex;\n }\n\n constructor(config: Knex.Config, options?: BackendPostgresOptions) {\n this.config = {\n ...config,\n postProcessResponse: (result, _queryContext) => {\n if (result === null || result === undefined) {\n return result;\n }\n\n if (config?.postProcessResponse) {\n result = config.postProcessResponse(result, _queryContext);\n }\n\n const camelizeRow = (row: Record<string, unknown>) =>\n Object.fromEntries(\n Object.entries(row).map(([key, value]) => [camelize(key, true), value]),\n );\n\n if (Array.isArray(result)) {\n return result.map(camelizeRow);\n }\n\n return camelizeRow(result);\n },\n };\n\n const { namespaceId, usePubSub, runMigrations } = {\n namespaceId: DEFAULT_NAMESPACE_ID,\n usePubSub: true,\n runMigrations: true,\n ...options,\n };\n\n this.namespaceId = namespaceId;\n this.usePubSub = usePubSub;\n this.runMigrations = runMigrations;\n }\n\n async initialize() {\n if (this.initialized) {\n return;\n }\n\n if (this.runMigrations) {\n await migrate(this.config, DEFAULT_SCHEMA);\n }\n\n this.initialized = true;\n }\n\n async subscribe(callback: OnSubscribed) {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n if (!this.usePubSub) {\n return;\n }\n\n if (!this.pubsub) {\n this.pubsub = await PostgresPubSub.create(this.knex);\n }\n\n this.pubsub.listenEvent(DEFAULT_LISTEN_CHANNEL, callback);\n }\n\n async publish(payload?: string): Promise<void> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n if (!this.usePubSub) {\n return;\n }\n\n await this.knex.raw(\n payload\n ? `NOTIFY ${DEFAULT_LISTEN_CHANNEL}, '${payload}'`\n : `NOTIFY ${DEFAULT_LISTEN_CHANNEL}`,\n );\n }\n\n async stop(): Promise<void> {\n if (!this.initialized) {\n return;\n }\n\n await this.pubsub?.destroy();\n this.pubsub = null;\n await this.knex.destroy();\n }\n\n async createWorkflowRun(params: CreateWorkflowRunParams): Promise<WorkflowRun> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n const qb = this.knex\n .withSchema(DEFAULT_SCHEMA)\n .table(\"workflow_runs\")\n .insert({\n namespace_id: this.namespaceId,\n id: crypto.randomUUID(),\n workflow_name: params.workflowName,\n version: params.version,\n status: \"pending\",\n idempotency_key: params.idempotencyKey,\n config: params.config,\n context: params.context,\n input: params.input,\n attempts: 0,\n available_at: params.availableAt ?? this.knex.fn.now(),\n deadline_at: params.deadlineAt,\n created_at: this.knex.fn.now(),\n updated_at: this.knex.fn.now(),\n })\n .returning(\"*\");\n\n const workflowRun = await qb;\n if (!workflowRun[0]) {\n throw new Error(\"Failed to create workflow run\");\n }\n\n return workflowRun[0];\n }\n\n async getWorkflowRun(params: GetWorkflowRunParams): Promise<WorkflowRun | null> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n const workflowRun = await this.knex\n .withSchema(DEFAULT_SCHEMA)\n .table(\"workflow_runs\")\n .where(\"namespace_id\", this.namespaceId)\n .where(\"id\", params.workflowRunId)\n .select(\n \"namespace_id\",\n \"id\",\n \"workflow_name\",\n \"version\",\n \"status\",\n \"idempotency_key\",\n \"config\",\n \"context\",\n \"input\",\n \"output\",\n \"error\",\n \"attempts\",\n \"parent_step_attempt_namespace_id\",\n \"parent_step_attempt_id\",\n \"worker_id\",\n \"available_at\",\n \"deadline_at\",\n \"started_at\",\n \"finished_at\",\n \"created_at\",\n \"updated_at\",\n )\n .first();\n\n return workflowRun ?? null;\n }\n\n async listWorkflowRuns(params: ListWorkflowRunsParams): Promise<PaginatedResponse<WorkflowRun>> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n const limit = params.limit ?? DEFAULT_PAGINATION_PAGE_SIZE;\n const { after, before } = params;\n\n let cursor: Cursor | null = null;\n if (after) {\n cursor = decodeCursor(after);\n } else if (before) {\n cursor = decodeCursor(before);\n }\n\n const qb = this.buildListWorkflowRunsWhere(params, cursor);\n const rows = await qb\n .orderBy(\"created_at\", before ? \"desc\" : \"asc\")\n .orderBy(\"id\", before ? \"desc\" : \"asc\")\n .limit(limit + 1);\n\n return this.processPaginationResults(\n rows,\n limit,\n typeof after === \"string\",\n typeof before === \"string\",\n );\n }\n\n private buildListWorkflowRunsWhere(params: ListWorkflowRunsParams, cursor: Cursor | null) {\n const { after } = params;\n const qb = this.knex\n .withSchema(DEFAULT_SCHEMA)\n .table(\"workflow_runs\")\n .where(\"namespace_id\", this.namespaceId);\n\n if (cursor) {\n const operator = after ? \">\" : \"<\";\n return qb.whereRaw(`(\"created_at\", \"id\") ${operator} (?, ?)`, [\n cursor.createdAt.toISOString(),\n cursor.id,\n ]);\n }\n\n return qb;\n }\n\n async claimWorkflowRun(params: ClaimWorkflowRunParams): Promise<WorkflowRun | null> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n const claimed = await this.knex\n .with(\"expired\", (qb) =>\n qb\n .withSchema(DEFAULT_SCHEMA)\n .table(\"workflow_runs\")\n .update({\n status: \"failed\",\n error: JSON.stringify({ message: \"Workflow run deadline exceeded\" }),\n worker_id: null,\n available_at: null,\n finished_at: this.knex.raw(\"NOW()\"),\n updated_at: this.knex.raw(\"NOW()\"),\n })\n .where(\"namespace_id\", this.namespaceId)\n .whereIn(\"status\", [\"pending\", \"running\", \"sleeping\"])\n .whereNotNull(\"deadline_at\")\n .where(\"deadline_at\", \"<=\", this.knex.raw(\"NOW()\"))\n .returning(\"id\"),\n )\n .with(\"candidate\", (qb) =>\n qb\n .withSchema(DEFAULT_SCHEMA)\n .select(\"id\")\n .from(\"workflow_runs\")\n .where(\"namespace_id\", this.namespaceId)\n .whereIn(\"status\", [\"pending\", \"running\", \"sleeping\"])\n .where(\"available_at\", \"<=\", this.knex.raw(\"NOW()\"))\n .where((qb2) => {\n qb2.whereNull(\"deadline_at\").orWhere(\"deadline_at\", \">\", this.knex.raw(\"NOW()\"));\n })\n .orderByRaw(\"CASE WHEN status = 'pending' THEN 0 ELSE 1 END\")\n .orderBy(\"available_at\", \"asc\")\n .orderBy(\"created_at\", \"asc\")\n .limit(1)\n .forUpdate()\n .skipLocked(),\n )\n .withSchema(DEFAULT_SCHEMA)\n .table(\"workflow_runs as wr\")\n .where(\"wr.namespace_id\", this.namespaceId)\n .where(\"wr.id\", this.knex.ref(\"candidate.id\"))\n .update({\n status: \"running\",\n attempts: this.knex.raw(\"wr.attempts + 1\"),\n worker_id: params.workerId,\n available_at: this.knex.raw(`NOW() + ${params.leaseDurationMs} * INTERVAL '1 millisecond'`),\n started_at: this.knex.raw(\"COALESCE(wr.started_at, NOW())\"),\n updated_at: this.knex.raw(\"NOW()\"),\n })\n .updateFrom(\"candidate\")\n .returning(\"wr.*\");\n\n return claimed[0] ?? null;\n }\n\n async extendWorkflowRunLease(params: ExtendWorkflowRunLeaseParams): Promise<WorkflowRun> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n const [updated] = await this.knex\n .withSchema(DEFAULT_SCHEMA)\n .table(\"workflow_runs\")\n .where(\"namespace_id\", this.namespaceId)\n .where(\"id\", params.workflowRunId)\n .where(\"status\", \"running\")\n .where(\"worker_id\", params.workerId)\n .update({\n available_at: this.knex.raw(`NOW() + ${params.leaseDurationMs} * INTERVAL '1 millisecond'`),\n updated_at: this.knex.fn.now(),\n })\n .returning(\"*\");\n\n if (!updated) {\n throw new Error(\"Failed to extend lease for workflow run\");\n }\n\n return updated;\n }\n\n async sleepWorkflowRun(params: SleepWorkflowRunParams): Promise<WorkflowRun> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n // 'succeeded' status is deprecated\n const [updated] = await this.knex\n .withSchema(DEFAULT_SCHEMA)\n .table(\"workflow_runs\")\n .where(\"namespace_id\", this.namespaceId)\n .where(\"id\", params.workflowRunId)\n .whereNotIn(\"status\", [\"succeeded\", \"completed\", \"failed\", \"canceled\"])\n .where(\"worker_id\", params.workerId)\n .update({\n status: \"sleeping\",\n available_at: params.availableAt,\n worker_id: null,\n updated_at: this.knex.fn.now(),\n })\n .returning(\"*\");\n\n if (!updated) {\n throw new Error(\"Failed to sleep workflow run\");\n }\n\n return updated;\n }\n\n async completeWorkflowRun(params: CompleteWorkflowRunParams): Promise<WorkflowRun> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n const [updated] = await this.knex\n .withSchema(DEFAULT_SCHEMA)\n .table(\"workflow_runs\")\n .where(\"namespace_id\", this.namespaceId)\n .where(\"id\", params.workflowRunId)\n .where(\"status\", \"running\")\n .where(\"worker_id\", params.workerId)\n .update({\n status: \"completed\",\n output: JSON.stringify(params.output),\n error: null,\n worker_id: params.workerId,\n available_at: null,\n finished_at: this.knex.fn.now(),\n updated_at: this.knex.fn.now(),\n })\n .returning(\"*\");\n\n if (!updated) {\n throw new Error(\"Failed to complete workflow run\");\n }\n\n return updated;\n }\n\n async failWorkflowRun(params: FailWorkflowRunParams): Promise<WorkflowRun> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n const { workflowRunId, error } = params;\n const { initialIntervalMs, backoffCoefficient, maximumIntervalMs } = DEFAULT_RETRY_POLICY;\n\n // this beefy query updates a workflow's status, available_at, and\n // finished_at based on the workflow's deadline and retry policy\n //\n // if the next retry would exceed the deadline, the run is marked as\n // 'failed' and finalized, otherwise, the run is rescheduled with an updated\n // 'available_at' timestamp for the next retry\n const retryIntervalExpr = `LEAST(${initialIntervalMs} * POWER(${backoffCoefficient}, \"attempts\" - 1), ${maximumIntervalMs}) * INTERVAL '1 millisecond'`;\n const deadlineExceededCondition = `\"deadline_at\" IS NOT NULL AND NOW() + (${retryIntervalExpr}) >= \"deadline_at\"`;\n\n const [updated] = await this.knex\n .withSchema(DEFAULT_SCHEMA)\n .table(\"workflow_runs\")\n .where(\"namespace_id\", this.namespaceId)\n .where(\"id\", workflowRunId)\n .where(\"status\", \"running\")\n .where(\"worker_id\", params.workerId)\n .update({\n status: this.knex.raw(\n `CASE WHEN ${deadlineExceededCondition} THEN 'failed' ELSE 'pending' END`,\n ),\n available_at: this.knex.raw(\n `CASE WHEN ${deadlineExceededCondition} THEN NULL ELSE NOW() + (${retryIntervalExpr}) END`,\n ),\n finished_at: this.knex.raw(\n `CASE WHEN ${deadlineExceededCondition} THEN NOW() ELSE NULL END`,\n ),\n error: JSON.stringify(error),\n worker_id: null,\n started_at: null,\n updated_at: this.knex.fn.now(),\n })\n .returning(\"*\");\n\n if (!updated) {\n throw new Error(\"Failed to mark workflow run failed\");\n }\n\n return updated;\n }\n\n async cancelWorkflowRun(params: CancelWorkflowRunParams): Promise<WorkflowRun> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n const [updated] = await this.knex\n .withSchema(DEFAULT_SCHEMA)\n .table(\"workflow_runs\")\n .where(\"namespace_id\", this.namespaceId)\n .where(\"id\", params.workflowRunId)\n .whereIn(\"status\", [\"pending\", \"running\", \"sleeping\"])\n .update({\n status: \"canceled\",\n worker_id: null,\n available_at: null,\n finished_at: this.knex.fn.now(),\n updated_at: this.knex.fn.now(),\n })\n .returning(\"*\");\n\n if (!updated) {\n // workflow may already be in a terminal state\n const existing = await this.getWorkflowRun({\n workflowRunId: params.workflowRunId,\n });\n if (!existing) {\n throw new Error(`Workflow run ${params.workflowRunId} does not exist`);\n }\n\n // if already canceled, just return it\n if (existing.status === \"canceled\") {\n return existing;\n }\n\n // throw error for completed/failed workflows\n // 'succeeded' status is deprecated\n if ([\"succeeded\", \"completed\", \"failed\"].includes(existing.status)) {\n throw new Error(\n `Cannot cancel workflow run ${params.workflowRunId} with status ${existing.status}`,\n );\n }\n\n throw new Error(\"Failed to cancel workflow run\");\n }\n\n return updated;\n }\n\n async createStepAttempt(params: CreateStepAttemptParams): Promise<StepAttempt> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n const [stepAttempt] = await this.knex\n .withSchema(DEFAULT_SCHEMA)\n .table(\"step_attempts\")\n .insert({\n namespace_id: this.namespaceId,\n id: crypto.randomUUID(),\n workflow_run_id: params.workflowRunId,\n step_name: params.stepName,\n kind: params.kind,\n status: \"running\",\n config: JSON.stringify(params.config),\n context: JSON.stringify(params.context),\n started_at: this.knex.fn.now(),\n created_at: this.knex.raw(\"date_trunc('milliseconds', NOW())\"),\n updated_at: this.knex.fn.now(),\n })\n .returning(\"*\");\n\n if (!stepAttempt) {\n throw new Error(\"Failed to create step attempt\");\n }\n\n return stepAttempt;\n }\n\n async getStepAttempt(params: GetStepAttemptParams): Promise<StepAttempt | null> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n const stepAttempt = await this.knex\n .withSchema(DEFAULT_SCHEMA)\n .table(\"step_attempts\")\n .where(\"namespace_id\", this.namespaceId)\n .where(\"id\", params.stepAttemptId)\n .first();\n\n return stepAttempt ?? null;\n }\n\n async listStepAttempts(params: ListStepAttemptsParams): Promise<PaginatedResponse<StepAttempt>> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n const limit = params.limit ?? DEFAULT_PAGINATION_PAGE_SIZE;\n const { after, before } = params;\n\n let cursor: Cursor | null = null;\n if (after) {\n cursor = decodeCursor(after);\n } else if (before) {\n cursor = decodeCursor(before);\n }\n\n const qb = this.buildListStepAttemptsWhere(params, cursor);\n const rows = await qb\n .orderBy(\"created_at\", before ? \"desc\" : \"asc\")\n .orderBy(\"id\", before ? \"desc\" : \"asc\")\n .limit(limit + 1);\n\n return this.processPaginationResults(\n rows,\n limit,\n typeof after === \"string\",\n typeof before === \"string\",\n );\n }\n\n private buildListStepAttemptsWhere(params: ListStepAttemptsParams, cursor: Cursor | null) {\n const { after } = params;\n const qb = this.knex\n .withSchema(DEFAULT_SCHEMA)\n .table(\"step_attempts\")\n .where(\"namespace_id\", this.namespaceId)\n .where(\"workflow_run_id\", params.workflowRunId);\n\n if (cursor) {\n const operator = after ? \">\" : \"<\";\n return qb.whereRaw(`(\"created_at\", \"id\") ${operator} (?, ?)`, [\n cursor.createdAt.toISOString(),\n cursor.id,\n ]);\n }\n\n return qb;\n }\n\n private processPaginationResults<T extends Cursor>(\n rows: T[],\n limit: number,\n hasAfter: boolean,\n hasBefore: boolean,\n ): PaginatedResponse<T> {\n const data = rows;\n let hasNext = false;\n let hasPrev = false;\n\n if (hasBefore) {\n data.reverse();\n if (data.length > limit) {\n hasPrev = true;\n data.shift();\n }\n hasNext = true;\n } else {\n if (data.length > limit) {\n hasNext = true;\n data.pop();\n }\n if (hasAfter) {\n hasPrev = true;\n }\n }\n\n const lastItem = data.at(-1);\n const nextCursor = hasNext && lastItem ? encodeCursor(lastItem) : null;\n const firstItem = data[0];\n const prevCursor = hasPrev && firstItem ? encodeCursor(firstItem) : null;\n\n return {\n data,\n pagination: {\n next: nextCursor,\n prev: prevCursor,\n },\n };\n }\n\n async completeStepAttempt(params: CompleteStepAttemptParams): Promise<StepAttempt> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n const [updated] = await this.knex\n .withSchema(DEFAULT_SCHEMA)\n .table(\"step_attempts as sa\")\n .update({\n status: \"completed\",\n output: JSON.stringify(params.output),\n error: null,\n finished_at: this.knex.fn.now(),\n updated_at: this.knex.fn.now(),\n })\n .updateFrom(`${DEFAULT_SCHEMA}.workflow_runs as wr`)\n .where(\"sa.namespace_id\", this.namespaceId)\n .where(\"sa.workflow_run_id\", params.workflowRunId)\n .where(\"sa.id\", params.stepAttemptId)\n .where(\"sa.status\", \"running\")\n .where(\"wr.namespace_id\", this.knex.ref(\"sa.namespace_id\"))\n .where(\"wr.id\", this.knex.ref(\"sa.workflow_run_id\"))\n .where(\"wr.status\", \"running\")\n .where(\"wr.worker_id\", params.workerId)\n .returning(\"sa.*\");\n\n if (!updated) {\n throw new Error(\"Failed to mark step attempt completed\");\n }\n\n return updated;\n }\n\n async failStepAttempt(params: FailStepAttemptParams): Promise<StepAttempt> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n const [updated] = await this.knex\n .withSchema(DEFAULT_SCHEMA)\n .table(\"step_attempts as sa\")\n .update({\n status: \"failed\",\n output: null,\n error: JSON.stringify(params.error),\n finished_at: this.knex.fn.now(),\n updated_at: this.knex.fn.now(),\n })\n .updateFrom(`${DEFAULT_SCHEMA}.workflow_runs as wr`)\n .where(\"sa.namespace_id\", this.namespaceId)\n .where(\"sa.workflow_run_id\", params.workflowRunId)\n .where(\"sa.id\", params.stepAttemptId)\n .where(\"sa.status\", \"running\")\n .where(\"wr.namespace_id\", this.knex.ref(\"sa.namespace_id\"))\n .where(\"wr.id\", this.knex.ref(\"sa.workflow_run_id\"))\n .where(\"wr.status\", \"running\")\n .where(\"wr.worker_id\", params.workerId)\n .returning(\"sa.*\");\n\n if (!updated) {\n throw new Error(\"Failed to mark step attempt failed\");\n }\n\n return updated;\n }\n}\n\n/**\n * Cursor used for pagination. Requires created_at and id fields. Because JS\n * Date does not natively support microsecond precision dates, created_at should\n * be stored with millisecond precision in paginated tables to avoid issues with\n * cursor comparisons.\n */\ninterface Cursor {\n createdAt: Date;\n id: string;\n}\n\nfunction encodeCursor(item: Cursor): string {\n const encoded = Buffer.from(\n JSON.stringify({ createdAt: item.createdAt.toISOString(), id: item.id }),\n ).toString(\"base64\");\n return encoded;\n}\n\nexport function decodeCursor(cursor: string): Cursor {\n const decoded = Buffer.from(cursor, \"base64\").toString(\"utf8\");\n const parsed = JSON.parse(decoded) as { createdAt: string; id: string };\n return {\n createdAt: new Date(parsed.createdAt),\n id: parsed.id,\n };\n}\n"],"names":["camelize","knex","DEFAULT_NAMESPACE_ID","DEFAULT_RETRY_POLICY","DEFAULT_SCHEMA","migrate","PostgresPubSub","DEFAULT_LISTEN_CHANNEL","DEFAULT_PAGINATION_PAGE_SIZE","BackendPostgres","config","namespaceId","usePubSub","pubsub","initialized","runMigrations","_knex","options","postProcessResponse","result","_queryContext","undefined","camelizeRow","row","Object","fromEntries","entries","map","key","value","Array","isArray","initialize","subscribe","callback","Error","create","listenEvent","publish","payload","raw","stop","destroy","createWorkflowRun","params","qb","withSchema","table","insert","namespace_id","id","crypto","randomUUID","workflow_name","workflowName","version","status","idempotency_key","idempotencyKey","context","input","attempts","available_at","availableAt","fn","now","deadline_at","deadlineAt","created_at","updated_at","returning","workflowRun","getWorkflowRun","where","workflowRunId","select","first","listWorkflowRuns","limit","after","before","cursor","decodeCursor","buildListWorkflowRunsWhere","rows","orderBy","processPaginationResults","operator","whereRaw","createdAt","toISOString","claimWorkflowRun","claimed","with","update","error","JSON","stringify","message","worker_id","finished_at","whereIn","whereNotNull","from","qb2","whereNull","orWhere","orderByRaw","forUpdate","skipLocked","ref","workerId","leaseDurationMs","started_at","updateFrom","extendWorkflowRunLease","updated","sleepWorkflowRun","whereNotIn","completeWorkflowRun","output","failWorkflowRun","initialIntervalMs","backoffCoefficient","maximumIntervalMs","retryIntervalExpr","deadlineExceededCondition","cancelWorkflowRun","existing","includes","createStepAttempt","stepAttempt","workflow_run_id","step_name","stepName","kind","getStepAttempt","stepAttemptId","listStepAttempts","buildListStepAttemptsWhere","hasAfter","hasBefore","data","hasNext","hasPrev","reverse","length","shift","pop","lastItem","at","nextCursor","encodeCursor","firstItem","prevCursor","pagination","next","prev","completeStepAttempt","failStepAttempt","item","encoded","Buffer","toString","decoded","parsed","parse","Date"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/database/backend.ts"],"sourcesContent":["import { getLogger } from \"@logtape/logtape\";\nimport { camelize } from \"inflection\";\nimport knex, { type Knex } from \"knex\";\nimport {\n type Backend,\n type CancelWorkflowRunParams,\n type ClaimWorkflowRunParams,\n type CompleteStepAttemptParams,\n type CompleteWorkflowRunParams,\n type CreateStepAttemptParams,\n type CreateWorkflowRunParams,\n DEFAULT_NAMESPACE_ID,\n type ExtendWorkflowRunLeaseParams,\n type FailStepAttemptParams,\n type FailWorkflowRunParams,\n type GetStepAttemptParams,\n type GetWorkflowRunParams,\n type ListStepAttemptsParams,\n type ListWorkflowRunsParams,\n type PaginatedResponse,\n type SleepWorkflowRunParams,\n} from \"../backend\";\nimport { DEFAULT_RETRY_POLICY } from \"../core/retry\";\nimport type { StepAttempt } from \"../core/step\";\nimport type { WorkflowRun } from \"../core/workflow\";\nimport { DEFAULT_SCHEMA, migrate } from \"./base\";\nimport { type OnSubscribed, PostgresPubSub } from \"./pubsub\";\n\nexport const DEFAULT_LISTEN_CHANNEL = \"new_tasks\" as const;\nconst DEFAULT_PAGINATION_PAGE_SIZE = 100 as const;\n\ninterface BackendPostgresOptions {\n namespaceId?: string;\n runMigrations?: boolean;\n\n // default: true\n usePubSub?: boolean;\n}\n\nconst logger = getLogger([\"sonamu\", \"internal\", \"tasks\"]);\n\n/**\n * Manages a connection to a Postgres database for workflow operations.\n */\nexport class BackendPostgres implements Backend {\n private config: Knex.Config;\n private namespaceId: string;\n private usePubSub: boolean;\n private pubsub: PostgresPubSub | null = null;\n private initialized: boolean = false;\n private runMigrations: boolean;\n\n private _knex: Knex | null = null;\n private get knex(): Knex {\n if (!this._knex) {\n this._knex = knex(this.config);\n }\n\n return this._knex;\n }\n\n constructor(config: Knex.Config, options?: BackendPostgresOptions) {\n this.config = {\n ...config,\n postProcessResponse: (result, _queryContext) => {\n if (result === null || result === undefined) {\n return result;\n }\n\n if (config?.postProcessResponse) {\n result = config.postProcessResponse(result, _queryContext);\n }\n\n const camelizeRow = (row: Record<string, unknown>) =>\n Object.fromEntries(\n Object.entries(row).map(([key, value]) => [camelize(key, true), value]),\n );\n\n if (Array.isArray(result)) {\n return result.map(camelizeRow);\n }\n\n return camelizeRow(result);\n },\n };\n\n const { namespaceId, usePubSub, runMigrations } = {\n namespaceId: DEFAULT_NAMESPACE_ID,\n usePubSub: true,\n runMigrations: true,\n ...options,\n };\n\n this.namespaceId = namespaceId;\n this.usePubSub = usePubSub;\n this.runMigrations = runMigrations;\n }\n\n async initialize() {\n if (this.initialized) {\n return;\n }\n\n if (this.runMigrations) {\n await migrate(this.config, DEFAULT_SCHEMA);\n }\n\n this.initialized = true;\n }\n\n async subscribe(callback: OnSubscribed) {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n if (!this.usePubSub) {\n return;\n }\n\n if (!this.pubsub) {\n this.pubsub = await PostgresPubSub.create(this.knex);\n }\n\n this.pubsub.listenEvent(DEFAULT_LISTEN_CHANNEL, callback);\n }\n\n async publish(payload?: string): Promise<void> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n if (!this.usePubSub) {\n return;\n }\n\n await this.knex.raw(\n payload\n ? `NOTIFY ${DEFAULT_LISTEN_CHANNEL}, '${payload}'`\n : `NOTIFY ${DEFAULT_LISTEN_CHANNEL}`,\n );\n }\n\n async stop(): Promise<void> {\n if (!this.initialized) {\n return;\n }\n\n await this.pubsub?.destroy();\n this.pubsub = null;\n await this.knex.destroy();\n }\n\n async createWorkflowRun(params: CreateWorkflowRunParams): Promise<WorkflowRun> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n const qb = this.knex\n .withSchema(DEFAULT_SCHEMA)\n .table(\"workflow_runs\")\n .insert({\n namespace_id: this.namespaceId,\n id: crypto.randomUUID(),\n workflow_name: params.workflowName,\n version: params.version,\n status: \"pending\",\n idempotency_key: params.idempotencyKey,\n config: params.config,\n context: params.context,\n input: params.input,\n attempts: 0,\n available_at: params.availableAt ?? this.knex.fn.now(),\n deadline_at: params.deadlineAt,\n created_at: this.knex.fn.now(),\n updated_at: this.knex.fn.now(),\n })\n .returning(\"*\");\n\n const workflowRun = await qb;\n if (!workflowRun[0]) {\n logger.error(\"Failed to create workflow run: {params}\", { params });\n throw new Error(\"Failed to create workflow run\");\n }\n\n return workflowRun[0];\n }\n\n async getWorkflowRun(params: GetWorkflowRunParams): Promise<WorkflowRun | null> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n const workflowRun = await this.knex\n .withSchema(DEFAULT_SCHEMA)\n .table(\"workflow_runs\")\n .where(\"namespace_id\", this.namespaceId)\n .where(\"id\", params.workflowRunId)\n .select(\n \"namespace_id\",\n \"id\",\n \"workflow_name\",\n \"version\",\n \"status\",\n \"idempotency_key\",\n \"config\",\n \"context\",\n \"input\",\n \"output\",\n \"error\",\n \"attempts\",\n \"parent_step_attempt_namespace_id\",\n \"parent_step_attempt_id\",\n \"worker_id\",\n \"available_at\",\n \"deadline_at\",\n \"started_at\",\n \"finished_at\",\n \"created_at\",\n \"updated_at\",\n )\n .first();\n\n return workflowRun ?? null;\n }\n\n async listWorkflowRuns(params: ListWorkflowRunsParams): Promise<PaginatedResponse<WorkflowRun>> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n const limit = params.limit ?? DEFAULT_PAGINATION_PAGE_SIZE;\n const { after, before } = params;\n\n let cursor: Cursor | null = null;\n if (after) {\n cursor = decodeCursor(after);\n } else if (before) {\n cursor = decodeCursor(before);\n }\n\n const qb = this.buildListWorkflowRunsWhere(params, cursor);\n const rows = await qb\n .orderBy(\"created_at\", before ? \"desc\" : \"asc\")\n .orderBy(\"id\", before ? \"desc\" : \"asc\")\n .limit(limit + 1);\n\n return this.processPaginationResults(\n rows,\n limit,\n typeof after === \"string\",\n typeof before === \"string\",\n );\n }\n\n private buildListWorkflowRunsWhere(params: ListWorkflowRunsParams, cursor: Cursor | null) {\n const { after } = params;\n const qb = this.knex\n .withSchema(DEFAULT_SCHEMA)\n .table(\"workflow_runs\")\n .where(\"namespace_id\", this.namespaceId);\n\n if (cursor) {\n const operator = after ? \">\" : \"<\";\n return qb.whereRaw(`(\"created_at\", \"id\") ${operator} (?, ?)`, [\n cursor.createdAt.toISOString(),\n cursor.id,\n ]);\n }\n\n return qb;\n }\n\n async claimWorkflowRun(params: ClaimWorkflowRunParams): Promise<WorkflowRun | null> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n const claimed = await this.knex\n .with(\"expired\", (qb) =>\n qb\n .withSchema(DEFAULT_SCHEMA)\n .table(\"workflow_runs\")\n .update({\n status: \"failed\",\n error: JSON.stringify({ message: \"Workflow run deadline exceeded\" }),\n worker_id: null,\n available_at: null,\n finished_at: this.knex.raw(\"NOW()\"),\n updated_at: this.knex.raw(\"NOW()\"),\n })\n .where(\"namespace_id\", this.namespaceId)\n .whereIn(\"status\", [\"pending\", \"running\", \"sleeping\"])\n .whereNotNull(\"deadline_at\")\n .where(\"deadline_at\", \"<=\", this.knex.raw(\"NOW()\"))\n .returning(\"id\"),\n )\n .with(\"candidate\", (qb) =>\n qb\n .withSchema(DEFAULT_SCHEMA)\n .select(\"id\")\n .from(\"workflow_runs\")\n .where(\"namespace_id\", this.namespaceId)\n .whereIn(\"status\", [\"pending\", \"running\", \"sleeping\"])\n .where(\"available_at\", \"<=\", this.knex.raw(\"NOW()\"))\n .where((qb2) => {\n qb2.whereNull(\"deadline_at\").orWhere(\"deadline_at\", \">\", this.knex.raw(\"NOW()\"));\n })\n .orderByRaw(\"CASE WHEN status = 'pending' THEN 0 ELSE 1 END\")\n .orderBy(\"available_at\", \"asc\")\n .orderBy(\"created_at\", \"asc\")\n .limit(1)\n .forUpdate()\n .skipLocked(),\n )\n .withSchema(DEFAULT_SCHEMA)\n .table(\"workflow_runs as wr\")\n .where(\"wr.namespace_id\", this.namespaceId)\n .where(\"wr.id\", this.knex.ref(\"candidate.id\"))\n .update({\n status: \"running\",\n attempts: this.knex.raw(\"wr.attempts + 1\"),\n worker_id: params.workerId,\n available_at: this.knex.raw(`NOW() + ${params.leaseDurationMs} * INTERVAL '1 millisecond'`),\n started_at: this.knex.raw(\"COALESCE(wr.started_at, NOW())\"),\n updated_at: this.knex.raw(\"NOW()\"),\n })\n .updateFrom(\"candidate\")\n .returning(\"wr.*\");\n\n return claimed[0] ?? null;\n }\n\n async extendWorkflowRunLease(params: ExtendWorkflowRunLeaseParams): Promise<WorkflowRun> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n const [updated] = await this.knex\n .withSchema(DEFAULT_SCHEMA)\n .table(\"workflow_runs\")\n .where(\"namespace_id\", this.namespaceId)\n .where(\"id\", params.workflowRunId)\n .where(\"status\", \"running\")\n .where(\"worker_id\", params.workerId)\n .update({\n available_at: this.knex.raw(`NOW() + ${params.leaseDurationMs} * INTERVAL '1 millisecond'`),\n updated_at: this.knex.fn.now(),\n })\n .returning(\"*\");\n\n if (!updated) {\n logger.error(\"Failed to extend lease for workflow run: {params}\", { params });\n throw new Error(\"Failed to extend lease for workflow run\");\n }\n\n return updated;\n }\n\n async sleepWorkflowRun(params: SleepWorkflowRunParams): Promise<WorkflowRun> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n // 'succeeded' status is deprecated\n const [updated] = await this.knex\n .withSchema(DEFAULT_SCHEMA)\n .table(\"workflow_runs\")\n .where(\"namespace_id\", this.namespaceId)\n .where(\"id\", params.workflowRunId)\n .whereNotIn(\"status\", [\"succeeded\", \"completed\", \"failed\", \"canceled\"])\n .where(\"worker_id\", params.workerId)\n .update({\n status: \"sleeping\",\n available_at: params.availableAt,\n worker_id: null,\n updated_at: this.knex.fn.now(),\n })\n .returning(\"*\");\n\n if (!updated) {\n logger.error(\"Failed to sleep workflow run: {params}\", { params });\n throw new Error(\"Failed to sleep workflow run\");\n }\n\n return updated;\n }\n\n async completeWorkflowRun(params: CompleteWorkflowRunParams): Promise<WorkflowRun> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n const [updated] = await this.knex\n .withSchema(DEFAULT_SCHEMA)\n .table(\"workflow_runs\")\n .where(\"namespace_id\", this.namespaceId)\n .where(\"id\", params.workflowRunId)\n .where(\"status\", \"running\")\n .where(\"worker_id\", params.workerId)\n .update({\n status: \"completed\",\n output: JSON.stringify(params.output),\n error: null,\n worker_id: params.workerId,\n available_at: null,\n finished_at: this.knex.fn.now(),\n updated_at: this.knex.fn.now(),\n })\n .returning(\"*\");\n\n if (!updated) {\n logger.error(\"Failed to complete workflow run: {params}\", { params });\n throw new Error(\"Failed to complete workflow run\");\n }\n\n return updated;\n }\n\n async failWorkflowRun(params: FailWorkflowRunParams): Promise<WorkflowRun> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n const { workflowRunId, error } = params;\n const { initialIntervalMs, backoffCoefficient, maximumIntervalMs } = DEFAULT_RETRY_POLICY;\n\n // this beefy query updates a workflow's status, available_at, and\n // finished_at based on the workflow's deadline and retry policy\n //\n // if the next retry would exceed the deadline, the run is marked as\n // 'failed' and finalized, otherwise, the run is rescheduled with an updated\n // 'available_at' timestamp for the next retry\n const retryIntervalExpr = `LEAST(${initialIntervalMs} * POWER(${backoffCoefficient}, \"attempts\" - 1), ${maximumIntervalMs}) * INTERVAL '1 millisecond'`;\n const deadlineExceededCondition = `\"deadline_at\" IS NOT NULL AND NOW() + (${retryIntervalExpr}) >= \"deadline_at\"`;\n\n const [updated] = await this.knex\n .withSchema(DEFAULT_SCHEMA)\n .table(\"workflow_runs\")\n .where(\"namespace_id\", this.namespaceId)\n .where(\"id\", workflowRunId)\n .where(\"status\", \"running\")\n .where(\"worker_id\", params.workerId)\n .update({\n status: this.knex.raw(\n `CASE WHEN ${deadlineExceededCondition} THEN 'failed' ELSE 'pending' END`,\n ),\n available_at: this.knex.raw(\n `CASE WHEN ${deadlineExceededCondition} THEN NULL ELSE NOW() + (${retryIntervalExpr}) END`,\n ),\n finished_at: this.knex.raw(\n `CASE WHEN ${deadlineExceededCondition} THEN NOW() ELSE NULL END`,\n ),\n error: JSON.stringify(error),\n worker_id: null,\n started_at: null,\n updated_at: this.knex.fn.now(),\n })\n .returning(\"*\");\n\n if (!updated) {\n logger.error(\"Failed to mark workflow run failed: {params}\", { params });\n throw new Error(\"Failed to mark workflow run failed\");\n }\n\n return updated;\n }\n\n async cancelWorkflowRun(params: CancelWorkflowRunParams): Promise<WorkflowRun> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n const [updated] = await this.knex\n .withSchema(DEFAULT_SCHEMA)\n .table(\"workflow_runs\")\n .where(\"namespace_id\", this.namespaceId)\n .where(\"id\", params.workflowRunId)\n .whereIn(\"status\", [\"pending\", \"running\", \"sleeping\"])\n .update({\n status: \"canceled\",\n worker_id: null,\n available_at: null,\n finished_at: this.knex.fn.now(),\n updated_at: this.knex.fn.now(),\n })\n .returning(\"*\");\n\n if (!updated) {\n // workflow may already be in a terminal state\n const existing = await this.getWorkflowRun({\n workflowRunId: params.workflowRunId,\n });\n if (!existing) {\n throw new Error(`Workflow run ${params.workflowRunId} does not exist`);\n }\n\n // if already canceled, just return it\n if (existing.status === \"canceled\") {\n return existing;\n }\n\n // throw error for completed/failed workflows\n // 'succeeded' status is deprecated\n if ([\"succeeded\", \"completed\", \"failed\"].includes(existing.status)) {\n logger.error(\"Cannot cancel workflow run: {params} with status {status}\", {\n params,\n status: existing.status,\n });\n throw new Error(\n `Cannot cancel workflow run ${params.workflowRunId} with status ${existing.status}`,\n );\n }\n\n logger.error(\"Failed to cancel workflow run: {params}\", { params });\n throw new Error(\"Failed to cancel workflow run\");\n }\n\n return updated;\n }\n\n async createStepAttempt(params: CreateStepAttemptParams): Promise<StepAttempt> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n const [stepAttempt] = await this.knex\n .withSchema(DEFAULT_SCHEMA)\n .table(\"step_attempts\")\n .insert({\n namespace_id: this.namespaceId,\n id: crypto.randomUUID(),\n workflow_run_id: params.workflowRunId,\n step_name: params.stepName,\n kind: params.kind,\n status: \"running\",\n config: JSON.stringify(params.config),\n context: JSON.stringify(params.context),\n started_at: this.knex.fn.now(),\n created_at: this.knex.raw(\"date_trunc('milliseconds', NOW())\"),\n updated_at: this.knex.fn.now(),\n })\n .returning(\"*\");\n\n if (!stepAttempt) {\n logger.error(\"Failed to create step attempt: {params}\", { params });\n throw new Error(\"Failed to create step attempt\");\n }\n\n return stepAttempt;\n }\n\n async getStepAttempt(params: GetStepAttemptParams): Promise<StepAttempt | null> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n const stepAttempt = await this.knex\n .withSchema(DEFAULT_SCHEMA)\n .table(\"step_attempts\")\n .where(\"namespace_id\", this.namespaceId)\n .where(\"id\", params.stepAttemptId)\n .first();\n\n return stepAttempt ?? null;\n }\n\n async listStepAttempts(params: ListStepAttemptsParams): Promise<PaginatedResponse<StepAttempt>> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n const limit = params.limit ?? DEFAULT_PAGINATION_PAGE_SIZE;\n const { after, before } = params;\n\n let cursor: Cursor | null = null;\n if (after) {\n cursor = decodeCursor(after);\n } else if (before) {\n cursor = decodeCursor(before);\n }\n\n const qb = this.buildListStepAttemptsWhere(params, cursor);\n const rows = await qb\n .orderBy(\"created_at\", before ? \"desc\" : \"asc\")\n .orderBy(\"id\", before ? \"desc\" : \"asc\")\n .limit(limit + 1);\n\n return this.processPaginationResults(\n rows,\n limit,\n typeof after === \"string\",\n typeof before === \"string\",\n );\n }\n\n private buildListStepAttemptsWhere(params: ListStepAttemptsParams, cursor: Cursor | null) {\n const { after } = params;\n const qb = this.knex\n .withSchema(DEFAULT_SCHEMA)\n .table(\"step_attempts\")\n .where(\"namespace_id\", this.namespaceId)\n .where(\"workflow_run_id\", params.workflowRunId);\n\n if (cursor) {\n const operator = after ? \">\" : \"<\";\n return qb.whereRaw(`(\"created_at\", \"id\") ${operator} (?, ?)`, [\n cursor.createdAt.toISOString(),\n cursor.id,\n ]);\n }\n\n return qb;\n }\n\n private processPaginationResults<T extends Cursor>(\n rows: T[],\n limit: number,\n hasAfter: boolean,\n hasBefore: boolean,\n ): PaginatedResponse<T> {\n const data = rows;\n let hasNext = false;\n let hasPrev = false;\n\n if (hasBefore) {\n data.reverse();\n if (data.length > limit) {\n hasPrev = true;\n data.shift();\n }\n hasNext = true;\n } else {\n if (data.length > limit) {\n hasNext = true;\n data.pop();\n }\n if (hasAfter) {\n hasPrev = true;\n }\n }\n\n const lastItem = data.at(-1);\n const nextCursor = hasNext && lastItem ? encodeCursor(lastItem) : null;\n const firstItem = data[0];\n const prevCursor = hasPrev && firstItem ? encodeCursor(firstItem) : null;\n\n return {\n data,\n pagination: {\n next: nextCursor,\n prev: prevCursor,\n },\n };\n }\n\n async completeStepAttempt(params: CompleteStepAttemptParams): Promise<StepAttempt> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n const [updated] = await this.knex\n .withSchema(DEFAULT_SCHEMA)\n .table(\"step_attempts as sa\")\n .update({\n status: \"completed\",\n output: JSON.stringify(params.output),\n error: null,\n finished_at: this.knex.fn.now(),\n updated_at: this.knex.fn.now(),\n })\n .updateFrom(`${DEFAULT_SCHEMA}.workflow_runs as wr`)\n .where(\"sa.namespace_id\", this.namespaceId)\n .where(\"sa.workflow_run_id\", params.workflowRunId)\n .where(\"sa.id\", params.stepAttemptId)\n .where(\"sa.status\", \"running\")\n .where(\"wr.namespace_id\", this.knex.ref(\"sa.namespace_id\"))\n .where(\"wr.id\", this.knex.ref(\"sa.workflow_run_id\"))\n .where(\"wr.status\", \"running\")\n .where(\"wr.worker_id\", params.workerId)\n .returning(\"sa.*\");\n\n if (!updated) {\n logger.error(\"Failed to mark step attempt completed: {params}\", { params });\n throw new Error(\"Failed to mark step attempt completed\");\n }\n\n return updated;\n }\n\n async failStepAttempt(params: FailStepAttemptParams): Promise<StepAttempt> {\n if (!this.initialized) {\n throw new Error(\"Backend not initialized\");\n }\n\n const [updated] = await this.knex\n .withSchema(DEFAULT_SCHEMA)\n .table(\"step_attempts as sa\")\n .update({\n status: \"failed\",\n output: null,\n error: JSON.stringify(params.error),\n finished_at: this.knex.fn.now(),\n updated_at: this.knex.fn.now(),\n })\n .updateFrom(`${DEFAULT_SCHEMA}.workflow_runs as wr`)\n .where(\"sa.namespace_id\", this.namespaceId)\n .where(\"sa.workflow_run_id\", params.workflowRunId)\n .where(\"sa.id\", params.stepAttemptId)\n .where(\"sa.status\", \"running\")\n .where(\"wr.namespace_id\", this.knex.ref(\"sa.namespace_id\"))\n .where(\"wr.id\", this.knex.ref(\"sa.workflow_run_id\"))\n .where(\"wr.status\", \"running\")\n .where(\"wr.worker_id\", params.workerId)\n .returning(\"sa.*\");\n\n if (!updated) {\n logger.error(\"Failed to mark step attempt failed: {params}\", { params });\n throw new Error(\"Failed to mark step attempt failed\");\n }\n\n return updated;\n }\n}\n\n/**\n * Cursor used for pagination. Requires created_at and id fields. Because JS\n * Date does not natively support microsecond precision dates, created_at should\n * be stored with millisecond precision in paginated tables to avoid issues with\n * cursor comparisons.\n */\ninterface Cursor {\n createdAt: Date;\n id: string;\n}\n\nfunction encodeCursor(item: Cursor): string {\n const encoded = Buffer.from(\n JSON.stringify({ createdAt: item.createdAt.toISOString(), id: item.id }),\n ).toString(\"base64\");\n return encoded;\n}\n\nexport function decodeCursor(cursor: string): Cursor {\n const decoded = Buffer.from(cursor, \"base64\").toString(\"utf8\");\n const parsed = JSON.parse(decoded) as { createdAt: string; id: string };\n return {\n createdAt: new Date(parsed.createdAt),\n id: parsed.id,\n };\n}\n"],"names":["getLogger","camelize","knex","DEFAULT_NAMESPACE_ID","DEFAULT_RETRY_POLICY","DEFAULT_SCHEMA","migrate","PostgresPubSub","DEFAULT_LISTEN_CHANNEL","DEFAULT_PAGINATION_PAGE_SIZE","logger","BackendPostgres","config","namespaceId","usePubSub","pubsub","initialized","runMigrations","_knex","options","postProcessResponse","result","_queryContext","undefined","camelizeRow","row","Object","fromEntries","entries","map","key","value","Array","isArray","initialize","subscribe","callback","Error","create","listenEvent","publish","payload","raw","stop","destroy","createWorkflowRun","params","qb","withSchema","table","insert","namespace_id","id","crypto","randomUUID","workflow_name","workflowName","version","status","idempotency_key","idempotencyKey","context","input","attempts","available_at","availableAt","fn","now","deadline_at","deadlineAt","created_at","updated_at","returning","workflowRun","error","getWorkflowRun","where","workflowRunId","select","first","listWorkflowRuns","limit","after","before","cursor","decodeCursor","buildListWorkflowRunsWhere","rows","orderBy","processPaginationResults","operator","whereRaw","createdAt","toISOString","claimWorkflowRun","claimed","with","update","JSON","stringify","message","worker_id","finished_at","whereIn","whereNotNull","from","qb2","whereNull","orWhere","orderByRaw","forUpdate","skipLocked","ref","workerId","leaseDurationMs","started_at","updateFrom","extendWorkflowRunLease","updated","sleepWorkflowRun","whereNotIn","completeWorkflowRun","output","failWorkflowRun","initialIntervalMs","backoffCoefficient","maximumIntervalMs","retryIntervalExpr","deadlineExceededCondition","cancelWorkflowRun","existing","includes","createStepAttempt","stepAttempt","workflow_run_id","step_name","stepName","kind","getStepAttempt","stepAttemptId","listStepAttempts","buildListStepAttemptsWhere","hasAfter","hasBefore","data","hasNext","hasPrev","reverse","length","shift","pop","lastItem","at","nextCursor","encodeCursor","firstItem","prevCursor","pagination","next","prev","completeStepAttempt","failStepAttempt","item","encoded","Buffer","toString","decoded","parsed","parse","Date"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"pubsub.d.ts","sourceRoot":"","sources":["../../src/database/pubsub.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAEtD,MAAM,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnF,qBAAa,cAAc;IAQL,OAAO,CAAC,QAAQ,CAAC,IAAI;IAPzC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,UAAU,CAAwC;IAG1D,OAAO,CAAC,WAAW,CAAoB;IAEvC,OAAO;IAWP,IAAI,SAAS,YAEZ;IAGK,OAAO;IAoCP,OAAO;WAOA,MAAM,CAAC,IAAI,EAAE,IAAI;IAO9B,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY;CAWpD"}
1
+ {"version":3,"file":"pubsub.d.ts","sourceRoot":"","sources":["../../src/database/pubsub.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAEtD,MAAM,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnF,qBAAa,cAAc;IAQL,OAAO,CAAC,QAAQ,CAAC,IAAI;IAPzC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,UAAU,CAAwC;IAG1D,OAAO,CAAC,WAAW,CAAoB;IAEvC,OAAO;IAWP,IAAI,SAAS,YAEZ;IAGK,OAAO;IAoCP,OAAO;WAaA,MAAM,CAAC,IAAI,EAAE,IAAI;IAO9B,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY;CAWpD"}
@@ -44,9 +44,15 @@ export class PostgresPubSub {
44
44
  }
45
45
  // destroy the listener and close the connection, do not destroy the knex connection
46
46
  async destroy() {
47
- this._destroyed = true;
48
- this._connection.off("close", this._onClosed);
49
- await this.knex.client.destroyRawConnection(this._connection);
47
+ if (this._destroyed) {
48
+ return;
49
+ }
50
+ try {
51
+ this._connection.off("close", this._onClosed);
52
+ await this.knex.client.destroyRawConnection(this._connection);
53
+ } finally{
54
+ this._destroyed = true;
55
+ }
50
56
  }
51
57
  // create a new listener and connect to the database
52
58
  static async create(knex) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/database/pubsub.ts"],"sourcesContent":["import assert from \"assert\";\nimport type { Knex } from \"knex\";\nimport { err, ok, type Result } from \"../core/result\";\n\nexport type OnSubscribed = (result: Result<string | null>) => void | Promise<void>;\n\nexport class PostgresPubSub {\n private _destroyed = false;\n private _onClosed: () => Promise<void>;\n private _listeners = new Map<string, Set<OnSubscribed>>();\n\n // biome-ignore lint/suspicious/noExplicitAny: Knex exposes a connection as any\n private _connection: any | null = null;\n\n private constructor(private readonly knex: Knex) {\n // Re-connect to the database when the connection is closed and not destroyed manually\n this._onClosed = (async () => {\n if (this._destroyed) {\n return;\n }\n\n await this.connect();\n }).bind(this);\n }\n\n get destroyed() {\n return this._destroyed;\n }\n\n // acquire new raw connection and set up listeners\n async connect() {\n const connection = await this.knex.client.acquireRawConnection();\n connection.on(\"close\", this._onClosed);\n connection.on(\n \"notification\",\n async ({ channel, payload: rawPayload }: { channel: string; payload: unknown }) => {\n const payload =\n typeof rawPayload === \"string\" && rawPayload.length !== 0 ? rawPayload : null;\n const listeners = this._listeners.get(channel);\n if (!listeners) {\n return;\n }\n\n const result = ok(payload);\n await Promise.allSettled(\n Array.from(listeners.values()).map((listener) => Promise.resolve(listener(result))),\n );\n },\n );\n connection.on(\"error\", async (error: Error) => {\n const result = err(error);\n await Promise.allSettled(\n Array.from(this._listeners.values())\n .flatMap((listeners) => Array.from(listeners))\n .map((listener) => Promise.resolve(listener(result))),\n );\n });\n\n for (const channel of this._listeners.keys()) {\n connection.query(`LISTEN ${channel}`);\n }\n\n this._connection = connection;\n }\n\n // destroy the listener and close the connection, do not destroy the knex connection\n async destroy() {\n this._destroyed = true;\n this._connection.off(\"close\", this._onClosed);\n await this.knex.client.destroyRawConnection(this._connection);\n }\n\n // create a new listener and connect to the database\n static async create(knex: Knex) {\n const listener = new PostgresPubSub(knex);\n await listener.connect();\n return listener;\n }\n\n // add a new listener to the channel\n listenEvent(channel: string, callback: OnSubscribed) {\n if (!this._listeners.has(channel)) {\n this._connection?.query(`LISTEN ${channel}`);\n this._listeners.set(channel, new Set<OnSubscribed>().add(callback));\n return;\n }\n\n const listeners = this._listeners.get(channel);\n assert(listeners, \"Listener channel not found\");\n listeners.add(callback);\n }\n}\n"],"names":["assert","err","ok","PostgresPubSub","_destroyed","_onClosed","_listeners","Map","_connection","knex","connect","bind","destroyed","connection","client","acquireRawConnection","on","channel","payload","rawPayload","length","listeners","get","result","Promise","allSettled","Array","from","values","map","listener","resolve","error","flatMap","keys","query","destroy","off","destroyRawConnection","create","listenEvent","callback","has","set","Set","add"],"mappings":"AAAA,OAAOA,YAAY,SAAS;AAE5B,SAASC,GAAG,EAAEC,EAAE,QAAqB,oBAAiB;AAItD,OAAO,MAAMC;;IACHC,aAAa,MAAM;IACnBC,UAA+B;IAC/BC,aAAa,IAAIC,MAAiC;IAE1D,+EAA+E;IACvEC,cAA0B,KAAK;IAEvC,YAAoB,AAAiBC,IAAU,CAAE;aAAZA,OAAAA;QACnC,sFAAsF;QACtF,IAAI,CAACJ,SAAS,GAAG,AAAC,CAAA;YAChB,IAAI,IAAI,CAACD,UAAU,EAAE;gBACnB;YACF;YAEA,MAAM,IAAI,CAACM,OAAO;QACpB,CAAA,EAAGC,IAAI,CAAC,IAAI;IACd;IAEA,IAAIC,YAAY;QACd,OAAO,IAAI,CAACR,UAAU;IACxB;IAEA,kDAAkD;IAClD,MAAMM,UAAU;QACd,MAAMG,aAAa,MAAM,IAAI,CAACJ,IAAI,CAACK,MAAM,CAACC,oBAAoB;QAC9DF,WAAWG,EAAE,CAAC,SAAS,IAAI,CAACX,SAAS;QACrCQ,WAAWG,EAAE,CACX,gBACA,OAAO,EAAEC,OAAO,EAAEC,SAASC,UAAU,EAAyC;YAC5E,MAAMD,UACJ,OAAOC,eAAe,YAAYA,WAAWC,MAAM,KAAK,IAAID,aAAa;YAC3E,MAAME,YAAY,IAAI,CAACf,UAAU,CAACgB,GAAG,CAACL;YACtC,IAAI,CAACI,WAAW;gBACd;YACF;YAEA,MAAME,SAASrB,GAAGgB;YAClB,MAAMM,QAAQC,UAAU,CACtBC,MAAMC,IAAI,CAACN,UAAUO,MAAM,IAAIC,GAAG,CAAC,CAACC,WAAaN,QAAQO,OAAO,CAACD,SAASP;QAE9E;QAEFV,WAAWG,EAAE,CAAC,SAAS,OAAOgB;YAC5B,MAAMT,SAAStB,IAAI+B;YACnB,MAAMR,QAAQC,UAAU,CACtBC,MAAMC,IAAI,CAAC,IAAI,CAACrB,UAAU,CAACsB,MAAM,IAC9BK,OAAO,CAAC,CAACZ,YAAcK,MAAMC,IAAI,CAACN,YAClCQ,GAAG,CAAC,CAACC,WAAaN,QAAQO,OAAO,CAACD,SAASP;QAElD;QAEA,KAAK,MAAMN,WAAW,IAAI,CAACX,UAAU,CAAC4B,IAAI,GAAI;YAC5CrB,WAAWsB,KAAK,CAAC,CAAC,OAAO,EAAElB,SAAS;QACtC;QAEA,IAAI,CAACT,WAAW,GAAGK;IACrB;IAEA,oFAAoF;IACpF,MAAMuB,UAAU;QACd,IAAI,CAAChC,UAAU,GAAG;QAClB,IAAI,CAACI,WAAW,CAAC6B,GAAG,CAAC,SAAS,IAAI,CAAChC,SAAS;QAC5C,MAAM,IAAI,CAACI,IAAI,CAACK,MAAM,CAACwB,oBAAoB,CAAC,IAAI,CAAC9B,WAAW;IAC9D;IAEA,oDAAoD;IACpD,aAAa+B,OAAO9B,IAAU,EAAE;QAC9B,MAAMqB,WAAW,IAAI3B,eAAeM;QACpC,MAAMqB,SAASpB,OAAO;QACtB,OAAOoB;IACT;IAEA,oCAAoC;IACpCU,YAAYvB,OAAe,EAAEwB,QAAsB,EAAE;QACnD,IAAI,CAAC,IAAI,CAACnC,UAAU,CAACoC,GAAG,CAACzB,UAAU;YACjC,IAAI,CAACT,WAAW,EAAE2B,MAAM,CAAC,OAAO,EAAElB,SAAS;YAC3C,IAAI,CAACX,UAAU,CAACqC,GAAG,CAAC1B,SAAS,IAAI2B,MAAoBC,GAAG,CAACJ;YACzD;QACF;QAEA,MAAMpB,YAAY,IAAI,CAACf,UAAU,CAACgB,GAAG,CAACL;QACtCjB,OAAOqB,WAAW;QAClBA,UAAUwB,GAAG,CAACJ;IAChB;AACF"}
1
+ {"version":3,"sources":["../../src/database/pubsub.ts"],"sourcesContent":["import assert from \"assert\";\nimport type { Knex } from \"knex\";\nimport { err, ok, type Result } from \"../core/result\";\n\nexport type OnSubscribed = (result: Result<string | null>) => void | Promise<void>;\n\nexport class PostgresPubSub {\n private _destroyed = false;\n private _onClosed: () => Promise<void>;\n private _listeners = new Map<string, Set<OnSubscribed>>();\n\n // biome-ignore lint/suspicious/noExplicitAny: Knex exposes a connection as any\n private _connection: any | null = null;\n\n private constructor(private readonly knex: Knex) {\n // Re-connect to the database when the connection is closed and not destroyed manually\n this._onClosed = (async () => {\n if (this._destroyed) {\n return;\n }\n\n await this.connect();\n }).bind(this);\n }\n\n get destroyed() {\n return this._destroyed;\n }\n\n // acquire new raw connection and set up listeners\n async connect() {\n const connection = await this.knex.client.acquireRawConnection();\n connection.on(\"close\", this._onClosed);\n connection.on(\n \"notification\",\n async ({ channel, payload: rawPayload }: { channel: string; payload: unknown }) => {\n const payload =\n typeof rawPayload === \"string\" && rawPayload.length !== 0 ? rawPayload : null;\n const listeners = this._listeners.get(channel);\n if (!listeners) {\n return;\n }\n\n const result = ok(payload);\n await Promise.allSettled(\n Array.from(listeners.values()).map((listener) => Promise.resolve(listener(result))),\n );\n },\n );\n connection.on(\"error\", async (error: Error) => {\n const result = err(error);\n await Promise.allSettled(\n Array.from(this._listeners.values())\n .flatMap((listeners) => Array.from(listeners))\n .map((listener) => Promise.resolve(listener(result))),\n );\n });\n\n for (const channel of this._listeners.keys()) {\n connection.query(`LISTEN ${channel}`);\n }\n\n this._connection = connection;\n }\n\n // destroy the listener and close the connection, do not destroy the knex connection\n async destroy() {\n if (this._destroyed) {\n return;\n }\n try {\n this._connection.off(\"close\", this._onClosed);\n await this.knex.client.destroyRawConnection(this._connection);\n } finally {\n this._destroyed = true;\n }\n }\n\n // create a new listener and connect to the database\n static async create(knex: Knex) {\n const listener = new PostgresPubSub(knex);\n await listener.connect();\n return listener;\n }\n\n // add a new listener to the channel\n listenEvent(channel: string, callback: OnSubscribed) {\n if (!this._listeners.has(channel)) {\n this._connection?.query(`LISTEN ${channel}`);\n this._listeners.set(channel, new Set<OnSubscribed>().add(callback));\n return;\n }\n\n const listeners = this._listeners.get(channel);\n assert(listeners, \"Listener channel not found\");\n listeners.add(callback);\n }\n}\n"],"names":["assert","err","ok","PostgresPubSub","_destroyed","_onClosed","_listeners","Map","_connection","knex","connect","bind","destroyed","connection","client","acquireRawConnection","on","channel","payload","rawPayload","length","listeners","get","result","Promise","allSettled","Array","from","values","map","listener","resolve","error","flatMap","keys","query","destroy","off","destroyRawConnection","create","listenEvent","callback","has","set","Set","add"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sonamu-kit/tasks",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "type": "module",
5
5
  "description": "Sonamu Task - Simple & Distributed Task Queue",
6
6
  "main": "./dist/index.js",
@@ -34,17 +34,19 @@
34
34
  "c12": "^3.3.2"
35
35
  },
36
36
  "devDependencies": {
37
- "@biomejs/biome": "^2.3.7",
37
+ "@types/inflection": "^2.0.0",
38
+ "@biomejs/biome": "^2.3.10",
38
39
  "@swc/cli": "^0.7.8",
39
- "@swc/core": "^1.15.3",
40
- "@types/node": "^24.9.2",
40
+ "@swc/core": "^1.13.5",
41
+ "@types/node": "25.0.3",
41
42
  "nodemon": "^3.1.10",
42
43
  "tsx": "^4.20.6",
43
44
  "typescript": "^5.9.3",
44
45
  "vitest": "^4.0.10"
45
46
  },
46
47
  "peerDependencies": {
47
- "knex": "^3.1.0"
48
+ "knex": "^3.1.0",
49
+ "@logtape/logtape": "1.3.5"
48
50
  },
49
51
  "optionalDependencies": {
50
52
  "pg-native": "^3.5.2"
package/src/client.ts CHANGED
@@ -184,7 +184,6 @@ export class OpenWorkflow {
184
184
  * Declare a workflow without providing its implementation (which is provided
185
185
  * separately via `implementWorkflow`). Returns a lightweight WorkflowSpec
186
186
  * that can be used to schedule workflow runs.
187
- * @param config - Workflow config
188
187
  * @param spec - Workflow spec
189
188
  * @returns Workflow spec
190
189
  * @example
@@ -14,7 +14,7 @@ type UnitAnyCase = Capitalize<Unit> | Uppercase<Unit> | Lowercase<Unit>;
14
14
  export type DurationString = `${number}` | `${number}${UnitAnyCase}` | `${number} ${UnitAnyCase}`;
15
15
 
16
16
  /**
17
- * Parse a duration string into milliseconds. Exmaples:
17
+ * Parse a duration string into milliseconds. Examples:
18
18
  * - short units: "1ms", "5s", "30m", "2h", "7d", "3w", "1y"
19
19
  * - long units: "1 millisecond", "5 seconds", "30 minutes", "2 hours", "7 days", "3 weeks", "1 year"
20
20
  * @param str - Duration string
@@ -116,7 +116,8 @@ export async function validateInput<RunInput, Input>(
116
116
  /**
117
117
  * Check if a workflow run status represents a terminal state.
118
118
  * @param status - The workflow run status
119
- * @returns True if the status is terminal (completed, failed, or canceled)
119
+ * @returns True if the status is terminal (succeeded, completed, failed, or canceled).
120
+ * Note: 'succeeded' is deprecated in favor of 'completed'.
120
121
  */
121
122
  export function isTerminalStatus(
122
123
  status: string,
@@ -1,3 +1,4 @@
1
+ import { getLogger } from "@logtape/logtape";
1
2
  import { camelize } from "inflection";
2
3
  import knex, { type Knex } from "knex";
3
4
  import {
@@ -36,6 +37,8 @@ interface BackendPostgresOptions {
36
37
  usePubSub?: boolean;
37
38
  }
38
39
 
40
+ const logger = getLogger(["sonamu", "internal", "tasks"]);
41
+
39
42
  /**
40
43
  * Manages a connection to a Postgres database for workflow operations.
41
44
  */
@@ -175,6 +178,7 @@ export class BackendPostgres implements Backend {
175
178
 
176
179
  const workflowRun = await qb;
177
180
  if (!workflowRun[0]) {
181
+ logger.error("Failed to create workflow run: {params}", { params });
178
182
  throw new Error("Failed to create workflow run");
179
183
  }
180
184
 
@@ -345,6 +349,7 @@ export class BackendPostgres implements Backend {
345
349
  .returning("*");
346
350
 
347
351
  if (!updated) {
352
+ logger.error("Failed to extend lease for workflow run: {params}", { params });
348
353
  throw new Error("Failed to extend lease for workflow run");
349
354
  }
350
355
 
@@ -373,6 +378,7 @@ export class BackendPostgres implements Backend {
373
378
  .returning("*");
374
379
 
375
380
  if (!updated) {
381
+ logger.error("Failed to sleep workflow run: {params}", { params });
376
382
  throw new Error("Failed to sleep workflow run");
377
383
  }
378
384
 
@@ -403,6 +409,7 @@ export class BackendPostgres implements Backend {
403
409
  .returning("*");
404
410
 
405
411
  if (!updated) {
412
+ logger.error("Failed to complete workflow run: {params}", { params });
406
413
  throw new Error("Failed to complete workflow run");
407
414
  }
408
415
 
@@ -451,6 +458,7 @@ export class BackendPostgres implements Backend {
451
458
  .returning("*");
452
459
 
453
460
  if (!updated) {
461
+ logger.error("Failed to mark workflow run failed: {params}", { params });
454
462
  throw new Error("Failed to mark workflow run failed");
455
463
  }
456
464
 
@@ -494,11 +502,16 @@ export class BackendPostgres implements Backend {
494
502
  // throw error for completed/failed workflows
495
503
  // 'succeeded' status is deprecated
496
504
  if (["succeeded", "completed", "failed"].includes(existing.status)) {
505
+ logger.error("Cannot cancel workflow run: {params} with status {status}", {
506
+ params,
507
+ status: existing.status,
508
+ });
497
509
  throw new Error(
498
510
  `Cannot cancel workflow run ${params.workflowRunId} with status ${existing.status}`,
499
511
  );
500
512
  }
501
513
 
514
+ logger.error("Failed to cancel workflow run: {params}", { params });
502
515
  throw new Error("Failed to cancel workflow run");
503
516
  }
504
517
 
@@ -529,6 +542,7 @@ export class BackendPostgres implements Backend {
529
542
  .returning("*");
530
543
 
531
544
  if (!stepAttempt) {
545
+ logger.error("Failed to create step attempt: {params}", { params });
532
546
  throw new Error("Failed to create step attempt");
533
547
  }
534
548
 
@@ -666,6 +680,7 @@ export class BackendPostgres implements Backend {
666
680
  .returning("sa.*");
667
681
 
668
682
  if (!updated) {
683
+ logger.error("Failed to mark step attempt completed: {params}", { params });
669
684
  throw new Error("Failed to mark step attempt completed");
670
685
  }
671
686
 
@@ -699,6 +714,7 @@ export class BackendPostgres implements Backend {
699
714
  .returning("sa.*");
700
715
 
701
716
  if (!updated) {
717
+ logger.error("Failed to mark step attempt failed: {params}", { params });
702
718
  throw new Error("Failed to mark step attempt failed");
703
719
  }
704
720
 
@@ -65,9 +65,15 @@ export class PostgresPubSub {
65
65
 
66
66
  // destroy the listener and close the connection, do not destroy the knex connection
67
67
  async destroy() {
68
- this._destroyed = true;
69
- this._connection.off("close", this._onClosed);
70
- await this.knex.client.destroyRawConnection(this._connection);
68
+ if (this._destroyed) {
69
+ return;
70
+ }
71
+ try {
72
+ this._connection.off("close", this._onClosed);
73
+ await this.knex.client.destroyRawConnection(this._connection);
74
+ } finally {
75
+ this._destroyed = true;
76
+ }
71
77
  }
72
78
 
73
79
  // create a new listener and connect to the database