@hatchet-dev/typescript-sdk 1.3.2 → 1.4.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/clients/dispatcher/heartbeat/heartbeat-worker.js +3 -2
- package/clients/hatchet-client/hatchet-client.d.ts +3 -5
- package/clients/hatchet-client/hatchet-client.js +11 -72
- package/clients/worker/worker.d.ts +6 -9
- package/clients/worker/worker.js +2 -164
- package/examples/fanout-worker.js +1 -2
- package/examples/manual-trigger.js +1 -1
- package/package.json +3 -2
- package/step.d.ts +13 -11
- package/step.js +44 -40
- package/util/grpc-helpers.d.ts +10 -0
- package/util/grpc-helpers.js +79 -0
- package/v1/client/admin.d.ts +64 -0
- package/v1/client/admin.js +155 -0
- package/v1/client/client.d.ts +14 -9
- package/v1/client/client.interface.d.ts +4 -2
- package/v1/client/client.js +28 -16
- package/v1/client/worker/context.d.ts +246 -0
- package/v1/client/worker/context.js +512 -0
- package/v1/client/worker/worker-internal.d.ts +62 -0
- package/v1/client/worker/worker-internal.js +703 -0
- package/v1/client/{worker.d.ts → worker/worker.d.ts} +15 -15
- package/v1/client/{worker.js → worker/worker.js} +14 -11
- package/v1/declaration.d.ts +3 -3
- package/v1/declaration.js +21 -14
- package/v1/examples/cancellations/run.js +4 -4
- package/v1/examples/cancellations/workflow.js +2 -2
- package/v1/examples/high-memory/child-worker.js +29 -0
- package/v1/examples/high-memory/parent-worker.d.ts +1 -0
- package/v1/examples/high-memory/parent-worker.js +29 -0
- package/v1/examples/high-memory/run.d.ts +1 -0
- package/v1/examples/high-memory/run.js +27 -0
- package/v1/examples/high-memory/workflow-with-child.d.ts +12 -0
- package/v1/examples/high-memory/workflow-with-child.js +48 -0
- package/v1/examples/with_timeouts/workflow.js +4 -4
- package/v1/index.d.ts +1 -1
- package/v1/index.js +1 -1
- package/v1/task.d.ts +2 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
- package/examples/api.js +0 -61
- /package/{examples/api.d.ts → v1/examples/high-memory/child-worker.d.ts} +0 -0
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.DurableContext = exports.Context = void 0;
|
|
16
|
+
/* eslint-disable no-underscore-dangle */
|
|
17
|
+
/* eslint-disable max-classes-per-file */
|
|
18
|
+
const declaration_1 = require("../../declaration");
|
|
19
|
+
const hatchet_error_1 = __importDefault(require("../../../util/errors/hatchet-error"));
|
|
20
|
+
const parse_1 = require("../../../util/parse");
|
|
21
|
+
const conditions_1 = require("../../conditions");
|
|
22
|
+
const transformer_1 = require("../../conditions/transformer");
|
|
23
|
+
const condition_1 = require("../../../protoc/v1/shared/condition");
|
|
24
|
+
const step_1 = require("../../../step");
|
|
25
|
+
class Context {
|
|
26
|
+
constructor(action, v1, worker) {
|
|
27
|
+
// @deprecated use ctx.abortController instead
|
|
28
|
+
this.controller = new AbortController();
|
|
29
|
+
this.overridesData = {};
|
|
30
|
+
this.spawnIndex = 0;
|
|
31
|
+
try {
|
|
32
|
+
const data = (0, parse_1.parseJSON)(action.actionPayload);
|
|
33
|
+
this.data = data;
|
|
34
|
+
this.action = action;
|
|
35
|
+
this.v1 = v1;
|
|
36
|
+
this.worker = new step_1.ContextWorker(worker);
|
|
37
|
+
this.logger = v1.config.logger(`Context Logger`, v1.config.log_level);
|
|
38
|
+
// if this is a getGroupKeyRunId, the data is the workflow input
|
|
39
|
+
if (action.getGroupKeyRunId !== '') {
|
|
40
|
+
this.input = data;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
this.input = data.input;
|
|
44
|
+
}
|
|
45
|
+
this.overridesData = data.overrides || {};
|
|
46
|
+
}
|
|
47
|
+
catch (e) {
|
|
48
|
+
throw new hatchet_error_1.default(`Could not parse payload: ${e.message}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
get abortController() {
|
|
52
|
+
return this.controller;
|
|
53
|
+
}
|
|
54
|
+
get cancelled() {
|
|
55
|
+
return this.controller.signal.aborted;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Retrieves the output of a parent task.
|
|
59
|
+
* @param parentTask - The a CreateTaskOpts or string of the parent task name.
|
|
60
|
+
* @returns The output of the specified parent task.
|
|
61
|
+
* @throws An error if the task output is not found.
|
|
62
|
+
*/
|
|
63
|
+
parentOutput(parentTask) {
|
|
64
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
65
|
+
// NOTE: parentOutput is async since we plan on potentially making this a cacheable server call
|
|
66
|
+
if (typeof parentTask !== 'string') {
|
|
67
|
+
return this.parentOutput(parentTask.name);
|
|
68
|
+
}
|
|
69
|
+
if (!this.data.parents) {
|
|
70
|
+
throw new hatchet_error_1.default('Parent task outputs not found');
|
|
71
|
+
}
|
|
72
|
+
if (!this.data.parents[parentTask]) {
|
|
73
|
+
throw new hatchet_error_1.default(`Output for parent task '${parentTask}' not found`);
|
|
74
|
+
}
|
|
75
|
+
return this.data.parents[parentTask];
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Returns errors from any task runs in the workflow.
|
|
80
|
+
* @returns A record mapping task names to error messages.
|
|
81
|
+
* @throws A warning if no errors are found (this method should be used in on-failure tasks).
|
|
82
|
+
* @deprecated use ctx.errors() instead
|
|
83
|
+
*/
|
|
84
|
+
stepRunErrors() {
|
|
85
|
+
return this.errors();
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Returns errors from any task runs in the workflow.
|
|
89
|
+
* @returns A record mapping task names to error messages.
|
|
90
|
+
* @throws A warning if no errors are found (this method should be used in on-failure tasks).
|
|
91
|
+
*/
|
|
92
|
+
errors() {
|
|
93
|
+
const errors = this.data.step_run_errors || {};
|
|
94
|
+
if (Object.keys(errors).length === 0) {
|
|
95
|
+
this.logger.error('No run errors found. `ctx.errors` is intended to be run in an on-failure task, and will only work on engine versions more recent than v0.53.10');
|
|
96
|
+
}
|
|
97
|
+
return errors;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Gets the dag conditional triggers for the current workflow run.
|
|
101
|
+
* @returns The triggers for the current workflow.
|
|
102
|
+
*/
|
|
103
|
+
triggers() {
|
|
104
|
+
return this.data.triggers;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Determines if the workflow was triggered by an event.
|
|
108
|
+
* @returns True if the workflow was triggered by an event, otherwise false.
|
|
109
|
+
*/
|
|
110
|
+
triggeredByEvent() {
|
|
111
|
+
var _a;
|
|
112
|
+
return ((_a = this.data) === null || _a === void 0 ? void 0 : _a.triggered_by) === 'event';
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Gets the name of the current workflow.
|
|
116
|
+
* @returns The name of the workflow.
|
|
117
|
+
*/
|
|
118
|
+
workflowName() {
|
|
119
|
+
return this.action.jobName;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Gets the user data associated with the workflow.
|
|
123
|
+
* @returns The user data.
|
|
124
|
+
*/
|
|
125
|
+
userData() {
|
|
126
|
+
var _a;
|
|
127
|
+
return (_a = this.data) === null || _a === void 0 ? void 0 : _a.user_data;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Gets the name of the current running task.
|
|
131
|
+
* @returns The name of the task.
|
|
132
|
+
*/
|
|
133
|
+
taskName() {
|
|
134
|
+
return this.action.stepName;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Gets the ID of the current workflow run.
|
|
138
|
+
* @returns The workflow run ID.
|
|
139
|
+
*/
|
|
140
|
+
workflowRunId() {
|
|
141
|
+
return this.action.workflowRunId;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Gets the ID of the current task run.
|
|
145
|
+
* @returns The task run ID.
|
|
146
|
+
*/
|
|
147
|
+
taskRunId() {
|
|
148
|
+
return this.action.stepRunId;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Gets the number of times the current task has been retried.
|
|
152
|
+
* @returns The retry count.
|
|
153
|
+
*/
|
|
154
|
+
retryCount() {
|
|
155
|
+
return this.action.retryCount;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Logs a message from the current task.
|
|
159
|
+
* @param message - The message to log.
|
|
160
|
+
* @param level - The log level (optional).
|
|
161
|
+
*/
|
|
162
|
+
log(message, level) {
|
|
163
|
+
const { stepRunId } = this.action;
|
|
164
|
+
if (!stepRunId) {
|
|
165
|
+
// log a warning
|
|
166
|
+
this.logger.warn('cannot log from context without stepRunId');
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
// FIXME: this is a hack to get around the fact that the log level is not typed
|
|
170
|
+
this.v1.event.putLog(stepRunId, message, level);
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Refreshes the timeout for the current task.
|
|
174
|
+
* @param incrementBy - The interval by which to increment the timeout.
|
|
175
|
+
* The interval should be specified in the format of '10s' for 10 seconds, '1m' for 1 minute, or '1d' for 1 day.
|
|
176
|
+
*/
|
|
177
|
+
refreshTimeout(incrementBy) {
|
|
178
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
179
|
+
const { stepRunId } = this.action;
|
|
180
|
+
if (!stepRunId) {
|
|
181
|
+
// log a warning
|
|
182
|
+
this.logger.warn('cannot refresh timeout from context without stepRunId');
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
yield this.v1._v0.dispatcher.refreshTimeout(incrementBy, stepRunId);
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Releases a worker slot for a task run such that the worker can pick up another task.
|
|
190
|
+
* Note: this is an advanced feature that may lead to unexpected behavior if used incorrectly.
|
|
191
|
+
* @returns A promise that resolves when the slot has been released.
|
|
192
|
+
*/
|
|
193
|
+
releaseSlot() {
|
|
194
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
195
|
+
yield this.v1._v0.dispatcher.client.releaseSlot({
|
|
196
|
+
stepRunId: this.action.stepRunId,
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Streams data from the current task run.
|
|
202
|
+
* @param data - The data to stream (string or binary).
|
|
203
|
+
* @returns A promise that resolves when the data has been streamed.
|
|
204
|
+
*/
|
|
205
|
+
putStream(data) {
|
|
206
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
207
|
+
const { stepRunId } = this.action;
|
|
208
|
+
if (!stepRunId) {
|
|
209
|
+
// log a warning
|
|
210
|
+
this.logger.warn('cannot log from context without stepRunId');
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
yield this.v1._v0.event.putStream(stepRunId, data);
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
spawnOptions(workflow, options) {
|
|
217
|
+
let workflowName;
|
|
218
|
+
if (typeof workflow === 'string') {
|
|
219
|
+
workflowName = workflow;
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
workflowName = workflow.id;
|
|
223
|
+
}
|
|
224
|
+
const opts = options || {};
|
|
225
|
+
const { sticky } = opts;
|
|
226
|
+
if (sticky && !this.worker.hasWorkflow(workflowName)) {
|
|
227
|
+
throw new hatchet_error_1.default(`Cannot run with sticky: workflow ${workflowName} is not registered on the worker`);
|
|
228
|
+
}
|
|
229
|
+
const { workflowRunId, stepRunId } = this.action;
|
|
230
|
+
const finalOpts = Object.assign(Object.assign({}, options), { parentId: workflowRunId, parentStepRunId: stepRunId, childIndex: this.spawnIndex, desiredWorkerId: sticky ? this.worker.id() : undefined });
|
|
231
|
+
this.spawnIndex += 1;
|
|
232
|
+
return { workflowName, opts: finalOpts };
|
|
233
|
+
}
|
|
234
|
+
spawn(workflow, input, options) {
|
|
235
|
+
const { workflowName, opts } = this.spawnOptions(workflow, options);
|
|
236
|
+
return this.v1.admin.runWorkflow(workflowName, input, opts);
|
|
237
|
+
}
|
|
238
|
+
spawnBulk(children) {
|
|
239
|
+
const workflows = children.map((child) => {
|
|
240
|
+
const { workflowName, opts } = this.spawnOptions(child.workflow, child.options);
|
|
241
|
+
return { workflowName, input: child.input, options: opts };
|
|
242
|
+
});
|
|
243
|
+
return this.v1.admin.runWorkflows(workflows);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Runs multiple children workflows in parallel without waiting for their results.
|
|
247
|
+
* @param children - An array of objects containing the workflow name, input data, and options for each workflow.
|
|
248
|
+
* @returns A list of workflow run references to the enqueued runs.
|
|
249
|
+
*/
|
|
250
|
+
bulkRunNoWaitChildren(children) {
|
|
251
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
252
|
+
return this.spawnBulk(children);
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Runs multiple children workflows in parallel and waits for all results.
|
|
257
|
+
* @param children - An array of objects containing the workflow name, input data, and options for each workflow.
|
|
258
|
+
* @returns A list of results from the children workflows.
|
|
259
|
+
*/
|
|
260
|
+
bulkRunChildren(children) {
|
|
261
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
262
|
+
const runs = yield this.bulkRunNoWaitChildren(children);
|
|
263
|
+
return Promise.all(runs.map((run) => run.output));
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Runs a new workflow and waits for its result.
|
|
268
|
+
*
|
|
269
|
+
* @param workflow - The workflow to run (name, Workflow instance, or WorkflowV1 instance).
|
|
270
|
+
* @param input - The input data for the workflow.
|
|
271
|
+
* @param options - An options object containing key, sticky, priority, and additionalMetadata.
|
|
272
|
+
* @returns The result of the workflow.
|
|
273
|
+
*/
|
|
274
|
+
runChild(workflow, input, options) {
|
|
275
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
276
|
+
const run = yield this.spawn(workflow, input, options);
|
|
277
|
+
return run.output;
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Enqueues a new workflow without waiting for its result.
|
|
282
|
+
*
|
|
283
|
+
* @param workflow - The workflow to enqueue (name, Workflow instance, or WorkflowV1 instance).
|
|
284
|
+
* @param input - The input data for the workflow.
|
|
285
|
+
* @param options - An options object containing key, sticky, priority, and additionalMetadata.
|
|
286
|
+
* @returns A reference to the spawned workflow run.
|
|
287
|
+
*/
|
|
288
|
+
runNoWaitChild(workflow, input, options) {
|
|
289
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
290
|
+
return this.spawn(workflow, input, options);
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Retrieves additional metadata associated with the current workflow run.
|
|
295
|
+
* @returns A record of metadata key-value pairs.
|
|
296
|
+
*/
|
|
297
|
+
additionalMetadata() {
|
|
298
|
+
if (!this.action.additionalMetadata) {
|
|
299
|
+
return {};
|
|
300
|
+
}
|
|
301
|
+
// parse the additional metadata
|
|
302
|
+
const res = (0, parse_1.parseJSON)(this.action.additionalMetadata);
|
|
303
|
+
return res;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Gets the index of this workflow if it was spawned as part of a bulk operation.
|
|
307
|
+
* @returns The child index number, or undefined if not set.
|
|
308
|
+
*/
|
|
309
|
+
childIndex() {
|
|
310
|
+
return this.action.childWorkflowIndex;
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Gets the key associated with this workflow if it was spawned as a child workflow.
|
|
314
|
+
* @returns The child key, or undefined if not set.
|
|
315
|
+
*/
|
|
316
|
+
childKey() {
|
|
317
|
+
return this.action.childWorkflowKey;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Gets the ID of the parent workflow run if this workflow was spawned as a child.
|
|
321
|
+
* @returns The parent workflow run ID, or undefined if not a child workflow.
|
|
322
|
+
*/
|
|
323
|
+
parentWorkflowRunId() {
|
|
324
|
+
return this.action.parentWorkflowRunId;
|
|
325
|
+
}
|
|
326
|
+
priority() {
|
|
327
|
+
switch (this.action.priority) {
|
|
328
|
+
case 1:
|
|
329
|
+
return declaration_1.Priority.LOW;
|
|
330
|
+
case 2:
|
|
331
|
+
return declaration_1.Priority.MEDIUM;
|
|
332
|
+
case 3:
|
|
333
|
+
return declaration_1.Priority.HIGH;
|
|
334
|
+
default:
|
|
335
|
+
return undefined;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
// FIXME: drop these at some point soon
|
|
339
|
+
/**
|
|
340
|
+
* Get the output of a task.
|
|
341
|
+
* @param task - The name of the task to get the output for.
|
|
342
|
+
* @returns The output of the task.
|
|
343
|
+
* @throws An error if the task output is not found.
|
|
344
|
+
* @deprecated use ctx.parentOutput instead
|
|
345
|
+
*/
|
|
346
|
+
stepOutput(step) {
|
|
347
|
+
if (!this.data.parents) {
|
|
348
|
+
throw new hatchet_error_1.default('Parent task outputs not found');
|
|
349
|
+
}
|
|
350
|
+
if (!this.data.parents[step]) {
|
|
351
|
+
throw new hatchet_error_1.default(`Output for parent task '${step}' not found`);
|
|
352
|
+
}
|
|
353
|
+
return this.data.parents[step];
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Gets the input data for the current workflow.
|
|
357
|
+
* @returns The input data for the workflow.
|
|
358
|
+
* @deprecated use task input parameter instead
|
|
359
|
+
*/
|
|
360
|
+
workflowInput() {
|
|
361
|
+
return this.input;
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Gets the name of the current task.
|
|
365
|
+
* @returns The name of the task.
|
|
366
|
+
* @deprecated use ctx.taskName instead
|
|
367
|
+
*/
|
|
368
|
+
stepName() {
|
|
369
|
+
return this.taskName();
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Spawns multiple workflows.
|
|
373
|
+
*
|
|
374
|
+
* @param workflows - An array of objects containing the workflow name, input data, and options for each workflow.
|
|
375
|
+
* @returns A list of references to the spawned workflow runs.
|
|
376
|
+
* @deprecated Use bulkRunNoWaitChildren or bulkRunChildren instead.
|
|
377
|
+
*/
|
|
378
|
+
spawnWorkflows(workflows) {
|
|
379
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
380
|
+
const { workflowRunId, stepRunId } = this.action;
|
|
381
|
+
const workflowRuns = workflows.map(({ workflow, input, options }) => {
|
|
382
|
+
let workflowName;
|
|
383
|
+
if (typeof workflow === 'string') {
|
|
384
|
+
workflowName = workflow;
|
|
385
|
+
}
|
|
386
|
+
else {
|
|
387
|
+
workflowName = workflow.id;
|
|
388
|
+
}
|
|
389
|
+
const name = this.v1.config.namespace + workflowName;
|
|
390
|
+
const opts = options || {};
|
|
391
|
+
const { sticky } = opts;
|
|
392
|
+
if (sticky && !this.worker.hasWorkflow(name)) {
|
|
393
|
+
throw new hatchet_error_1.default(`Cannot run with sticky: workflow ${name} is not registered on the worker`);
|
|
394
|
+
}
|
|
395
|
+
const resp = {
|
|
396
|
+
workflowName: name,
|
|
397
|
+
input,
|
|
398
|
+
options: Object.assign(Object.assign({}, opts), { parentId: workflowRunId, parentStepRunId: stepRunId, childIndex: this.spawnIndex, desiredWorkerId: sticky ? this.worker.id() : undefined }),
|
|
399
|
+
};
|
|
400
|
+
this.spawnIndex += 1;
|
|
401
|
+
return resp;
|
|
402
|
+
});
|
|
403
|
+
try {
|
|
404
|
+
const batchSize = 10;
|
|
405
|
+
let resp = [];
|
|
406
|
+
for (let i = 0; i < workflowRuns.length; i += batchSize) {
|
|
407
|
+
const batch = workflowRuns.slice(i, i + batchSize);
|
|
408
|
+
const batchResp = yield this.v1._v0.admin.runWorkflows(batch);
|
|
409
|
+
resp = resp.concat(batchResp);
|
|
410
|
+
}
|
|
411
|
+
const res = [];
|
|
412
|
+
resp.forEach((ref, index) => {
|
|
413
|
+
const wf = workflows[index].workflow;
|
|
414
|
+
if (wf instanceof declaration_1.TaskWorkflowDeclaration) {
|
|
415
|
+
// eslint-disable-next-line no-param-reassign
|
|
416
|
+
ref._standalone_task_name = wf._standalone_task_name;
|
|
417
|
+
}
|
|
418
|
+
res.push(ref);
|
|
419
|
+
});
|
|
420
|
+
return resp;
|
|
421
|
+
}
|
|
422
|
+
catch (e) {
|
|
423
|
+
throw new hatchet_error_1.default(e.message);
|
|
424
|
+
}
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Spawns a new workflow.
|
|
429
|
+
*
|
|
430
|
+
* @param workflow - The workflow to spawn (name, Workflow instance, or WorkflowV1 instance).
|
|
431
|
+
* @param input - The input data for the workflow.
|
|
432
|
+
* @param options - Additional options for spawning the workflow.
|
|
433
|
+
* @returns A reference to the spawned workflow run.
|
|
434
|
+
* @deprecated Use runChild or runNoWaitChild instead.
|
|
435
|
+
*/
|
|
436
|
+
spawnWorkflow(workflow, input, options) {
|
|
437
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
438
|
+
const { workflowRunId, stepRunId } = this.action;
|
|
439
|
+
let workflowName = '';
|
|
440
|
+
if (typeof workflow === 'string') {
|
|
441
|
+
workflowName = workflow;
|
|
442
|
+
}
|
|
443
|
+
else {
|
|
444
|
+
workflowName = workflow.id;
|
|
445
|
+
}
|
|
446
|
+
const name = this.v1.config.namespace + workflowName;
|
|
447
|
+
const opts = options || {};
|
|
448
|
+
const { sticky } = opts;
|
|
449
|
+
if (sticky && !this.worker.hasWorkflow(name)) {
|
|
450
|
+
throw new hatchet_error_1.default(`cannot run with sticky: workflow ${name} is not registered on the worker`);
|
|
451
|
+
}
|
|
452
|
+
try {
|
|
453
|
+
const resp = yield this.v1._v0.admin.runWorkflow(name, input, Object.assign({ parentId: workflowRunId, parentStepRunId: stepRunId, childIndex: this.spawnIndex, desiredWorkerId: sticky ? this.worker.id() : undefined }, opts));
|
|
454
|
+
this.spawnIndex += 1;
|
|
455
|
+
if (workflow instanceof declaration_1.TaskWorkflowDeclaration) {
|
|
456
|
+
resp._standalone_task_name = workflow._standalone_task_name;
|
|
457
|
+
}
|
|
458
|
+
return resp;
|
|
459
|
+
}
|
|
460
|
+
catch (e) {
|
|
461
|
+
throw new hatchet_error_1.default(e.message);
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
exports.Context = Context;
|
|
467
|
+
class DurableContext extends Context {
|
|
468
|
+
constructor() {
|
|
469
|
+
super(...arguments);
|
|
470
|
+
this.waitKey = 0;
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Pauses execution for the specified duration.
|
|
474
|
+
* Duration is "global" meaning it will wait in real time regardless of transient failures like worker restarts.
|
|
475
|
+
* @param duration - The duration to sleep for.
|
|
476
|
+
* @returns A promise that resolves when the sleep duration has elapsed.
|
|
477
|
+
*/
|
|
478
|
+
sleepFor(duration, readableDataKey) {
|
|
479
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
480
|
+
return this.waitFor({ sleepFor: duration, readableDataKey });
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Pauses execution until the specified conditions are met.
|
|
485
|
+
* Conditions are "global" meaning they will wait in real time regardless of transient failures like worker restarts.
|
|
486
|
+
* @param conditions - The conditions to wait for.
|
|
487
|
+
* @returns A promise that resolves with the event that satisfied the conditions.
|
|
488
|
+
*/
|
|
489
|
+
waitFor(conditions) {
|
|
490
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
491
|
+
const pbConditions = (0, transformer_1.conditionsToPb)((0, conditions_1.Render)(condition_1.Action.CREATE, conditions));
|
|
492
|
+
// eslint-disable-next-line no-plusplus
|
|
493
|
+
const key = `waitFor-${this.waitKey++}`;
|
|
494
|
+
yield this.v1._v0.durableListener.registerDurableEvent({
|
|
495
|
+
taskId: this.action.stepRunId,
|
|
496
|
+
signalKey: key,
|
|
497
|
+
sleepConditions: pbConditions.sleepConditions,
|
|
498
|
+
userEventConditions: pbConditions.userEventConditions,
|
|
499
|
+
});
|
|
500
|
+
const listener = this.v1._v0.durableListener.subscribe({
|
|
501
|
+
taskId: this.action.stepRunId,
|
|
502
|
+
signalKey: key,
|
|
503
|
+
});
|
|
504
|
+
const event = yield listener.get();
|
|
505
|
+
// Convert event.data from Uint8Array to string if needed
|
|
506
|
+
const eventData = event.data instanceof Uint8Array ? new TextDecoder().decode(event.data) : event.data;
|
|
507
|
+
const res = JSON.parse(eventData);
|
|
508
|
+
return res.CREATE;
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
exports.DurableContext = DurableContext;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Action, ActionListener } from '../../../clients/dispatcher/action-listener';
|
|
2
|
+
import { StepActionEvent, StepActionEventType, GroupKeyActionEvent, GroupKeyActionEventType } from '../../../protoc/dispatcher';
|
|
3
|
+
import HatchetPromise from '../../../util/hatchet-promise/hatchet-promise';
|
|
4
|
+
import { Workflow } from '../../../workflow';
|
|
5
|
+
import { Logger } from '../../../util/logger';
|
|
6
|
+
import { WebhookWorkerCreateRequest } from '../../../clients/rest/generated/data-contracts';
|
|
7
|
+
import { BaseWorkflowDeclaration, WorkflowDefinition } from '../../declaration';
|
|
8
|
+
import { HatchetClient } from '../..';
|
|
9
|
+
import { WorkerLabels } from '../../../clients/dispatcher/dispatcher-client';
|
|
10
|
+
import { StepRunFunction } from '../../../step';
|
|
11
|
+
import { Context } from './context';
|
|
12
|
+
export type ActionRegistry = Record<Action['actionId'], Function>;
|
|
13
|
+
export interface WorkerOpts {
|
|
14
|
+
name: string;
|
|
15
|
+
handleKill?: boolean;
|
|
16
|
+
maxRuns?: number;
|
|
17
|
+
labels?: WorkerLabels;
|
|
18
|
+
}
|
|
19
|
+
export declare class V1Worker {
|
|
20
|
+
client: HatchetClient;
|
|
21
|
+
name: string;
|
|
22
|
+
workerId: string | undefined;
|
|
23
|
+
killing: boolean;
|
|
24
|
+
handle_kill: boolean;
|
|
25
|
+
action_registry: ActionRegistry;
|
|
26
|
+
workflow_registry: Array<WorkflowDefinition | Workflow>;
|
|
27
|
+
listener: ActionListener | undefined;
|
|
28
|
+
futures: Record<Action['stepRunId'], HatchetPromise<any>>;
|
|
29
|
+
contexts: Record<Action['stepRunId'], Context<any, any>>;
|
|
30
|
+
maxRuns?: number;
|
|
31
|
+
logger: Logger;
|
|
32
|
+
registeredWorkflowPromises: Array<Promise<any>>;
|
|
33
|
+
labels: WorkerLabels;
|
|
34
|
+
constructor(client: HatchetClient, options: {
|
|
35
|
+
name: string;
|
|
36
|
+
handleKill?: boolean;
|
|
37
|
+
maxRuns?: number;
|
|
38
|
+
labels?: WorkerLabels;
|
|
39
|
+
});
|
|
40
|
+
private registerActions;
|
|
41
|
+
getHandler(workflows: Workflow[]): void;
|
|
42
|
+
registerWebhook(webhook: WebhookWorkerCreateRequest): Promise<import("axios").AxiosResponse<import("../../../clients/rest/generated/data-contracts").WebhookWorkerCreated, any>>;
|
|
43
|
+
/**
|
|
44
|
+
* @deprecated use registerWorkflow instead
|
|
45
|
+
*/
|
|
46
|
+
register_workflow(initWorkflow: Workflow): Promise<void>;
|
|
47
|
+
registerDurableActionsV1(workflow: WorkflowDefinition): void;
|
|
48
|
+
private registerActionsV1;
|
|
49
|
+
registerWorkflowV1(initWorkflow: BaseWorkflowDeclaration<any, any>): Promise<void>;
|
|
50
|
+
registerWorkflow(initWorkflow: Workflow): Promise<void>;
|
|
51
|
+
registerAction<T, K>(actionId: string, action: StepRunFunction<T, K>): void;
|
|
52
|
+
handleStartStepRun(action: Action): Promise<void>;
|
|
53
|
+
handleStartGroupKeyRun(action: Action): Promise<void>;
|
|
54
|
+
getStepActionEvent(action: Action, eventType: StepActionEventType, shouldNotRetry: boolean, payload?: any, retryCount?: number): StepActionEvent;
|
|
55
|
+
getGroupKeyActionEvent(action: Action, eventType: GroupKeyActionEventType, payload?: any): GroupKeyActionEvent;
|
|
56
|
+
handleCancelStepRun(action: Action): Promise<void>;
|
|
57
|
+
stop(): Promise<void>;
|
|
58
|
+
exitGracefully(handleKill: boolean): Promise<void>;
|
|
59
|
+
start(): Promise<void>;
|
|
60
|
+
handleAction(action: Action): Promise<void>;
|
|
61
|
+
upsertLabels(labels: WorkerLabels): Promise<WorkerLabels>;
|
|
62
|
+
}
|