@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
package/step.js
CHANGED
|
@@ -45,7 +45,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
45
45
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
46
46
|
};
|
|
47
47
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
-
exports.
|
|
48
|
+
exports.V0DurableContext = exports.V0Context = exports.ContextWorker = exports.CreateStepSchema = exports.DesiredWorkerLabelSchema = exports.CreateRateLimitSchema = void 0;
|
|
49
49
|
exports.mapRateLimit = mapRateLimit;
|
|
50
50
|
/* eslint-disable no-underscore-dangle */
|
|
51
51
|
/* eslint-disable max-classes-per-file */
|
|
@@ -131,7 +131,7 @@ class ContextWorker {
|
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
exports.ContextWorker = ContextWorker;
|
|
134
|
-
class
|
|
134
|
+
class V0Context {
|
|
135
135
|
constructor(action, client, worker) {
|
|
136
136
|
// @deprecated use ctx.abortController instead
|
|
137
137
|
this.controller = new AbortController();
|
|
@@ -141,7 +141,7 @@ class Context {
|
|
|
141
141
|
const data = (0, parse_1.parseJSON)(action.actionPayload);
|
|
142
142
|
this.data = data;
|
|
143
143
|
this.action = action;
|
|
144
|
-
this.
|
|
144
|
+
this.v0 = client;
|
|
145
145
|
this.worker = new ContextWorker(worker);
|
|
146
146
|
this.logger = client.config.logger(`Context Logger`, client.config.log_level);
|
|
147
147
|
// if this is a getGroupKeyRunId, the data is the workflow input
|
|
@@ -301,7 +301,7 @@ class Context {
|
|
|
301
301
|
this.logger.warn('cannot log from context without stepRunId');
|
|
302
302
|
return;
|
|
303
303
|
}
|
|
304
|
-
this.
|
|
304
|
+
this.v0.event.putLog(stepRunId, message, level);
|
|
305
305
|
}
|
|
306
306
|
/**
|
|
307
307
|
* Refreshes the timeout for the current task.
|
|
@@ -316,7 +316,7 @@ class Context {
|
|
|
316
316
|
this.logger.warn('cannot refresh timeout from context without stepRunId');
|
|
317
317
|
return;
|
|
318
318
|
}
|
|
319
|
-
yield this.
|
|
319
|
+
yield this.v0.dispatcher.refreshTimeout(incrementBy, stepRunId);
|
|
320
320
|
});
|
|
321
321
|
}
|
|
322
322
|
/**
|
|
@@ -326,7 +326,7 @@ class Context {
|
|
|
326
326
|
*/
|
|
327
327
|
releaseSlot() {
|
|
328
328
|
return __awaiter(this, void 0, void 0, function* () {
|
|
329
|
-
yield this.
|
|
329
|
+
yield this.v0.dispatcher.client.releaseSlot({
|
|
330
330
|
stepRunId: this.action.stepRunId,
|
|
331
331
|
});
|
|
332
332
|
});
|
|
@@ -344,7 +344,7 @@ class Context {
|
|
|
344
344
|
this.logger.warn('cannot log from context without stepRunId');
|
|
345
345
|
return;
|
|
346
346
|
}
|
|
347
|
-
yield this.
|
|
347
|
+
yield this.v0.event.putStream(stepRunId, data);
|
|
348
348
|
});
|
|
349
349
|
}
|
|
350
350
|
/**
|
|
@@ -386,7 +386,7 @@ class Context {
|
|
|
386
386
|
else {
|
|
387
387
|
workflowName = workflow.id;
|
|
388
388
|
}
|
|
389
|
-
const name = this.
|
|
389
|
+
const name = this.v0.config.namespace + workflowName;
|
|
390
390
|
const opts = options || {};
|
|
391
391
|
const { sticky } = opts;
|
|
392
392
|
if (sticky && !this.worker.hasWorkflow(name)) {
|
|
@@ -401,11 +401,11 @@ class Context {
|
|
|
401
401
|
return resp;
|
|
402
402
|
});
|
|
403
403
|
try {
|
|
404
|
-
const batchSize =
|
|
404
|
+
const batchSize = 100;
|
|
405
405
|
let resp = [];
|
|
406
406
|
for (let i = 0; i < workflowRuns.length; i += batchSize) {
|
|
407
407
|
const batch = workflowRuns.slice(i, i + batchSize);
|
|
408
|
-
const batchResp = yield this.
|
|
408
|
+
const batchResp = yield this.v0.admin.runWorkflows(batch);
|
|
409
409
|
resp = resp.concat(batchResp);
|
|
410
410
|
}
|
|
411
411
|
const res = [];
|
|
@@ -447,7 +447,9 @@ class Context {
|
|
|
447
447
|
* @returns A reference to the spawned workflow run.
|
|
448
448
|
*/
|
|
449
449
|
runNoWaitChild(workflow, input, options) {
|
|
450
|
-
return this
|
|
450
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
451
|
+
return this.spawnWorkflow(workflow, input, options);
|
|
452
|
+
});
|
|
451
453
|
}
|
|
452
454
|
/**
|
|
453
455
|
* Spawns a new workflow.
|
|
@@ -459,31 +461,33 @@ class Context {
|
|
|
459
461
|
* @deprecated Use runChild or runNoWaitChild instead.
|
|
460
462
|
*/
|
|
461
463
|
spawnWorkflow(workflow, input, options) {
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
else {
|
|
468
|
-
workflowName = workflow.id;
|
|
469
|
-
}
|
|
470
|
-
const name = this.client.config.namespace + workflowName;
|
|
471
|
-
const opts = options || {};
|
|
472
|
-
const { sticky } = opts;
|
|
473
|
-
if (sticky && !this.worker.hasWorkflow(name)) {
|
|
474
|
-
throw new hatchet_error_1.default(`cannot run with sticky: workflow ${name} is not registered on the worker`);
|
|
475
|
-
}
|
|
476
|
-
try {
|
|
477
|
-
const resp = this.client.admin.runWorkflow(name, input, Object.assign({ parentId: workflowRunId, parentStepRunId: stepRunId, childIndex: this.spawnIndex, desiredWorkerId: sticky ? this.worker.id() : undefined }, opts));
|
|
478
|
-
this.spawnIndex += 1;
|
|
479
|
-
if (workflow instanceof declaration_1.TaskWorkflowDeclaration) {
|
|
480
|
-
resp._standalone_task_name = workflow._standalone_task_name;
|
|
464
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
465
|
+
const { workflowRunId, stepRunId } = this.action;
|
|
466
|
+
let workflowName = '';
|
|
467
|
+
if (typeof workflow === 'string') {
|
|
468
|
+
workflowName = workflow;
|
|
481
469
|
}
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
470
|
+
else {
|
|
471
|
+
workflowName = workflow.id;
|
|
472
|
+
}
|
|
473
|
+
const name = this.v0.config.namespace + workflowName;
|
|
474
|
+
const opts = options || {};
|
|
475
|
+
const { sticky } = opts;
|
|
476
|
+
if (sticky && !this.worker.hasWorkflow(name)) {
|
|
477
|
+
throw new hatchet_error_1.default(`cannot run with sticky: workflow ${name} is not registered on the worker`);
|
|
478
|
+
}
|
|
479
|
+
try {
|
|
480
|
+
const resp = yield this.v0.admin.runWorkflow(name, input, Object.assign({ parentId: workflowRunId, parentStepRunId: stepRunId, childIndex: this.spawnIndex, desiredWorkerId: sticky ? this.worker.id() : undefined }, opts));
|
|
481
|
+
this.spawnIndex += 1;
|
|
482
|
+
if (workflow instanceof declaration_1.TaskWorkflowDeclaration) {
|
|
483
|
+
resp._standalone_task_name = workflow._standalone_task_name;
|
|
484
|
+
}
|
|
485
|
+
return resp;
|
|
486
|
+
}
|
|
487
|
+
catch (e) {
|
|
488
|
+
throw new hatchet_error_1.default(e.message);
|
|
489
|
+
}
|
|
490
|
+
});
|
|
487
491
|
}
|
|
488
492
|
/**
|
|
489
493
|
* Retrieves additional metadata associated with the current workflow run.
|
|
@@ -531,8 +535,8 @@ class Context {
|
|
|
531
535
|
}
|
|
532
536
|
}
|
|
533
537
|
}
|
|
534
|
-
exports.
|
|
535
|
-
class
|
|
538
|
+
exports.V0Context = V0Context;
|
|
539
|
+
class V0DurableContext extends V0Context {
|
|
536
540
|
constructor() {
|
|
537
541
|
super(...arguments);
|
|
538
542
|
this.waitKey = 0;
|
|
@@ -559,13 +563,13 @@ class DurableContext extends Context {
|
|
|
559
563
|
const pbConditions = (0, transformer_1.conditionsToPb)((0, conditions_1.Render)(condition_1.Action.CREATE, conditions));
|
|
560
564
|
// eslint-disable-next-line no-plusplus
|
|
561
565
|
const key = `waitFor-${this.waitKey++}`;
|
|
562
|
-
yield this.
|
|
566
|
+
yield this.v0.durableListener.registerDurableEvent({
|
|
563
567
|
taskId: this.action.stepRunId,
|
|
564
568
|
signalKey: key,
|
|
565
569
|
sleepConditions: pbConditions.sleepConditions,
|
|
566
570
|
userEventConditions: pbConditions.userEventConditions,
|
|
567
571
|
});
|
|
568
|
-
const listener = this.
|
|
572
|
+
const listener = this.v0.durableListener.subscribe({
|
|
569
573
|
taskId: this.action.stepRunId,
|
|
570
574
|
signalKey: key,
|
|
571
575
|
});
|
|
@@ -577,7 +581,7 @@ class DurableContext extends Context {
|
|
|
577
581
|
});
|
|
578
582
|
}
|
|
579
583
|
}
|
|
580
|
-
exports.
|
|
584
|
+
exports.V0DurableContext = V0DurableContext;
|
|
581
585
|
function mapRateLimit(limits) {
|
|
582
586
|
if (!limits)
|
|
583
587
|
return [];
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ClientConfig } from '../clients/hatchet-client';
|
|
2
|
+
import { ChannelCredentials, CompatServiceDefinition } from 'nice-grpc';
|
|
3
|
+
import { ClientMiddlewareCall, CallOptions } from 'nice-grpc-common';
|
|
4
|
+
export declare const channelFactory: (config: ClientConfig, credentials: ChannelCredentials) => import("nice-grpc").Channel;
|
|
5
|
+
export declare const addTokenMiddleware: (token: string) => <Request, Response>(call: ClientMiddlewareCall<Request, Response>, options: CallOptions) => AsyncGenerator<Awaited<Response>, Awaited<Response> | undefined, undefined>;
|
|
6
|
+
export declare const createGrpcClient: <T extends CompatServiceDefinition>(config: ClientConfig, serviceDefinition: T) => {
|
|
7
|
+
factory: import("nice-grpc").ClientFactory<{}>;
|
|
8
|
+
channel: import("nice-grpc").Channel;
|
|
9
|
+
client: import("nice-grpc").RawClient<import("nice-grpc").NormalizedServiceDefinition<T>, {}>;
|
|
10
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
3
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
4
|
+
var m = o[Symbol.asyncIterator], i;
|
|
5
|
+
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
|
6
|
+
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
7
|
+
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
8
|
+
};
|
|
9
|
+
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
|
|
10
|
+
var __asyncDelegator = (this && this.__asyncDelegator) || function (o) {
|
|
11
|
+
var i, p;
|
|
12
|
+
return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
|
|
13
|
+
function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }
|
|
14
|
+
};
|
|
15
|
+
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
|
|
16
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
17
|
+
var g = generator.apply(thisArg, _arguments || []), i, q = [];
|
|
18
|
+
return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
|
|
19
|
+
function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
|
|
20
|
+
function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
|
|
21
|
+
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
|
|
22
|
+
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
|
|
23
|
+
function fulfill(value) { resume("next", value); }
|
|
24
|
+
function reject(value) { resume("throw", value); }
|
|
25
|
+
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
|
|
26
|
+
};
|
|
27
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
+
exports.createGrpcClient = exports.addTokenMiddleware = exports.channelFactory = void 0;
|
|
29
|
+
const nice_grpc_1 = require("nice-grpc");
|
|
30
|
+
const nice_grpc_common_1 = require("nice-grpc-common");
|
|
31
|
+
const config_loader_1 = require("./config-loader");
|
|
32
|
+
const channelFactory = (config, credentials) => (0, nice_grpc_1.createChannel)(config.host_port, credentials, {
|
|
33
|
+
'grpc.ssl_target_name_override': config.tls_config.server_name,
|
|
34
|
+
'grpc.keepalive_timeout_ms': 60 * 1000,
|
|
35
|
+
'grpc.client_idle_timeout_ms': 60 * 1000,
|
|
36
|
+
// Send keepalive pings every 10 seconds, default is 2 hours.
|
|
37
|
+
'grpc.keepalive_time_ms': 10 * 1000,
|
|
38
|
+
// Allow keepalive pings when there are no gRPC calls.
|
|
39
|
+
'grpc.keepalive_permit_without_calls': 1,
|
|
40
|
+
});
|
|
41
|
+
exports.channelFactory = channelFactory;
|
|
42
|
+
const addTokenMiddleware = (token) => function _(call, options) {
|
|
43
|
+
return __asyncGenerator(this, arguments, function* _1() {
|
|
44
|
+
var _a, e_1, _b, _c;
|
|
45
|
+
const optionsWithAuth = Object.assign(Object.assign({}, options), { metadata: new nice_grpc_common_1.Metadata({ authorization: `bearer ${token}` }) });
|
|
46
|
+
if (!call.responseStream) {
|
|
47
|
+
const response = yield __await(yield* __asyncDelegator(__asyncValues(call.next(call.request, optionsWithAuth))));
|
|
48
|
+
return yield __await(response);
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
for (var _d = true, _e = __asyncValues(call.next(call.request, optionsWithAuth)), _f; _f = yield __await(_e.next()), _a = _f.done, !_a; _d = true) {
|
|
52
|
+
_c = _f.value;
|
|
53
|
+
_d = false;
|
|
54
|
+
const response = _c;
|
|
55
|
+
yield yield __await(response);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
59
|
+
finally {
|
|
60
|
+
try {
|
|
61
|
+
if (!_d && !_a && (_b = _e.return)) yield __await(_b.call(_e));
|
|
62
|
+
}
|
|
63
|
+
finally { if (e_1) throw e_1.error; }
|
|
64
|
+
}
|
|
65
|
+
return yield __await(undefined);
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
exports.addTokenMiddleware = addTokenMiddleware;
|
|
69
|
+
const createGrpcClient = (config, serviceDefinition) => {
|
|
70
|
+
const credentials = config_loader_1.ConfigLoader.createCredentials(config.tls_config);
|
|
71
|
+
const clientFactory = (0, nice_grpc_1.createClientFactory)().use((0, exports.addTokenMiddleware)(config.token));
|
|
72
|
+
const channel = (0, exports.channelFactory)(config, credentials);
|
|
73
|
+
return {
|
|
74
|
+
factory: clientFactory,
|
|
75
|
+
channel,
|
|
76
|
+
client: clientFactory.create(serviceDefinition, channel),
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
exports.createGrpcClient = createGrpcClient;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { ClientConfig } from '../../clients/hatchet-client/client-config';
|
|
2
|
+
import WorkflowRunRef from '../../util/workflow-run-ref';
|
|
3
|
+
import { Priority, RateLimitDuration, RunsClient } from './..';
|
|
4
|
+
import { RunListenerClient } from '../../clients/listeners/run-listener/child-listener-client';
|
|
5
|
+
import { Api } from '../../clients/rest/generated/Api';
|
|
6
|
+
import { WorkflowServiceClient } from '../../protoc/workflows';
|
|
7
|
+
import { Logger } from '../../util/logger';
|
|
8
|
+
export type WorkflowRun<T = object> = {
|
|
9
|
+
workflowName: string;
|
|
10
|
+
input: T;
|
|
11
|
+
options?: {
|
|
12
|
+
parentId?: string | undefined;
|
|
13
|
+
parentStepRunId?: string | undefined;
|
|
14
|
+
childIndex?: number | undefined;
|
|
15
|
+
childKey?: string | undefined;
|
|
16
|
+
additionalMetadata?: Record<string, string> | undefined;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
export declare class AdminClient {
|
|
20
|
+
config: ClientConfig;
|
|
21
|
+
grpc: WorkflowServiceClient;
|
|
22
|
+
listenerClient: RunListenerClient;
|
|
23
|
+
runs: RunsClient;
|
|
24
|
+
logger: Logger;
|
|
25
|
+
constructor(config: ClientConfig, api: Api, runs: RunsClient);
|
|
26
|
+
/**
|
|
27
|
+
* Run a new instance of a workflow with the given input. This will create a new workflow run and return the ID of the
|
|
28
|
+
* new run.
|
|
29
|
+
* @param workflowName the name of the workflow to run
|
|
30
|
+
* @param input an object containing the input to the workflow
|
|
31
|
+
* @param options an object containing the options to run the workflow
|
|
32
|
+
* @returns the ID of the new workflow run
|
|
33
|
+
*/
|
|
34
|
+
runWorkflow<Q = object, P = object>(workflowName: string, input: Q, options?: {
|
|
35
|
+
parentId?: string | undefined;
|
|
36
|
+
parentStepRunId?: string | undefined;
|
|
37
|
+
childIndex?: number | undefined;
|
|
38
|
+
childKey?: string | undefined;
|
|
39
|
+
additionalMetadata?: Record<string, string> | undefined;
|
|
40
|
+
desiredWorkerId?: string | undefined;
|
|
41
|
+
priority?: Priority;
|
|
42
|
+
}): Promise<WorkflowRunRef<P>>;
|
|
43
|
+
/**
|
|
44
|
+
* Run multiple workflows runs with the given input and options. This will create new workflow runs and return their IDs.
|
|
45
|
+
* Order is preserved in the response.
|
|
46
|
+
* @param workflowRuns an array of objects containing the workflow name, input, and options for each workflow run
|
|
47
|
+
* @returns an array of workflow run references
|
|
48
|
+
*/
|
|
49
|
+
runWorkflows<Q = object, P = object>(workflowRuns: Array<{
|
|
50
|
+
workflowName: string;
|
|
51
|
+
input: Q;
|
|
52
|
+
options?: {
|
|
53
|
+
parentId?: string | undefined;
|
|
54
|
+
parentStepRunId?: string | undefined;
|
|
55
|
+
childIndex?: number | undefined;
|
|
56
|
+
childKey?: string | undefined;
|
|
57
|
+
additionalMetadata?: Record<string, string> | undefined;
|
|
58
|
+
desiredWorkerId?: string | undefined;
|
|
59
|
+
priority?: Priority;
|
|
60
|
+
};
|
|
61
|
+
}>, batchSize?: number): Promise<WorkflowRunRef<P>[]>;
|
|
62
|
+
private batchWorkflows;
|
|
63
|
+
putRateLimit(key: string, limit: number, duration?: RateLimitDuration): Promise<void>;
|
|
64
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
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.AdminClient = void 0;
|
|
16
|
+
const hatchet_error_1 = __importDefault(require("../../util/errors/hatchet-error"));
|
|
17
|
+
const workflow_run_ref_1 = __importDefault(require("../../util/workflow-run-ref"));
|
|
18
|
+
const grpc_helpers_1 = require("../../util/grpc-helpers");
|
|
19
|
+
const child_listener_client_1 = require("../../clients/listeners/run-listener/child-listener-client");
|
|
20
|
+
const workflows_1 = require("../../protoc/workflows");
|
|
21
|
+
class AdminClient {
|
|
22
|
+
constructor(config, api, runs) {
|
|
23
|
+
this.config = config;
|
|
24
|
+
this.logger = config.logger(`Admin`, config.log_level);
|
|
25
|
+
const { client, channel, factory } = (0, grpc_helpers_1.createGrpcClient)(config, workflows_1.WorkflowServiceDefinition);
|
|
26
|
+
this.grpc = client;
|
|
27
|
+
this.listenerClient = new child_listener_client_1.RunListenerClient(config, channel, factory, api);
|
|
28
|
+
this.runs = runs;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Run a new instance of a workflow with the given input. This will create a new workflow run and return the ID of the
|
|
32
|
+
* new run.
|
|
33
|
+
* @param workflowName the name of the workflow to run
|
|
34
|
+
* @param input an object containing the input to the workflow
|
|
35
|
+
* @param options an object containing the options to run the workflow
|
|
36
|
+
* @returns the ID of the new workflow run
|
|
37
|
+
*/
|
|
38
|
+
runWorkflow(workflowName, input, options) {
|
|
39
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
40
|
+
let computedName = workflowName;
|
|
41
|
+
try {
|
|
42
|
+
if (this.config.namespace && !workflowName.startsWith(this.config.namespace)) {
|
|
43
|
+
computedName = this.config.namespace + workflowName;
|
|
44
|
+
}
|
|
45
|
+
const inputStr = JSON.stringify(input);
|
|
46
|
+
const resp = yield this.grpc.triggerWorkflow(Object.assign(Object.assign({ name: computedName, input: inputStr }, options), { additionalMetadata: (options === null || options === void 0 ? void 0 : options.additionalMetadata)
|
|
47
|
+
? JSON.stringify(options === null || options === void 0 ? void 0 : options.additionalMetadata)
|
|
48
|
+
: undefined, priority: options === null || options === void 0 ? void 0 : options.priority }));
|
|
49
|
+
const id = resp.workflowRunId;
|
|
50
|
+
const ref = new workflow_run_ref_1.default(id, this.listenerClient, this.runs, options === null || options === void 0 ? void 0 : options.parentId);
|
|
51
|
+
yield ref.getWorkflowRunId();
|
|
52
|
+
return ref;
|
|
53
|
+
}
|
|
54
|
+
catch (e) {
|
|
55
|
+
throw new hatchet_error_1.default(e.message);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Run multiple workflows runs with the given input and options. This will create new workflow runs and return their IDs.
|
|
61
|
+
* Order is preserved in the response.
|
|
62
|
+
* @param workflowRuns an array of objects containing the workflow name, input, and options for each workflow run
|
|
63
|
+
* @returns an array of workflow run references
|
|
64
|
+
*/
|
|
65
|
+
runWorkflows(workflowRuns_1) {
|
|
66
|
+
return __awaiter(this, arguments, void 0, function* (workflowRuns, batchSize = 500) {
|
|
67
|
+
// Prepare workflows to be triggered in bulk
|
|
68
|
+
const workflowRequests = workflowRuns.map(({ workflowName, input, options }) => {
|
|
69
|
+
let computedName = workflowName;
|
|
70
|
+
if (this.config.namespace && !workflowName.startsWith(this.config.namespace)) {
|
|
71
|
+
computedName = this.config.namespace + workflowName;
|
|
72
|
+
}
|
|
73
|
+
const inputStr = JSON.stringify(input);
|
|
74
|
+
return Object.assign(Object.assign({ name: computedName, input: inputStr }, options), { additionalMetadata: (options === null || options === void 0 ? void 0 : options.additionalMetadata)
|
|
75
|
+
? JSON.stringify(options.additionalMetadata)
|
|
76
|
+
: undefined });
|
|
77
|
+
});
|
|
78
|
+
const batches = this.batchWorkflows(workflowRequests, batchSize);
|
|
79
|
+
this.logger.debug(`batching ${batches.length} batches`);
|
|
80
|
+
try {
|
|
81
|
+
const allResults = [];
|
|
82
|
+
// Process each batch
|
|
83
|
+
for (let batchIndex = 0; batchIndex < batches.length; batchIndex += 1) {
|
|
84
|
+
const batch = batches[batchIndex];
|
|
85
|
+
const { requests, originalIndices } = batch;
|
|
86
|
+
// Call the bulk trigger workflow method for this batch
|
|
87
|
+
const bulkTriggerWorkflowResponse = yield this.grpc.bulkTriggerWorkflow(workflows_1.BulkTriggerWorkflowRequest.create({
|
|
88
|
+
workflows: requests,
|
|
89
|
+
}));
|
|
90
|
+
this.logger.debug(`batch ${batchIndex + 1} of ${batches.length}`);
|
|
91
|
+
// Map the results back to their original indices
|
|
92
|
+
const batchResults = bulkTriggerWorkflowResponse.workflowRunIds.map((resp, index) => {
|
|
93
|
+
const originalIndex = originalIndices[index];
|
|
94
|
+
const { options } = workflowRuns[originalIndex];
|
|
95
|
+
return new workflow_run_ref_1.default(resp, this.listenerClient, this.runs, options === null || options === void 0 ? void 0 : options.parentId);
|
|
96
|
+
});
|
|
97
|
+
allResults.push(...batchResults);
|
|
98
|
+
}
|
|
99
|
+
return allResults;
|
|
100
|
+
}
|
|
101
|
+
catch (e) {
|
|
102
|
+
throw new hatchet_error_1.default(e.message);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
batchWorkflows(workflowRequests, batchSize) {
|
|
107
|
+
const payloadLimit = 4 * 1024 * 1024; // 4MB limit
|
|
108
|
+
const batches = [];
|
|
109
|
+
let currentBatch = [];
|
|
110
|
+
let currentBatchIndices = [];
|
|
111
|
+
let currentBatchSize = 0;
|
|
112
|
+
for (let i = 0; i < workflowRequests.length; i += 1) {
|
|
113
|
+
const request = workflowRequests[i];
|
|
114
|
+
const requestSize = Buffer.byteLength(JSON.stringify(request), 'utf8');
|
|
115
|
+
// Check if adding this request would exceed either the payload limit or batch size
|
|
116
|
+
if (currentBatchSize + requestSize > payloadLimit || currentBatch.length >= batchSize) {
|
|
117
|
+
// If we have a batch, add it to batches
|
|
118
|
+
if (currentBatch.length > 0) {
|
|
119
|
+
batches.push({
|
|
120
|
+
requests: currentBatch,
|
|
121
|
+
originalIndices: currentBatchIndices,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
// Start a new batch
|
|
125
|
+
currentBatch = [request];
|
|
126
|
+
currentBatchIndices = [i];
|
|
127
|
+
currentBatchSize = requestSize;
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
// Add to current batch
|
|
131
|
+
currentBatch.push(request);
|
|
132
|
+
currentBatchIndices.push(i);
|
|
133
|
+
currentBatchSize += requestSize;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// Add the last batch if it exists
|
|
137
|
+
if (currentBatch.length > 0) {
|
|
138
|
+
batches.push({
|
|
139
|
+
requests: currentBatch,
|
|
140
|
+
originalIndices: currentBatchIndices,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
return batches;
|
|
144
|
+
}
|
|
145
|
+
putRateLimit(key, limit, duration) {
|
|
146
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
147
|
+
yield this.grpc.putRateLimit({
|
|
148
|
+
key,
|
|
149
|
+
limit,
|
|
150
|
+
duration,
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
exports.AdminClient = AdminClient;
|
package/v1/client/client.d.ts
CHANGED
|
@@ -1,30 +1,31 @@
|
|
|
1
|
-
import { ClientConfig,
|
|
1
|
+
import { ClientConfig, HatchetClientOptions, LegacyHatchetClient } from '../../clients/hatchet-client';
|
|
2
2
|
import { AxiosRequestConfig } from 'axios';
|
|
3
3
|
import WorkflowRunRef from '../../util/workflow-run-ref';
|
|
4
4
|
import { Workflow as V0Workflow } from '../../workflow';
|
|
5
|
-
import {
|
|
5
|
+
import { V0DurableContext } from '../../step';
|
|
6
6
|
import { Api } from '../../clients/rest';
|
|
7
7
|
import { CreateTaskWorkflowOpts, CreateWorkflowOpts, RunOpts, BaseWorkflowDeclaration, WorkflowDeclaration, TaskWorkflowDeclaration, CreateDurableTaskWorkflowOpts } from '../declaration';
|
|
8
8
|
import { IHatchetClient } from './client.interface';
|
|
9
|
-
import { CreateWorkerOpts, Worker } from './worker';
|
|
9
|
+
import { CreateWorkerOpts, Worker } from './worker/worker';
|
|
10
10
|
import { MetricsClient } from './features/metrics';
|
|
11
11
|
import { WorkersClient } from './features/workers';
|
|
12
12
|
import { WorkflowsClient } from './features/workflows';
|
|
13
13
|
import { RunsClient } from './features/runs';
|
|
14
14
|
import { InputType, OutputType, UnknownInputType, StrictWorkflowOutputType } from '../types';
|
|
15
15
|
import { RatelimitsClient } from './features';
|
|
16
|
+
import { AdminClient } from './admin';
|
|
16
17
|
/**
|
|
17
18
|
* HatchetV1 implements the main client interface for interacting with the Hatchet workflow engine.
|
|
18
19
|
* It provides methods for creating and executing workflows, as well as managing workers.
|
|
19
20
|
*/
|
|
20
21
|
export declare class HatchetClient implements IHatchetClient {
|
|
21
22
|
/** The underlying v0 client instance */
|
|
22
|
-
_v0:
|
|
23
|
+
_v0: LegacyHatchetClient;
|
|
23
24
|
_api: Api;
|
|
24
25
|
/**
|
|
25
26
|
* @deprecated v0 client will be removed in a future release, please upgrade to v1
|
|
26
27
|
*/
|
|
27
|
-
get v0():
|
|
28
|
+
get v0(): LegacyHatchetClient;
|
|
28
29
|
/** The tenant ID for the Hatchet client */
|
|
29
30
|
tenantId: string;
|
|
30
31
|
_isV1: boolean | undefined;
|
|
@@ -44,6 +45,8 @@ export declare class HatchetClient implements IHatchetClient {
|
|
|
44
45
|
* @returns A new Hatchet client instance
|
|
45
46
|
*/
|
|
46
47
|
static init(config?: Partial<ClientConfig>, options?: HatchetClientOptions, axiosConfig?: AxiosRequestConfig): HatchetClient;
|
|
48
|
+
private _config;
|
|
49
|
+
get config(): ClientConfig;
|
|
47
50
|
/**
|
|
48
51
|
* Creates a new workflow definition.
|
|
49
52
|
* @template I - The input type for the workflow
|
|
@@ -86,7 +89,7 @@ export declare class HatchetClient implements IHatchetClient {
|
|
|
86
89
|
* @param options Durable task configuration options with function that defines types
|
|
87
90
|
* @returns A TaskWorkflowDeclaration instance with inferred types
|
|
88
91
|
*/
|
|
89
|
-
durableTask<Fn extends (input: I, ctx:
|
|
92
|
+
durableTask<Fn extends (input: I, ctx: V0DurableContext<I>) => O | Promise<O>, I extends InputType = Parameters<Fn>[0], O extends OutputType = ReturnType<Fn> extends Promise<infer P> ? P extends OutputType ? P : void : ReturnType<Fn> extends OutputType ? ReturnType<Fn> : void>(options: {
|
|
90
93
|
fn: Fn;
|
|
91
94
|
} & Omit<CreateDurableTaskWorkflowOpts<I, O>, 'fn'>): TaskWorkflowDeclaration<I, O>;
|
|
92
95
|
/**
|
|
@@ -98,7 +101,7 @@ export declare class HatchetClient implements IHatchetClient {
|
|
|
98
101
|
* @param options - Configuration options for the workflow run
|
|
99
102
|
* @returns A WorkflowRunRef containing the run ID and methods to interact with the run
|
|
100
103
|
*/
|
|
101
|
-
runNoWait<I extends InputType = UnknownInputType, O extends OutputType = void>(workflow: BaseWorkflowDeclaration<I, O> | string | V0Workflow, input: I, options: RunOpts): WorkflowRunRef<O
|
|
104
|
+
runNoWait<I extends InputType = UnknownInputType, O extends OutputType = void>(workflow: BaseWorkflowDeclaration<I, O> | string | V0Workflow, input: I, options: RunOpts): Promise<WorkflowRunRef<O>>;
|
|
102
105
|
/**
|
|
103
106
|
* @alias run
|
|
104
107
|
* Triggers a workflow run and waits for the result.
|
|
@@ -194,10 +197,12 @@ export declare class HatchetClient implements IHatchetClient {
|
|
|
194
197
|
* @returns A API client instance
|
|
195
198
|
*/
|
|
196
199
|
get api(): Api<unknown>;
|
|
200
|
+
_admin: AdminClient | undefined;
|
|
197
201
|
/**
|
|
198
|
-
*
|
|
202
|
+
* Get the admin client for creating and managing workflows
|
|
203
|
+
* @returns A admin client instance
|
|
199
204
|
*/
|
|
200
|
-
get admin():
|
|
205
|
+
get admin(): AdminClient;
|
|
201
206
|
/**
|
|
202
207
|
* Creates a new worker instance for processing workflow tasks.
|
|
203
208
|
* @param options - Configuration options for creating the worker
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { LegacyHatchetClient } from '../../clients/hatchet-client';
|
|
2
2
|
import { MetricsClient } from './features/metrics';
|
|
3
3
|
import { RunsClient } from './features/runs';
|
|
4
4
|
import { WorkersClient } from './features/workers';
|
|
5
5
|
import { WorkflowsClient } from './features/workflows';
|
|
6
|
+
import { AdminClient } from './admin';
|
|
6
7
|
export interface IHatchetClient {
|
|
7
|
-
_v0:
|
|
8
|
+
_v0: LegacyHatchetClient;
|
|
8
9
|
metrics: MetricsClient;
|
|
9
10
|
runs: RunsClient;
|
|
10
11
|
workflows: WorkflowsClient;
|
|
11
12
|
workers: WorkersClient;
|
|
13
|
+
admin: AdminClient;
|
|
12
14
|
}
|