@hatchet-dev/typescript-sdk 0.1.1 → 0.1.4

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.
Files changed (57) hide show
  1. package/clients/admin/admin-client.d.ts +12 -0
  2. package/clients/admin/admin-client.js +47 -0
  3. package/clients/dispatcher/action-listener.d.ts +26 -0
  4. package/clients/dispatcher/action-listener.js +113 -0
  5. package/clients/dispatcher/dispatcher-client.d.ts +20 -0
  6. package/clients/dispatcher/dispatcher-client.js +58 -0
  7. package/clients/event/event-client.d.ts +11 -0
  8. package/clients/event/event-client.js +32 -0
  9. package/clients/hatchet-client/client-config.d.ts +72 -0
  10. package/clients/hatchet-client/client-config.js +17 -0
  11. package/clients/hatchet-client/hatchet-client.d.ts +26 -0
  12. package/clients/hatchet-client/hatchet-client.js +133 -0
  13. package/clients/hatchet-client/index.d.ts +2 -0
  14. package/clients/hatchet-client/index.js +18 -0
  15. package/clients/worker/index.d.ts +1 -0
  16. package/clients/worker/index.js +17 -0
  17. package/clients/worker/worker.d.ts +34 -0
  18. package/clients/worker/worker.js +317 -0
  19. package/index.d.ts +2 -0
  20. package/index.js +4 -0
  21. package/package.json +3 -2
  22. package/protoc/dispatcher/dispatcher.d.ts +333 -0
  23. package/protoc/dispatcher/dispatcher.js +1152 -0
  24. package/protoc/dispatcher/index.d.ts +1 -0
  25. package/protoc/dispatcher/index.js +17 -0
  26. package/protoc/events/events.d.ts +165 -0
  27. package/protoc/events/events.js +443 -0
  28. package/protoc/events/index.d.ts +1 -0
  29. package/protoc/events/index.js +17 -0
  30. package/protoc/google/protobuf/timestamp.d.ts +121 -0
  31. package/protoc/google/protobuf/timestamp.js +110 -0
  32. package/protoc/google/protobuf/wrappers.d.ts +160 -0
  33. package/protoc/google/protobuf/wrappers.js +527 -0
  34. package/protoc/workflows/index.d.ts +1 -0
  35. package/protoc/workflows/index.js +17 -0
  36. package/protoc/workflows/workflows.d.ts +464 -0
  37. package/protoc/workflows/workflows.js +1951 -0
  38. package/sdk.d.ts +2 -0
  39. package/sdk.js +4 -0
  40. package/step.d.ts +33 -0
  41. package/step.js +65 -0
  42. package/util/config-loader/config-loader.d.ts +13 -0
  43. package/util/config-loader/config-loader.js +85 -0
  44. package/util/config-loader/index.d.ts +1 -0
  45. package/util/config-loader/index.js +17 -0
  46. package/util/errors/hatchet-error.d.ts +4 -0
  47. package/util/errors/hatchet-error.js +9 -0
  48. package/util/hatchet-promise/hatchet-promise.d.ts +6 -0
  49. package/util/hatchet-promise/hatchet-promise.js +12 -0
  50. package/util/logger/index.d.ts +1 -0
  51. package/util/logger/index.js +17 -0
  52. package/util/logger/logger.d.ts +12 -0
  53. package/util/logger/logger.js +37 -0
  54. package/util/sleep.d.ts +2 -0
  55. package/util/sleep.js +6 -0
  56. package/workflow.d.ts +111 -0
  57. package/workflow.js +54 -0
