pg-workflows 0.1.0 → 0.1.1
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/README.md +52 -29
- package/dist/index.cjs +6 -6
- package/dist/index.js +3 -3
- package/dist/index.js.map +3 -3
- package/package.json +5 -6
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# pg-workflows
|
|
2
2
|
|
|
3
|
-
**The simplest Postgres workflow engine for TypeScript.** Durable execution, event-driven orchestration, and automatic retries
|
|
3
|
+
**The simplest Postgres workflow engine for TypeScript.** Durable execution, event-driven orchestration, and automatic retries - powered entirely by PostgreSQL. No extra infrastructure. No vendor lock-in.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/pg-workflows)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
@@ -15,7 +15,7 @@ npm install pg-workflows
|
|
|
15
15
|
|
|
16
16
|
## Why pg-workflows?
|
|
17
17
|
|
|
18
|
-
Most workflow engines ask you to adopt an entirely new platform
|
|
18
|
+
Most workflow engines ask you to adopt an entirely new platform - a new runtime, a new deployment target, a new bill. **pg-workflows takes a different approach**: if you already have PostgreSQL, you already have everything you need.
|
|
19
19
|
|
|
20
20
|
| | pg-workflows | Temporal | Inngest | DBOS | pgflow |
|
|
21
21
|
|---|:---:|:---:|:---:|:---:|:---:|
|
|
@@ -41,15 +41,15 @@ If you need enterprise-grade features like distributed tracing, complex DAG sche
|
|
|
41
41
|
|
|
42
42
|
## Features
|
|
43
43
|
|
|
44
|
-
- **Durable Execution on Postgres**
|
|
45
|
-
- **Step-by-Step Execution**
|
|
46
|
-
- **Event-Driven Orchestration**
|
|
47
|
-
- **Pause and Resume**
|
|
48
|
-
- **Built-in Retries**
|
|
49
|
-
- **Configurable Timeouts**
|
|
50
|
-
- **Progress Tracking**
|
|
51
|
-
- **Input Validation**
|
|
52
|
-
- **Built on pg-boss**
|
|
44
|
+
- **Durable Execution on Postgres** - Workflow state is persisted in PostgreSQL. Workflows survive process crashes, restarts, and deployments.
|
|
45
|
+
- **Step-by-Step Execution** - Break complex processes into discrete, resumable steps. Each step runs exactly once, even across retries.
|
|
46
|
+
- **Event-Driven Orchestration** - Pause workflows and wait for external events with `step.waitFor()`. Resume automatically when signals arrive.
|
|
47
|
+
- **Pause and Resume** - Manually pause long-running workflows and resume them later via API.
|
|
48
|
+
- **Built-in Retries** - Automatic retries with exponential backoff at the workflow level.
|
|
49
|
+
- **Configurable Timeouts** - Set workflow-level and step-level timeouts to prevent runaway executions.
|
|
50
|
+
- **Progress Tracking** - Monitor workflow completion percentage, completed steps, and total steps in real-time.
|
|
51
|
+
- **Input Validation** - Define schemas with Zod for type-safe, validated workflow inputs.
|
|
52
|
+
- **Built on pg-boss** - Leverages the battle-tested [pg-boss](https://github.com/timgit/pg-boss) job queue for reliable task scheduling.
|
|
53
53
|
|
|
54
54
|
---
|
|
55
55
|
|
|
@@ -58,11 +58,11 @@ If you need enterprise-grade features like distributed tracing, complex DAG sche
|
|
|
58
58
|
pg-workflows uses PostgreSQL as both the **job queue** and the **state store**. Under the hood:
|
|
59
59
|
|
|
60
60
|
1. **Define** workflows as TypeScript functions with discrete steps
|
|
61
|
-
2. **Start** a workflow run
|
|
62
|
-
3. **Execute** steps one by one
|
|
63
|
-
4. **Pause** on `waitFor()` or `pause()`
|
|
61
|
+
2. **Start** a workflow run - the engine creates a database record and enqueues the first execution
|
|
62
|
+
3. **Execute** steps one by one - each step's result is persisted before moving to the next
|
|
63
|
+
4. **Pause** on `waitFor()` or `pause()` - the workflow sleeps with zero resource consumption
|
|
64
64
|
5. **Resume** when an external event arrives or `resumeWorkflow()` is called
|
|
65
|
-
6. **Complete**
|
|
65
|
+
6. **Complete** - the final result is stored and the workflow is marked as done
|
|
66
66
|
|
|
67
67
|
All state lives in PostgreSQL. No Redis. No message broker. No external scheduler. Just Postgres.
|
|
68
68
|
|
|
@@ -165,12 +165,12 @@ console.log(`Progress: ${progress.completionPercentage}%`);
|
|
|
165
165
|
|
|
166
166
|
## What Can You Build?
|
|
167
167
|
|
|
168
|
-
- **User Onboarding Flows**
|
|
169
|
-
- **Payment & Checkout Pipelines**
|
|
170
|
-
- **AI & LLM Pipelines**
|
|
171
|
-
- **Background Job Orchestration**
|
|
172
|
-
- **Approval Workflows**
|
|
173
|
-
- **Data Processing Pipelines**
|
|
168
|
+
- **User Onboarding Flows** - Multi-step signup sequences with email verification, waiting for user actions, and conditional paths.
|
|
169
|
+
- **Payment & Checkout Pipelines** - Durable payment processing that survives failures, with automatic retries and event-driven confirmations.
|
|
170
|
+
- **AI & LLM Pipelines** - Chain LLM calls with built-in retries for flaky APIs. Persist intermediate results across steps.
|
|
171
|
+
- **Background Job Orchestration** - Replace fragile cron jobs with durable, observable workflows that track progress.
|
|
172
|
+
- **Approval Workflows** - Pause execution and wait for human approval events before proceeding.
|
|
173
|
+
- **Data Processing Pipelines** - ETL workflows with step-by-step execution, error handling, and progress monitoring.
|
|
174
174
|
|
|
175
175
|
---
|
|
176
176
|
|
|
@@ -200,7 +200,7 @@ Steps are the building blocks of durable workflows. Each step is executed **exac
|
|
|
200
200
|
|
|
201
201
|
```typescript
|
|
202
202
|
await step.run('step-id', async () => {
|
|
203
|
-
// This will only execute once
|
|
203
|
+
// This will only execute once - the result is persisted in Postgres
|
|
204
204
|
return { result: 'data' };
|
|
205
205
|
});
|
|
206
206
|
```
|
|
@@ -216,6 +216,29 @@ const eventData = await step.waitFor('wait-step', {
|
|
|
216
216
|
});
|
|
217
217
|
```
|
|
218
218
|
|
|
219
|
+
### Resource ID
|
|
220
|
+
|
|
221
|
+
The optional `resourceId` associates a workflow run with an external entity in your application — a user, an order, a subscription, or any domain object the workflow operates on. It serves two purposes:
|
|
222
|
+
|
|
223
|
+
1. **Association** — Links each workflow run to the business entity it belongs to, so you can query all runs for a given resource.
|
|
224
|
+
2. **Scoping** — When provided, all read and write operations (get, update, pause, resume, cancel, trigger events) include `resource_id` in their database queries, ensuring you only access workflow runs that belong to that resource. This is useful for enforcing tenant isolation or ownership checks.
|
|
225
|
+
|
|
226
|
+
`resourceId` is optional on every API method. If you don't need to group or scope runs by an external entity, you can omit it entirely and use `runId` alone.
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
// Start a workflow scoped to a specific user
|
|
230
|
+
const run = await engine.startWorkflow({
|
|
231
|
+
workflowId: 'send-welcome-email',
|
|
232
|
+
resourceId: 'user-123', // ties this run to user-123
|
|
233
|
+
input: { email: 'user@example.com' },
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
// Later, list all workflow runs for that user
|
|
237
|
+
const { items } = await engine.getRuns({
|
|
238
|
+
resourceId: 'user-123',
|
|
239
|
+
});
|
|
240
|
+
```
|
|
241
|
+
|
|
219
242
|
### Pause and Resume
|
|
220
243
|
|
|
221
244
|
Manually pause a workflow and resume it later:
|
|
@@ -321,7 +344,7 @@ const engine = new WorkflowEngine({
|
|
|
321
344
|
| `start(asEngine?, options?)` | Start the engine and workers |
|
|
322
345
|
| `stop()` | Stop the engine gracefully |
|
|
323
346
|
| `registerWorkflow(definition)` | Register a workflow definition |
|
|
324
|
-
| `startWorkflow({ workflowId, resourceId?, input, options? })` | Start a new workflow run |
|
|
347
|
+
| `startWorkflow({ workflowId, resourceId?, input, options? })` | Start a new workflow run. `resourceId` optionally ties the run to an external entity (see [Resource ID](#resource-id)). |
|
|
325
348
|
| `pauseWorkflow({ runId, resourceId? })` | Pause a running workflow |
|
|
326
349
|
| `resumeWorkflow({ runId, resourceId?, options? })` | Resume a paused workflow |
|
|
327
350
|
| `cancelWorkflow({ runId, resourceId? })` | Cancel a workflow |
|
|
@@ -393,8 +416,8 @@ enum WorkflowStatus {
|
|
|
393
416
|
|
|
394
417
|
The engine automatically runs migrations on startup to create the required tables:
|
|
395
418
|
|
|
396
|
-
- `workflow_runs`
|
|
397
|
-
- `pgboss.*`
|
|
419
|
+
- `workflow_runs` - Stores workflow execution state, step results, and timeline. The optional `resource_id` column (indexed) associates each run with an external entity in your application. See [Resource ID](#resource-id).
|
|
420
|
+
- `pgboss.*` - pg-boss job queue tables for reliable task scheduling
|
|
398
421
|
|
|
399
422
|
---
|
|
400
423
|
|
|
@@ -402,10 +425,10 @@ The engine automatically runs migrations on startup to create the required table
|
|
|
402
425
|
|
|
403
426
|
As championed by [postgresforeverything.com](https://postgresforeverything.com/), PostgreSQL is one of the most reliable, feature-rich, and cost-effective databases ever built. pg-workflows embraces this philosophy:
|
|
404
427
|
|
|
405
|
-
- **One database to rule them all**
|
|
406
|
-
- **Battle-tested reliability**
|
|
407
|
-
- **Zero operational overhead**
|
|
408
|
-
- **Full queryability**
|
|
428
|
+
- **One database to rule them all** - Your application data and workflow state live in the same PostgreSQL instance. No distributed systems headaches.
|
|
429
|
+
- **Battle-tested reliability** - PostgreSQL's ACID transactions guarantee your workflow state is always consistent.
|
|
430
|
+
- **Zero operational overhead** - No Redis cluster to manage. No message broker to monitor. No external service to pay for.
|
|
431
|
+
- **Full queryability** - Inspect, debug, and analyze workflow runs with plain SQL.
|
|
409
432
|
|
|
410
433
|
If you're already running Postgres (and you probably should be), adding durable workflows is as simple as:
|
|
411
434
|
|
package/dist/index.cjs
CHANGED
|
@@ -63,7 +63,7 @@ function workflow(id, handler, { inputSchema, timeout, retries } = {}) {
|
|
|
63
63
|
};
|
|
64
64
|
}
|
|
65
65
|
// src/engine.ts
|
|
66
|
-
var
|
|
66
|
+
var import_es_toolkit = require("es-toolkit");
|
|
67
67
|
|
|
68
68
|
// src/ast-parser.ts
|
|
69
69
|
var ts = __toESM(require("typescript"));
|
|
@@ -571,7 +571,7 @@ class WorkflowEngine {
|
|
|
571
571
|
throw new WorkflowEngineError(`Workflow ${workflowId} has no steps`, workflowId);
|
|
572
572
|
}
|
|
573
573
|
const initialStepId = workflow2.steps[0]?.id;
|
|
574
|
-
const run = await withPostgresTransaction(this.boss.getDb(), async (
|
|
574
|
+
const run = await withPostgresTransaction(this.boss.getDb(), async (_db) => {
|
|
575
575
|
const timeoutAt = options?.timeout ? new Date(Date.now() + options.timeout) : workflow2.timeout ? new Date(Date.now() + workflow2.timeout) : null;
|
|
576
576
|
const insertedRun = await insertWorkflowRun({
|
|
577
577
|
resourceId,
|
|
@@ -769,7 +769,7 @@ class WorkflowEngine {
|
|
|
769
769
|
status: "running" /* RUNNING */,
|
|
770
770
|
pausedAt: null,
|
|
771
771
|
resumedAt: new Date,
|
|
772
|
-
timeline:
|
|
772
|
+
timeline: import_es_toolkit.merge(run.timeline, {
|
|
773
773
|
[run.currentStepId]: {
|
|
774
774
|
output: event?.data ?? {},
|
|
775
775
|
timestamp: new Date
|
|
@@ -924,7 +924,7 @@ class WorkflowEngine {
|
|
|
924
924
|
runId: run.id,
|
|
925
925
|
resourceId: run.resourceId ?? undefined,
|
|
926
926
|
data: {
|
|
927
|
-
timeline:
|
|
927
|
+
timeline: import_es_toolkit.merge(run.timeline, {
|
|
928
928
|
[stepId]: {
|
|
929
929
|
output: result === undefined ? {} : result,
|
|
930
930
|
timestamp: new Date
|
|
@@ -981,7 +981,7 @@ ${error.stack}` : String(error)
|
|
|
981
981
|
data: {
|
|
982
982
|
status: "paused" /* PAUSED */,
|
|
983
983
|
currentStepId: stepId,
|
|
984
|
-
timeline:
|
|
984
|
+
timeline: import_es_toolkit.merge(run.timeline, {
|
|
985
985
|
[`${stepId}-wait-for`]: {
|
|
986
986
|
waitFor: {
|
|
987
987
|
eventName,
|
|
@@ -1046,5 +1046,5 @@ ${error.stack}` : String(error)
|
|
|
1046
1046
|
}
|
|
1047
1047
|
}
|
|
1048
1048
|
|
|
1049
|
-
//# debugId=
|
|
1049
|
+
//# debugId=7A180DA27B38390864756E2164756E21
|
|
1050
1050
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ function workflow(id, handler, { inputSchema, timeout, retries } = {}) {
|
|
|
9
9
|
};
|
|
10
10
|
}
|
|
11
11
|
// src/engine.ts
|
|
12
|
-
import merge from "
|
|
12
|
+
import { merge } from "es-toolkit";
|
|
13
13
|
|
|
14
14
|
// src/ast-parser.ts
|
|
15
15
|
import * as ts from "typescript";
|
|
@@ -517,7 +517,7 @@ class WorkflowEngine {
|
|
|
517
517
|
throw new WorkflowEngineError(`Workflow ${workflowId} has no steps`, workflowId);
|
|
518
518
|
}
|
|
519
519
|
const initialStepId = workflow2.steps[0]?.id;
|
|
520
|
-
const run = await withPostgresTransaction(this.boss.getDb(), async (
|
|
520
|
+
const run = await withPostgresTransaction(this.boss.getDb(), async (_db) => {
|
|
521
521
|
const timeoutAt = options?.timeout ? new Date(Date.now() + options.timeout) : workflow2.timeout ? new Date(Date.now() + workflow2.timeout) : null;
|
|
522
522
|
const insertedRun = await insertWorkflowRun({
|
|
523
523
|
resourceId,
|
|
@@ -1000,5 +1000,5 @@ export {
|
|
|
1000
1000
|
StepType
|
|
1001
1001
|
};
|
|
1002
1002
|
|
|
1003
|
-
//# debugId=
|
|
1003
|
+
//# debugId=C8B85FE5A7CFFA6264756E2164756E21
|
|
1004
1004
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
"sources": ["src/definition.ts", "src/engine.ts", "src/ast-parser.ts", "src/db/migration.ts", "src/db/queries.ts", "src/error.ts", "src/types.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"import type {\n inferParameters,\n Parameters,\n WorkflowContext,\n WorkflowDefinition,\n WorkflowOptions,\n} from './types';\n\nexport function workflow<I extends Parameters>(\n id: string,\n handler: (context: WorkflowContext<inferParameters<I>>) => Promise<unknown>,\n { inputSchema, timeout, retries }: WorkflowOptions<I> = {},\n): WorkflowDefinition<I> {\n return {\n id,\n handler,\n inputSchema,\n timeout,\n retries,\n };\n}\n",
|
|
6
|
-
"import merge from 'lodash/merge';\nimport type { Db, Job, PgBoss } from 'pg-boss';\nimport type { z } from 'zod';\nimport { parseWorkflowHandler } from './ast-parser';\nimport { runMigrations } from './db/migration';\nimport {\n getWorkflowRun,\n getWorkflowRuns,\n insertWorkflowRun,\n updateWorkflowRun,\n withPostgresTransaction,\n} from './db/queries';\nimport type { WorkflowRun } from './db/types';\nimport { WorkflowEngineError, WorkflowRunNotFoundError } from './error';\nimport {\n type InternalWorkflowDefinition,\n type InternalWorkflowLogger,\n type InternalWorkflowLoggerContext,\n type inferParameters,\n type Parameters,\n StepType,\n type WorkflowContext,\n type WorkflowDefinition,\n type WorkflowLogger,\n type WorkflowRunProgress,\n WorkflowStatus,\n} from './types';\n\nconst PAUSE_EVENT_NAME = '__internal_pause';\nconst WORKFLOW_RUN_QUEUE_NAME = 'workflow-run';\nconst LOG_PREFIX = '[WorkflowEngine]';\n\nconst StepTypeToIcon = {\n [StepType.RUN]: 'λ',\n [StepType.WAIT_FOR]: '○',\n [StepType.PAUSE]: '⏸',\n [StepType.WAIT_UNTIL]: '⏲',\n};\n\n// Timeline entry types\ntype TimelineStepEntry = {\n output?: unknown;\n timestamp: Date;\n};\n\ntype TimelineWaitForEntry = {\n waitFor: {\n eventName: string;\n timeout?: number;\n };\n timestamp: Date;\n};\n\ntype WorkflowRunJobParameters = {\n runId: string;\n resourceId?: string;\n workflowId: string;\n input: unknown;\n event?: {\n name: string;\n data?: Record<string, unknown>;\n };\n};\n\nconst defaultLogger: WorkflowLogger = {\n log: (_message: string) => console.warn(_message),\n error: (message: string, error: Error) => console.error(message, error),\n};\n\nconst defaultExpireInSeconds = process.env.WORKFLOW_RUN_EXPIRE_IN_SECONDS\n ? Number.parseInt(process.env.WORKFLOW_RUN_EXPIRE_IN_SECONDS, 10)\n : 5 * 60; // 5 minutes\n\nexport class WorkflowEngine {\n private boss: PgBoss;\n private db: Db;\n private unregisteredWorkflows = new Map<string, WorkflowDefinition>();\n private _started = false;\n\n public workflows: Map<string, InternalWorkflowDefinition> = new Map<\n string,\n InternalWorkflowDefinition\n >();\n private logger: InternalWorkflowLogger;\n\n constructor({\n workflows,\n logger,\n boss,\n }: Partial<{\n workflows: WorkflowDefinition[];\n logger: WorkflowLogger;\n boss: PgBoss;\n }> = {}) {\n this.logger = this.buildLogger(logger ?? defaultLogger);\n\n if (workflows) {\n this.unregisteredWorkflows = new Map(workflows.map((workflow) => [workflow.id, workflow]));\n }\n\n if (!boss) {\n throw new WorkflowEngineError('PgBoss instance is required in constructor');\n }\n this.boss = boss;\n this.db = boss.getDb();\n }\n\n async start(\n asEngine = true,\n { batchSize }: { batchSize?: number } = { batchSize: 1 },\n ): Promise<void> {\n if (this._started) {\n return;\n }\n\n // Start boss first to get the database connection\n await this.boss.start();\n\n await runMigrations(this.boss.getDb());\n\n if (this.unregisteredWorkflows.size > 0) {\n for (const workflow of this.unregisteredWorkflows.values()) {\n await this.registerWorkflow(workflow);\n }\n }\n\n await this.boss.createQueue(WORKFLOW_RUN_QUEUE_NAME);\n\n const numWorkers: number = +(process.env.WORKFLOW_RUN_WORKERS ?? 3);\n\n if (asEngine) {\n for (let i = 0; i < numWorkers; i++) {\n await this.boss.work<WorkflowRunJobParameters>(\n WORKFLOW_RUN_QUEUE_NAME,\n { pollingIntervalSeconds: 0.5, batchSize },\n (job) => this.handleWorkflowRun(job),\n );\n this.logger.log(\n `Worker ${i + 1}/${numWorkers} started for queue ${WORKFLOW_RUN_QUEUE_NAME}`,\n );\n }\n }\n\n this._started = true;\n\n this.logger.log('Workflow engine started!');\n }\n\n async stop(): Promise<void> {\n await this.boss.stop();\n\n this._started = false;\n\n this.logger.log('Workflow engine stopped');\n }\n\n async registerWorkflow(definition: WorkflowDefinition): Promise<WorkflowEngine> {\n if (this.workflows.has(definition.id)) {\n throw new WorkflowEngineError(\n `Workflow ${definition.id} is already registered`,\n definition.id,\n );\n }\n\n const { steps } = parseWorkflowHandler(definition.handler);\n\n this.workflows.set(definition.id, {\n ...definition,\n steps,\n });\n\n this.logger.log(`Registered workflow \"${definition.id}\" with steps:`);\n for (const step of steps.values()) {\n const tags = [];\n if (step.conditional) tags.push('[conditional]');\n if (step.loop) tags.push('[loop]');\n if (step.isDynamic) tags.push('[dynamic]');\n this.logger.log(` └─ (${StepTypeToIcon[step.type]}) ${step.id} ${tags.join(' ')}`);\n }\n\n return this;\n }\n\n async unregisterWorkflow(workflowId: string): Promise<WorkflowEngine> {\n this.workflows.delete(workflowId);\n return this;\n }\n\n async unregisterAllWorkflows(): Promise<WorkflowEngine> {\n this.workflows.clear();\n return this;\n }\n\n async startWorkflow({\n resourceId,\n workflowId,\n input,\n options,\n }: {\n resourceId?: string;\n workflowId: string;\n input: unknown;\n options?: {\n timeout?: number;\n retries?: number;\n expireInSeconds?: number;\n batchSize?: number;\n };\n }): Promise<WorkflowRun> {\n if (!this._started) {\n await this.start(false, { batchSize: options?.batchSize ?? 1 });\n }\n\n const workflow = this.workflows.get(workflowId);\n if (!workflow) {\n throw new WorkflowEngineError(`Unknown workflow ${workflowId}`);\n }\n\n if (workflow.steps.length === 0 || !workflow.steps[0]) {\n throw new WorkflowEngineError(`Workflow ${workflowId} has no steps`, workflowId);\n }\n const initialStepId = workflow.steps[0]?.id;\n\n const run = await withPostgresTransaction(this.boss.getDb(), async (db) => {\n const timeoutAt = options?.timeout\n ? new Date(Date.now() + options.timeout)\n : workflow.timeout\n ? new Date(Date.now() + workflow.timeout)\n : null;\n\n const insertedRun = await insertWorkflowRun(\n {\n resourceId,\n workflowId,\n currentStepId: initialStepId,\n status: WorkflowStatus.RUNNING,\n input,\n maxRetries: options?.retries ?? workflow.retries ?? 0,\n timeoutAt,\n },\n this.boss.getDb(),\n );\n\n const job: WorkflowRunJobParameters = {\n runId: insertedRun.id,\n resourceId,\n workflowId,\n input,\n };\n\n await this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {\n startAfter: new Date(),\n expireInSeconds: options?.expireInSeconds ?? defaultExpireInSeconds,\n });\n\n return insertedRun;\n });\n\n this.logger.log('Started workflow run', {\n runId: run.id,\n workflowId,\n });\n\n return run;\n }\n\n async pauseWorkflow({\n runId,\n resourceId,\n }: {\n runId: string;\n resourceId?: string;\n }): Promise<WorkflowRun> {\n await this.checkIfHasStarted();\n\n // TODO: Pause all running steps immediately\n const run = await this.updateRun({\n runId,\n resourceId,\n data: {\n status: WorkflowStatus.PAUSED,\n pausedAt: new Date(),\n },\n });\n\n this.logger.log('Paused workflow run', {\n runId,\n workflowId: run.workflowId,\n });\n\n return run;\n }\n\n async resumeWorkflow({\n runId,\n resourceId,\n options,\n }: {\n runId: string;\n resourceId?: string;\n options?: { expireInSeconds?: number };\n }): Promise<WorkflowRun> {\n await this.checkIfHasStarted();\n\n return this.triggerEvent({\n runId,\n resourceId,\n eventName: PAUSE_EVENT_NAME,\n data: {},\n options,\n });\n }\n\n async cancelWorkflow({\n runId,\n resourceId,\n }: {\n runId: string;\n resourceId?: string;\n }): Promise<WorkflowRun> {\n await this.checkIfHasStarted();\n\n const run = await this.updateRun({\n runId,\n resourceId,\n data: {\n status: WorkflowStatus.CANCELLED,\n },\n });\n\n this.logger.log(`cancelled workflow run with id ${runId}`);\n\n return run;\n }\n\n async triggerEvent({\n runId,\n resourceId,\n eventName,\n data,\n options,\n }: {\n runId: string;\n resourceId?: string;\n eventName: string;\n data?: Record<string, unknown>;\n options?: {\n expireInSeconds?: number;\n };\n }): Promise<WorkflowRun> {\n await this.checkIfHasStarted();\n\n const run = await this.getRun({ runId, resourceId });\n\n const job: WorkflowRunJobParameters = {\n runId: run.id,\n resourceId,\n workflowId: run.workflowId,\n input: run.input,\n event: {\n name: eventName,\n data,\n },\n };\n\n this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {\n expireInSeconds: options?.expireInSeconds ?? defaultExpireInSeconds,\n });\n\n this.logger.log(`event ${eventName} sent for workflow run with id ${runId}`);\n return run;\n }\n\n async getRun(\n { runId, resourceId }: { runId: string; resourceId?: string },\n { exclusiveLock = false, db }: { exclusiveLock?: boolean; db?: Db } = {},\n ): Promise<WorkflowRun> {\n const run = await getWorkflowRun({ runId, resourceId }, { exclusiveLock, db: db ?? this.db });\n\n if (!run) {\n throw new WorkflowRunNotFoundError(runId);\n }\n\n return run;\n }\n\n async updateRun(\n {\n runId,\n resourceId,\n data,\n }: {\n runId: string;\n resourceId?: string;\n data: Partial<WorkflowRun>;\n },\n { db }: { db?: Db } = {},\n ): Promise<WorkflowRun> {\n const run = await updateWorkflowRun({ runId, resourceId, data }, db ?? this.db);\n\n if (!run) {\n throw new WorkflowRunNotFoundError(runId);\n }\n\n return run;\n }\n\n async checkProgress({\n runId,\n resourceId,\n }: {\n runId: string;\n resourceId?: string;\n }): Promise<WorkflowRunProgress> {\n const run = await this.getRun({ runId, resourceId });\n const workflow = this.workflows.get(run.workflowId);\n\n if (!workflow) {\n throw new WorkflowEngineError(`Workflow ${run.workflowId} not found`, run.workflowId, runId);\n }\n const steps = workflow?.steps ?? [];\n\n let completionPercentage = 0;\n let completedSteps = 0;\n\n if (steps.length > 0) {\n completedSteps = Object.values(run.timeline).filter(\n (step): step is TimelineStepEntry =>\n typeof step === 'object' &&\n step !== null &&\n 'output' in step &&\n step.output !== undefined,\n ).length;\n\n if (run.status === WorkflowStatus.COMPLETED) {\n completionPercentage = 100;\n } else if (run.status === WorkflowStatus.FAILED || run.status === WorkflowStatus.CANCELLED) {\n completionPercentage = Math.min((completedSteps / steps.length) * 100, 100);\n } else {\n const currentStepIndex = steps.findIndex((step) => step.id === run.currentStepId);\n if (currentStepIndex >= 0) {\n completionPercentage = (currentStepIndex / steps.length) * 100;\n } else {\n const completedSteps = Object.keys(run.timeline).length;\n\n completionPercentage = Math.min((completedSteps / steps.length) * 100, 100);\n }\n }\n }\n\n return {\n ...run,\n completedSteps,\n completionPercentage: Math.round(completionPercentage * 100) / 100, // Round to 2 decimal places\n totalSteps: steps.length,\n };\n }\n\n private async handleWorkflowRun([job]: Job<WorkflowRunJobParameters>[]) {\n const { runId, resourceId, workflowId, input, event } = job?.data ?? {};\n\n if (!runId) {\n throw new WorkflowEngineError('Invalid workflow run job, missing runId', workflowId);\n }\n\n if (!resourceId) {\n throw new WorkflowEngineError('Invalid workflow run job, missing resourceId', workflowId);\n }\n\n if (!workflowId) {\n throw new WorkflowEngineError(\n 'Invalid workflow run job, missing workflowId',\n undefined,\n runId,\n );\n }\n\n const workflow = this.workflows.get(workflowId);\n if (!workflow) {\n throw new WorkflowEngineError(`Workflow ${workflowId} not found`, workflowId, runId);\n }\n\n this.logger.log('Processing workflow run...', {\n runId,\n workflowId,\n });\n\n let run = await this.getRun({ runId, resourceId });\n\n try {\n if (run.status === WorkflowStatus.CANCELLED) {\n this.logger.log(`Workflow run ${runId} is cancelled, skipping`);\n return;\n }\n\n if (!run.currentStepId) {\n throw new WorkflowEngineError('Missing current step id', workflowId, runId);\n }\n\n if (run.status === WorkflowStatus.PAUSED) {\n const waitForStepEntry = run.timeline[`${run.currentStepId}-wait-for`];\n const waitForStep =\n waitForStepEntry && typeof waitForStepEntry === 'object' && 'waitFor' in waitForStepEntry\n ? (waitForStepEntry as TimelineWaitForEntry)\n : null;\n const currentStepEntry = run.timeline[run.currentStepId];\n const currentStep =\n currentStepEntry && typeof currentStepEntry === 'object' && 'output' in currentStepEntry\n ? (currentStepEntry as TimelineStepEntry)\n : null;\n const waitFor = waitForStep?.waitFor;\n const hasCurrentStepOutput = currentStep?.output !== undefined;\n\n if (waitFor && waitFor.eventName === event?.name && !hasCurrentStepOutput) {\n run = await this.updateRun({\n runId,\n resourceId,\n data: {\n status: WorkflowStatus.RUNNING,\n pausedAt: null,\n resumedAt: new Date(),\n timeline: merge(run.timeline, {\n [run.currentStepId]: {\n output: event?.data ?? {},\n timestamp: new Date(),\n },\n }),\n jobId: job?.id,\n },\n });\n } else {\n run = await this.updateRun({\n runId,\n resourceId,\n data: {\n status: WorkflowStatus.RUNNING,\n pausedAt: null,\n resumedAt: new Date(),\n jobId: job?.id,\n },\n });\n }\n }\n\n const context: WorkflowContext = {\n input: run.input as z.ZodTypeAny,\n workflowId: run.workflowId,\n runId: run.id,\n timeline: run.timeline,\n logger: this.logger,\n step: {\n run: async <T>(stepId: string, handler: () => Promise<T>) => {\n if (!run) {\n throw new WorkflowEngineError('Missing workflow run', workflowId, runId);\n }\n\n return this.runStep({\n stepId,\n run,\n handler,\n }) as Promise<T>;\n },\n waitFor: async <T extends Parameters>(\n stepId: string,\n { eventName, timeout }: { eventName: string; timeout?: number; schema?: T },\n ) => {\n if (!run) {\n throw new WorkflowEngineError('Missing workflow run', workflowId, runId);\n }\n return this.waitForEvent({\n run,\n stepId,\n eventName,\n timeout,\n }) as Promise<inferParameters<T>>;\n },\n // @ts-expect-error TODO: Implement waitUntil\n waitUntil: async ({ date }: { date: Date }) => {\n return this.waitUntil(runId, date);\n },\n pause: async (stepId: string) => {\n if (!run) {\n throw new WorkflowEngineError('Missing workflow run', workflowId, runId);\n }\n return this.pauseStep({\n stepId,\n run,\n });\n },\n },\n };\n\n const result = await workflow.handler(context);\n\n run = await this.getRun({ runId, resourceId });\n\n if (\n run.status === WorkflowStatus.RUNNING &&\n run.currentStepId === workflow.steps[workflow.steps.length - 1]?.id\n ) {\n const normalizedResult = result === undefined ? {} : result;\n await this.updateRun({\n runId,\n resourceId,\n data: {\n status: WorkflowStatus.COMPLETED,\n output: normalizedResult,\n completedAt: new Date(),\n jobId: job?.id,\n },\n });\n\n this.logger.log('Workflow run completed.', {\n runId,\n workflowId,\n });\n }\n } catch (error) {\n if (run.retryCount < run.maxRetries) {\n await this.updateRun({\n runId,\n resourceId,\n data: {\n retryCount: run.retryCount + 1,\n jobId: job?.id,\n },\n });\n\n const retryDelay = 2 ** run.retryCount * 1000;\n\n // NOTE: Do not use pg-boss retryLimit and retryBackoff so that we can fully control the retry logic from the WorkflowEngine and not PGBoss.\n const pgBossJob: WorkflowRunJobParameters = {\n runId,\n resourceId,\n workflowId,\n input,\n };\n await this.boss?.send('workflow-run', pgBossJob, { retryDelay });\n\n return;\n }\n\n // TODO: Ensure that this code always runs, even if worker is stopped unexpectedly.\n await this.updateRun({\n runId,\n resourceId,\n data: {\n status: WorkflowStatus.FAILED,\n error: error instanceof Error ? error.message : String(error),\n jobId: job?.id,\n },\n });\n\n throw error;\n }\n }\n\n private async runStep({\n stepId,\n run,\n handler,\n }: {\n stepId: string;\n run: WorkflowRun;\n handler: () => Promise<unknown>;\n }) {\n return withPostgresTransaction(this.db, async (db) => {\n const persistedRun = await this.getRun(\n { runId: run.id, resourceId: run.resourceId ?? undefined },\n {\n exclusiveLock: true,\n db,\n },\n );\n\n if (\n persistedRun.status === WorkflowStatus.CANCELLED ||\n persistedRun.status === WorkflowStatus.PAUSED ||\n persistedRun.status === WorkflowStatus.FAILED\n ) {\n this.logger.log(`Step ${stepId} skipped, workflow run is ${persistedRun.status}`, {\n runId: run.id,\n workflowId: run.workflowId,\n });\n\n return;\n }\n\n try {\n let result: unknown;\n\n // If the step has already been run, return the result\n const timelineStepEntry = persistedRun.timeline[stepId];\n const timelineStep =\n timelineStepEntry &&\n typeof timelineStepEntry === 'object' &&\n 'output' in timelineStepEntry\n ? (timelineStepEntry as TimelineStepEntry)\n : null;\n if (timelineStep?.output !== undefined) {\n result = timelineStep.output;\n } else {\n await this.updateRun(\n {\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n currentStepId: stepId,\n },\n },\n { db },\n );\n\n this.logger.log(`Running step ${stepId}...`, {\n runId: run.id,\n workflowId: run.workflowId,\n });\n\n result = await handler();\n\n run = await this.updateRun(\n {\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n timeline: merge(run.timeline, {\n [stepId]: {\n output: result === undefined ? {} : result,\n timestamp: new Date(),\n },\n }),\n },\n },\n { db },\n );\n }\n\n const finalResult = result === undefined ? {} : result;\n return finalResult;\n } catch (error) {\n this.logger.error(`Step ${stepId} failed:`, error as Error, {\n runId: run.id,\n workflowId: run.workflowId,\n });\n\n await this.updateRun(\n {\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n status: WorkflowStatus.FAILED,\n error: error instanceof Error ? `${error.message}\\n${error.stack}` : String(error),\n },\n },\n { db },\n );\n\n throw error;\n }\n });\n }\n\n private async waitForEvent({\n run,\n stepId,\n eventName,\n timeout,\n }: {\n run: WorkflowRun;\n stepId: string;\n eventName: string;\n timeout?: number;\n }) {\n const persistedRun = await this.getRun({\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n });\n\n if (\n persistedRun.status === WorkflowStatus.CANCELLED ||\n persistedRun.status === WorkflowStatus.PAUSED ||\n persistedRun.status === WorkflowStatus.FAILED\n ) {\n this.logger.log(`Step ${stepId} skipped, workflow run is ${persistedRun.status}`, {\n runId: run.id,\n workflowId: run.workflowId,\n });\n\n return;\n }\n\n const timelineStepCheckEntry = persistedRun.timeline[stepId];\n const timelineStepCheck =\n timelineStepCheckEntry &&\n typeof timelineStepCheckEntry === 'object' &&\n 'output' in timelineStepCheckEntry\n ? (timelineStepCheckEntry as TimelineStepEntry)\n : null;\n if (timelineStepCheck?.output !== undefined) {\n return timelineStepCheck.output;\n }\n\n await this.updateRun({\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n status: WorkflowStatus.PAUSED,\n currentStepId: stepId,\n timeline: merge(run.timeline, {\n [`${stepId}-wait-for`]: {\n waitFor: {\n eventName,\n timeout,\n },\n timestamp: new Date(),\n },\n }),\n pausedAt: new Date(),\n },\n });\n\n this.logger.log(`Running step ${stepId}, waiting for event ${eventName}...`, {\n runId: run.id,\n workflowId: run.workflowId,\n });\n }\n\n private async pauseStep({ stepId, run }: { stepId: string; run: WorkflowRun }): Promise<void> {\n await this.waitForEvent({\n run,\n stepId,\n eventName: PAUSE_EVENT_NAME,\n });\n }\n\n private async waitUntil(runId: string, _date: Date): Promise<void> {\n throw new WorkflowEngineError('Not implemented yet', undefined, runId);\n }\n\n private async checkIfHasStarted(): Promise<void> {\n if (!this._started) {\n throw new WorkflowEngineError('Workflow engine not started');\n }\n }\n\n private buildLogger(logger: WorkflowLogger): InternalWorkflowLogger {\n return {\n log: (message: string, context?: InternalWorkflowLoggerContext) => {\n const { runId, workflowId } = context ?? {};\n const parts = [LOG_PREFIX, workflowId, runId].filter(Boolean).join(' ');\n logger.log(`${parts}: ${message}`);\n },\n error: (message: string, error: Error, context?: InternalWorkflowLoggerContext) => {\n const { runId, workflowId } = context ?? {};\n const parts = [LOG_PREFIX, workflowId, runId].filter(Boolean).join(' ');\n logger.error(`${parts}: ${message}`, error);\n },\n };\n }\n\n async getRuns({\n resourceId,\n startingAfter,\n endingBefore,\n limit = 20,\n statuses,\n workflowId,\n }: {\n resourceId?: string;\n startingAfter?: string | null;\n endingBefore?: string | null;\n limit?: number;\n statuses?: WorkflowStatus[];\n workflowId?: string;\n }): Promise<{\n items: WorkflowRun[];\n nextCursor: string | null;\n prevCursor: string | null;\n hasMore: boolean;\n hasPrev: boolean;\n }> {\n return getWorkflowRuns(\n {\n resourceId,\n startingAfter,\n endingBefore,\n limit,\n statuses,\n workflowId,\n },\n this.db,\n );\n }\n}\n",
|
|
6
|
+
"import { merge } from 'es-toolkit';\nimport type { Db, Job, PgBoss } from 'pg-boss';\nimport type { z } from 'zod';\nimport { parseWorkflowHandler } from './ast-parser';\nimport { runMigrations } from './db/migration';\nimport {\n getWorkflowRun,\n getWorkflowRuns,\n insertWorkflowRun,\n updateWorkflowRun,\n withPostgresTransaction,\n} from './db/queries';\nimport type { WorkflowRun } from './db/types';\nimport { WorkflowEngineError, WorkflowRunNotFoundError } from './error';\nimport {\n type InternalWorkflowDefinition,\n type InternalWorkflowLogger,\n type InternalWorkflowLoggerContext,\n type inferParameters,\n type Parameters,\n StepType,\n type WorkflowContext,\n type WorkflowDefinition,\n type WorkflowLogger,\n type WorkflowRunProgress,\n WorkflowStatus,\n} from './types';\n\nconst PAUSE_EVENT_NAME = '__internal_pause';\nconst WORKFLOW_RUN_QUEUE_NAME = 'workflow-run';\nconst LOG_PREFIX = '[WorkflowEngine]';\n\nconst StepTypeToIcon = {\n [StepType.RUN]: 'λ',\n [StepType.WAIT_FOR]: '○',\n [StepType.PAUSE]: '⏸',\n [StepType.WAIT_UNTIL]: '⏲',\n};\n\n// Timeline entry types\ntype TimelineStepEntry = {\n output?: unknown;\n timestamp: Date;\n};\n\ntype TimelineWaitForEntry = {\n waitFor: {\n eventName: string;\n timeout?: number;\n };\n timestamp: Date;\n};\n\ntype WorkflowRunJobParameters = {\n runId: string;\n resourceId?: string;\n workflowId: string;\n input: unknown;\n event?: {\n name: string;\n data?: Record<string, unknown>;\n };\n};\n\nconst defaultLogger: WorkflowLogger = {\n log: (_message: string) => console.warn(_message),\n error: (message: string, error: Error) => console.error(message, error),\n};\n\nconst defaultExpireInSeconds = process.env.WORKFLOW_RUN_EXPIRE_IN_SECONDS\n ? Number.parseInt(process.env.WORKFLOW_RUN_EXPIRE_IN_SECONDS, 10)\n : 5 * 60; // 5 minutes\n\nexport class WorkflowEngine {\n private boss: PgBoss;\n private db: Db;\n private unregisteredWorkflows = new Map<string, WorkflowDefinition>();\n private _started = false;\n\n public workflows: Map<string, InternalWorkflowDefinition> = new Map<\n string,\n InternalWorkflowDefinition\n >();\n private logger: InternalWorkflowLogger;\n\n constructor({\n workflows,\n logger,\n boss,\n }: Partial<{\n workflows: WorkflowDefinition[];\n logger: WorkflowLogger;\n boss: PgBoss;\n }> = {}) {\n this.logger = this.buildLogger(logger ?? defaultLogger);\n\n if (workflows) {\n this.unregisteredWorkflows = new Map(workflows.map((workflow) => [workflow.id, workflow]));\n }\n\n if (!boss) {\n throw new WorkflowEngineError('PgBoss instance is required in constructor');\n }\n this.boss = boss;\n this.db = boss.getDb();\n }\n\n async start(\n asEngine = true,\n { batchSize }: { batchSize?: number } = { batchSize: 1 },\n ): Promise<void> {\n if (this._started) {\n return;\n }\n\n // Start boss first to get the database connection\n await this.boss.start();\n\n await runMigrations(this.boss.getDb());\n\n if (this.unregisteredWorkflows.size > 0) {\n for (const workflow of this.unregisteredWorkflows.values()) {\n await this.registerWorkflow(workflow);\n }\n }\n\n await this.boss.createQueue(WORKFLOW_RUN_QUEUE_NAME);\n\n const numWorkers: number = +(process.env.WORKFLOW_RUN_WORKERS ?? 3);\n\n if (asEngine) {\n for (let i = 0; i < numWorkers; i++) {\n await this.boss.work<WorkflowRunJobParameters>(\n WORKFLOW_RUN_QUEUE_NAME,\n { pollingIntervalSeconds: 0.5, batchSize },\n (job) => this.handleWorkflowRun(job),\n );\n this.logger.log(\n `Worker ${i + 1}/${numWorkers} started for queue ${WORKFLOW_RUN_QUEUE_NAME}`,\n );\n }\n }\n\n this._started = true;\n\n this.logger.log('Workflow engine started!');\n }\n\n async stop(): Promise<void> {\n await this.boss.stop();\n\n this._started = false;\n\n this.logger.log('Workflow engine stopped');\n }\n\n async registerWorkflow(definition: WorkflowDefinition): Promise<WorkflowEngine> {\n if (this.workflows.has(definition.id)) {\n throw new WorkflowEngineError(\n `Workflow ${definition.id} is already registered`,\n definition.id,\n );\n }\n\n const { steps } = parseWorkflowHandler(definition.handler);\n\n this.workflows.set(definition.id, {\n ...definition,\n steps,\n });\n\n this.logger.log(`Registered workflow \"${definition.id}\" with steps:`);\n for (const step of steps.values()) {\n const tags = [];\n if (step.conditional) tags.push('[conditional]');\n if (step.loop) tags.push('[loop]');\n if (step.isDynamic) tags.push('[dynamic]');\n this.logger.log(` └─ (${StepTypeToIcon[step.type]}) ${step.id} ${tags.join(' ')}`);\n }\n\n return this;\n }\n\n async unregisterWorkflow(workflowId: string): Promise<WorkflowEngine> {\n this.workflows.delete(workflowId);\n return this;\n }\n\n async unregisterAllWorkflows(): Promise<WorkflowEngine> {\n this.workflows.clear();\n return this;\n }\n\n async startWorkflow({\n resourceId,\n workflowId,\n input,\n options,\n }: {\n resourceId?: string;\n workflowId: string;\n input: unknown;\n options?: {\n timeout?: number;\n retries?: number;\n expireInSeconds?: number;\n batchSize?: number;\n };\n }): Promise<WorkflowRun> {\n if (!this._started) {\n await this.start(false, { batchSize: options?.batchSize ?? 1 });\n }\n\n const workflow = this.workflows.get(workflowId);\n if (!workflow) {\n throw new WorkflowEngineError(`Unknown workflow ${workflowId}`);\n }\n\n if (workflow.steps.length === 0 || !workflow.steps[0]) {\n throw new WorkflowEngineError(`Workflow ${workflowId} has no steps`, workflowId);\n }\n const initialStepId = workflow.steps[0]?.id;\n\n const run = await withPostgresTransaction(this.boss.getDb(), async (_db) => {\n const timeoutAt = options?.timeout\n ? new Date(Date.now() + options.timeout)\n : workflow.timeout\n ? new Date(Date.now() + workflow.timeout)\n : null;\n\n const insertedRun = await insertWorkflowRun(\n {\n resourceId,\n workflowId,\n currentStepId: initialStepId,\n status: WorkflowStatus.RUNNING,\n input,\n maxRetries: options?.retries ?? workflow.retries ?? 0,\n timeoutAt,\n },\n this.boss.getDb(),\n );\n\n const job: WorkflowRunJobParameters = {\n runId: insertedRun.id,\n resourceId,\n workflowId,\n input,\n };\n\n await this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {\n startAfter: new Date(),\n expireInSeconds: options?.expireInSeconds ?? defaultExpireInSeconds,\n });\n\n return insertedRun;\n });\n\n this.logger.log('Started workflow run', {\n runId: run.id,\n workflowId,\n });\n\n return run;\n }\n\n async pauseWorkflow({\n runId,\n resourceId,\n }: {\n runId: string;\n resourceId?: string;\n }): Promise<WorkflowRun> {\n await this.checkIfHasStarted();\n\n // TODO: Pause all running steps immediately\n const run = await this.updateRun({\n runId,\n resourceId,\n data: {\n status: WorkflowStatus.PAUSED,\n pausedAt: new Date(),\n },\n });\n\n this.logger.log('Paused workflow run', {\n runId,\n workflowId: run.workflowId,\n });\n\n return run;\n }\n\n async resumeWorkflow({\n runId,\n resourceId,\n options,\n }: {\n runId: string;\n resourceId?: string;\n options?: { expireInSeconds?: number };\n }): Promise<WorkflowRun> {\n await this.checkIfHasStarted();\n\n return this.triggerEvent({\n runId,\n resourceId,\n eventName: PAUSE_EVENT_NAME,\n data: {},\n options,\n });\n }\n\n async cancelWorkflow({\n runId,\n resourceId,\n }: {\n runId: string;\n resourceId?: string;\n }): Promise<WorkflowRun> {\n await this.checkIfHasStarted();\n\n const run = await this.updateRun({\n runId,\n resourceId,\n data: {\n status: WorkflowStatus.CANCELLED,\n },\n });\n\n this.logger.log(`cancelled workflow run with id ${runId}`);\n\n return run;\n }\n\n async triggerEvent({\n runId,\n resourceId,\n eventName,\n data,\n options,\n }: {\n runId: string;\n resourceId?: string;\n eventName: string;\n data?: Record<string, unknown>;\n options?: {\n expireInSeconds?: number;\n };\n }): Promise<WorkflowRun> {\n await this.checkIfHasStarted();\n\n const run = await this.getRun({ runId, resourceId });\n\n const job: WorkflowRunJobParameters = {\n runId: run.id,\n resourceId,\n workflowId: run.workflowId,\n input: run.input,\n event: {\n name: eventName,\n data,\n },\n };\n\n this.boss.send(WORKFLOW_RUN_QUEUE_NAME, job, {\n expireInSeconds: options?.expireInSeconds ?? defaultExpireInSeconds,\n });\n\n this.logger.log(`event ${eventName} sent for workflow run with id ${runId}`);\n return run;\n }\n\n async getRun(\n { runId, resourceId }: { runId: string; resourceId?: string },\n { exclusiveLock = false, db }: { exclusiveLock?: boolean; db?: Db } = {},\n ): Promise<WorkflowRun> {\n const run = await getWorkflowRun({ runId, resourceId }, { exclusiveLock, db: db ?? this.db });\n\n if (!run) {\n throw new WorkflowRunNotFoundError(runId);\n }\n\n return run;\n }\n\n async updateRun(\n {\n runId,\n resourceId,\n data,\n }: {\n runId: string;\n resourceId?: string;\n data: Partial<WorkflowRun>;\n },\n { db }: { db?: Db } = {},\n ): Promise<WorkflowRun> {\n const run = await updateWorkflowRun({ runId, resourceId, data }, db ?? this.db);\n\n if (!run) {\n throw new WorkflowRunNotFoundError(runId);\n }\n\n return run;\n }\n\n async checkProgress({\n runId,\n resourceId,\n }: {\n runId: string;\n resourceId?: string;\n }): Promise<WorkflowRunProgress> {\n const run = await this.getRun({ runId, resourceId });\n const workflow = this.workflows.get(run.workflowId);\n\n if (!workflow) {\n throw new WorkflowEngineError(`Workflow ${run.workflowId} not found`, run.workflowId, runId);\n }\n const steps = workflow?.steps ?? [];\n\n let completionPercentage = 0;\n let completedSteps = 0;\n\n if (steps.length > 0) {\n completedSteps = Object.values(run.timeline).filter(\n (step): step is TimelineStepEntry =>\n typeof step === 'object' &&\n step !== null &&\n 'output' in step &&\n step.output !== undefined,\n ).length;\n\n if (run.status === WorkflowStatus.COMPLETED) {\n completionPercentage = 100;\n } else if (run.status === WorkflowStatus.FAILED || run.status === WorkflowStatus.CANCELLED) {\n completionPercentage = Math.min((completedSteps / steps.length) * 100, 100);\n } else {\n const currentStepIndex = steps.findIndex((step) => step.id === run.currentStepId);\n if (currentStepIndex >= 0) {\n completionPercentage = (currentStepIndex / steps.length) * 100;\n } else {\n const completedSteps = Object.keys(run.timeline).length;\n\n completionPercentage = Math.min((completedSteps / steps.length) * 100, 100);\n }\n }\n }\n\n return {\n ...run,\n completedSteps,\n completionPercentage: Math.round(completionPercentage * 100) / 100, // Round to 2 decimal places\n totalSteps: steps.length,\n };\n }\n\n private async handleWorkflowRun([job]: Job<WorkflowRunJobParameters>[]) {\n const { runId, resourceId, workflowId, input, event } = job?.data ?? {};\n\n if (!runId) {\n throw new WorkflowEngineError('Invalid workflow run job, missing runId', workflowId);\n }\n\n if (!resourceId) {\n throw new WorkflowEngineError('Invalid workflow run job, missing resourceId', workflowId);\n }\n\n if (!workflowId) {\n throw new WorkflowEngineError(\n 'Invalid workflow run job, missing workflowId',\n undefined,\n runId,\n );\n }\n\n const workflow = this.workflows.get(workflowId);\n if (!workflow) {\n throw new WorkflowEngineError(`Workflow ${workflowId} not found`, workflowId, runId);\n }\n\n this.logger.log('Processing workflow run...', {\n runId,\n workflowId,\n });\n\n let run = await this.getRun({ runId, resourceId });\n\n try {\n if (run.status === WorkflowStatus.CANCELLED) {\n this.logger.log(`Workflow run ${runId} is cancelled, skipping`);\n return;\n }\n\n if (!run.currentStepId) {\n throw new WorkflowEngineError('Missing current step id', workflowId, runId);\n }\n\n if (run.status === WorkflowStatus.PAUSED) {\n const waitForStepEntry = run.timeline[`${run.currentStepId}-wait-for`];\n const waitForStep =\n waitForStepEntry && typeof waitForStepEntry === 'object' && 'waitFor' in waitForStepEntry\n ? (waitForStepEntry as TimelineWaitForEntry)\n : null;\n const currentStepEntry = run.timeline[run.currentStepId];\n const currentStep =\n currentStepEntry && typeof currentStepEntry === 'object' && 'output' in currentStepEntry\n ? (currentStepEntry as TimelineStepEntry)\n : null;\n const waitFor = waitForStep?.waitFor;\n const hasCurrentStepOutput = currentStep?.output !== undefined;\n\n if (waitFor && waitFor.eventName === event?.name && !hasCurrentStepOutput) {\n run = await this.updateRun({\n runId,\n resourceId,\n data: {\n status: WorkflowStatus.RUNNING,\n pausedAt: null,\n resumedAt: new Date(),\n timeline: merge(run.timeline, {\n [run.currentStepId]: {\n output: event?.data ?? {},\n timestamp: new Date(),\n },\n }),\n jobId: job?.id,\n },\n });\n } else {\n run = await this.updateRun({\n runId,\n resourceId,\n data: {\n status: WorkflowStatus.RUNNING,\n pausedAt: null,\n resumedAt: new Date(),\n jobId: job?.id,\n },\n });\n }\n }\n\n const context: WorkflowContext = {\n input: run.input as z.ZodTypeAny,\n workflowId: run.workflowId,\n runId: run.id,\n timeline: run.timeline,\n logger: this.logger,\n step: {\n run: async <T>(stepId: string, handler: () => Promise<T>) => {\n if (!run) {\n throw new WorkflowEngineError('Missing workflow run', workflowId, runId);\n }\n\n return this.runStep({\n stepId,\n run,\n handler,\n }) as Promise<T>;\n },\n waitFor: async <T extends Parameters>(\n stepId: string,\n { eventName, timeout }: { eventName: string; timeout?: number; schema?: T },\n ) => {\n if (!run) {\n throw new WorkflowEngineError('Missing workflow run', workflowId, runId);\n }\n return this.waitForEvent({\n run,\n stepId,\n eventName,\n timeout,\n }) as Promise<inferParameters<T>>;\n },\n // @ts-expect-error TODO: Implement waitUntil\n waitUntil: async ({ date }: { date: Date }) => {\n return this.waitUntil(runId, date);\n },\n pause: async (stepId: string) => {\n if (!run) {\n throw new WorkflowEngineError('Missing workflow run', workflowId, runId);\n }\n return this.pauseStep({\n stepId,\n run,\n });\n },\n },\n };\n\n const result = await workflow.handler(context);\n\n run = await this.getRun({ runId, resourceId });\n\n if (\n run.status === WorkflowStatus.RUNNING &&\n run.currentStepId === workflow.steps[workflow.steps.length - 1]?.id\n ) {\n const normalizedResult = result === undefined ? {} : result;\n await this.updateRun({\n runId,\n resourceId,\n data: {\n status: WorkflowStatus.COMPLETED,\n output: normalizedResult,\n completedAt: new Date(),\n jobId: job?.id,\n },\n });\n\n this.logger.log('Workflow run completed.', {\n runId,\n workflowId,\n });\n }\n } catch (error) {\n if (run.retryCount < run.maxRetries) {\n await this.updateRun({\n runId,\n resourceId,\n data: {\n retryCount: run.retryCount + 1,\n jobId: job?.id,\n },\n });\n\n const retryDelay = 2 ** run.retryCount * 1000;\n\n // NOTE: Do not use pg-boss retryLimit and retryBackoff so that we can fully control the retry logic from the WorkflowEngine and not PGBoss.\n const pgBossJob: WorkflowRunJobParameters = {\n runId,\n resourceId,\n workflowId,\n input,\n };\n await this.boss?.send('workflow-run', pgBossJob, { retryDelay });\n\n return;\n }\n\n // TODO: Ensure that this code always runs, even if worker is stopped unexpectedly.\n await this.updateRun({\n runId,\n resourceId,\n data: {\n status: WorkflowStatus.FAILED,\n error: error instanceof Error ? error.message : String(error),\n jobId: job?.id,\n },\n });\n\n throw error;\n }\n }\n\n private async runStep({\n stepId,\n run,\n handler,\n }: {\n stepId: string;\n run: WorkflowRun;\n handler: () => Promise<unknown>;\n }) {\n return withPostgresTransaction(this.db, async (db) => {\n const persistedRun = await this.getRun(\n { runId: run.id, resourceId: run.resourceId ?? undefined },\n {\n exclusiveLock: true,\n db,\n },\n );\n\n if (\n persistedRun.status === WorkflowStatus.CANCELLED ||\n persistedRun.status === WorkflowStatus.PAUSED ||\n persistedRun.status === WorkflowStatus.FAILED\n ) {\n this.logger.log(`Step ${stepId} skipped, workflow run is ${persistedRun.status}`, {\n runId: run.id,\n workflowId: run.workflowId,\n });\n\n return;\n }\n\n try {\n let result: unknown;\n\n // If the step has already been run, return the result\n const timelineStepEntry = persistedRun.timeline[stepId];\n const timelineStep =\n timelineStepEntry &&\n typeof timelineStepEntry === 'object' &&\n 'output' in timelineStepEntry\n ? (timelineStepEntry as TimelineStepEntry)\n : null;\n if (timelineStep?.output !== undefined) {\n result = timelineStep.output;\n } else {\n await this.updateRun(\n {\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n currentStepId: stepId,\n },\n },\n { db },\n );\n\n this.logger.log(`Running step ${stepId}...`, {\n runId: run.id,\n workflowId: run.workflowId,\n });\n\n result = await handler();\n\n run = await this.updateRun(\n {\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n timeline: merge(run.timeline, {\n [stepId]: {\n output: result === undefined ? {} : result,\n timestamp: new Date(),\n },\n }),\n },\n },\n { db },\n );\n }\n\n const finalResult = result === undefined ? {} : result;\n return finalResult;\n } catch (error) {\n this.logger.error(`Step ${stepId} failed:`, error as Error, {\n runId: run.id,\n workflowId: run.workflowId,\n });\n\n await this.updateRun(\n {\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n status: WorkflowStatus.FAILED,\n error: error instanceof Error ? `${error.message}\\n${error.stack}` : String(error),\n },\n },\n { db },\n );\n\n throw error;\n }\n });\n }\n\n private async waitForEvent({\n run,\n stepId,\n eventName,\n timeout,\n }: {\n run: WorkflowRun;\n stepId: string;\n eventName: string;\n timeout?: number;\n }) {\n const persistedRun = await this.getRun({\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n });\n\n if (\n persistedRun.status === WorkflowStatus.CANCELLED ||\n persistedRun.status === WorkflowStatus.PAUSED ||\n persistedRun.status === WorkflowStatus.FAILED\n ) {\n this.logger.log(`Step ${stepId} skipped, workflow run is ${persistedRun.status}`, {\n runId: run.id,\n workflowId: run.workflowId,\n });\n\n return;\n }\n\n const timelineStepCheckEntry = persistedRun.timeline[stepId];\n const timelineStepCheck =\n timelineStepCheckEntry &&\n typeof timelineStepCheckEntry === 'object' &&\n 'output' in timelineStepCheckEntry\n ? (timelineStepCheckEntry as TimelineStepEntry)\n : null;\n if (timelineStepCheck?.output !== undefined) {\n return timelineStepCheck.output;\n }\n\n await this.updateRun({\n runId: run.id,\n resourceId: run.resourceId ?? undefined,\n data: {\n status: WorkflowStatus.PAUSED,\n currentStepId: stepId,\n timeline: merge(run.timeline, {\n [`${stepId}-wait-for`]: {\n waitFor: {\n eventName,\n timeout,\n },\n timestamp: new Date(),\n },\n }),\n pausedAt: new Date(),\n },\n });\n\n this.logger.log(`Running step ${stepId}, waiting for event ${eventName}...`, {\n runId: run.id,\n workflowId: run.workflowId,\n });\n }\n\n private async pauseStep({ stepId, run }: { stepId: string; run: WorkflowRun }): Promise<void> {\n await this.waitForEvent({\n run,\n stepId,\n eventName: PAUSE_EVENT_NAME,\n });\n }\n\n private async waitUntil(runId: string, _date: Date): Promise<void> {\n throw new WorkflowEngineError('Not implemented yet', undefined, runId);\n }\n\n private async checkIfHasStarted(): Promise<void> {\n if (!this._started) {\n throw new WorkflowEngineError('Workflow engine not started');\n }\n }\n\n private buildLogger(logger: WorkflowLogger): InternalWorkflowLogger {\n return {\n log: (message: string, context?: InternalWorkflowLoggerContext) => {\n const { runId, workflowId } = context ?? {};\n const parts = [LOG_PREFIX, workflowId, runId].filter(Boolean).join(' ');\n logger.log(`${parts}: ${message}`);\n },\n error: (message: string, error: Error, context?: InternalWorkflowLoggerContext) => {\n const { runId, workflowId } = context ?? {};\n const parts = [LOG_PREFIX, workflowId, runId].filter(Boolean).join(' ');\n logger.error(`${parts}: ${message}`, error);\n },\n };\n }\n\n async getRuns({\n resourceId,\n startingAfter,\n endingBefore,\n limit = 20,\n statuses,\n workflowId,\n }: {\n resourceId?: string;\n startingAfter?: string | null;\n endingBefore?: string | null;\n limit?: number;\n statuses?: WorkflowStatus[];\n workflowId?: string;\n }): Promise<{\n items: WorkflowRun[];\n nextCursor: string | null;\n prevCursor: string | null;\n hasMore: boolean;\n hasPrev: boolean;\n }> {\n return getWorkflowRuns(\n {\n resourceId,\n startingAfter,\n endingBefore,\n limit,\n statuses,\n workflowId,\n },\n this.db,\n );\n }\n}\n",
|
|
7
7
|
"import * as ts from 'typescript';\nimport type { InternalStepDefinition, StepType, WorkflowContext } from './types';\n\ntype ParseWorkflowHandlerReturnType = {\n steps: InternalStepDefinition[];\n};\n\nexport function parseWorkflowHandler(\n handler: (context: WorkflowContext) => Promise<unknown>,\n): ParseWorkflowHandlerReturnType {\n const handlerSource = handler.toString();\n const sourceFile = ts.createSourceFile('handler.ts', handlerSource, ts.ScriptTarget.Latest, true);\n\n const steps: Map<string, InternalStepDefinition> = new Map();\n\n function isInConditional(node: ts.Node): boolean {\n let current = node.parent;\n while (current) {\n if (\n ts.isIfStatement(current) ||\n ts.isConditionalExpression(current) ||\n ts.isSwitchStatement(current) ||\n ts.isCaseClause(current)\n ) {\n return true;\n }\n current = current.parent;\n }\n return false;\n }\n\n function isInLoop(node: ts.Node): boolean {\n let current = node.parent;\n while (current) {\n if (\n ts.isForStatement(current) ||\n ts.isForInStatement(current) ||\n ts.isForOfStatement(current) ||\n ts.isWhileStatement(current) ||\n ts.isDoStatement(current)\n ) {\n return true;\n }\n current = current.parent;\n }\n return false;\n }\n\n function extractStepId(arg: ts.Expression): {\n id: string;\n isDynamic: boolean;\n } {\n if (ts.isStringLiteral(arg) || ts.isNoSubstitutionTemplateLiteral(arg)) {\n return { id: arg.text, isDynamic: false };\n }\n\n if (ts.isTemplateExpression(arg)) {\n let templateStr = arg.head.text;\n for (const span of arg.templateSpans) {\n templateStr += `\\${...}`;\n templateStr += span.literal.text;\n }\n return { id: templateStr, isDynamic: true };\n }\n\n return { id: arg.getText(sourceFile), isDynamic: true };\n }\n\n function visit(node: ts.Node) {\n if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression)) {\n const propertyAccess = node.expression;\n const objectName = propertyAccess.expression.getText(sourceFile);\n const methodName = propertyAccess.name.text;\n\n if (\n objectName === 'step' &&\n (methodName === 'run' || methodName === 'waitFor' || methodName === 'pause')\n ) {\n const firstArg = node.arguments[0];\n if (firstArg) {\n const { id, isDynamic } = extractStepId(firstArg);\n\n const stepDefinition: InternalStepDefinition = {\n id,\n type: methodName as StepType,\n conditional: isInConditional(node),\n loop: isInLoop(node),\n isDynamic,\n };\n\n if (steps.has(id)) {\n throw new Error(\n `Duplicate step ID detected: '${id}'. Step IDs must be unique within a workflow.`,\n );\n }\n\n steps.set(id, stepDefinition);\n }\n }\n }\n\n ts.forEachChild(node, visit);\n }\n\n visit(sourceFile);\n\n return { steps: Array.from(steps.values()) };\n}\n",
|
|
8
8
|
"import type { Db } from 'pg-boss';\n\nexport async function runMigrations(db: Db): Promise<void> {\n const tableExistsResult = await db.executeSql(\n `\n SELECT EXISTS (\n SELECT FROM information_schema.tables \n WHERE table_schema = 'public' \n AND table_name = 'workflow_runs'\n );\n `,\n [],\n );\n\n if (!tableExistsResult.rows[0]?.exists) {\n await db.executeSql(\n `\n CREATE TABLE workflow_runs (\n id varchar(32) PRIMARY KEY NOT NULL,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n resource_id varchar(32),\n workflow_id varchar(32) NOT NULL,\n status text DEFAULT 'pending' NOT NULL,\n input jsonb NOT NULL,\n output jsonb,\n error text,\n current_step_id varchar(256) NOT NULL,\n timeline jsonb DEFAULT '{}'::jsonb NOT NULL,\n paused_at timestamp with time zone,\n resumed_at timestamp with time zone,\n completed_at timestamp with time zone,\n timeout_at timestamp with time zone,\n retry_count integer DEFAULT 0 NOT NULL,\n max_retries integer DEFAULT 0 NOT NULL,\n job_id varchar(256)\n );\n `,\n [],\n );\n\n await db.executeSql(\n `\n CREATE INDEX workflow_runs_workflow_id_idx ON workflow_runs USING btree (workflow_id);\n `,\n [],\n );\n\n await db.executeSql(\n `\n CREATE INDEX workflow_runs_created_at_idx ON workflow_runs USING btree (created_at);\n `,\n [],\n );\n\n await db.executeSql(\n `\n CREATE INDEX workflow_runs_resource_id_idx ON workflow_runs USING btree (resource_id);\n `,\n [],\n );\n }\n}\n",
|
|
9
9
|
"import ksuid from 'ksuid';\nimport type { Db } from 'pg-boss';\nimport type { WorkflowRun } from './types';\n\nexport function generateKSUID(prefix?: string): string {\n return `${prefix ? `${prefix}_` : ''}${ksuid.randomSync().string}`;\n}\n\ntype WorkflowRunRow = {\n id: string;\n created_at: string | Date;\n updated_at: string | Date;\n resource_id: string | null;\n workflow_id: string;\n status: 'pending' | 'running' | 'paused' | 'completed' | 'failed' | 'cancelled';\n input: string | unknown;\n output: string | unknown | null;\n error: string | null;\n current_step_id: string;\n timeline: string | Record<string, unknown>;\n paused_at: string | Date | null;\n resumed_at: string | Date | null;\n completed_at: string | Date | null;\n timeout_at: string | Date | null;\n retry_count: number;\n max_retries: number;\n job_id: string | null;\n};\n\nfunction mapRowToWorkflowRun(row: WorkflowRunRow): WorkflowRun {\n return {\n id: row.id,\n createdAt: new Date(row.created_at),\n updatedAt: new Date(row.updated_at),\n resourceId: row.resource_id,\n workflowId: row.workflow_id,\n status: row.status,\n input: typeof row.input === 'string' ? JSON.parse(row.input) : row.input,\n output:\n typeof row.output === 'string'\n ? row.output.trim().startsWith('{') || row.output.trim().startsWith('[')\n ? JSON.parse(row.output)\n : row.output\n : (row.output ?? null),\n error: row.error,\n currentStepId: row.current_step_id,\n timeline: typeof row.timeline === 'string' ? JSON.parse(row.timeline) : row.timeline,\n pausedAt: row.paused_at ? new Date(row.paused_at) : null,\n resumedAt: row.resumed_at ? new Date(row.resumed_at) : null,\n completedAt: row.completed_at ? new Date(row.completed_at) : null,\n timeoutAt: row.timeout_at ? new Date(row.timeout_at) : null,\n retryCount: row.retry_count,\n maxRetries: row.max_retries,\n jobId: row.job_id,\n };\n}\n\nexport async function insertWorkflowRun(\n {\n resourceId,\n workflowId,\n currentStepId,\n status,\n input,\n maxRetries,\n timeoutAt,\n }: {\n resourceId?: string;\n workflowId: string;\n currentStepId: string;\n status: string;\n input: unknown;\n maxRetries: number;\n timeoutAt: Date | null;\n },\n db: Db,\n): Promise<WorkflowRun> {\n const runId = generateKSUID('run');\n const now = new Date();\n\n const result = await db.executeSql(\n `INSERT INTO workflow_runs (\n id, \n resource_id, \n workflow_id, \n current_step_id, \n status, \n input, \n max_retries, \n timeout_at,\n created_at,\n updated_at,\n timeline,\n retry_count\n )\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)\n RETURNING *`,\n [\n runId,\n resourceId ?? null,\n workflowId,\n currentStepId,\n status,\n JSON.stringify(input),\n maxRetries,\n timeoutAt,\n now,\n now,\n '{}',\n 0,\n ],\n );\n\n const insertedRun = result.rows[0];\n\n if (!insertedRun) {\n throw new Error('Failed to insert workflow run');\n }\n\n return mapRowToWorkflowRun(insertedRun);\n}\n\nexport async function getWorkflowRun(\n {\n runId,\n resourceId,\n }: {\n runId: string;\n resourceId?: string;\n },\n { exclusiveLock = false, db }: { exclusiveLock?: boolean; db: Db },\n): Promise<WorkflowRun | null> {\n const lockSuffix = exclusiveLock ? 'FOR UPDATE' : '';\n\n const result = resourceId\n ? await db.executeSql(\n `SELECT * FROM workflow_runs \n WHERE id = $1 AND resource_id = $2\n ${lockSuffix}`,\n [runId, resourceId],\n )\n : await db.executeSql(\n `SELECT * FROM workflow_runs \n WHERE id = $1\n ${lockSuffix}`,\n [runId],\n );\n\n const run = result.rows[0];\n\n if (!run) {\n return null;\n }\n\n return mapRowToWorkflowRun(run);\n}\n\nexport async function updateWorkflowRun(\n {\n runId,\n resourceId,\n data,\n }: {\n runId: string;\n resourceId?: string;\n data: Partial<WorkflowRun>;\n },\n db: Db,\n): Promise<WorkflowRun | null> {\n const now = new Date();\n\n const updates: string[] = ['updated_at = $1'];\n const values: (string | number | Date | null)[] = [now];\n let paramIndex = 2;\n\n if (data.status !== undefined) {\n updates.push(`status = $${paramIndex}`);\n values.push(data.status);\n paramIndex++;\n }\n if (data.currentStepId !== undefined) {\n updates.push(`current_step_id = $${paramIndex}`);\n values.push(data.currentStepId);\n paramIndex++;\n }\n if (data.timeline !== undefined) {\n updates.push(`timeline = $${paramIndex}`);\n values.push(JSON.stringify(data.timeline));\n paramIndex++;\n }\n if (data.pausedAt !== undefined) {\n updates.push(`paused_at = $${paramIndex}`);\n values.push(data.pausedAt);\n paramIndex++;\n }\n if (data.resumedAt !== undefined) {\n updates.push(`resumed_at = $${paramIndex}`);\n values.push(data.resumedAt);\n paramIndex++;\n }\n if (data.completedAt !== undefined) {\n updates.push(`completed_at = $${paramIndex}`);\n values.push(data.completedAt);\n paramIndex++;\n }\n if (data.output !== undefined) {\n updates.push(`output = $${paramIndex}`);\n values.push(JSON.stringify(data.output));\n paramIndex++;\n }\n if (data.error !== undefined) {\n updates.push(`error = $${paramIndex}`);\n values.push(data.error);\n paramIndex++;\n }\n if (data.retryCount !== undefined) {\n updates.push(`retry_count = $${paramIndex}`);\n values.push(data.retryCount);\n paramIndex++;\n }\n if (data.jobId !== undefined) {\n updates.push(`job_id = $${paramIndex}`);\n values.push(data.jobId);\n paramIndex++;\n }\n\n const whereClause = resourceId\n ? `WHERE id = $${paramIndex} AND resource_id = $${paramIndex + 1}`\n : `WHERE id = $${paramIndex}`;\n\n values.push(runId);\n if (resourceId) {\n values.push(resourceId);\n }\n\n const query = `\n UPDATE workflow_runs \n SET ${updates.join(', ')}\n ${whereClause}\n RETURNING *\n `;\n\n const result = await db.executeSql(query, values);\n const run = result.rows[0];\n\n if (!run) {\n return null;\n }\n\n return mapRowToWorkflowRun(run);\n}\n\nexport async function getWorkflowRuns(\n {\n resourceId,\n startingAfter,\n endingBefore,\n limit = 20,\n statuses,\n workflowId,\n }: {\n resourceId?: string;\n startingAfter?: string | null;\n endingBefore?: string | null;\n limit?: number;\n statuses?: string[];\n workflowId?: string;\n },\n db: Db,\n): Promise<{\n items: WorkflowRun[];\n nextCursor: string | null;\n prevCursor: string | null;\n hasMore: boolean;\n hasPrev: boolean;\n}> {\n const conditions: string[] = [];\n const values: (string | number | string[] | Date)[] = [];\n let paramIndex = 1;\n\n if (resourceId) {\n conditions.push(`resource_id = $${paramIndex}`);\n values.push(resourceId);\n paramIndex++;\n }\n\n if (statuses && statuses.length > 0) {\n conditions.push(`status = ANY($${paramIndex})`);\n values.push(statuses);\n paramIndex++;\n }\n\n if (workflowId) {\n conditions.push(`workflow_id = $${paramIndex}`);\n values.push(workflowId);\n paramIndex++;\n }\n\n if (startingAfter) {\n const cursorResult = await db.executeSql(\n 'SELECT created_at FROM workflow_runs WHERE id = $1 LIMIT 1',\n [startingAfter],\n );\n if (cursorResult.rows[0]?.created_at) {\n conditions.push(`created_at < $${paramIndex}`);\n values.push(\n typeof cursorResult.rows[0].created_at === 'string'\n ? new Date(cursorResult.rows[0].created_at)\n : cursorResult.rows[0].created_at,\n );\n paramIndex++;\n }\n }\n\n if (endingBefore) {\n const cursorResult = await db.executeSql(\n 'SELECT created_at FROM workflow_runs WHERE id = $1 LIMIT 1',\n [endingBefore],\n );\n if (cursorResult.rows[0]?.created_at) {\n conditions.push(`created_at > $${paramIndex}`);\n values.push(\n typeof cursorResult.rows[0].created_at === 'string'\n ? new Date(cursorResult.rows[0].created_at)\n : cursorResult.rows[0].created_at,\n );\n paramIndex++;\n }\n }\n\n const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';\n const actualLimit = Math.min(Math.max(limit, 1), 100) + 1;\n\n const query = `\n SELECT * FROM workflow_runs\n ${whereClause}\n ORDER BY created_at DESC\n LIMIT $${paramIndex}\n `;\n values.push(actualLimit);\n\n const result = await db.executeSql(query, values);\n const rows = result.rows;\n\n const hasMore = rows.length > (limit ?? 20);\n const rawItems = hasMore ? rows.slice(0, limit) : rows;\n const items = rawItems.map((row) => mapRowToWorkflowRun(row));\n const hasPrev = !!endingBefore;\n const nextCursor = hasMore && items.length > 0 ? (items[items.length - 1]?.id ?? null) : null;\n const prevCursor = hasPrev && items.length > 0 ? (items[0]?.id ?? null) : null;\n\n return { items, nextCursor, prevCursor, hasMore, hasPrev };\n}\n\nexport async function withPostgresTransaction<T>(\n db: Db,\n callback: (db: Db) => Promise<T>,\n): Promise<T> {\n try {\n await db.executeSql('BEGIN', []);\n const result = await callback(db);\n await db.executeSql('COMMIT', []);\n return result;\n } catch (error) {\n await db.executeSql('ROLLBACK', []);\n throw error;\n }\n}\n",
|
|
10
10
|
"export class WorkflowEngineError extends Error {\n constructor(\n message: string,\n public readonly workflowId?: string,\n public readonly runId?: string,\n public override readonly cause: Error | undefined = undefined,\n ) {\n super(message);\n this.name = 'WorkflowEngineError';\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, WorkflowEngineError);\n }\n }\n}\n\nexport class WorkflowRunNotFoundError extends WorkflowEngineError {\n constructor(runId?: string, workflowId?: string) {\n super('Workflow run not found', workflowId, runId);\n this.name = 'WorkflowRunNotFoundError';\n }\n}\n",
|
|
11
11
|
"import type { z } from 'zod';\nimport type { WorkflowRun } from './db/types';\n\nexport enum WorkflowStatus {\n PENDING = 'pending',\n RUNNING = 'running',\n PAUSED = 'paused',\n COMPLETED = 'completed',\n FAILED = 'failed',\n CANCELLED = 'cancelled',\n}\n\nexport enum StepType {\n PAUSE = 'pause',\n RUN = 'run',\n WAIT_FOR = 'waitFor',\n WAIT_UNTIL = 'waitUntil',\n}\n\nexport type Parameters = z.ZodTypeAny;\nexport type inferParameters<P extends Parameters> = P extends z.ZodTypeAny ? z.infer<P> : never;\n\nexport type WorkflowOptions<I extends Parameters> = {\n timeout?: number;\n retries?: number;\n inputSchema?: I;\n};\n\nexport interface WorkflowLogger {\n log(message: string): void;\n error(message: string, ...args: unknown[]): void;\n}\n\nexport type InternalWorkflowLoggerContext = {\n runId?: string;\n workflowId?: string;\n};\nexport interface InternalWorkflowLogger {\n log(message: string, context?: InternalWorkflowLoggerContext): void;\n error(message: string, error: Error, context?: InternalWorkflowLoggerContext): void;\n}\n\nexport type StepContext = {\n run: <T>(stepId: string, handler: () => Promise<T>) => Promise<T>;\n waitFor: <T extends Parameters>(\n stepId: string,\n { eventName, timeout, schema }: { eventName: string; timeout?: number; schema?: T },\n ) => Promise<inferParameters<T>>;\n waitUntil: (stepId: string, { date }: { date: Date }) => Promise<void>;\n pause: (stepId: string) => Promise<void>;\n};\n\nexport type WorkflowContext<T extends Parameters = Parameters> = {\n input: T;\n step: StepContext;\n workflowId: string;\n runId: string;\n timeline: Record<string, unknown>;\n logger: WorkflowLogger;\n};\n\nexport type WorkflowDefinition<T extends Parameters = Parameters> = {\n id: string;\n handler: (context: WorkflowContext<inferParameters<T>>) => Promise<unknown>;\n inputSchema?: T;\n timeout?: number; // milliseconds\n retries?: number;\n};\n\nexport type InternalStepDefinition = {\n id: string;\n type: StepType;\n conditional: boolean;\n loop: boolean;\n isDynamic: boolean;\n};\n\nexport type InternalWorkflowDefinition<T extends Parameters = Parameters> =\n WorkflowDefinition<T> & {\n steps: InternalStepDefinition[];\n };\n\nexport type WorkflowRunProgress = WorkflowRun & {\n completionPercentage: number;\n totalSteps: number;\n completedSteps: number;\n};\n"
|
|
12
12
|
],
|
|
13
|
-
"mappings": "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",
|
|
14
|
-
"debugId": "
|
|
13
|
+
"mappings": "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",
|
|
14
|
+
"debugId": "7A180DA27B38390864756E2164756E21",
|
|
15
15
|
"names": []
|
|
16
16
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pg-workflows",
|
|
3
|
-
"description": "The simplest Postgres workflow engine for TypeScript
|
|
4
|
-
"version": "0.1.
|
|
3
|
+
"description": "The simplest Postgres workflow engine for TypeScript - durable execution, event-driven orchestration, and automatic retries powered entirely by PostgreSQL",
|
|
4
|
+
"version": "0.1.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist"
|
|
@@ -66,17 +66,16 @@
|
|
|
66
66
|
"registry": "https://registry.npmjs.org/"
|
|
67
67
|
},
|
|
68
68
|
"dependencies": {
|
|
69
|
+
"es-toolkit": "^1.44.0",
|
|
69
70
|
"ksuid": "^3.0.0",
|
|
70
|
-
"lodash": "^4.17.21",
|
|
71
71
|
"pg": "^8.13.1",
|
|
72
72
|
"pg-boss": ">=12.0.0",
|
|
73
|
-
"
|
|
74
|
-
"
|
|
73
|
+
"typescript": "^5.9.3",
|
|
74
|
+
"zod": "^3.24.0"
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|
|
77
77
|
"@biomejs/biome": "^2.3.10",
|
|
78
78
|
"@electric-sql/pglite": "^0.3.14",
|
|
79
|
-
"@types/lodash": "^4.17.13",
|
|
80
79
|
"@types/node": "^22.10.2",
|
|
81
80
|
"@types/pg": "^8.11.10",
|
|
82
81
|
"bunup": "^0.16.11",
|