semola 0.5.4 → 0.6.0
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 +18 -45
- package/dist/chunk-CKQMccvm.cjs +28 -0
- package/dist/lib/api/index.cjs +29 -15
- package/dist/lib/api/index.mjs +30 -16
- package/dist/lib/cache/index.cjs +47 -22
- package/dist/lib/cache/index.d.cts +3 -24
- package/dist/lib/cache/index.d.mts +3 -24
- package/dist/lib/cache/index.mjs +48 -23
- package/dist/lib/cron/index.cjs +117 -117
- package/dist/lib/cron/index.mjs +118 -118
- package/dist/lib/errors/index.d.cts +12 -1
- package/dist/lib/errors/index.d.mts +12 -1
- package/dist/lib/logging/index.cjs +1 -0
- package/dist/lib/orm/index.cjs +1642 -0
- package/dist/lib/orm/index.d.cts +402 -0
- package/dist/lib/orm/index.d.mts +402 -0
- package/dist/lib/orm/index.mjs +1630 -0
- package/dist/lib/prompts/index.cjs +89 -89
- package/dist/lib/prompts/index.d.cts +12 -33
- package/dist/lib/prompts/index.d.mts +12 -33
- package/dist/lib/prompts/index.mjs +89 -90
- package/dist/lib/pubsub/index.cjs +43 -19
- package/dist/lib/pubsub/index.d.cts +3 -18
- package/dist/lib/pubsub/index.d.mts +3 -18
- package/dist/lib/pubsub/index.mjs +44 -20
- package/dist/lib/queue/index.cjs +40 -10
- package/dist/lib/queue/index.d.cts +11 -4
- package/dist/lib/queue/index.d.mts +11 -4
- package/dist/lib/queue/index.mjs +39 -11
- package/dist/lib/workflow/index.cjs +285 -282
- package/dist/lib/workflow/index.d.cts +76 -11
- package/dist/lib/workflow/index.d.mts +76 -11
- package/dist/lib/workflow/index.mjs +278 -284
- package/package.json +11 -1
- package/dist/index-BhGNDjPq.d.mts +0 -13
- package/dist/index-DxSbeGP-.d.cts +0 -13
|
@@ -1,11 +1,73 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_chunk = require("../../chunk-CKQMccvm.cjs");
|
|
2
3
|
const require_lib_errors_index = require("../errors/index.cjs");
|
|
4
|
+
let node_assert = require("node:assert");
|
|
5
|
+
node_assert = require_chunk.__toESM(node_assert);
|
|
6
|
+
//#region src/lib/workflow/errors.ts
|
|
7
|
+
var WorkflowError = class extends Error {
|
|
8
|
+
constructor(message) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = "WorkflowError";
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
var NotFoundError = class extends Error {
|
|
14
|
+
constructor(message) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.name = "NotFoundError";
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
var StateError = class extends Error {
|
|
20
|
+
constructor(message) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.name = "StateError";
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
var SerializationError = class extends Error {
|
|
26
|
+
constructor(message) {
|
|
27
|
+
super(message);
|
|
28
|
+
this.name = "SerializationError";
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
var ExecutionError = class extends Error {
|
|
32
|
+
constructor(message) {
|
|
33
|
+
super(message);
|
|
34
|
+
this.name = "ExecutionError";
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
var LockError = class extends Error {
|
|
38
|
+
constructor(message) {
|
|
39
|
+
super(message);
|
|
40
|
+
this.name = "LockError";
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
var CancelledError = class extends Error {
|
|
44
|
+
constructor(message) {
|
|
45
|
+
super(message);
|
|
46
|
+
this.name = "CancelledError";
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
//#endregion
|
|
3
50
|
//#region src/lib/workflow/index.ts
|
|
4
51
|
const DEFAULT_LOCK_TTL = 300 * 1e3;
|
|
52
|
+
const DEFAULT_RETRIES = 3;
|
|
53
|
+
const DEFAULT_RETRY_BASE_DELAY = 1e3;
|
|
54
|
+
const DEFAULT_RETRY_MULTIPLIER = 2;
|
|
55
|
+
const DEFAULT_RETRY_MAX_DELAY = 3e4;
|
|
5
56
|
const now = () => Date.now();
|
|
6
|
-
const
|
|
7
|
-
if (
|
|
8
|
-
|
|
57
|
+
const delay = async (ms, signal, isCancelled) => {
|
|
58
|
+
if (signal.aborted) throw new CancelledError("Workflow execution was aborted during retry backoff");
|
|
59
|
+
const deadline = now() + ms;
|
|
60
|
+
const pollInterval = 50;
|
|
61
|
+
while (now() < deadline) {
|
|
62
|
+
if (signal.aborted) throw new CancelledError("Workflow execution was aborted during retry backoff");
|
|
63
|
+
if (isCancelled) {
|
|
64
|
+
if (await isCancelled()) throw new CancelledError("Workflow execution was cancelled during retry backoff");
|
|
65
|
+
}
|
|
66
|
+
const remaining = deadline - now();
|
|
67
|
+
await new Promise((resolve) => {
|
|
68
|
+
setTimeout(resolve, Math.min(pollInterval, remaining));
|
|
69
|
+
});
|
|
70
|
+
}
|
|
9
71
|
};
|
|
10
72
|
const envelopeSerialize = (value) => {
|
|
11
73
|
return JSON.stringify({ value });
|
|
@@ -27,69 +89,67 @@ const knownStatuses = [
|
|
|
27
89
|
var WorkflowDefinition = class {
|
|
28
90
|
options;
|
|
29
91
|
lockTTL;
|
|
92
|
+
retries;
|
|
93
|
+
retryBaseDelay;
|
|
94
|
+
retryMultiplier;
|
|
95
|
+
retryMaxDelay;
|
|
30
96
|
constructor(options) {
|
|
31
97
|
this.options = options;
|
|
32
98
|
this.lockTTL = options.lockTTL ?? DEFAULT_LOCK_TTL;
|
|
99
|
+
this.retries = options.retries ?? DEFAULT_RETRIES;
|
|
100
|
+
this.retryBaseDelay = options.retryBackoff?.baseDelay ?? DEFAULT_RETRY_BASE_DELAY;
|
|
101
|
+
this.retryMultiplier = options.retryBackoff?.multiplier ?? DEFAULT_RETRY_MULTIPLIER;
|
|
102
|
+
this.retryMaxDelay = options.retryBackoff?.maxDelay ?? DEFAULT_RETRY_MAX_DELAY;
|
|
103
|
+
node_assert.default.ok(Number.isFinite(this.retries) && this.retries >= 0, "Invalid retries: must be a non-negative finite number");
|
|
104
|
+
node_assert.default.ok(Number.isFinite(this.retryBaseDelay) && this.retryBaseDelay > 0, "Invalid retryBackoff.baseDelay: must be a positive finite number");
|
|
105
|
+
node_assert.default.ok(Number.isFinite(this.retryMultiplier) && this.retryMultiplier > 0, "Invalid retryBackoff.multiplier: must be a positive finite number");
|
|
106
|
+
node_assert.default.ok(Number.isFinite(this.retryMaxDelay) && this.retryMaxDelay > 0, "Invalid retryBackoff.maxDelay: must be a positive finite number");
|
|
107
|
+
}
|
|
108
|
+
runHook(hook) {
|
|
109
|
+
return require_lib_errors_index.mightThrow(Promise.resolve().then(() => hook()));
|
|
110
|
+
}
|
|
111
|
+
computeBackoffDelay(attempt) {
|
|
112
|
+
return Math.min(this.retryBaseDelay * this.retryMultiplier ** (attempt - 1), this.retryMaxDelay);
|
|
33
113
|
}
|
|
34
114
|
async start(input, options) {
|
|
35
115
|
const executionId = options?.executionId ?? crypto.randomUUID();
|
|
36
|
-
|
|
37
|
-
if (createError) return require_lib_errors_index.err(createError.type, createError.message);
|
|
116
|
+
await this.createExecution(executionId, input);
|
|
38
117
|
return this.execute(executionId, input);
|
|
39
118
|
}
|
|
40
119
|
async run(input, options) {
|
|
41
|
-
const
|
|
42
|
-
if (
|
|
43
|
-
|
|
44
|
-
if (startData.status === "cancelled") return require_lib_errors_index.err("WorkflowCancelledError", `Workflow execution ${startData.executionId} was cancelled`);
|
|
45
|
-
if (startData.status !== "completed") return require_lib_errors_index.err("WorkflowExecutionError", `Workflow execution ${startData.executionId} did not complete`);
|
|
46
|
-
const [getError, execution] = await this.get(startData.executionId);
|
|
47
|
-
if (getError) return require_lib_errors_index.err(getError.type, getError.message);
|
|
48
|
-
if (!execution) return require_lib_errors_index.err("WorkflowError", "Unexpected empty execution");
|
|
49
|
-
return require_lib_errors_index.ok(execution.result);
|
|
120
|
+
const startData = await this.start(input, options);
|
|
121
|
+
if (startData.status === "cancelled") throw new CancelledError(`Workflow execution ${startData.executionId} was cancelled`);
|
|
122
|
+
return (await this.get(startData.executionId)).result;
|
|
50
123
|
}
|
|
51
124
|
async resume(executionId) {
|
|
52
|
-
const
|
|
53
|
-
if (
|
|
54
|
-
if (!execution) return require_lib_errors_index.err("WorkflowNotFoundError", `Workflow execution ${executionId} not found`);
|
|
55
|
-
if (execution.status === "completed") return require_lib_errors_index.ok({
|
|
125
|
+
const execution = await this.get(executionId);
|
|
126
|
+
if (execution.status === "completed") return {
|
|
56
127
|
executionId,
|
|
57
128
|
status: execution.status
|
|
58
|
-
}
|
|
59
|
-
if (execution.status === "cancelled") return
|
|
129
|
+
};
|
|
130
|
+
if (execution.status === "cancelled") return {
|
|
60
131
|
executionId,
|
|
61
132
|
status: execution.status
|
|
62
|
-
}
|
|
133
|
+
};
|
|
63
134
|
return this.execute(executionId, execution.input);
|
|
64
135
|
}
|
|
65
136
|
async get(executionId) {
|
|
66
|
-
const
|
|
67
|
-
if (
|
|
68
|
-
if (!status) return require_lib_errors_index.err("WorkflowNotFoundError", `Workflow execution ${executionId} not found`);
|
|
137
|
+
const status = await this.getMeta(executionId, "status");
|
|
138
|
+
if (!status) throw new NotFoundError(`Workflow execution ${executionId} not found`);
|
|
69
139
|
const normalizedStatus = this.normalizeStatus(status);
|
|
70
|
-
if (!normalizedStatus)
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
if (createdAt === null)
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if (updatedAt === null) return require_lib_errors_index.err("WorkflowStateError", `Workflow execution ${executionId} is missing updatedAt`);
|
|
84
|
-
const [metaError, errorMessage] = await this.getMeta(executionId, "error");
|
|
85
|
-
if (metaError) return require_lib_errors_index.err(metaError.type, metaError.message);
|
|
86
|
-
const [completedAtError, completedAt] = await this.readNumberMeta(executionId, "completedAt");
|
|
87
|
-
if (completedAtError) return require_lib_errors_index.err(completedAtError.type, completedAtError.message);
|
|
88
|
-
const [failedAtError, failedAt] = await this.readNumberMeta(executionId, "failedAt");
|
|
89
|
-
if (failedAtError) return require_lib_errors_index.err(failedAtError.type, failedAtError.message);
|
|
90
|
-
const [cancelledAtError, cancelledAt] = await this.readNumberMeta(executionId, "cancelledAt");
|
|
91
|
-
if (cancelledAtError) return require_lib_errors_index.err(cancelledAtError.type, cancelledAtError.message);
|
|
92
|
-
return require_lib_errors_index.ok({
|
|
140
|
+
if (!normalizedStatus) throw new StateError(`Workflow execution ${executionId} has invalid status ${status}`);
|
|
141
|
+
const input = await this.readInput(executionId);
|
|
142
|
+
const result = await this.readResult(executionId);
|
|
143
|
+
const steps = await this.readStepSnapshots(executionId);
|
|
144
|
+
const createdAt = await this.readNumberMeta(executionId, "createdAt");
|
|
145
|
+
const updatedAt = await this.readNumberMeta(executionId, "updatedAt");
|
|
146
|
+
const errorMessage = await this.getMeta(executionId, "error");
|
|
147
|
+
const completedAt = await this.readNumberMeta(executionId, "completedAt");
|
|
148
|
+
const failedAt = await this.readNumberMeta(executionId, "failedAt");
|
|
149
|
+
const cancelledAt = await this.readNumberMeta(executionId, "cancelledAt");
|
|
150
|
+
if (createdAt === null) throw new StateError(`Workflow execution ${executionId} is missing createdAt`);
|
|
151
|
+
if (updatedAt === null) throw new StateError(`Workflow execution ${executionId} is missing updatedAt`);
|
|
152
|
+
return {
|
|
93
153
|
id: executionId,
|
|
94
154
|
name: this.options.name,
|
|
95
155
|
status: normalizedStatus,
|
|
@@ -102,31 +162,24 @@ var WorkflowDefinition = class {
|
|
|
102
162
|
failedAt,
|
|
103
163
|
cancelledAt,
|
|
104
164
|
steps
|
|
105
|
-
}
|
|
165
|
+
};
|
|
106
166
|
}
|
|
107
167
|
async cancel(executionId) {
|
|
108
|
-
const
|
|
109
|
-
if (
|
|
110
|
-
if (!execution) return require_lib_errors_index.err("WorkflowNotFoundError", `Workflow execution ${executionId} not found`);
|
|
111
|
-
if (execution.status === "completed") return require_lib_errors_index.err("WorkflowStateError", `Workflow execution ${executionId} is already completed`);
|
|
168
|
+
const execution = await this.get(executionId);
|
|
169
|
+
if (execution.status === "completed") throw new StateError(`Workflow execution ${executionId} is already completed`);
|
|
112
170
|
const timestamp = now();
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
const [clearErrorError] = await this.setMeta(executionId, "error", "");
|
|
120
|
-
if (clearErrorError) return require_lib_errors_index.err(clearErrorError.type, clearErrorError.message);
|
|
121
|
-
const [clearFailedAtError] = await this.setMeta(executionId, "failedAt", "");
|
|
122
|
-
if (clearFailedAtError) return require_lib_errors_index.err(clearFailedAtError.type, clearFailedAtError.message);
|
|
123
|
-
return require_lib_errors_index.ok({
|
|
171
|
+
await this.setMeta(executionId, "status", "cancelled");
|
|
172
|
+
await this.setMeta(executionId, "updatedAt", String(timestamp));
|
|
173
|
+
await this.setMeta(executionId, "cancelledAt", String(timestamp));
|
|
174
|
+
await this.setMeta(executionId, "error", "");
|
|
175
|
+
await this.setMeta(executionId, "failedAt", "");
|
|
176
|
+
return {
|
|
124
177
|
executionId,
|
|
125
178
|
createdAt: execution.createdAt,
|
|
126
179
|
cancelledAt: timestamp,
|
|
127
180
|
updatedAt: timestamp,
|
|
128
181
|
status: "cancelled"
|
|
129
|
-
}
|
|
182
|
+
};
|
|
130
183
|
}
|
|
131
184
|
executionKey(executionId) {
|
|
132
185
|
return `workflow:${this.options.name}:execution:${executionId}`;
|
|
@@ -141,12 +194,9 @@ var WorkflowDefinition = class {
|
|
|
141
194
|
return `${this.executionKey(executionId)}:lock`;
|
|
142
195
|
}
|
|
143
196
|
async createExecution(executionId, input) {
|
|
144
|
-
const
|
|
145
|
-
if (serializeError) return require_lib_errors_index.err("WorkflowSerializationError", `Unable to serialize workflow input for ${executionId}`);
|
|
197
|
+
const serializedInput = this.serializeInput(input);
|
|
146
198
|
const timestamp = now();
|
|
147
|
-
|
|
148
|
-
if (statusReadError) return require_lib_errors_index.err(statusReadError.type, statusReadError.message);
|
|
149
|
-
if (existingStatus) return require_lib_errors_index.err("WorkflowStateError", `Workflow execution ${executionId} already exists`);
|
|
199
|
+
if (await this.getMeta(executionId, "status")) throw new StateError(`Workflow execution ${executionId} already exists`);
|
|
150
200
|
const metadata = {
|
|
151
201
|
status: "pending",
|
|
152
202
|
input: serializedInput,
|
|
@@ -160,61 +210,44 @@ var WorkflowDefinition = class {
|
|
|
160
210
|
steps: "[]"
|
|
161
211
|
};
|
|
162
212
|
const [writeError] = await require_lib_errors_index.mightThrow(this.options.redis.hset(this.metaKey(executionId), metadata));
|
|
163
|
-
if (writeError)
|
|
164
|
-
return require_lib_errors_index.ok(null);
|
|
213
|
+
if (writeError) throw new WorkflowError(`Unable to persist metadata for execution ${executionId}`);
|
|
165
214
|
}
|
|
166
215
|
async execute(executionId, input) {
|
|
167
216
|
const token = crypto.randomUUID();
|
|
168
|
-
|
|
169
|
-
if (
|
|
170
|
-
const [statusCheckError, currentStatus] = await this.getMeta(executionId, "status");
|
|
171
|
-
if (statusCheckError) {
|
|
217
|
+
await this.acquireLock(executionId, token);
|
|
218
|
+
if (await this.getMeta(executionId, "status") === "cancelled") {
|
|
172
219
|
await this.releaseLock(executionId, token);
|
|
173
|
-
|
|
174
|
-
}
|
|
175
|
-
if (currentStatus === "cancelled") {
|
|
176
|
-
await this.releaseLock(executionId, token);
|
|
177
|
-
return require_lib_errors_index.err("WorkflowStateError", `Workflow execution ${executionId} was cancelled`);
|
|
220
|
+
throw new StateError(`Workflow execution ${executionId} was cancelled`);
|
|
178
221
|
}
|
|
179
222
|
const timestamp = now();
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
await this.releaseLock(executionId, token);
|
|
183
|
-
return require_lib_errors_index.err(runningStatusError.type, runningStatusError.message);
|
|
184
|
-
}
|
|
185
|
-
const [runningUpdatedAtError] = await this.setMeta(executionId, "updatedAt", String(timestamp));
|
|
186
|
-
if (runningUpdatedAtError) {
|
|
187
|
-
await this.releaseLock(executionId, token);
|
|
188
|
-
return require_lib_errors_index.err(runningUpdatedAtError.type, runningUpdatedAtError.message);
|
|
189
|
-
}
|
|
223
|
+
await this.setMeta(executionId, "status", "running");
|
|
224
|
+
await this.setMeta(executionId, "updatedAt", String(timestamp));
|
|
190
225
|
const controller = new AbortController();
|
|
191
226
|
const renewInterval = Math.floor(this.lockTTL / 3);
|
|
192
227
|
let lockLost = false;
|
|
193
228
|
const renewTimer = setInterval(async () => {
|
|
194
|
-
const [renewError] = await this.extendLock(executionId, token);
|
|
229
|
+
const [renewError] = await require_lib_errors_index.mightThrow(this.extendLock(executionId, token));
|
|
195
230
|
if (renewError) {
|
|
196
231
|
lockLost = true;
|
|
197
232
|
controller.abort();
|
|
198
233
|
clearInterval(renewTimer);
|
|
199
234
|
}
|
|
200
235
|
}, renewInterval);
|
|
236
|
+
if (this.options.hooks?.onStart) await this.runHook(() => this.options.hooks?.onStart?.({
|
|
237
|
+
executionId,
|
|
238
|
+
input
|
|
239
|
+
}));
|
|
201
240
|
const step = async (name, handler) => {
|
|
202
|
-
|
|
203
|
-
if (cancelledError) return Promise.reject(new Error(cancelledError.message));
|
|
204
|
-
if (cancelled) {
|
|
241
|
+
await this.throwIfCancelled(executionId, () => {
|
|
205
242
|
controller.abort();
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
const [readError, cachedStep] = await this.readStepOutput(executionId, name);
|
|
209
|
-
if (readError) return Promise.reject(new Error(readError.message));
|
|
243
|
+
});
|
|
244
|
+
const cachedStep = await this.readStepOutput(executionId, name);
|
|
210
245
|
if (cachedStep.found) return cachedStep.value;
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
if (writeError) return Promise.reject(new Error(writeError.message));
|
|
215
|
-
return output;
|
|
246
|
+
return this.runStepWithRetries(executionId, input, name, handler, controller.signal, () => {
|
|
247
|
+
controller.abort();
|
|
248
|
+
});
|
|
216
249
|
};
|
|
217
|
-
const
|
|
250
|
+
const handlerOutcome = await require_lib_errors_index.mightThrow(Promise.resolve(this.options.handler({
|
|
218
251
|
input,
|
|
219
252
|
executionId,
|
|
220
253
|
signal: controller.signal,
|
|
@@ -223,188 +256,166 @@ var WorkflowDefinition = class {
|
|
|
223
256
|
clearInterval(renewTimer);
|
|
224
257
|
if (lockLost) {
|
|
225
258
|
await this.releaseLock(executionId, token);
|
|
226
|
-
|
|
227
|
-
}
|
|
228
|
-
const [cancelledError, cancelled] = await this.isCancelled(executionId);
|
|
229
|
-
if (cancelledError) {
|
|
230
|
-
await this.releaseLock(executionId, token);
|
|
231
|
-
return require_lib_errors_index.err(cancelledError.type, cancelledError.message);
|
|
259
|
+
throw new LockError(`Lock expired during execution ${executionId}`);
|
|
232
260
|
}
|
|
233
|
-
if (
|
|
261
|
+
if (await this.isCancelled(executionId)) {
|
|
234
262
|
const cancelledAt = now();
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
await this.releaseLock(executionId, token);
|
|
243
|
-
return require_lib_errors_index.err(cancelledUpdatedAtError.type, cancelledUpdatedAtError.message);
|
|
244
|
-
}
|
|
245
|
-
const [cancelledAtError] = await this.setMeta(executionId, "cancelledAt", String(cancelledAt));
|
|
246
|
-
if (cancelledAtError) {
|
|
247
|
-
await this.releaseLock(executionId, token);
|
|
248
|
-
return require_lib_errors_index.err(cancelledAtError.type, cancelledAtError.message);
|
|
249
|
-
}
|
|
263
|
+
await this.setMeta(executionId, "status", "cancelled");
|
|
264
|
+
await this.setMeta(executionId, "updatedAt", String(cancelledAt));
|
|
265
|
+
await this.setMeta(executionId, "cancelledAt", String(cancelledAt));
|
|
266
|
+
if (this.options.hooks?.onCancel) await this.runHook(() => this.options.hooks?.onCancel?.({
|
|
267
|
+
executionId,
|
|
268
|
+
input
|
|
269
|
+
}));
|
|
250
270
|
await this.releaseLock(executionId, token);
|
|
251
|
-
return
|
|
271
|
+
return {
|
|
252
272
|
executionId,
|
|
253
273
|
status: "cancelled"
|
|
254
|
-
}
|
|
274
|
+
};
|
|
255
275
|
}
|
|
276
|
+
const [handlerError, result] = handlerOutcome;
|
|
256
277
|
if (handlerError) {
|
|
257
278
|
const failedAt = now();
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
}
|
|
263
|
-
const [failedMessageError] = await this.setMeta(executionId, "error", toErrorMessage(handlerError));
|
|
264
|
-
if (failedMessageError) {
|
|
265
|
-
await this.releaseLock(executionId, token);
|
|
266
|
-
return require_lib_errors_index.err(failedMessageError.type, failedMessageError.message);
|
|
267
|
-
}
|
|
268
|
-
const [failedUpdatedAtError] = await this.setMeta(executionId, "updatedAt", String(failedAt));
|
|
269
|
-
if (failedUpdatedAtError) {
|
|
270
|
-
await this.releaseLock(executionId, token);
|
|
271
|
-
return require_lib_errors_index.err(failedUpdatedAtError.type, failedUpdatedAtError.message);
|
|
272
|
-
}
|
|
273
|
-
const [failedAtError] = await this.setMeta(executionId, "failedAt", String(failedAt));
|
|
274
|
-
if (failedAtError) {
|
|
275
|
-
await this.releaseLock(executionId, token);
|
|
276
|
-
return require_lib_errors_index.err(failedAtError.type, failedAtError.message);
|
|
277
|
-
}
|
|
279
|
+
await this.setMeta(executionId, "status", "failed");
|
|
280
|
+
await this.setMeta(executionId, "error", handlerError.message);
|
|
281
|
+
await this.setMeta(executionId, "updatedAt", String(failedAt));
|
|
282
|
+
await this.setMeta(executionId, "failedAt", String(failedAt));
|
|
278
283
|
await this.releaseLock(executionId, token);
|
|
279
|
-
|
|
284
|
+
throw new ExecutionError(`Workflow execution ${executionId} failed: ${handlerError.message}`);
|
|
280
285
|
}
|
|
281
|
-
const [serializeResultError, serializedResult] = this.serializeResult(result);
|
|
286
|
+
const [serializeResultError, serializedResult] = require_lib_errors_index.mightThrowSync(() => this.serializeResult(result));
|
|
282
287
|
if (serializeResultError) {
|
|
283
288
|
const failedAt = now();
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
}
|
|
289
|
-
const [failedMessageError] = await this.setMeta(executionId, "error", serializeResultError.message);
|
|
290
|
-
if (failedMessageError) {
|
|
291
|
-
await this.releaseLock(executionId, token);
|
|
292
|
-
return require_lib_errors_index.err(failedMessageError.type, failedMessageError.message);
|
|
293
|
-
}
|
|
294
|
-
const [failedUpdatedAtError] = await this.setMeta(executionId, "updatedAt", String(failedAt));
|
|
295
|
-
if (failedUpdatedAtError) {
|
|
296
|
-
await this.releaseLock(executionId, token);
|
|
297
|
-
return require_lib_errors_index.err(failedUpdatedAtError.type, failedUpdatedAtError.message);
|
|
298
|
-
}
|
|
299
|
-
const [failedAtError] = await this.setMeta(executionId, "failedAt", String(failedAt));
|
|
300
|
-
if (failedAtError) {
|
|
301
|
-
await this.releaseLock(executionId, token);
|
|
302
|
-
return require_lib_errors_index.err(failedAtError.type, failedAtError.message);
|
|
303
|
-
}
|
|
289
|
+
await this.setMeta(executionId, "status", "failed");
|
|
290
|
+
await this.setMeta(executionId, "error", serializeResultError.message);
|
|
291
|
+
await this.setMeta(executionId, "updatedAt", String(failedAt));
|
|
292
|
+
await this.setMeta(executionId, "failedAt", String(failedAt));
|
|
304
293
|
await this.releaseLock(executionId, token);
|
|
305
|
-
|
|
294
|
+
throw new SerializationError(`Unable to serialize workflow result for ${executionId}`);
|
|
306
295
|
}
|
|
307
296
|
const completedAt = now();
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
if (
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
if (completedClearErrorError) {
|
|
320
|
-
await this.releaseLock(executionId, token);
|
|
321
|
-
return require_lib_errors_index.err(completedClearErrorError.type, completedClearErrorError.message);
|
|
322
|
-
}
|
|
323
|
-
const [completedClearFailedAtError] = await this.setMeta(executionId, "failedAt", "");
|
|
324
|
-
if (completedClearFailedAtError) {
|
|
325
|
-
await this.releaseLock(executionId, token);
|
|
326
|
-
return require_lib_errors_index.err(completedClearFailedAtError.type, completedClearFailedAtError.message);
|
|
327
|
-
}
|
|
328
|
-
const [completedUpdatedAtError] = await this.setMeta(executionId, "updatedAt", String(completedAt));
|
|
329
|
-
if (completedUpdatedAtError) {
|
|
330
|
-
await this.releaseLock(executionId, token);
|
|
331
|
-
return require_lib_errors_index.err(completedUpdatedAtError.type, completedUpdatedAtError.message);
|
|
332
|
-
}
|
|
333
|
-
const [completedAtError] = await this.setMeta(executionId, "completedAt", String(completedAt));
|
|
334
|
-
if (completedAtError) {
|
|
335
|
-
await this.releaseLock(executionId, token);
|
|
336
|
-
return require_lib_errors_index.err(completedAtError.type, completedAtError.message);
|
|
337
|
-
}
|
|
297
|
+
await this.setMeta(executionId, "result", serializedResult);
|
|
298
|
+
await this.setMeta(executionId, "status", "completed");
|
|
299
|
+
await this.setMeta(executionId, "error", "");
|
|
300
|
+
await this.setMeta(executionId, "failedAt", "");
|
|
301
|
+
await this.setMeta(executionId, "updatedAt", String(completedAt));
|
|
302
|
+
await this.setMeta(executionId, "completedAt", String(completedAt));
|
|
303
|
+
if (this.options.hooks?.onComplete) await this.runHook(() => this.options.hooks?.onComplete?.({
|
|
304
|
+
executionId,
|
|
305
|
+
input,
|
|
306
|
+
result
|
|
307
|
+
}));
|
|
338
308
|
await this.releaseLock(executionId, token);
|
|
339
|
-
return
|
|
309
|
+
return {
|
|
340
310
|
executionId,
|
|
341
311
|
status: "completed"
|
|
342
|
-
}
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
async throwIfCancelled(executionId, abort) {
|
|
315
|
+
if (await this.isCancelled(executionId)) {
|
|
316
|
+
abort();
|
|
317
|
+
throw new CancelledError(`Workflow execution ${executionId} was cancelled`);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
async runStepWithRetries(executionId, input, stepName, handler, signal, abort) {
|
|
321
|
+
let attempt = 1;
|
|
322
|
+
const errorHistory = [];
|
|
323
|
+
while (true) {
|
|
324
|
+
await this.throwIfCancelled(executionId, abort);
|
|
325
|
+
const [stepError, output] = await require_lib_errors_index.mightThrow(Promise.resolve(handler(input, signal)));
|
|
326
|
+
if (!stepError) {
|
|
327
|
+
await this.writeStepOutput(executionId, stepName, output);
|
|
328
|
+
return output;
|
|
329
|
+
}
|
|
330
|
+
const errorMsg = stepError.message;
|
|
331
|
+
errorHistory.push({
|
|
332
|
+
attempt,
|
|
333
|
+
error: errorMsg,
|
|
334
|
+
timestamp: now()
|
|
335
|
+
});
|
|
336
|
+
if (attempt <= this.retries) {
|
|
337
|
+
const nextRetryDelayMs = this.computeBackoffDelay(attempt);
|
|
338
|
+
if (this.options.hooks?.onRetry) await this.runHook(() => this.options.hooks?.onRetry?.({
|
|
339
|
+
executionId,
|
|
340
|
+
input,
|
|
341
|
+
stepName,
|
|
342
|
+
error: errorMsg,
|
|
343
|
+
attempt,
|
|
344
|
+
nextRetryDelayMs,
|
|
345
|
+
retriesRemaining: this.retries - attempt
|
|
346
|
+
}));
|
|
347
|
+
const [delayError] = await require_lib_errors_index.mightThrow(delay(nextRetryDelayMs, signal, () => this.isCancelled(executionId)));
|
|
348
|
+
if (delayError) throw delayError;
|
|
349
|
+
attempt++;
|
|
350
|
+
continue;
|
|
351
|
+
}
|
|
352
|
+
if (this.options.hooks?.onError) await this.runHook(() => this.options.hooks?.onError?.({
|
|
353
|
+
executionId,
|
|
354
|
+
input,
|
|
355
|
+
stepName,
|
|
356
|
+
error: errorMsg,
|
|
357
|
+
totalAttempts: attempt,
|
|
358
|
+
errorHistory
|
|
359
|
+
}));
|
|
360
|
+
throw stepError;
|
|
361
|
+
}
|
|
343
362
|
}
|
|
344
363
|
async acquireLock(executionId, token) {
|
|
345
364
|
const [lockError, lockResult] = await require_lib_errors_index.mightThrow(this.options.redis.set(this.lockKey(executionId), token, "PX", String(this.lockTTL), "NX"));
|
|
346
|
-
if (lockError)
|
|
347
|
-
if (lockResult !== "OK")
|
|
348
|
-
return require_lib_errors_index.ok(null);
|
|
365
|
+
if (lockError) throw new LockError(`Unable to acquire lock for execution ${executionId}`);
|
|
366
|
+
if (lockResult !== "OK") throw new LockError(`Workflow execution ${executionId} is already running`);
|
|
349
367
|
}
|
|
350
368
|
async releaseLock(executionId, token) {
|
|
351
|
-
|
|
369
|
+
await require_lib_errors_index.mightThrow(this.options.redis.send("EVAL", [
|
|
352
370
|
"if redis.call('GET', KEYS[1]) == ARGV[1] then return redis.call('DEL', KEYS[1]) else return 0 end",
|
|
353
371
|
"1",
|
|
354
372
|
this.lockKey(executionId),
|
|
355
373
|
token
|
|
356
374
|
]));
|
|
357
|
-
if (evalError) return require_lib_errors_index.err("WorkflowLockError", `Unable to release lock for execution ${executionId}`);
|
|
358
|
-
return require_lib_errors_index.ok(null);
|
|
359
375
|
}
|
|
360
376
|
async extendLock(executionId, token) {
|
|
361
|
-
const [evalError,
|
|
377
|
+
const [evalError, extendResult] = await require_lib_errors_index.mightThrow(this.options.redis.send("EVAL", [
|
|
362
378
|
"if redis.call('GET', KEYS[1]) == ARGV[1] then return redis.call('PEXPIRE', KEYS[1], ARGV[2]) else return 0 end",
|
|
363
379
|
"1",
|
|
364
380
|
this.lockKey(executionId),
|
|
365
381
|
token,
|
|
366
382
|
String(this.lockTTL)
|
|
367
383
|
]));
|
|
368
|
-
if (evalError)
|
|
369
|
-
if (
|
|
370
|
-
return require_lib_errors_index.ok(null);
|
|
384
|
+
if (evalError) throw new LockError(`Unable to extend lock for execution ${executionId}`);
|
|
385
|
+
if (extendResult === 0) throw new LockError(`Lock ownership lost for execution ${executionId}`);
|
|
371
386
|
}
|
|
372
387
|
async isCancelled(executionId) {
|
|
373
|
-
|
|
374
|
-
if (statusError) return require_lib_errors_index.err(statusError.type, statusError.message);
|
|
375
|
-
return require_lib_errors_index.ok(status === "cancelled");
|
|
388
|
+
return await this.getMeta(executionId, "status") === "cancelled";
|
|
376
389
|
}
|
|
377
390
|
async setMeta(executionId, field, value) {
|
|
378
391
|
const [writeError] = await require_lib_errors_index.mightThrow(this.options.redis.hset(this.metaKey(executionId), field, value));
|
|
379
|
-
if (writeError)
|
|
380
|
-
return require_lib_errors_index.ok(null);
|
|
392
|
+
if (writeError) throw new WorkflowError(`Unable to persist ${field} for execution ${executionId}`);
|
|
381
393
|
}
|
|
382
394
|
async getMeta(executionId, field) {
|
|
383
395
|
const [readError, value] = await require_lib_errors_index.mightThrow(this.options.redis.hget(this.metaKey(executionId), field));
|
|
384
|
-
if (readError)
|
|
385
|
-
if (value === null || value === void 0) return
|
|
386
|
-
if (typeof value !== "string")
|
|
387
|
-
if (value.length === 0) return
|
|
388
|
-
return
|
|
396
|
+
if (readError) throw new WorkflowError(`Unable to read ${field} for execution ${executionId}`);
|
|
397
|
+
if (value === null || value === void 0) return null;
|
|
398
|
+
if (typeof value !== "string") throw new StateError(`Invalid ${field} value for execution ${executionId}`);
|
|
399
|
+
if (value.length === 0) return null;
|
|
400
|
+
return value;
|
|
389
401
|
}
|
|
390
402
|
async readNumberMeta(executionId, field) {
|
|
391
|
-
const
|
|
392
|
-
if (
|
|
393
|
-
if (!value) return require_lib_errors_index.ok(null);
|
|
403
|
+
const value = await this.getMeta(executionId, field);
|
|
404
|
+
if (!value) return null;
|
|
394
405
|
const parsed = Number(value);
|
|
395
|
-
if (!Number.isFinite(parsed))
|
|
396
|
-
return
|
|
406
|
+
if (!Number.isFinite(parsed)) throw new StateError(`Invalid ${field} value for execution ${executionId}`);
|
|
407
|
+
return parsed;
|
|
397
408
|
}
|
|
398
409
|
runSerializer(value, serializer, label) {
|
|
399
410
|
const [serializeError, serialized] = require_lib_errors_index.mightThrowSync(() => serializer(value));
|
|
400
|
-
if (serializeError)
|
|
401
|
-
if (typeof serialized !== "string")
|
|
402
|
-
return
|
|
411
|
+
if (serializeError) throw new SerializationError(`Unable to serialize ${label}: ${serializeError.message}`);
|
|
412
|
+
if (typeof serialized !== "string") throw new SerializationError(`${label} serializer must return a string`);
|
|
413
|
+
return serialized;
|
|
403
414
|
}
|
|
404
415
|
runDeserializer(raw, deserializer, label) {
|
|
405
|
-
const
|
|
406
|
-
if (
|
|
407
|
-
return
|
|
416
|
+
const result = require_lib_errors_index.mightThrowSync(() => deserializer(raw));
|
|
417
|
+
if (result[0]) throw new SerializationError(`Unable to deserialize ${label}: ${result[0].message}`);
|
|
418
|
+
return result[1];
|
|
408
419
|
}
|
|
409
420
|
serializeInput(input) {
|
|
410
421
|
return this.runSerializer(input, this.options.serializeInput ?? envelopeSerialize, "workflow input");
|
|
@@ -414,7 +425,7 @@ var WorkflowDefinition = class {
|
|
|
414
425
|
return this.runDeserializer(raw, deserializer, "workflow input");
|
|
415
426
|
}
|
|
416
427
|
serializeResult(result) {
|
|
417
|
-
if (result === null) return
|
|
428
|
+
if (result === null) return envelopeSerialize(null);
|
|
418
429
|
return this.runSerializer(result, this.options.serializeResult ?? envelopeSerialize, "workflow result");
|
|
419
430
|
}
|
|
420
431
|
deserializeResult(raw) {
|
|
@@ -429,91 +440,76 @@ var WorkflowDefinition = class {
|
|
|
429
440
|
return this.runDeserializer(raw, deserializer, "step output");
|
|
430
441
|
}
|
|
431
442
|
async readInput(executionId) {
|
|
432
|
-
const
|
|
433
|
-
if (
|
|
434
|
-
if (!raw) return require_lib_errors_index.err("WorkflowStateError", `Workflow execution ${executionId} input not found`);
|
|
443
|
+
const raw = await this.getMeta(executionId, "input");
|
|
444
|
+
if (!raw) throw new StateError(`Workflow execution ${executionId} input not found`);
|
|
435
445
|
return this.deserializeInput(raw);
|
|
436
446
|
}
|
|
437
447
|
async readResult(executionId) {
|
|
438
|
-
const
|
|
439
|
-
if (
|
|
440
|
-
|
|
441
|
-
const [deserializeError, result] = this.deserializeResult(raw);
|
|
442
|
-
if (deserializeError) return require_lib_errors_index.err(deserializeError.type, deserializeError.message);
|
|
443
|
-
return require_lib_errors_index.ok(result);
|
|
448
|
+
const raw = await this.getMeta(executionId, "result");
|
|
449
|
+
if (!raw) return null;
|
|
450
|
+
return this.deserializeResult(raw);
|
|
444
451
|
}
|
|
445
452
|
async writeStepOutput(executionId, stepName, output) {
|
|
446
|
-
const [serializeError, serializedOutput] = this.serializeStepOutput(output);
|
|
447
|
-
if (serializeError) return require_lib_errors_index.err("WorkflowSerializationError", `Unable to serialize step ${stepName} output`);
|
|
448
453
|
const payload = {
|
|
449
|
-
output:
|
|
454
|
+
output: this.serializeStepOutput(output),
|
|
450
455
|
completedAt: now()
|
|
451
456
|
};
|
|
452
457
|
const [payloadError, payloadRaw] = require_lib_errors_index.mightThrowSync(() => JSON.stringify(payload));
|
|
453
|
-
if (payloadError || typeof payloadRaw !== "string")
|
|
458
|
+
if (payloadError || typeof payloadRaw !== "string") throw new SerializationError(`Unable to persist step ${stepName} output`);
|
|
454
459
|
const [writeError] = await require_lib_errors_index.mightThrow(this.options.redis.hset(this.stepsKey(executionId), stepName, payloadRaw));
|
|
455
|
-
if (writeError)
|
|
456
|
-
const
|
|
457
|
-
if (stepNamesError) return require_lib_errors_index.err(stepNamesError.type, stepNamesError.message);
|
|
460
|
+
if (writeError) throw new WorkflowError(`Unable to persist step ${stepName} for execution ${executionId}`);
|
|
461
|
+
const stepNames = await this.readStepNames(executionId);
|
|
458
462
|
if (!stepNames.includes(stepName)) {
|
|
459
463
|
const nextStepNames = [...stepNames, stepName];
|
|
460
464
|
const [serializeStepsError, serializedSteps] = require_lib_errors_index.mightThrowSync(() => JSON.stringify(nextStepNames));
|
|
461
|
-
if (serializeStepsError || typeof serializedSteps !== "string")
|
|
462
|
-
|
|
463
|
-
if (updateStepsError) return require_lib_errors_index.err(updateStepsError.type, updateStepsError.message);
|
|
465
|
+
if (serializeStepsError || typeof serializedSteps !== "string") throw new SerializationError(`Unable to persist step history for execution ${executionId}`);
|
|
466
|
+
await this.setMeta(executionId, "steps", serializedSteps);
|
|
464
467
|
}
|
|
465
|
-
|
|
466
|
-
if (updatedError) return require_lib_errors_index.err(updatedError.type, updatedError.message);
|
|
467
|
-
return require_lib_errors_index.ok(null);
|
|
468
|
+
await this.setMeta(executionId, "updatedAt", String(now()));
|
|
468
469
|
}
|
|
469
470
|
async readStepOutput(executionId, stepName) {
|
|
470
471
|
const [readError, payloadRaw] = await require_lib_errors_index.mightThrow(this.options.redis.hget(this.stepsKey(executionId), stepName));
|
|
471
|
-
if (readError)
|
|
472
|
-
if (!payloadRaw) return
|
|
472
|
+
if (readError) throw new WorkflowError(`Unable to read step ${stepName} for execution ${executionId}`);
|
|
473
|
+
if (!payloadRaw) return {
|
|
473
474
|
found: false,
|
|
474
475
|
value: null
|
|
475
|
-
}
|
|
476
|
-
if (typeof payloadRaw !== "string")
|
|
476
|
+
};
|
|
477
|
+
if (typeof payloadRaw !== "string") throw new StateError(`Invalid step payload for ${stepName} in execution ${executionId}`);
|
|
477
478
|
const [parseError, parsed] = require_lib_errors_index.mightThrowSync(() => JSON.parse(payloadRaw));
|
|
478
|
-
if (parseError || parsed === null || typeof parsed !== "object")
|
|
479
|
-
if (typeof parsed.output !== "string")
|
|
479
|
+
if (parseError || parsed === null || typeof parsed !== "object") throw new StateError(`Invalid step payload for ${stepName} in execution ${executionId}`);
|
|
480
|
+
if (typeof parsed.output !== "string") throw new StateError(`Invalid step output for ${stepName} in execution ${executionId}`);
|
|
480
481
|
const outputRaw = parsed.output;
|
|
481
|
-
|
|
482
|
-
if (deserializeError) return require_lib_errors_index.err(deserializeError.type, deserializeError.message);
|
|
483
|
-
return require_lib_errors_index.ok({
|
|
482
|
+
return {
|
|
484
483
|
found: true,
|
|
485
|
-
value
|
|
486
|
-
}
|
|
484
|
+
value: this.deserializeStepOutput(outputRaw)
|
|
485
|
+
};
|
|
487
486
|
}
|
|
488
487
|
async readStepNames(executionId) {
|
|
489
|
-
const
|
|
490
|
-
if (
|
|
491
|
-
if (!stepsRaw) return require_lib_errors_index.ok([]);
|
|
488
|
+
const stepsRaw = await this.getMeta(executionId, "steps");
|
|
489
|
+
if (!stepsRaw) return [];
|
|
492
490
|
const [parseError, values] = require_lib_errors_index.mightThrowSync(() => JSON.parse(stepsRaw));
|
|
493
|
-
if (parseError || !Array.isArray(values))
|
|
491
|
+
if (parseError || !Array.isArray(values)) throw new StateError(`Invalid step index for execution ${executionId}`);
|
|
494
492
|
const stepNames = [];
|
|
495
493
|
for (const value of values) if (typeof value === "string") stepNames.push(value);
|
|
496
|
-
return
|
|
494
|
+
return stepNames;
|
|
497
495
|
}
|
|
498
496
|
async readStepSnapshots(executionId) {
|
|
499
|
-
const
|
|
500
|
-
if (stepNamesError) return [stepNamesError, []];
|
|
497
|
+
const stepNames = await this.readStepNames(executionId);
|
|
501
498
|
const steps = [];
|
|
502
499
|
for (const stepName of stepNames) {
|
|
503
500
|
const [readError, payloadRaw] = await require_lib_errors_index.mightThrow(this.options.redis.hget(this.stepsKey(executionId), stepName));
|
|
504
|
-
if (readError)
|
|
501
|
+
if (readError) throw new WorkflowError(`Unable to read step ${stepName} for execution ${executionId}`);
|
|
505
502
|
if (!payloadRaw) continue;
|
|
506
|
-
if (typeof payloadRaw !== "string")
|
|
503
|
+
if (typeof payloadRaw !== "string") throw new StateError(`Invalid step payload for ${stepName} in execution ${executionId}`);
|
|
507
504
|
const [parseError, parsed] = require_lib_errors_index.mightThrowSync(() => JSON.parse(payloadRaw));
|
|
508
|
-
if (parseError || parsed === null || typeof parsed !== "object")
|
|
509
|
-
if (typeof parsed.completedAt !== "number")
|
|
510
|
-
const completedAt = parsed.completedAt;
|
|
505
|
+
if (parseError || parsed === null || typeof parsed !== "object") throw new StateError(`Invalid step payload for ${stepName} in execution ${executionId}`);
|
|
506
|
+
if (typeof parsed.completedAt !== "number") throw new StateError(`Invalid step payload for ${stepName} in execution ${executionId}`);
|
|
511
507
|
steps.push({
|
|
512
508
|
name: stepName,
|
|
513
|
-
completedAt
|
|
509
|
+
completedAt: parsed.completedAt
|
|
514
510
|
});
|
|
515
511
|
}
|
|
516
|
-
return
|
|
512
|
+
return steps;
|
|
517
513
|
}
|
|
518
514
|
normalizeStatus(value) {
|
|
519
515
|
for (const status of knownStatuses) if (status === value) return status;
|
|
@@ -531,4 +527,11 @@ const defineWorkflow = (options) => {
|
|
|
531
527
|
};
|
|
532
528
|
};
|
|
533
529
|
//#endregion
|
|
530
|
+
exports.CancelledError = CancelledError;
|
|
531
|
+
exports.ExecutionError = ExecutionError;
|
|
532
|
+
exports.LockError = LockError;
|
|
533
|
+
exports.NotFoundError = NotFoundError;
|
|
534
|
+
exports.SerializationError = SerializationError;
|
|
535
|
+
exports.StateError = StateError;
|
|
536
|
+
exports.WorkflowError = WorkflowError;
|
|
534
537
|
exports.defineWorkflow = defineWorkflow;
|