@hatchet-dev/typescript-sdk 0.10.0 → 0.12.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/clients/admin/admin-client.d.ts +1 -0
- package/clients/dispatcher/dispatcher-client.d.ts +3 -0
- package/clients/dispatcher/dispatcher-client.js +20 -1
- package/clients/hatchet-client/hatchet-client.d.ts +2 -2
- package/clients/hatchet-client/hatchet-client.js +11 -4
- package/clients/listener/listener-client.d.ts +10 -4
- package/clients/listener/listener-client.js +45 -13
- package/clients/worker/worker.d.ts +12 -0
- package/clients/worker/worker.js +54 -2
- package/examples/affinity-workers.d.ts +1 -0
- package/examples/affinity-workers.js +93 -0
- package/examples/api.d.ts +1 -0
- package/examples/api.js +61 -0
- package/examples/concurrency/cancel-in-progress/concurrency-event.d.ts +1 -0
- package/examples/concurrency/cancel-in-progress/concurrency-event.js +37 -0
- package/examples/concurrency/cancel-in-progress/concurrency-worker.d.ts +1 -0
- package/examples/concurrency/cancel-in-progress/concurrency-worker.js +66 -0
- package/examples/concurrency/group-round-robin/concurrency-event.d.ts +1 -0
- package/examples/concurrency/group-round-robin/concurrency-event.js +35 -0
- package/examples/concurrency/group-round-robin/concurrency-worker.d.ts +1 -0
- package/examples/concurrency/group-round-robin/concurrency-worker.js +61 -0
- package/examples/dag-worker.d.ts +1 -0
- package/examples/dag-worker.js +76 -0
- package/examples/example-event-with-results.d.ts +1 -0
- package/examples/example-event-with-results.js +50 -0
- package/examples/example-event.d.ts +1 -0
- package/examples/example-event.js +10 -0
- package/examples/fanout-worker.d.ts +1 -0
- package/examples/fanout-worker.js +69 -0
- package/examples/logger.d.ts +1 -0
- package/examples/logger.js +50 -0
- package/examples/manual-trigger.d.ts +1 -0
- package/examples/manual-trigger.js +46 -0
- package/examples/multi-workflow.d.ts +1 -0
- package/examples/multi-workflow.js +55 -0
- package/examples/namespaced-worker.d.ts +1 -0
- package/examples/namespaced-worker.js +56 -0
- package/examples/on-failure.d.ts +1 -0
- package/examples/on-failure.js +53 -0
- package/examples/playground.d.ts +1 -0
- package/examples/playground.js +39 -0
- package/examples/rate-limit/events.d.ts +1 -0
- package/examples/rate-limit/events.js +16 -0
- package/examples/rate-limit/worker.d.ts +1 -0
- package/examples/rate-limit/worker.js +43 -0
- package/examples/retries-worker.d.ts +1 -0
- package/examples/retries-worker.js +60 -0
- package/examples/simple-worker.d.ts +1 -0
- package/examples/simple-worker.js +55 -0
- package/examples/sticky-worker.d.ts +1 -0
- package/examples/sticky-worker.js +73 -0
- package/examples/stream-by-additional-meta.d.ts +1 -0
- package/examples/stream-by-additional-meta.js +55 -0
- package/package.json +24 -21
- package/protoc/dispatcher/dispatcher.d.ts +109 -2
- package/protoc/dispatcher/dispatcher.js +518 -17
- package/protoc/events/events.d.ts +1 -1
- package/protoc/events/events.js +0 -5
- package/protoc/google/protobuf/timestamp.js +0 -8
- package/protoc/workflows/workflows.d.ts +82 -1
- package/protoc/workflows/workflows.js +404 -9
- package/step.d.ts +79 -2
- package/step.js +90 -3
- package/util/config-loader/config-loader.js +9 -8
- package/util/workflow-run-ref.d.ts +3 -0
- package/util/workflow-run-ref.js +21 -4
- package/workflow.d.ts +116 -1
- package/workflow.js +6 -1
|
@@ -76,6 +76,7 @@ export declare class AdminClient {
|
|
|
76
76
|
childIndex?: number | undefined;
|
|
77
77
|
childKey?: string | undefined;
|
|
78
78
|
additionalMetadata?: Record<string, string> | undefined;
|
|
79
|
+
desiredWorkerId?: string | undefined;
|
|
79
80
|
}): WorkflowRunRef<P>;
|
|
80
81
|
/**
|
|
81
82
|
* @deprecated use listWorkflows instead
|
|
@@ -3,11 +3,13 @@ import { DispatcherClient as PbDispatcherClient, StepActionEvent, GroupKeyAction
|
|
|
3
3
|
import { ClientConfig } from '../hatchet-client/client-config';
|
|
4
4
|
import { Logger } from '../../util/logger';
|
|
5
5
|
import { ActionListener } from './action-listener';
|
|
6
|
+
export type WorkerLabels = Record<string, string | number | undefined>;
|
|
6
7
|
interface GetActionListenerOptions {
|
|
7
8
|
workerName: string;
|
|
8
9
|
services: string[];
|
|
9
10
|
actions: string[];
|
|
10
11
|
maxRuns?: number;
|
|
12
|
+
labels: Record<string, string | number | undefined>;
|
|
11
13
|
}
|
|
12
14
|
export declare class DispatcherClient {
|
|
13
15
|
config: ClientConfig;
|
|
@@ -19,5 +21,6 @@ export declare class DispatcherClient {
|
|
|
19
21
|
sendGroupKeyActionEvent(in_: GroupKeyActionEvent): Promise<import("../../protoc/dispatcher").ActionEventResponse>;
|
|
20
22
|
putOverridesData(in_: DeepPartial<OverridesData>): Promise<void | import("../../protoc/dispatcher").OverridesDataResponse>;
|
|
21
23
|
refreshTimeout(incrementTimeoutBy: string, stepRunId: string): Promise<import("../../protoc/dispatcher").RefreshTimeoutResponse>;
|
|
24
|
+
upsertWorkerLabels(workerId: string, labels: WorkerLabels): Promise<import("../../protoc/dispatcher").UpsertWorkerLabelsResponse>;
|
|
22
25
|
}
|
|
23
26
|
export {};
|
|
@@ -27,7 +27,7 @@ class DispatcherClient {
|
|
|
27
27
|
getActionListener(options) {
|
|
28
28
|
return __awaiter(this, void 0, void 0, function* () {
|
|
29
29
|
// Register the worker
|
|
30
|
-
const registration = yield this.client.register(Object.assign({}, options));
|
|
30
|
+
const registration = yield this.client.register(Object.assign(Object.assign({}, options), { labels: options.labels ? mapLabels(options.labels) : undefined }));
|
|
31
31
|
return new action_listener_1.ActionListener(this, registration.workerId);
|
|
32
32
|
});
|
|
33
33
|
}
|
|
@@ -71,5 +71,24 @@ class DispatcherClient {
|
|
|
71
71
|
}
|
|
72
72
|
});
|
|
73
73
|
}
|
|
74
|
+
upsertWorkerLabels(workerId, labels) {
|
|
75
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
76
|
+
try {
|
|
77
|
+
return yield this.client.upsertWorkerLabels({
|
|
78
|
+
workerId,
|
|
79
|
+
labels: mapLabels(labels),
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
catch (e) {
|
|
83
|
+
throw new hatchet_error_1.default(e.message);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
74
87
|
}
|
|
75
88
|
exports.DispatcherClient = DispatcherClient;
|
|
89
|
+
function mapLabels(in_) {
|
|
90
|
+
return Object.entries(in_).reduce((acc, [key, value]) => (Object.assign(Object.assign({}, acc), { [key]: {
|
|
91
|
+
strValue: typeof value === 'string' ? value : undefined,
|
|
92
|
+
intValue: typeof value === 'number' ? value : undefined,
|
|
93
|
+
} })), {});
|
|
94
|
+
}
|
|
@@ -3,7 +3,7 @@ import { DispatcherClient } from '../dispatcher/dispatcher-client';
|
|
|
3
3
|
import { AdminClient } from '../admin/admin-client';
|
|
4
4
|
import { CallOptions, ChannelCredentials, ClientMiddlewareCall } from 'nice-grpc';
|
|
5
5
|
import { Workflow } from '../../workflow';
|
|
6
|
-
import { Worker } from '../worker';
|
|
6
|
+
import { Worker, WorkerOpts } from '../worker';
|
|
7
7
|
import Logger from '../../util/logger/logger';
|
|
8
8
|
import { AxiosRequestConfig } from 'axios';
|
|
9
9
|
import { ClientConfig } from './client-config';
|
|
@@ -28,6 +28,6 @@ export declare class HatchetClient {
|
|
|
28
28
|
constructor(config?: Partial<ClientConfig>, options?: HatchetClientOptions, axiosOpts?: AxiosRequestConfig);
|
|
29
29
|
static init(config?: Partial<ClientConfig>, options?: HatchetClientOptions, axiosConfig?: AxiosRequestConfig): HatchetClient;
|
|
30
30
|
run(workflow: string | Workflow): Promise<Worker>;
|
|
31
|
-
worker(workflow: string | Workflow,
|
|
31
|
+
worker(workflow: string | Workflow, opts?: Omit<WorkerOpts, 'name'> | number): Promise<Worker>;
|
|
32
32
|
webhooks(workflows: Workflow[]): import("../worker/handler").WebhookHandler;
|
|
33
33
|
}
|
|
@@ -128,13 +128,20 @@ class HatchetClient {
|
|
|
128
128
|
return worker;
|
|
129
129
|
});
|
|
130
130
|
}
|
|
131
|
-
worker(workflow,
|
|
131
|
+
worker(workflow, opts) {
|
|
132
132
|
return __awaiter(this, void 0, void 0, function* () {
|
|
133
133
|
const name = typeof workflow === 'string' ? workflow : workflow.id;
|
|
134
|
-
|
|
134
|
+
let options = {
|
|
135
135
|
name,
|
|
136
|
-
|
|
137
|
-
|
|
136
|
+
};
|
|
137
|
+
if (typeof opts === 'number') {
|
|
138
|
+
this.logger.warn('@deprecated maxRuns param is deprecated and will be removed in a future release in favor of WorkerOpts');
|
|
139
|
+
options = Object.assign(Object.assign({}, options), { maxRuns: opts });
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
options = Object.assign(Object.assign({}, options), opts);
|
|
143
|
+
}
|
|
144
|
+
const worker = new worker_1.Worker(this, options);
|
|
138
145
|
if (typeof workflow !== 'string') {
|
|
139
146
|
yield worker.registerWorkflow(workflow);
|
|
140
147
|
return worker;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Channel, ClientFactory } from 'nice-grpc';
|
|
2
2
|
import { EventEmitter } from 'events';
|
|
3
|
-
import { DispatcherClient as PbDispatcherClient, DispatcherClient } from '../../protoc/dispatcher';
|
|
3
|
+
import { DispatcherClient as PbDispatcherClient, DispatcherClient, WorkflowEvent } from '../../protoc/dispatcher';
|
|
4
4
|
import { ClientConfig } from '../hatchet-client/client-config';
|
|
5
5
|
import { Logger } from '../../util/logger';
|
|
6
6
|
import { Api } from '../rest';
|
|
@@ -27,10 +27,14 @@ export declare class RunEventListener {
|
|
|
27
27
|
q: Array<StepRunEvent>;
|
|
28
28
|
eventEmitter: EventEmitter<[never]>;
|
|
29
29
|
pollInterval: any;
|
|
30
|
-
constructor(
|
|
30
|
+
constructor(client: DispatcherClient);
|
|
31
|
+
static forRunId(workflowRunId: string, client: DispatcherClient): RunEventListener;
|
|
32
|
+
static forAdditionalMeta(key: string, value: string, client: DispatcherClient): RunEventListener;
|
|
31
33
|
emit(event: StepRunEvent): void;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
+
listenForRunId(workflowRunId: string): Promise<void>;
|
|
35
|
+
listenForAdditionalMeta(key: string, value: string): Promise<void>;
|
|
36
|
+
listenLoop(listenerFactory: () => AsyncIterable<WorkflowEvent>): Promise<void>;
|
|
37
|
+
retrySubscribe(listenerFactory: () => AsyncIterable<WorkflowEvent>): Promise<AsyncIterable<WorkflowEvent>>;
|
|
34
38
|
stream(): AsyncGenerator<StepRunEvent, void, unknown>;
|
|
35
39
|
}
|
|
36
40
|
export declare class ListenerClient {
|
|
@@ -42,4 +46,6 @@ export declare class ListenerClient {
|
|
|
42
46
|
constructor(config: ClientConfig, channel: Channel, factory: ClientFactory, api: Api);
|
|
43
47
|
get(workflowRunId: string): import("./child-listener-client").Streamable;
|
|
44
48
|
stream(workflowRunId: string): Promise<AsyncGenerator<StepRunEvent, void, unknown>>;
|
|
49
|
+
streamByRunId(workflowRunId: string): Promise<AsyncGenerator<StepRunEvent, void, unknown>>;
|
|
50
|
+
streamByAdditionalMeta(key: string, value: string): Promise<AsyncGenerator<StepRunEvent, void, unknown>>;
|
|
45
51
|
}
|
|
@@ -95,23 +95,47 @@ const workflowStatusMap = {
|
|
|
95
95
|
[data_contracts_1.WorkflowRunStatus.QUEUED]: undefined,
|
|
96
96
|
};
|
|
97
97
|
class RunEventListener {
|
|
98
|
-
constructor(
|
|
98
|
+
constructor(client) {
|
|
99
99
|
this.q = [];
|
|
100
100
|
this.eventEmitter = new events_1.EventEmitter();
|
|
101
101
|
this.client = client;
|
|
102
|
-
|
|
102
|
+
}
|
|
103
|
+
static forRunId(workflowRunId, client) {
|
|
104
|
+
const listener = new RunEventListener(client);
|
|
105
|
+
listener.listenForRunId(workflowRunId);
|
|
106
|
+
return listener;
|
|
107
|
+
}
|
|
108
|
+
static forAdditionalMeta(key, value, client) {
|
|
109
|
+
const listener = new RunEventListener(client);
|
|
110
|
+
listener.listenForAdditionalMeta(key, value);
|
|
111
|
+
return listener;
|
|
103
112
|
}
|
|
104
113
|
emit(event) {
|
|
105
114
|
this.q.push(event);
|
|
106
115
|
this.eventEmitter.emit('event');
|
|
107
116
|
}
|
|
108
|
-
|
|
117
|
+
listenForRunId(workflowRunId) {
|
|
109
118
|
return __awaiter(this, void 0, void 0, function* () {
|
|
110
|
-
|
|
111
|
-
var _d;
|
|
112
|
-
let listener = this.client.subscribeToWorkflowEvents({
|
|
119
|
+
const listenerFactory = () => this.client.subscribeToWorkflowEvents({
|
|
113
120
|
workflowRunId,
|
|
114
121
|
});
|
|
122
|
+
return this.listenLoop(listenerFactory);
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
listenForAdditionalMeta(key, value) {
|
|
126
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
127
|
+
const listenerFactory = () => this.client.subscribeToWorkflowEvents({
|
|
128
|
+
additionalMetaKey: key,
|
|
129
|
+
additionalMetaValue: value,
|
|
130
|
+
});
|
|
131
|
+
return this.listenLoop(listenerFactory);
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
listenLoop(listenerFactory) {
|
|
135
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
136
|
+
var _a, e_1, _b, _c;
|
|
137
|
+
var _d;
|
|
138
|
+
let listener = listenerFactory();
|
|
115
139
|
try {
|
|
116
140
|
try {
|
|
117
141
|
for (var _e = true, listener_1 = __asyncValues(listener), listener_1_1; listener_1_1 = yield listener_1.next(), _a = listener_1_1.done, !_a; _e = true) {
|
|
@@ -140,21 +164,18 @@ class RunEventListener {
|
|
|
140
164
|
return;
|
|
141
165
|
}
|
|
142
166
|
if (e.code === nice_grpc_1.Status.UNAVAILABLE) {
|
|
143
|
-
listener = yield this.retrySubscribe(
|
|
167
|
+
listener = yield this.retrySubscribe(listenerFactory);
|
|
144
168
|
}
|
|
145
169
|
}
|
|
146
170
|
});
|
|
147
171
|
}
|
|
148
|
-
retrySubscribe(
|
|
172
|
+
retrySubscribe(listenerFactory) {
|
|
149
173
|
return __awaiter(this, void 0, void 0, function* () {
|
|
150
174
|
let retries = 0;
|
|
151
175
|
while (retries < DEFAULT_EVENT_LISTENER_RETRY_COUNT) {
|
|
152
176
|
try {
|
|
153
177
|
yield (0, sleep_1.default)(DEFAULT_EVENT_LISTENER_RETRY_INTERVAL);
|
|
154
|
-
|
|
155
|
-
workflowRunId,
|
|
156
|
-
});
|
|
157
|
-
return listener;
|
|
178
|
+
return listenerFactory();
|
|
158
179
|
}
|
|
159
180
|
catch (e) {
|
|
160
181
|
retries += 1;
|
|
@@ -209,7 +230,18 @@ class ListenerClient {
|
|
|
209
230
|
}
|
|
210
231
|
stream(workflowRunId) {
|
|
211
232
|
return __awaiter(this, void 0, void 0, function* () {
|
|
212
|
-
const listener =
|
|
233
|
+
const listener = RunEventListener.forRunId(workflowRunId, this.client);
|
|
234
|
+
return listener.stream();
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
streamByRunId(workflowRunId) {
|
|
238
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
239
|
+
return this.stream(workflowRunId);
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
streamByAdditionalMeta(key, value) {
|
|
243
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
244
|
+
const listener = RunEventListener.forAdditionalMeta(key, value, this.client);
|
|
213
245
|
return listener.stream();
|
|
214
246
|
});
|
|
215
247
|
}
|
|
@@ -7,23 +7,34 @@ import { Logger } from '../../util/logger';
|
|
|
7
7
|
import { WebhookHandler } from './handler';
|
|
8
8
|
import { WebhookWorkerCreateRequest } from '../rest/generated/data-contracts';
|
|
9
9
|
import { Context, StepRunFunction } from '../../step';
|
|
10
|
+
import { WorkerLabels } from '../dispatcher/dispatcher-client';
|
|
10
11
|
export type ActionRegistry = Record<Action['actionId'], Function>;
|
|
12
|
+
export interface WorkerOpts {
|
|
13
|
+
name: string;
|
|
14
|
+
handleKill?: boolean;
|
|
15
|
+
maxRuns?: number;
|
|
16
|
+
labels?: WorkerLabels;
|
|
17
|
+
}
|
|
11
18
|
export declare class Worker {
|
|
12
19
|
client: HatchetClient;
|
|
13
20
|
name: string;
|
|
21
|
+
workerId: string | undefined;
|
|
14
22
|
killing: boolean;
|
|
15
23
|
handle_kill: boolean;
|
|
16
24
|
action_registry: ActionRegistry;
|
|
25
|
+
workflow_registry: Workflow[];
|
|
17
26
|
listener: ActionListener | undefined;
|
|
18
27
|
futures: Record<Action['stepRunId'], HatchetPromise<any>>;
|
|
19
28
|
contexts: Record<Action['stepRunId'], Context<any, any>>;
|
|
20
29
|
maxRuns?: number;
|
|
21
30
|
logger: Logger;
|
|
22
31
|
registeredWorkflowPromises: Array<Promise<any>>;
|
|
32
|
+
labels: WorkerLabels;
|
|
23
33
|
constructor(client: HatchetClient, options: {
|
|
24
34
|
name: string;
|
|
25
35
|
handleKill?: boolean;
|
|
26
36
|
maxRuns?: number;
|
|
37
|
+
labels?: WorkerLabels;
|
|
27
38
|
});
|
|
28
39
|
private registerActions;
|
|
29
40
|
getHandler(workflows: Workflow[]): WebhookHandler;
|
|
@@ -43,4 +54,5 @@ export declare class Worker {
|
|
|
43
54
|
exitGracefully(handleKill: boolean): Promise<void>;
|
|
44
55
|
start(): Promise<void>;
|
|
45
56
|
handleAction(action: Action): Promise<void>;
|
|
57
|
+
upsertLabels(labels: WorkerLabels): Promise<WorkerLabels>;
|
|
46
58
|
}
|
package/clients/worker/worker.js
CHANGED
|
@@ -29,13 +29,16 @@ const handler_1 = require("./handler");
|
|
|
29
29
|
const step_1 = require("../../step");
|
|
30
30
|
class Worker {
|
|
31
31
|
constructor(client, options) {
|
|
32
|
+
this.workflow_registry = [];
|
|
32
33
|
this.futures = {};
|
|
33
34
|
this.contexts = {};
|
|
34
35
|
this.registeredWorkflowPromises = [];
|
|
36
|
+
this.labels = {};
|
|
35
37
|
this.client = client;
|
|
36
38
|
this.name = this.client.config.namespace + options.name;
|
|
37
39
|
this.action_registry = {};
|
|
38
40
|
this.maxRuns = options.maxRuns;
|
|
41
|
+
this.labels = options.labels || {};
|
|
39
42
|
process.on('SIGTERM', () => this.exitGracefully(true));
|
|
40
43
|
process.on('SIGINT', () => this.exitGracefully(true));
|
|
41
44
|
this.killing = false;
|
|
@@ -103,6 +106,7 @@ class Worker {
|
|
|
103
106
|
userData: '{}',
|
|
104
107
|
retries: workflow.onFailure.retries || 0,
|
|
105
108
|
rateLimits: (_b = workflow.onFailure.rate_limits) !== null && _b !== void 0 ? _b : [],
|
|
109
|
+
workerLabels: {}, // no worker labels for on failure steps
|
|
106
110
|
},
|
|
107
111
|
],
|
|
108
112
|
}
|
|
@@ -119,6 +123,7 @@ class Worker {
|
|
|
119
123
|
concurrency,
|
|
120
124
|
scheduleTimeout: workflow.scheduleTimeout,
|
|
121
125
|
onFailureJob,
|
|
126
|
+
sticky: workflow.sticky,
|
|
122
127
|
jobs: [
|
|
123
128
|
{
|
|
124
129
|
name: workflow.id,
|
|
@@ -134,6 +139,7 @@ class Worker {
|
|
|
134
139
|
userData: '{}',
|
|
135
140
|
retries: step.retries || 0,
|
|
136
141
|
rateLimits: (_b = step.rate_limits) !== null && _b !== void 0 ? _b : [], // Add the missing rateLimits property
|
|
142
|
+
workerLabels: toPbWorkerLabel(step.worker_labels),
|
|
137
143
|
});
|
|
138
144
|
}),
|
|
139
145
|
},
|
|
@@ -141,6 +147,7 @@ class Worker {
|
|
|
141
147
|
});
|
|
142
148
|
this.registeredWorkflowPromises.push(registeredWorkflow);
|
|
143
149
|
yield registeredWorkflow;
|
|
150
|
+
this.workflow_registry.push(workflow);
|
|
144
151
|
}
|
|
145
152
|
catch (e) {
|
|
146
153
|
throw new hatchet_error_1.default(`Could not register workflow: ${e.message}`);
|
|
@@ -155,7 +162,7 @@ class Worker {
|
|
|
155
162
|
return __awaiter(this, void 0, void 0, function* () {
|
|
156
163
|
const { actionId } = action;
|
|
157
164
|
try {
|
|
158
|
-
const context = new step_1.Context(action, this.client);
|
|
165
|
+
const context = new step_1.Context(action, this.client, this);
|
|
159
166
|
this.contexts[action.stepRunId] = context;
|
|
160
167
|
const step = this.action_registry[actionId];
|
|
161
168
|
if (!step) {
|
|
@@ -234,7 +241,7 @@ class Worker {
|
|
|
234
241
|
return __awaiter(this, void 0, void 0, function* () {
|
|
235
242
|
const { actionId } = action;
|
|
236
243
|
try {
|
|
237
|
-
const context = new step_1.Context(action, this.client);
|
|
244
|
+
const context = new step_1.Context(action, this.client, this);
|
|
238
245
|
const key = action.getGroupKeyRunId;
|
|
239
246
|
if (!key) {
|
|
240
247
|
this.logger.error(`No group key run id provided for action ${actionId}`);
|
|
@@ -383,7 +390,9 @@ class Worker {
|
|
|
383
390
|
services: ['default'],
|
|
384
391
|
actions: Object.keys(this.action_registry),
|
|
385
392
|
maxRuns: this.maxRuns,
|
|
393
|
+
labels: this.labels,
|
|
386
394
|
});
|
|
395
|
+
this.workerId = this.listener.workerId;
|
|
387
396
|
const generator = this.listener.actions();
|
|
388
397
|
this.logger.info(`Worker ${this.name} listening for actions`);
|
|
389
398
|
try {
|
|
@@ -433,5 +442,48 @@ class Worker {
|
|
|
433
442
|
}
|
|
434
443
|
});
|
|
435
444
|
}
|
|
445
|
+
upsertLabels(labels) {
|
|
446
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
447
|
+
this.labels = labels;
|
|
448
|
+
if (!this.workerId) {
|
|
449
|
+
this.logger.warn('Worker not registered.');
|
|
450
|
+
return this.labels;
|
|
451
|
+
}
|
|
452
|
+
this.client.dispatcher.upsertWorkerLabels(this.workerId, labels);
|
|
453
|
+
return this.labels;
|
|
454
|
+
});
|
|
455
|
+
}
|
|
436
456
|
}
|
|
437
457
|
exports.Worker = Worker;
|
|
458
|
+
function toPbWorkerLabel(in_) {
|
|
459
|
+
if (!in_) {
|
|
460
|
+
return {};
|
|
461
|
+
}
|
|
462
|
+
return Object.entries(in_).reduce((acc, [key, value]) => {
|
|
463
|
+
if (!value) {
|
|
464
|
+
return Object.assign(Object.assign({}, acc), { [key]: {
|
|
465
|
+
strValue: undefined,
|
|
466
|
+
intValue: undefined,
|
|
467
|
+
} });
|
|
468
|
+
}
|
|
469
|
+
if (typeof value === 'string') {
|
|
470
|
+
return Object.assign(Object.assign({}, acc), { [key]: {
|
|
471
|
+
strValue: value,
|
|
472
|
+
intValue: undefined,
|
|
473
|
+
} });
|
|
474
|
+
}
|
|
475
|
+
if (typeof value === 'number') {
|
|
476
|
+
return Object.assign(Object.assign({}, acc), { [key]: {
|
|
477
|
+
strValue: undefined,
|
|
478
|
+
intValue: value,
|
|
479
|
+
} });
|
|
480
|
+
}
|
|
481
|
+
return Object.assign(Object.assign({}, acc), { [key]: {
|
|
482
|
+
strValue: typeof value.value === 'string' ? value.value : undefined,
|
|
483
|
+
intValue: typeof value.value === 'number' ? value.value : undefined,
|
|
484
|
+
required: value.required,
|
|
485
|
+
weight: value.weight,
|
|
486
|
+
comparator: value.comparator,
|
|
487
|
+
} });
|
|
488
|
+
}, {});
|
|
489
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,93 @@
|
|
|
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
|
+
const workflows_1 = require("../protoc/workflows");
|
|
16
|
+
const sdk_1 = __importDefault(require("../sdk"));
|
|
17
|
+
const hatchet = sdk_1.default.init();
|
|
18
|
+
const workflow = {
|
|
19
|
+
id: 'affinity-workflow',
|
|
20
|
+
description: 'test',
|
|
21
|
+
steps: [
|
|
22
|
+
{
|
|
23
|
+
name: 'step1',
|
|
24
|
+
run: (ctx) => __awaiter(void 0, void 0, void 0, function* () {
|
|
25
|
+
const results = [];
|
|
26
|
+
// eslint-disable-next-line no-plusplus
|
|
27
|
+
for (let i = 0; i < 50; i++) {
|
|
28
|
+
const result = yield ctx.spawnWorkflow(childWorkflow.id, {});
|
|
29
|
+
results.push(result.result());
|
|
30
|
+
}
|
|
31
|
+
console.log('Spawned 50 child workflows');
|
|
32
|
+
console.log('Results:', yield Promise.all(results));
|
|
33
|
+
return { step1: 'step1 results!' };
|
|
34
|
+
}),
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
};
|
|
38
|
+
const childWorkflow = {
|
|
39
|
+
id: 'child-affinity-workflow',
|
|
40
|
+
description: 'test',
|
|
41
|
+
steps: [
|
|
42
|
+
{
|
|
43
|
+
name: 'child-step1',
|
|
44
|
+
worker_labels: {
|
|
45
|
+
model: {
|
|
46
|
+
value: 'xyz',
|
|
47
|
+
required: true,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
run: (ctx) => __awaiter(void 0, void 0, void 0, function* () {
|
|
51
|
+
console.log('starting child-step1 with the following input', ctx.workflowInput());
|
|
52
|
+
return { childStep1: 'childStep1 results!' };
|
|
53
|
+
}),
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: 'child-step2',
|
|
57
|
+
worker_labels: {
|
|
58
|
+
memory: {
|
|
59
|
+
value: 512,
|
|
60
|
+
required: true,
|
|
61
|
+
comparator: workflows_1.WorkerLabelComparator.LESS_THAN,
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
run: (ctx) => __awaiter(void 0, void 0, void 0, function* () {
|
|
65
|
+
console.log('starting child-step2 with the following input', ctx.workflowInput());
|
|
66
|
+
return { childStep2: 'childStep2 results!' };
|
|
67
|
+
}),
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
};
|
|
71
|
+
function main() {
|
|
72
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
73
|
+
const worker1 = yield hatchet.worker('affinity-worker-1', {
|
|
74
|
+
labels: {
|
|
75
|
+
model: 'abc',
|
|
76
|
+
memory: 1024,
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
yield worker1.registerWorkflow(workflow);
|
|
80
|
+
yield worker1.registerWorkflow(childWorkflow);
|
|
81
|
+
worker1.start();
|
|
82
|
+
const worker2 = yield hatchet.worker('affinity-worker-2', {
|
|
83
|
+
labels: {
|
|
84
|
+
model: 'xyz',
|
|
85
|
+
memory: 512,
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
yield worker2.registerWorkflow(workflow);
|
|
89
|
+
yield worker2.registerWorkflow(childWorkflow);
|
|
90
|
+
worker2.start();
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
main();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/examples/api.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
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
|
+
const __1 = __importDefault(require(".."));
|
|
16
|
+
const opts = {
|
|
17
|
+
name: 'api-workflow',
|
|
18
|
+
description: 'My workflow',
|
|
19
|
+
version: '',
|
|
20
|
+
eventTriggers: [],
|
|
21
|
+
cronTriggers: [],
|
|
22
|
+
scheduledTriggers: [],
|
|
23
|
+
concurrency: undefined,
|
|
24
|
+
jobs: [
|
|
25
|
+
{
|
|
26
|
+
name: 'my-job',
|
|
27
|
+
description: 'Job description',
|
|
28
|
+
steps: [
|
|
29
|
+
{
|
|
30
|
+
retries: 0,
|
|
31
|
+
readableId: 'custom-step',
|
|
32
|
+
action: `slack:example`,
|
|
33
|
+
timeout: '60s',
|
|
34
|
+
inputs: '{}',
|
|
35
|
+
parents: [],
|
|
36
|
+
workerLabels: {},
|
|
37
|
+
userData: `{
|
|
38
|
+
"example": "value"
|
|
39
|
+
}`,
|
|
40
|
+
rateLimits: [],
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
};
|
|
46
|
+
function main() {
|
|
47
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
48
|
+
const hatchet = __1.default.init();
|
|
49
|
+
const { admin } = hatchet;
|
|
50
|
+
yield admin.putWorkflow(opts);
|
|
51
|
+
const worker = yield hatchet.worker('example-worker');
|
|
52
|
+
worker.registerAction('slack:example', (ctx) => __awaiter(this, void 0, void 0, function* () {
|
|
53
|
+
const setData = ctx.userData();
|
|
54
|
+
console.log('executed step1!', setData);
|
|
55
|
+
return { step1: 'step1' };
|
|
56
|
+
}));
|
|
57
|
+
yield hatchet.admin.runWorkflow('api-workflow', {});
|
|
58
|
+
worker.start();
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
main();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
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
|
+
const sdk_1 = __importDefault(require("../../../sdk"));
|
|
16
|
+
const hatchet = sdk_1.default.init();
|
|
17
|
+
const sleep = (ms) => new Promise((resolve) => {
|
|
18
|
+
setTimeout(resolve, ms);
|
|
19
|
+
});
|
|
20
|
+
function main() {
|
|
21
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
22
|
+
hatchet.event.push('concurrency:create', {
|
|
23
|
+
data: 'event 1',
|
|
24
|
+
userId: 'user1',
|
|
25
|
+
});
|
|
26
|
+
// step 1 will wait 5000 ms,
|
|
27
|
+
// so sending a second event
|
|
28
|
+
// before that will cancel
|
|
29
|
+
// the first run and run the second event
|
|
30
|
+
yield sleep(1000);
|
|
31
|
+
hatchet.event.push('concurrency:create', {
|
|
32
|
+
data: 'event 2',
|
|
33
|
+
userId: 'user1',
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
main();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|