@@ -0,0 +1,34 @@
1
+ import { HatchetClient } from '../../../../src/clients/hatchet-client';
2
+ import { Action, ActionListener } from '../../../../src/clients/dispatcher/action-listener';
3
+ import { StepActionEvent, StepActionEventType, GroupKeyActionEvent, GroupKeyActionEventType } from '../../../../src/protoc/dispatcher';
4
+ import HatchetPromise from '../../../../src/util/hatchet-promise/hatchet-promise';
5
+ import { Workflow } from '../../../../src/workflow';
6
+ import { Logger } from '../../../../src/util/logger';
7
+ import { Context } from '../../step';
8
+ export type ActionRegistry = Record<Action['actionId'], Function>;
9
+ export declare class Worker {
10
+ serviceName: string;
11
+ client: HatchetClient;
12
+ name: string;
13
+ killing: boolean;
14
+ handle_kill: boolean;
15
+ action_registry: ActionRegistry;
16
+ concurrency_action_registry: ActionRegistry;
17
+ listener: ActionListener | undefined;
18
+ futures: Record<Action['stepRunId'], HatchetPromise<any>>;
19
+ contexts: Record<Action['stepRunId'], Context<any>>;
20
+ logger: Logger;
21
+ constructor(client: HatchetClient, options: {
22
+ name: string;
23
+ handleKill?: boolean;
24
+ });
25
+ registerWorkflow(workflow: Workflow): Promise<void>;
26
+ handleStartStepRun(action: Action): void;
27
+ handleStartGroupKeyRun(action: Action): void;
28
+ getStepActionEvent(action: Action, eventType: StepActionEventType, payload?: any): StepActionEvent;
29
+ getGroupKeyActionEvent(action: Action, eventType: GroupKeyActionEventType, payload?: any): GroupKeyActionEvent;
30
+ handleCancelStepRun(action: Action): void;
31
+ stop(): Promise<void>;
32
+ exitGracefully(): Promise<void>;
33
+ start(): Promise<void>;
34
+ }
@@ -0,0 +1,317 @@
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 __asyncValues = (this && this.__asyncValues) || function (o) {
12
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
13
+ var m = o[Symbol.asyncIterator], i;
14
+ 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);
15
+ 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); }); }; }
16
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
17
+ };
18
+ var __importDefault = (this && this.__importDefault) || function (mod) {
19
+ return (mod && mod.__esModule) ? mod : { "default": mod };
20
+ };
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.Worker = void 0;
23
+ const hatchet_error_1 = __importDefault(require("../../../../src/util/errors/hatchet-error"));
24
+ const dispatcher_1 = require("../../../../src/protoc/dispatcher");
25
+ const hatchet_promise_1 = __importDefault(require("../../../../src/util/hatchet-promise/hatchet-promise"));
26
+ const workflows_1 = require("../../../../src/protoc/workflows");
27
+ const logger_1 = require("../../../../src/util/logger");
28
+ const sleep_1 = __importDefault(require("../../../../src/util/sleep"));
29
+ const step_1 = require("../../step");
30
+ class Worker {
31
+ constructor(client, options) {
32
+ this.serviceName = 'default';
33
+ this.futures = {};
34
+ this.contexts = {};
35
+ this.client = client;
36
+ this.name = options.name;
37
+ this.action_registry = {};
38
+ this.concurrency_action_registry = {};
39
+ process.on('SIGTERM', () => this.exitGracefully());
40
+ process.on('SIGINT', () => this.exitGracefully());
41
+ this.killing = false;
42
+ this.handle_kill = options.handleKill === undefined ? true : options.handleKill;
43
+ this.logger = new logger_1.Logger(`Worker/${this.name}`, this.client.config.log_level);
44
+ }
45
+ registerWorkflow(workflow) {
46
+ var _a, _b;
47
+ return __awaiter(this, void 0, void 0, function* () {
48
+ try {
49
+ const concurrency = ((_a = workflow.concurrency) === null || _a === void 0 ? void 0 : _a.action)
50
+ ? {
51
+ action: `${this.serviceName}:${workflow.concurrency.action}`,
52
+ maxRuns: workflow.concurrency.maxRuns || 1,
53
+ limitStrategy: workflow.concurrency.limitStrategy || workflows_1.ConcurrencyLimitStrategy.CANCEL_IN_PROGRESS,
54
+ }
55
+ : undefined;
56
+ yield this.client.admin.put_workflow({
57
+ name: workflow.id,
58
+ description: workflow.description,
59
+ version: workflow.version || '',
60
+ eventTriggers: workflow.on.event ? [workflow.on.event] : [],
61
+ cronTriggers: workflow.on.cron ? [workflow.on.cron] : [],
62
+ scheduledTriggers: [],
63
+ concurrency,
64
+ jobs: [
65
+ {
66
+ name: workflow.id,
67
+ timeout: workflow.timeout || '60s',
68
+ description: workflow.description,
69
+ steps: workflow.steps.map((step) => {
70
+ var _a;
71
+ return ({
72
+ readableId: step.name,
73
+ action: `${this.serviceName}:${step.name}`,
74
+ timeout: step.timeout || '60s',
75
+ inputs: '{}',
76
+ parents: (_a = step.parents) !== null && _a !== void 0 ? _a : [],
77
+ });
78
+ }),
79
+ },
80
+ ],
81
+ });
82
+ }
83
+ catch (e) {
84
+ throw new hatchet_error_1.default(`Could not register workflow: ${e.message}`);
85
+ }
86
+ this.action_registry = workflow.steps.reduce((acc, step) => {
87
+ acc[`${this.serviceName}:${step.name}`] = step.run;
88
+ return acc;
89
+ }, {});
90
+ this.concurrency_action_registry = ((_b = workflow.concurrency) === null || _b === void 0 ? void 0 : _b.action)
91
+ ? {
92
+ [`${this.serviceName}:${workflow.concurrency.action}`]: workflow.concurrency.key,
93
+ }
94
+ : {};
95
+ });
96
+ }
97
+ handleStartStepRun(action) {
98
+ const { actionId } = action;
99
+ const context = new step_1.Context(action.actionPayload);
100
+ this.contexts[action.stepRunId] = context;
101
+ const step = this.action_registry[actionId];
102
+ if (!step) {
103
+ this.logger.error(`Could not find step '${actionId}'`);
104
+ return;
105
+ }
106
+ const run = () => __awaiter(this, void 0, void 0, function* () {
107
+ return step(context);
108
+ });
109
+ const success = (result) => {
110
+ this.logger.info(`Step run ${action.stepRunId} succeeded`);
111
+ try {
112
+ // Send the action event to the dispatcher
113
+ const event = this.getStepActionEvent(action, dispatcher_1.StepActionEventType.STEP_EVENT_TYPE_COMPLETED, result);
114
+ this.client.dispatcher.sendStepActionEvent(event);
115
+ // delete the run from the futures
116
+ delete this.futures[action.stepRunId];
117
+ }
118
+ catch (e) {
119
+ this.logger.error(`Could not send action event: ${e.message}`);
120
+ }
121
+ };
122
+ const failure = (error) => {
123
+ this.logger.error(`Step run ${action.stepRunId} failed: ${error.message}`);
124
+ try {
125
+ // Send the action event to the dispatcher
126
+ const event = this.getStepActionEvent(action, dispatcher_1.StepActionEventType.STEP_EVENT_TYPE_FAILED, error);
127
+ this.client.dispatcher.sendStepActionEvent(event);
128
+ // delete the run from the futures
129
+ delete this.futures[action.stepRunId];
130
+ }
131
+ catch (e) {
132
+ this.logger.error(`Could not send action event: ${e.message}`);
133
+ }
134
+ };
135
+ const future = new hatchet_promise_1.default(run().then(success).catch(failure));
136
+ this.futures[action.stepRunId] = future;
137
+ try {
138
+ // Send the action event to the dispatcher
139
+ const event = this.getStepActionEvent(action, dispatcher_1.StepActionEventType.STEP_EVENT_TYPE_STARTED);
140
+ this.client.dispatcher.sendStepActionEvent(event);
141
+ }
142
+ catch (e) {
143
+ this.logger.error(`Could not send action event: ${e.message}`);
144
+ }
145
+ }
146
+ handleStartGroupKeyRun(action) {
147
+ const { actionId } = action;
148
+ const context = new step_1.Context(action.actionPayload);
149
+ const key = action.getGroupKeyRunId;
150
+ this.contexts[key] = context;
151
+ const step = this.action_registry[actionId];
152
+ if (!step) {
153
+ this.logger.error(`Could not find step '${actionId}'`);
154
+ return;
155
+ }
156
+ const run = () => __awaiter(this, void 0, void 0, function* () {
157
+ return step(context);
158
+ });
159
+ const success = (result) => {
160
+ this.logger.info(`Step run ${action.stepRunId} succeeded`);
161
+ try {
162
+ // Send the action event to the dispatcher
163
+ const event = this.getGroupKeyActionEvent(action, dispatcher_1.GroupKeyActionEventType.GROUP_KEY_EVENT_TYPE_COMPLETED, result);
164
+ this.client.dispatcher.sendGroupKeyActionEvent(event);
165
+ // delete the run from the futures
166
+ delete this.futures[key];
167
+ }
168
+ catch (e) {
169
+ this.logger.error(`Could not send action event: ${e.message}`);
170
+ }
171
+ };
172
+ const failure = (error) => {
173
+ this.logger.error(`Step run ${key} failed: ${error.message}`);
174
+ try {
175
+ // Send the action event to the dispatcher
176
+ const event = this.getGroupKeyActionEvent(action, dispatcher_1.GroupKeyActionEventType.GROUP_KEY_EVENT_TYPE_FAILED, error);
177
+ this.client.dispatcher.sendGroupKeyActionEvent(event);
178
+ // delete the run from the futures
179
+ delete this.futures[key];
180
+ }
181
+ catch (e) {
182
+ this.logger.error(`Could not send action event: ${e.message}`);
183
+ }
184
+ };
185
+ const future = new hatchet_promise_1.default(run().then(success).catch(failure));
186
+ this.futures[action.getGroupKeyRunId] = future;
187
+ try {
188
+ // Send the action event to the dispatcher
189
+ const event = this.getStepActionEvent(action, dispatcher_1.StepActionEventType.STEP_EVENT_TYPE_STARTED);
190
+ this.client.dispatcher.sendStepActionEvent(event);
191
+ }
192
+ catch (e) {
193
+ this.logger.error(`Could not send action event: ${e.message}`);
194
+ }
195
+ }
196
+ getStepActionEvent(action, eventType, payload = '') {
197
+ return {
198
+ workerId: this.name,
199
+ jobId: action.jobId,
200
+ jobRunId: action.jobRunId,
201
+ stepId: action.stepId,
202
+ stepRunId: action.stepRunId,
203
+ actionId: action.actionId,
204
+ eventTimestamp: new Date(),
205
+ eventType,
206
+ eventPayload: JSON.stringify(payload),
207
+ };
208
+ }
209
+ getGroupKeyActionEvent(action, eventType, payload = '') {
210
+ return {
211
+ workerId: this.name,
212
+ workflowRunId: action.workflowRunId,
213
+ getGroupKeyRunId: action.getGroupKeyRunId,
214
+ actionId: action.actionId,
215
+ eventTimestamp: new Date(),
216
+ eventType,
217
+ eventPayload: JSON.stringify(payload),
218
+ };
219
+ }
220
+ handleCancelStepRun(action) {
221
+ const { stepRunId } = action;
222
+ const future = this.futures[stepRunId];
223
+ const context = this.contexts[stepRunId];
224
+ // TODO send cancel signal to context
225
+ // if (context && context.cancel) {
226
+ // context.cancel();
227
+ // delete this.contexts[stepRunId];
228
+ // }
229
+ if (future) {
230
+ future.cancel();
231
+ delete this.futures[stepRunId];
232
+ }
233
+ }
234
+ stop() {
235
+ return __awaiter(this, void 0, void 0, function* () {
236
+ yield this.exitGracefully();
237
+ });
238
+ }
239
+ exitGracefully() {
240
+ var _a;
241
+ return __awaiter(this, void 0, void 0, function* () {
242
+ this.killing = true;
243
+ this.logger.info('Starting to exit...');
244
+ try {
245
+ (_a = this.listener) === null || _a === void 0 ? void 0 : _a.unregister();
246
+ }
247
+ catch (e) {
248
+ this.logger.error(`Could not unregister listener: ${e.message}`);
249
+ }
250
+ this.logger.info('Gracefully exiting hatchet worker, running tasks will attempt to finish...');
251
+ // attempt to wait for futures to finish
252
+ yield Promise.all(Object.values(this.futures).map(({ promise }) => promise));
253
+ if (this.handle_kill) {
254
+ this.logger.info('Exiting hatchet worker...');
255
+ process.exit(0);
256
+ }
257
+ });
258
+ }
259
+ start() {
260
+ var _a, e_1, _b, _c;
261
+ return __awaiter(this, void 0, void 0, function* () {
262
+ let retries = 0;
263
+ while (retries < 5) {
264
+ try {
265
+ this.listener = yield this.client.dispatcher.getActionListener({
266
+ workerName: this.name,
267
+ services: ['default'],
268
+ actions: Object.keys(this.action_registry),
269
+ });
270
+ const generator = this.listener.actions();
271
+ this.logger.info(`Worker ${this.name} listening for actions`);
272
+ try {
273
+ for (var _d = true, generator_1 = (e_1 = void 0, __asyncValues(generator)), generator_1_1; generator_1_1 = yield generator_1.next(), _a = generator_1_1.done, !_a; _d = true) {
274
+ _c = generator_1_1.value;
275
+ _d = false;
276
+ const action = _c;
277
+ this.logger.info(`Worker ${this.name} received action ${action.actionId}:${action.actionType}`);
278
+ if (action.actionType === dispatcher_1.ActionType.START_STEP_RUN) {
279
+ this.handleStartStepRun(action);
280
+ }
281
+ else if (action.actionType === dispatcher_1.ActionType.CANCEL_STEP_RUN) {
282
+ this.handleCancelStepRun(action);
283
+ }
284
+ else if (action.actionType === dispatcher_1.ActionType.START_GET_GROUP_KEY) {
285
+ this.handleStartGroupKeyRun(action);
286
+ }
287
+ else {
288
+ this.logger.error(`Worker ${this.name} received unknown action type ${action.actionType}`);
289
+ }
290
+ }
291
+ }
292
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
293
+ finally {
294
+ try {
295
+ if (!_d && !_a && (_b = generator_1.return)) yield _b.call(generator_1);
296
+ }
297
+ finally { if (e_1) throw e_1.error; }
298
+ }
299
+ break;
300
+ }
301
+ catch (e) {
302
+ this.logger.error(`Could not start worker: ${e.message}`);
303
+ retries += 1;
304
+ const wait = 500;
305
+ this.logger.error(`Could not start worker, retrying in ${500} seconds`);
306
+ yield (0, sleep_1.default)(wait);
307
+ }
308
+ }
309
+ if (this.killing)
310
+ return;
311
+ if (retries > 5) {
312
+ throw new hatchet_error_1.default('Could not start worker after 5 retries');
313
+ }
314
+ });
315
+ }
316
+ }
317
+ exports.Worker = Worker;
package/index.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ import { HatchetClient as Hatchet } from '../../src/clients/hatchet-client';
2
+ export default Hatchet;
package/index.js ADDED
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const hatchet_client_1 = require("../../src/clients/hatchet-client");
4
+ exports.default = hatchet_client_1.HatchetClient;
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@hatchet-dev/typescript-sdk",
3
- "version": "0.1.1",
3
+ "version": "0.1.4",
4
4
  "description": "Background task orchestration & visibility for developers",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "files": [
8
- "dist",
8
+ "*",
9
9
  "!**/*.test.js",
10
10
  "!**/*.test.d.ts"
11
11
  ],
@@ -15,6 +15,7 @@
15
15
  },
16
16
  "scripts": {
17
17
  "prepare": "npm run build",
18
+ "fix-paths": "",
18
19
  "build": "tsc && resolve-tspaths",
19
20
  "test": "jest",
20
21
  "test:watch": "jest --watch",