@hatchet-dev/typescript-sdk 1.9.4 → 1.9.5
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/action-listener.d.ts +1 -0
- package/clients/dispatcher/action-listener.js +16 -0
- package/package.json +1 -1
- package/v1/client/worker/worker-internal.js +6 -2
- package/v1/declaration.d.ts +1 -1
- package/v1/examples/affinity/affinity-workers.d.ts +1 -0
- package/v1/examples/affinity/affinity-workers.js +87 -0
- package/v1/examples/logging/byo-logger.d.ts +1 -0
- package/v1/examples/logging/byo-logger.js +73 -0
- package/v1/examples/logging/logger.d.ts +1 -0
- package/v1/examples/logging/logger.js +46 -0
- package/v1/examples/with_timeouts/workflow.js +0 -1
- package/v1/task.d.ts +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
|
@@ -23,6 +23,7 @@ export declare class ActionListener {
|
|
|
23
23
|
done: boolean;
|
|
24
24
|
listenStrategy: ListenStrategy;
|
|
25
25
|
heartbeat: Heartbeat;
|
|
26
|
+
abortController?: AbortController;
|
|
26
27
|
constructor(client: DispatcherClient, workerId: string, retryInterval?: number, retryCount?: number);
|
|
27
28
|
actions: () => AsyncGenerator<Action, void, unknown>;
|
|
28
29
|
setListenStrategy(strategy: ListenStrategy): Promise<void>;
|
|
@@ -36,6 +36,7 @@ exports.ActionListener = void 0;
|
|
|
36
36
|
exports.createActionKey = createActionKey;
|
|
37
37
|
const dispatcher_1 = require("../../protoc/dispatcher");
|
|
38
38
|
const nice_grpc_1 = require("nice-grpc");
|
|
39
|
+
const abort_controller_x_1 = require("abort-controller-x");
|
|
39
40
|
const sleep_1 = __importDefault(require("../../util/sleep"));
|
|
40
41
|
const hatchet_error_1 = __importDefault(require("../../util/errors/hatchet-error"));
|
|
41
42
|
const heartbeat_controller_1 = require("./heartbeat/heartbeat-controller");
|
|
@@ -96,6 +97,11 @@ class ActionListener {
|
|
|
96
97
|
}
|
|
97
98
|
}
|
|
98
99
|
catch (e) {
|
|
100
|
+
// If the stream was aborted (e.g., during worker shutdown), exit gracefully
|
|
101
|
+
if ((0, abort_controller_x_1.isAbortError)(e)) {
|
|
102
|
+
client.logger.info('Listener aborted, exiting generator');
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
99
105
|
client.logger.info('Listener error');
|
|
100
106
|
// if this is a HatchetError, we should throw this error
|
|
101
107
|
if (e instanceof hatchet_error_1.default) {
|
|
@@ -157,15 +163,21 @@ class ActionListener {
|
|
|
157
163
|
yield (0, sleep_1.default)(DEFAULT_ACTION_LISTENER_RETRY_INTERVAL);
|
|
158
164
|
}
|
|
159
165
|
try {
|
|
166
|
+
// Create a new AbortController for this connection
|
|
167
|
+
this.abortController = new AbortController();
|
|
160
168
|
if (this.listenStrategy === ListenStrategy.LISTEN_STRATEGY_V1) {
|
|
161
169
|
const result = this.client.listen({
|
|
162
170
|
workerId: this.workerId,
|
|
171
|
+
}, {
|
|
172
|
+
signal: this.abortController.signal,
|
|
163
173
|
});
|
|
164
174
|
this.logger.green('Connection established using LISTEN_STRATEGY_V1');
|
|
165
175
|
return result;
|
|
166
176
|
}
|
|
167
177
|
const res = this.client.listenV2({
|
|
168
178
|
workerId: this.workerId,
|
|
179
|
+
}, {
|
|
180
|
+
signal: this.abortController.signal,
|
|
169
181
|
});
|
|
170
182
|
yield this.heartbeat.start();
|
|
171
183
|
this.logger.green('Connection established using LISTEN_STRATEGY_V2');
|
|
@@ -187,6 +199,10 @@ class ActionListener {
|
|
|
187
199
|
return __awaiter(this, void 0, void 0, function* () {
|
|
188
200
|
this.done = true;
|
|
189
201
|
this.heartbeat.stop();
|
|
202
|
+
// Abort the gRPC stream to immediately cancel the generator
|
|
203
|
+
if (this.abortController) {
|
|
204
|
+
this.abortController.abort('Worker stopping');
|
|
205
|
+
}
|
|
190
206
|
try {
|
|
191
207
|
return yield this.client.unsubscribe({
|
|
192
208
|
workerId: this.workerId,
|
package/package.json
CHANGED
|
@@ -92,14 +92,18 @@ class V1Worker {
|
|
|
92
92
|
});
|
|
93
93
|
}
|
|
94
94
|
registerDurableActionsV1(workflow) {
|
|
95
|
-
const newActions = workflow._durableTasks
|
|
95
|
+
const newActions = workflow._durableTasks
|
|
96
|
+
.filter((task) => !!task.fn)
|
|
97
|
+
.reduce((acc, task) => {
|
|
96
98
|
acc[`${(0, apply_namespace_1.applyNamespace)(workflow.name, this.client.config.namespace).toLowerCase()}:${task.name.toLowerCase()}`] = (ctx) => task.fn(ctx.input, ctx);
|
|
97
99
|
return acc;
|
|
98
100
|
}, {});
|
|
99
101
|
this.action_registry = Object.assign(Object.assign({}, this.action_registry), newActions);
|
|
100
102
|
}
|
|
101
103
|
registerActionsV1(workflow) {
|
|
102
|
-
const newActions = workflow._tasks
|
|
104
|
+
const newActions = workflow._tasks
|
|
105
|
+
.filter((task) => !!task.fn)
|
|
106
|
+
.reduce((acc, task) => {
|
|
103
107
|
acc[`${workflow.name}:${task.name.toLowerCase()}`] = (ctx) => task.fn(ctx.input, ctx);
|
|
104
108
|
return acc;
|
|
105
109
|
}, {});
|
package/v1/declaration.d.ts
CHANGED
|
@@ -295,7 +295,7 @@ export declare class WorkflowDeclaration<I extends InputType = UnknownInputType,
|
|
|
295
295
|
*/
|
|
296
296
|
task<Name extends string, Fn extends Name extends keyof O ? (input: I, ctx: Context<I>) => O[Name] extends OutputType ? O[Name] | Promise<O[Name]> : void : (input: I, ctx: Context<I>) => void, FnReturn = ReturnType<Fn> extends Promise<infer P> ? P : ReturnType<Fn>, TO extends OutputType = Name extends keyof O ? O[Name] extends OutputType ? O[Name] : never : FnReturn extends OutputType ? FnReturn : never>(options: (Omit<CreateWorkflowTaskOpts<I, TO>, 'fn'> & {
|
|
297
297
|
name: Name;
|
|
298
|
-
fn
|
|
298
|
+
fn?: Fn;
|
|
299
299
|
}) | TaskWorkflowDeclaration<I, TO>): CreateWorkflowTaskOpts<I, TO>;
|
|
300
300
|
/**
|
|
301
301
|
* Adds an onFailure task to the workflow.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,87 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const workflows_1 = require("../../../protoc/workflows");
|
|
13
|
+
const hatchet_client_1 = require("../hatchet-client");
|
|
14
|
+
// > AffinityWorkflow
|
|
15
|
+
const workflow = hatchet_client_1.hatchet.workflow({
|
|
16
|
+
name: 'affinity-workflow',
|
|
17
|
+
description: 'test',
|
|
18
|
+
});
|
|
19
|
+
workflow.task({
|
|
20
|
+
name: 'step1',
|
|
21
|
+
fn: (_, ctx) => __awaiter(void 0, void 0, void 0, function* () {
|
|
22
|
+
const results = [];
|
|
23
|
+
// eslint-disable-next-line no-plusplus
|
|
24
|
+
for (let i = 0; i < 50; i++) {
|
|
25
|
+
const result = yield ctx.spawnWorkflow(childWorkflow.id, {});
|
|
26
|
+
results.push(result.output);
|
|
27
|
+
}
|
|
28
|
+
console.log('Spawned 50 child workflows');
|
|
29
|
+
console.log('Results:', yield Promise.all(results));
|
|
30
|
+
return { step1: 'step1 results!' };
|
|
31
|
+
}),
|
|
32
|
+
});
|
|
33
|
+
// !!
|
|
34
|
+
const childWorkflow = hatchet_client_1.hatchet.workflow({
|
|
35
|
+
name: 'child-affinity-workflow',
|
|
36
|
+
description: 'test',
|
|
37
|
+
});
|
|
38
|
+
childWorkflow.task({
|
|
39
|
+
name: 'child-step1',
|
|
40
|
+
desiredWorkerLabels: {
|
|
41
|
+
model: {
|
|
42
|
+
value: 'xyz',
|
|
43
|
+
required: true,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
fn: (ctx) => __awaiter(void 0, void 0, void 0, function* () {
|
|
47
|
+
return { childStep1: 'childStep1 results!' };
|
|
48
|
+
}),
|
|
49
|
+
});
|
|
50
|
+
childWorkflow.task({
|
|
51
|
+
name: 'child-step2',
|
|
52
|
+
desiredWorkerLabels: {
|
|
53
|
+
memory: {
|
|
54
|
+
value: 512,
|
|
55
|
+
required: true,
|
|
56
|
+
comparator: workflows_1.WorkerLabelComparator.LESS_THAN,
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
fn: (ctx) => __awaiter(void 0, void 0, void 0, function* () {
|
|
60
|
+
return { childStep2: 'childStep2 results!' };
|
|
61
|
+
}),
|
|
62
|
+
});
|
|
63
|
+
function main() {
|
|
64
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
65
|
+
// > AffinityWorker
|
|
66
|
+
const worker1 = yield hatchet_client_1.hatchet.worker('affinity-worker-1', {
|
|
67
|
+
labels: {
|
|
68
|
+
model: 'abc',
|
|
69
|
+
memory: 1024,
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
// !!
|
|
73
|
+
yield worker1.registerWorkflow(workflow);
|
|
74
|
+
yield worker1.registerWorkflow(childWorkflow);
|
|
75
|
+
worker1.start();
|
|
76
|
+
const worker2 = yield hatchet_client_1.hatchet.worker('affinity-worker-2', {
|
|
77
|
+
labels: {
|
|
78
|
+
model: 'xyz',
|
|
79
|
+
memory: 512,
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
yield worker2.registerWorkflow(workflow);
|
|
83
|
+
yield worker2.registerWorkflow(childWorkflow);
|
|
84
|
+
worker2.start();
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
main();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,73 @@
|
|
|
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
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
16
|
+
const pino_1 = __importDefault(require("pino"));
|
|
17
|
+
const sdk_1 = __importDefault(require("../../../sdk"));
|
|
18
|
+
// > Create Pino logger
|
|
19
|
+
const logger = (0, pino_1.default)();
|
|
20
|
+
class PinoLogger {
|
|
21
|
+
constructor(context, logLevel = 'DEBUG') {
|
|
22
|
+
this.logLevel = logLevel;
|
|
23
|
+
this.context = context;
|
|
24
|
+
}
|
|
25
|
+
debug(message, extra) {
|
|
26
|
+
logger.debug(extra, message);
|
|
27
|
+
}
|
|
28
|
+
info(message, extra) {
|
|
29
|
+
logger.info(extra, message);
|
|
30
|
+
}
|
|
31
|
+
green(message, extra) {
|
|
32
|
+
logger.info(extra, `%c${message}`);
|
|
33
|
+
}
|
|
34
|
+
warn(message, error, extra) {
|
|
35
|
+
logger.warn(extra, `${message} ${error}`);
|
|
36
|
+
}
|
|
37
|
+
error(message, error, extra) {
|
|
38
|
+
logger.error(extra, `${message} ${error}`);
|
|
39
|
+
}
|
|
40
|
+
// optional util method
|
|
41
|
+
util(key, message, extra) {
|
|
42
|
+
// for example you may want to expose a trace method
|
|
43
|
+
if (key === 'trace') {
|
|
44
|
+
logger.info(extra, 'trace');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const hatchet = sdk_1.default.init({
|
|
49
|
+
log_level: 'DEBUG',
|
|
50
|
+
logger: (ctx, level) => new PinoLogger(ctx, level),
|
|
51
|
+
});
|
|
52
|
+
// !!
|
|
53
|
+
// > Use the logger
|
|
54
|
+
const workflow = hatchet.task({
|
|
55
|
+
name: 'byo-logger-example',
|
|
56
|
+
fn: (ctx) => __awaiter(void 0, void 0, void 0, function* () {
|
|
57
|
+
// eslint-disable-next-line no-plusplus
|
|
58
|
+
for (let i = 0; i < 5; i++) {
|
|
59
|
+
logger.info(`log message ${i}`);
|
|
60
|
+
}
|
|
61
|
+
return { step1: 'completed step run' };
|
|
62
|
+
}),
|
|
63
|
+
});
|
|
64
|
+
// !!
|
|
65
|
+
function main() {
|
|
66
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
67
|
+
const worker = yield hatchet.worker('byo-logger-worker', {
|
|
68
|
+
workflows: [workflow],
|
|
69
|
+
});
|
|
70
|
+
worker.start();
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
main();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const hatchet_client_1 = require("../hatchet-client");
|
|
13
|
+
const sleep = (ms) => new Promise((resolve) => {
|
|
14
|
+
setTimeout(resolve, ms);
|
|
15
|
+
});
|
|
16
|
+
// > Logger
|
|
17
|
+
const workflow = hatchet_client_1.hatchet.workflow({
|
|
18
|
+
name: 'logger-example',
|
|
19
|
+
description: 'test',
|
|
20
|
+
on: {
|
|
21
|
+
event: 'user:create',
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
workflow.task({
|
|
25
|
+
name: 'logger-step1',
|
|
26
|
+
fn: (_, ctx) => __awaiter(void 0, void 0, void 0, function* () {
|
|
27
|
+
// log in a for loop
|
|
28
|
+
// eslint-disable-next-line no-plusplus
|
|
29
|
+
for (let i = 0; i < 10; i++) {
|
|
30
|
+
ctx.logger.info(`log message ${i}`);
|
|
31
|
+
yield sleep(200);
|
|
32
|
+
}
|
|
33
|
+
return { step1: 'completed step run' };
|
|
34
|
+
}),
|
|
35
|
+
});
|
|
36
|
+
// !!
|
|
37
|
+
function main() {
|
|
38
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
39
|
+
const worker = yield hatchet_client_1.hatchet.worker('logger-worker', {
|
|
40
|
+
slots: 1,
|
|
41
|
+
workflows: [workflow],
|
|
42
|
+
});
|
|
43
|
+
yield worker.start();
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
main();
|
|
@@ -13,7 +13,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.refreshTimeout = exports.withTimeouts = void 0;
|
|
16
|
-
// > Declaring a Task
|
|
17
16
|
const sleep_1 = __importDefault(require("../../../util/sleep"));
|
|
18
17
|
const hatchet_client_1 = require("../hatchet-client");
|
|
19
18
|
// > Execution Timeout
|
package/v1/task.d.ts
CHANGED
|
@@ -55,7 +55,7 @@ export type CreateBaseTaskOpts<I extends InputType = UnknownInputType, O extends
|
|
|
55
55
|
* @param ctx The execution context for the task.
|
|
56
56
|
* @returns The result of the task execution.
|
|
57
57
|
*/
|
|
58
|
-
fn
|
|
58
|
+
fn?: C;
|
|
59
59
|
/**
|
|
60
60
|
* @deprecated use executionTimeout instead
|
|
61
61
|
*/
|
package/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const HATCHET_VERSION = "1.9.
|
|
1
|
+
export declare const HATCHET_VERSION = "1.9.5";
|
package/version.js
CHANGED