@workglow/task-graph 0.0.52
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/LICENSE +201 -0
- package/README.md +1280 -0
- package/dist/browser.d.ts +7 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +2842 -0
- package/dist/browser.js.map +33 -0
- package/dist/bun.d.ts +7 -0
- package/dist/bun.d.ts.map +1 -0
- package/dist/bun.js +2843 -0
- package/dist/bun.js.map +33 -0
- package/dist/common.d.ts +33 -0
- package/dist/common.d.ts.map +1 -0
- package/dist/node.d.ts +7 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +2842 -0
- package/dist/node.js.map +33 -0
- package/dist/storage/TaskGraphRepository.d.ts +92 -0
- package/dist/storage/TaskGraphRepository.d.ts.map +1 -0
- package/dist/storage/TaskGraphTabularRepository.d.ts +73 -0
- package/dist/storage/TaskGraphTabularRepository.d.ts.map +1 -0
- package/dist/storage/TaskOutputRepository.d.ts +93 -0
- package/dist/storage/TaskOutputRepository.d.ts.map +1 -0
- package/dist/storage/TaskOutputTabularRepository.d.ts +84 -0
- package/dist/storage/TaskOutputTabularRepository.d.ts.map +1 -0
- package/dist/task/ArrayTask.d.ts +72 -0
- package/dist/task/ArrayTask.d.ts.map +1 -0
- package/dist/task/ConditionalTask.d.ts +278 -0
- package/dist/task/ConditionalTask.d.ts.map +1 -0
- package/dist/task/GraphAsTask.d.ts +79 -0
- package/dist/task/GraphAsTask.d.ts.map +1 -0
- package/dist/task/GraphAsTaskRunner.d.ts +36 -0
- package/dist/task/GraphAsTaskRunner.d.ts.map +1 -0
- package/dist/task/ITask.d.ts +144 -0
- package/dist/task/ITask.d.ts.map +1 -0
- package/dist/task/ITaskRunner.d.ts +36 -0
- package/dist/task/ITaskRunner.d.ts.map +1 -0
- package/dist/task/JobQueueFactory.d.ts +23 -0
- package/dist/task/JobQueueFactory.d.ts.map +1 -0
- package/dist/task/JobQueueTask.d.ts +65 -0
- package/dist/task/JobQueueTask.d.ts.map +1 -0
- package/dist/task/Task.d.ts +334 -0
- package/dist/task/Task.d.ts.map +1 -0
- package/dist/task/TaskError.d.ts +66 -0
- package/dist/task/TaskError.d.ts.map +1 -0
- package/dist/task/TaskEvents.d.ts +40 -0
- package/dist/task/TaskEvents.d.ts.map +1 -0
- package/dist/task/TaskJSON.d.ts +82 -0
- package/dist/task/TaskJSON.d.ts.map +1 -0
- package/dist/task/TaskQueueRegistry.d.ts +69 -0
- package/dist/task/TaskQueueRegistry.d.ts.map +1 -0
- package/dist/task/TaskRegistry.d.ts +31 -0
- package/dist/task/TaskRegistry.d.ts.map +1 -0
- package/dist/task/TaskRunner.d.ts +99 -0
- package/dist/task/TaskRunner.d.ts.map +1 -0
- package/dist/task/TaskTypes.d.ts +68 -0
- package/dist/task/TaskTypes.d.ts.map +1 -0
- package/dist/task-graph/Conversions.d.ts +28 -0
- package/dist/task-graph/Conversions.d.ts.map +1 -0
- package/dist/task-graph/Dataflow.d.ts +73 -0
- package/dist/task-graph/Dataflow.d.ts.map +1 -0
- package/dist/task-graph/DataflowEvents.d.ts +34 -0
- package/dist/task-graph/DataflowEvents.d.ts.map +1 -0
- package/dist/task-graph/ITaskGraph.d.ts +38 -0
- package/dist/task-graph/ITaskGraph.d.ts.map +1 -0
- package/dist/task-graph/IWorkflow.d.ts +13 -0
- package/dist/task-graph/IWorkflow.d.ts.map +1 -0
- package/dist/task-graph/TaskGraph.d.ts +230 -0
- package/dist/task-graph/TaskGraph.d.ts.map +1 -0
- package/dist/task-graph/TaskGraphEvents.d.ts +54 -0
- package/dist/task-graph/TaskGraphEvents.d.ts.map +1 -0
- package/dist/task-graph/TaskGraphRunner.d.ts +202 -0
- package/dist/task-graph/TaskGraphRunner.d.ts.map +1 -0
- package/dist/task-graph/TaskGraphScheduler.d.ts +56 -0
- package/dist/task-graph/TaskGraphScheduler.d.ts.map +1 -0
- package/dist/task-graph/Workflow.d.ts +155 -0
- package/dist/task-graph/Workflow.d.ts.map +1 -0
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +59 -0
- package/src/storage/README.md +61 -0
- package/src/task/ConditionalTask.README.md +268 -0
- package/src/task/README.md +251 -0
- package/src/task-graph/README.md +142 -0
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
# Task System Documentation
|
|
2
|
+
|
|
3
|
+
This module provides a flexible task processing system with support for various task types, dependency management, and error handling.
|
|
4
|
+
|
|
5
|
+
- [Key Components](#key-components)
|
|
6
|
+
- [Core Classes](#core-classes)
|
|
7
|
+
- [Task Types](#task-types)
|
|
8
|
+
- [A Simple Task](#a-simple-task)
|
|
9
|
+
- [GraphAsTask](#graphastask)
|
|
10
|
+
- [ArrayTask](#arraytask)
|
|
11
|
+
- [Job Queue Tasks](#job-queue-tasks)
|
|
12
|
+
- [Task Lifecycle](#task-lifecycle)
|
|
13
|
+
- [Event Handling](#event-handling)
|
|
14
|
+
- [Input/Output Schemas](#inputoutput-schemas)
|
|
15
|
+
- [Registry \& Queues](#registry--queues)
|
|
16
|
+
- [Error Handling](#error-handling)
|
|
17
|
+
- [Testing](#testing)
|
|
18
|
+
- [Installation](#installation)
|
|
19
|
+
|
|
20
|
+
## Key Components
|
|
21
|
+
|
|
22
|
+
### Core Classes
|
|
23
|
+
|
|
24
|
+
- `Task`: Base class implementing core task functionality
|
|
25
|
+
- `ArrayTask`: Executes a task or a task with multiple inputs in parallel with a subGraph
|
|
26
|
+
- `JobQueueTask`: Integrates with job queue system for distributed processing
|
|
27
|
+
|
|
28
|
+
## Task Types
|
|
29
|
+
|
|
30
|
+
### A Simple Task
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
interface MyTaskInput {
|
|
34
|
+
input: number;
|
|
35
|
+
}
|
|
36
|
+
interface MyTaskOutput {
|
|
37
|
+
result: number;
|
|
38
|
+
}
|
|
39
|
+
class MyTask extends Task {
|
|
40
|
+
static readonly type = "MyTask"; // Required, unique identifier for the task
|
|
41
|
+
static readonly category = "Utility"; // Optional, used for grouping tasks in UI
|
|
42
|
+
static readonly title = "My Task"; // Optional, used for a UI
|
|
43
|
+
static readonly description = "My Task Description"; // Optional, used for a UI
|
|
44
|
+
declare runInputData: MyTaskInput;
|
|
45
|
+
declare runOutputData: MyTaskOutput;
|
|
46
|
+
static inputSchema = Type.Object({
|
|
47
|
+
input: Type.Number(),
|
|
48
|
+
});
|
|
49
|
+
static outputSchema = Type.Object({
|
|
50
|
+
result: Type.Number(),
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// typically you either override execute or executeReactive, but not both
|
|
54
|
+
async execute(input: MyTaskInput, { signal, updateProgress }: IExecuteContext) {
|
|
55
|
+
await sleep(1000);
|
|
56
|
+
if (signal.aborted) {
|
|
57
|
+
throw new TaskAbortedError("Task aborted");
|
|
58
|
+
}
|
|
59
|
+
await updateProgress(0.5, "Processing...");
|
|
60
|
+
// Do something with the input that takes a long time
|
|
61
|
+
await sleep(1000);
|
|
62
|
+
return { result: input.input * 2 };
|
|
63
|
+
}
|
|
64
|
+
async executeReactive(input: MyTaskInput, output: MyTaskOutput) {
|
|
65
|
+
return { result: input.input * 2 };
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### GraphAsTask
|
|
71
|
+
|
|
72
|
+
- GraphAsTask tasks are tasks that contain other tasks. They are represented as an internal TaskGraph.
|
|
73
|
+
- A ArrayTask is a compound task that can run a task as normal, or if the inputs are an array and the input definition has x-replicate=true defined for that input, then the task will run parallel copies with a subGraph.
|
|
74
|
+
|
|
75
|
+
### ArrayTask
|
|
76
|
+
|
|
77
|
+
- ArrayTask is a task that can run a task as normal, or if the inputs are an arryay and the input definition has x-replicate=true, then the task will run parallel copies with a subGraph.
|
|
78
|
+
- The subGraph is a TaskGraph that is created from the inputs of the task.
|
|
79
|
+
- The results of the subGraph are combined such that the outputs are turned into arrays.
|
|
80
|
+
|
|
81
|
+
### Job Queue Tasks
|
|
82
|
+
|
|
83
|
+
JobQueueTask is a task that can be used to run a task in a job queue. This is useful for when there might be rate limits or other constraints on the task that make it better to run in a job queue than in the main thread.
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
class MyJobTask extends JobQueueTask {
|
|
87
|
+
async createJob() {
|
|
88
|
+
return new Job({
|
|
89
|
+
input: this.runInputData,
|
|
90
|
+
execute: (input) => ({ result: input.value * 3 }),
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Task Lifecycle
|
|
97
|
+
|
|
98
|
+
- **Statuses**: `Pending` → `Processing` → (`Completed`|`Failed`|`Aborted`)
|
|
99
|
+
- **Methods**:
|
|
100
|
+
- `run()`: Full execution with caching, calls the subclass `execute` method
|
|
101
|
+
- `runReactive()`: Lightweight execution for UI updates, calls the subclass `executeReactive` method
|
|
102
|
+
- `abort()`: Cancel running task
|
|
103
|
+
|
|
104
|
+
## Event Handling
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
task.on("start", () => console.log("Task started"));
|
|
108
|
+
task.on("progress", (p) => console.log(`Progress: ${p}%`));
|
|
109
|
+
task.on("complete", () => console.log("Task completed"));
|
|
110
|
+
task.on("error", (err) => console.error("Task failed", err));
|
|
111
|
+
task.on("abort", () => console.log("Task aborted"));
|
|
112
|
+
task.on("regenerate", () => console.log("Task regenerated"));
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Input/Output Schemas
|
|
116
|
+
|
|
117
|
+
The input and output schemas are JSON schemas that are used to validate the input and output of the task. These can be defined using plain JSON Schema objects, TypeBox, or Zod. All schemas must be compatible with `DataPortSchema` from `@workglow/util`.
|
|
118
|
+
|
|
119
|
+
### Using Plain JSON Schema
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
import { DataPortSchema } from "@workglow/util";
|
|
123
|
+
|
|
124
|
+
static inputSchema = () => {
|
|
125
|
+
return {
|
|
126
|
+
type: "object",
|
|
127
|
+
properties: {
|
|
128
|
+
username: {
|
|
129
|
+
type: "string",
|
|
130
|
+
title: "User Name",
|
|
131
|
+
description: "The name of the user",
|
|
132
|
+
default: "guest",
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
additionalProperties: false,
|
|
136
|
+
} as const satisfies DataPortSchema;
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
static outputSchema = () => {
|
|
140
|
+
return {
|
|
141
|
+
type: "object",
|
|
142
|
+
properties: {
|
|
143
|
+
result: {
|
|
144
|
+
type: "number",
|
|
145
|
+
title: "Processing Result",
|
|
146
|
+
description: "The result of the processing",
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
required: ["result"],
|
|
150
|
+
additionalProperties: false,
|
|
151
|
+
} as const satisfies DataPortSchema;
|
|
152
|
+
};
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Using TypeBox
|
|
156
|
+
|
|
157
|
+
TypeBox schemas are JSON Schema compatible and can be used directly:
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
import { Type } from "@sinclair/typebox";
|
|
161
|
+
import { DataPortSchema } from "@workglow/util";
|
|
162
|
+
|
|
163
|
+
static inputSchema = () => {
|
|
164
|
+
return Type.Object({
|
|
165
|
+
username: Type.String({
|
|
166
|
+
title: "User Name",
|
|
167
|
+
description: "The name of the user",
|
|
168
|
+
default: "guest",
|
|
169
|
+
}),
|
|
170
|
+
}) satisfies DataPortSchema;
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
static outputSchema = () => {
|
|
174
|
+
return Type.Object({
|
|
175
|
+
result: Type.Number({
|
|
176
|
+
title: "Processing Result",
|
|
177
|
+
description: "The result of the processing",
|
|
178
|
+
}),
|
|
179
|
+
}) satisfies DataPortSchema;
|
|
180
|
+
};
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Using Zod
|
|
184
|
+
|
|
185
|
+
Zod 4 has built-in JSON Schema support using the `.toJSONSchema()` method:
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
import { z } from "zod";
|
|
189
|
+
import { DataPortSchema } from "@workglow/util";
|
|
190
|
+
|
|
191
|
+
// Define Zod schemas
|
|
192
|
+
const inputSchemaZod = z.object({
|
|
193
|
+
username: z.string().default("guest").describe("The name of the user"),
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
const outputSchemaZod = z.object({
|
|
197
|
+
result: z.number().describe("The result of the processing"),
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
// Infer TypeScript types using Zod's built-in type inference
|
|
201
|
+
type MyInput = z.infer<typeof inputSchemaZod>;
|
|
202
|
+
type MyOutput = z.infer<typeof outputSchemaZod>;
|
|
203
|
+
|
|
204
|
+
static inputSchema = () => {
|
|
205
|
+
return inputSchemaZod.toJSONSchema() as DataPortSchema;
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
static outputSchema = () => {
|
|
209
|
+
return outputSchemaZod.toJSONSchema() as DataPortSchema;
|
|
210
|
+
};
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Registry & Queues
|
|
214
|
+
|
|
215
|
+
The TaskRegistry is used to register tasks to there is a global registry. This is useful for a node based UI to allow tasks to be dragged and dropped onto the canvas.
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
TaskRegistry.registerTask(MyTask);
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
The TaskQueueRegistry is used to get a queue for a given name. This is useful for when you want to run a task in a job queue. A queue can be created for a given task type, and all the tasks of that type will be added to the queue.
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
// Queue management
|
|
225
|
+
const queue = getTaskQueueRegistry().getQueue("processing");
|
|
226
|
+
queue.add(new MyJobTask());
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## Error Handling
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
try {
|
|
233
|
+
await task.run();
|
|
234
|
+
} catch (err) {
|
|
235
|
+
if (err instanceof TaskAbortedError) {
|
|
236
|
+
console.log("Task was aborted");
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## Testing
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
bun test
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## Installation
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
bun add @workglow/task-system
|
|
251
|
+
```
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Task Graph Package
|
|
2
|
+
|
|
3
|
+
A robust TypeScript library for creating and managing task graphs with dependencies, enabling complex workflow orchestration and execution.
|
|
4
|
+
|
|
5
|
+
- [Features](#features)
|
|
6
|
+
- [Installation](#installation)
|
|
7
|
+
- [Basic Usage](#basic-usage)
|
|
8
|
+
- [Creating a Task Graph](#creating-a-task-graph)
|
|
9
|
+
- [Executing Tasks](#executing-tasks)
|
|
10
|
+
- [Workflow API](#workflow-api)
|
|
11
|
+
- [Key Components](#key-components)
|
|
12
|
+
- [TaskGraph](#taskgraph)
|
|
13
|
+
- [Dataflow](#dataflow)
|
|
14
|
+
- [TaskGraphRunner](#taskgraphrunner)
|
|
15
|
+
- [Workflow](#workflow)
|
|
16
|
+
- [Testing](#testing)
|
|
17
|
+
- [API Reference](#api-reference)
|
|
18
|
+
- [`TaskGraph` Class](#taskgraph-class)
|
|
19
|
+
- [`Workflow` Class](#workflow-class)
|
|
20
|
+
- [Testing](#testing-1)
|
|
21
|
+
- [License](#license)
|
|
22
|
+
|
|
23
|
+
## Features
|
|
24
|
+
|
|
25
|
+
- Directed Acyclic Graph (DAG) structure for task dependencies
|
|
26
|
+
- Data flow management between task inputs/outputs
|
|
27
|
+
- Workflow builder API with fluent interface
|
|
28
|
+
- Provenance tracking
|
|
29
|
+
- Caching of task results (same run on same input returns cached result)
|
|
30
|
+
- Error handling and abortion support
|
|
31
|
+
- Serial and parallel execution patterns
|
|
32
|
+
- Reactive execution capabilities to drive UI updates
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# Within the monorepo
|
|
38
|
+
npm install @workglow/task-graph
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Basic Usage
|
|
42
|
+
|
|
43
|
+
### Creating a Task Graph
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
import { TaskGraph, Dataflow } from "@workglow/task-graph";
|
|
47
|
+
|
|
48
|
+
const graph = new TaskGraph();
|
|
49
|
+
const task1 = new TestTask({ input: "hello" }, { id: "task1" });
|
|
50
|
+
const task2 = new TestTask({ input: "world" }, { id: "task2" });
|
|
51
|
+
|
|
52
|
+
graph.addTasks([task1, task2]);
|
|
53
|
+
graph.addDataflow(new Dataflow("task1", "output", "task2", "input"));
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Executing Tasks
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
const results = await graph.run();
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Workflow API
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
const workflow = new Workflow()
|
|
66
|
+
.SimpleTask({ input: "start" })
|
|
67
|
+
.rename("output", "input")
|
|
68
|
+
.SimpleProcessingTask()
|
|
69
|
+
.parallel(
|
|
70
|
+
(w) => w.TestParallelTask1(),
|
|
71
|
+
(w) => w.TestParallelTask2()
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
const output = await workflow.run();
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Key Components
|
|
78
|
+
|
|
79
|
+
### TaskGraph
|
|
80
|
+
|
|
81
|
+
- Manages nodes (tasks) and edges (data flows)
|
|
82
|
+
- Topological sorting
|
|
83
|
+
- Serialization/deserialization
|
|
84
|
+
- Dependency tracking
|
|
85
|
+
|
|
86
|
+
### Dataflow
|
|
87
|
+
|
|
88
|
+
- Connects task outputs to inputs
|
|
89
|
+
- Value propagation
|
|
90
|
+
- Provenance tracking
|
|
91
|
+
|
|
92
|
+
### TaskGraphRunner
|
|
93
|
+
|
|
94
|
+
- Executes tasks with dependency resolution
|
|
95
|
+
- Multiple scheduler implementations
|
|
96
|
+
- Error handling and recovery
|
|
97
|
+
- Abortion support
|
|
98
|
+
|
|
99
|
+
### Workflow
|
|
100
|
+
|
|
101
|
+
- Fluent API for graph construction
|
|
102
|
+
- Automatic input/output matching
|
|
103
|
+
- Parallel task groups
|
|
104
|
+
- Error reporting
|
|
105
|
+
|
|
106
|
+
## Testing
|
|
107
|
+
|
|
108
|
+
Tests use Bun test runner. To run tests:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
bun test
|
|
112
|
+
bun test:watch # For development
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## API Reference
|
|
116
|
+
|
|
117
|
+
### `TaskGraph` Class
|
|
118
|
+
|
|
119
|
+
- `addTask(task: Task)`: Add a task
|
|
120
|
+
- `addDataflow(dataflow: Dataflow)`: Connect tasks
|
|
121
|
+
- `getSourceTasks()`/`getTargetTasks()`: Navigate dependencies
|
|
122
|
+
- `toJSON()`: Serialize graph structure
|
|
123
|
+
|
|
124
|
+
### `Workflow` Class
|
|
125
|
+
|
|
126
|
+
- `createWorkflow()`: Task-specific builder methods
|
|
127
|
+
- `parallel()`: Create parallel execution branches
|
|
128
|
+
- `rename()`: Customize input/output mappings
|
|
129
|
+
- `pop()`: Pop a task from the workflow (only use in a repl!)
|
|
130
|
+
- `run()`: Execute workflow
|
|
131
|
+
|
|
132
|
+
### Testing
|
|
133
|
+
|
|
134
|
+
Tests use Bun test runner. To run tests:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
bun test
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## License
|
|
141
|
+
|
|
142
|
+
Apache 2.0 - See [LICENSE](../../../LICENSE) file for details
|