@hatchet-dev/typescript-sdk 0.1.15 → 0.1.18
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 +2 -0
- package/clients/admin/admin-client.js +4 -3
- package/clients/dispatcher/action-listener.d.ts +9 -3
- package/clients/dispatcher/action-listener.js +45 -23
- package/clients/dispatcher/dispatcher-client.js +4 -7
- package/clients/hatchet-client/hatchet-client.d.ts +0 -1
- package/clients/hatchet-client/hatchet-client.js +8 -5
- package/clients/worker/worker.d.ts +0 -1
- package/clients/worker/worker.js +41 -52
- package/package.json +2 -1
- package/protoc/workflows/workflows.d.ts +2 -0
- package/protoc/workflows/workflows.js +16 -1
- package/util/config-loader/config-loader.d.ts +1 -1
- package/util/config-loader/config-loader.js +16 -15
- package/util/retrier.d.ts +2 -0
- package/util/retrier.js +36 -0
- package/workflow.d.ts +3 -0
- package/workflow.js +1 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Channel, ClientFactory } from 'nice-grpc';
|
|
2
2
|
import { CreateWorkflowVersionOpts, WorkflowServiceClient } from '../../protoc/workflows';
|
|
3
3
|
import { ClientConfig } from '../hatchet-client/client-config';
|
|
4
|
+
import { Logger } from '../../util/logger';
|
|
4
5
|
import { Api } from '../rest';
|
|
5
6
|
/**
|
|
6
7
|
* AdminClient is a client for interacting with the Hatchet Admin API. This allows you to configure, trigger,
|
|
@@ -23,6 +24,7 @@ export declare class AdminClient {
|
|
|
23
24
|
client: WorkflowServiceClient;
|
|
24
25
|
api: Api;
|
|
25
26
|
tenantId: string;
|
|
27
|
+
logger: Logger;
|
|
26
28
|
constructor(config: ClientConfig, channel: Channel, factory: ClientFactory, api: Api, tenantId: string);
|
|
27
29
|
/**
|
|
28
30
|
* Creates a new workflow or updates an existing workflow. If the workflow already exists, Hatchet will automatically
|
|
@@ -15,6 +15,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
exports.AdminClient = void 0;
|
|
16
16
|
const workflows_1 = require("../../protoc/workflows");
|
|
17
17
|
const hatchet_error_1 = __importDefault(require("../../util/errors/hatchet-error"));
|
|
18
|
+
const logger_1 = require("../../util/logger");
|
|
19
|
+
const retrier_1 = require("../../util/retrier");
|
|
18
20
|
/**
|
|
19
21
|
* AdminClient is a client for interacting with the Hatchet Admin API. This allows you to configure, trigger,
|
|
20
22
|
* and monitor workflows.
|
|
@@ -37,6 +39,7 @@ class AdminClient {
|
|
|
37
39
|
this.client = factory.create(workflows_1.WorkflowServiceDefinition, channel);
|
|
38
40
|
this.api = api;
|
|
39
41
|
this.tenantId = tenantId;
|
|
42
|
+
this.logger = new logger_1.Logger(`Admin`, config.log_level);
|
|
40
43
|
}
|
|
41
44
|
/**
|
|
42
45
|
* Creates a new workflow or updates an existing workflow. If the workflow already exists, Hatchet will automatically
|
|
@@ -46,9 +49,7 @@ class AdminClient {
|
|
|
46
49
|
put_workflow(workflow) {
|
|
47
50
|
return __awaiter(this, void 0, void 0, function* () {
|
|
48
51
|
try {
|
|
49
|
-
yield this.client.putWorkflow({
|
|
50
|
-
opts: workflow,
|
|
51
|
-
});
|
|
52
|
+
yield (0, retrier_1.retrier)(() => __awaiter(this, void 0, void 0, function* () { return this.client.putWorkflow({ opts: workflow }); }), this.logger);
|
|
52
53
|
}
|
|
53
54
|
catch (e) {
|
|
54
55
|
throw new hatchet_error_1.default(e.message);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DispatcherClient as PbDispatcherClient, AssignedAction } from '../../protoc/dispatcher';
|
|
2
2
|
import { ClientConfig } from '../hatchet-client/client-config';
|
|
3
|
+
import { Logger } from '../../util/logger';
|
|
3
4
|
import { DispatcherClient } from './dispatcher-client';
|
|
4
5
|
export interface Action {
|
|
5
6
|
tenantId: string;
|
|
@@ -17,10 +18,15 @@ export interface Action {
|
|
|
17
18
|
export declare class ActionListener {
|
|
18
19
|
config: ClientConfig;
|
|
19
20
|
client: PbDispatcherClient;
|
|
20
|
-
listener: AsyncIterable<AssignedAction>;
|
|
21
21
|
workerId: string;
|
|
22
|
-
|
|
22
|
+
logger: Logger;
|
|
23
|
+
lastConnectionAttempt: number;
|
|
24
|
+
retries: number;
|
|
25
|
+
retryInterval: number;
|
|
26
|
+
retryCount: number;
|
|
27
|
+
constructor(client: DispatcherClient, workerId: string, retryInterval?: number, retryCount?: number);
|
|
23
28
|
actions: () => AsyncGenerator<Action, void, unknown>;
|
|
24
|
-
|
|
29
|
+
incrementRetries(): Promise<void>;
|
|
30
|
+
getListenClient(): Promise<AsyncIterable<AssignedAction>>;
|
|
25
31
|
unregister(): Promise<import("../../protoc/dispatcher").WorkerUnsubscribeResponse>;
|
|
26
32
|
}
|
|
@@ -8,6 +8,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
+
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
|
|
11
12
|
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
12
13
|
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
13
14
|
var m = o[Symbol.asyncIterator], i;
|
|
@@ -15,7 +16,6 @@ var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
|
15
16
|
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
17
|
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
17
18
|
};
|
|
18
|
-
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
|
|
19
19
|
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
|
|
20
20
|
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
21
21
|
var g = generator.apply(thisArg, _arguments || []), i, q = [];
|
|
@@ -36,17 +36,22 @@ exports.ActionListener = void 0;
|
|
|
36
36
|
const nice_grpc_1 = require("nice-grpc");
|
|
37
37
|
const sleep_1 = __importDefault(require("../../util/sleep"));
|
|
38
38
|
const hatchet_error_1 = __importDefault(require("../../util/errors/hatchet-error"));
|
|
39
|
-
const
|
|
39
|
+
const logger_1 = require("../../util/logger");
|
|
40
|
+
const DEFAULT_ACTION_LISTENER_RETRY_INTERVAL = 5000; // milliseconds
|
|
40
41
|
const DEFAULT_ACTION_LISTENER_RETRY_COUNT = 5;
|
|
41
42
|
class ActionListener {
|
|
42
|
-
constructor(client,
|
|
43
|
+
constructor(client, workerId, retryInterval = DEFAULT_ACTION_LISTENER_RETRY_INTERVAL, retryCount = DEFAULT_ACTION_LISTENER_RETRY_COUNT) {
|
|
44
|
+
this.lastConnectionAttempt = 0;
|
|
45
|
+
this.retries = 0;
|
|
46
|
+
this.retryInterval = DEFAULT_ACTION_LISTENER_RETRY_INTERVAL;
|
|
47
|
+
this.retryCount = DEFAULT_ACTION_LISTENER_RETRY_COUNT;
|
|
43
48
|
this.actions = () => (function gen(client) {
|
|
44
49
|
return __asyncGenerator(this, arguments, function* gen_1() {
|
|
45
50
|
var _a, e_1, _b, _c;
|
|
46
51
|
while (true) {
|
|
47
52
|
try {
|
|
48
53
|
try {
|
|
49
|
-
for (var _d = true, _e = (e_1 = void 0, __asyncValues(client.
|
|
54
|
+
for (var _d = true, _e = (e_1 = void 0, __asyncValues(yield __await(client.getListenClient()))), _f; _f = yield __await(_e.next()), _a = _f.done, !_a; _d = true) {
|
|
50
55
|
_c = _f.value;
|
|
51
56
|
_d = false;
|
|
52
57
|
const assignedAction = _c;
|
|
@@ -63,38 +68,55 @@ class ActionListener {
|
|
|
63
68
|
}
|
|
64
69
|
}
|
|
65
70
|
catch (e) {
|
|
71
|
+
// if this is a HatchetError, we should throw this error
|
|
72
|
+
if (e instanceof hatchet_error_1.default) {
|
|
73
|
+
throw e;
|
|
74
|
+
}
|
|
66
75
|
if (e.code === nice_grpc_1.Status.CANCELLED) {
|
|
67
76
|
break;
|
|
68
77
|
}
|
|
69
|
-
|
|
70
|
-
client.retrySubscribe();
|
|
71
|
-
}
|
|
72
|
-
break;
|
|
78
|
+
client.incrementRetries();
|
|
73
79
|
}
|
|
74
80
|
}
|
|
75
81
|
});
|
|
76
82
|
})(this);
|
|
77
83
|
this.config = client.config;
|
|
78
84
|
this.client = client.client;
|
|
79
|
-
this.listener = listener;
|
|
80
85
|
this.workerId = workerId;
|
|
86
|
+
this.logger = new logger_1.Logger(`ActionListener`, this.config.log_level);
|
|
87
|
+
this.retryInterval = retryInterval;
|
|
88
|
+
this.retryCount = retryCount;
|
|
81
89
|
}
|
|
82
|
-
|
|
90
|
+
incrementRetries() {
|
|
83
91
|
return __awaiter(this, void 0, void 0, function* () {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
92
|
+
this.retries += 1;
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
getListenClient() {
|
|
96
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
97
|
+
const currentTime = Math.floor(Date.now());
|
|
98
|
+
// subtract 1000 from the last connection attempt to account for the time it takes to establish the listener
|
|
99
|
+
if (currentTime - this.lastConnectionAttempt - 1000 > this.retryInterval) {
|
|
100
|
+
this.retries = 0;
|
|
101
|
+
}
|
|
102
|
+
this.lastConnectionAttempt = currentTime;
|
|
103
|
+
if (this.retries > DEFAULT_ACTION_LISTENER_RETRY_COUNT) {
|
|
104
|
+
throw new hatchet_error_1.default(`Could not subscribe to the worker after ${DEFAULT_ACTION_LISTENER_RETRY_COUNT} retries`);
|
|
105
|
+
}
|
|
106
|
+
this.logger.info(`Connecting to Hatchet to establish listener for actions... ${this.retries}/${DEFAULT_ACTION_LISTENER_RETRY_COUNT} (last attempt: ${this.lastConnectionAttempt})`);
|
|
107
|
+
if (this.retries >= 1) {
|
|
108
|
+
yield (0, sleep_1.default)(DEFAULT_ACTION_LISTENER_RETRY_INTERVAL);
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
return this.client.listen({
|
|
112
|
+
workerId: this.workerId,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
catch (e) {
|
|
116
|
+
this.retries += 1;
|
|
117
|
+
this.logger.error(`Attempt ${this.retries}: Failed to connect, retrying...`); // Optional: log retry attempt
|
|
118
|
+
return this.getListenClient();
|
|
96
119
|
}
|
|
97
|
-
throw new hatchet_error_1.default(`Could not subscribe to the worker after ${DEFAULT_ACTION_LISTENER_RETRY_COUNT} retries`);
|
|
98
120
|
});
|
|
99
121
|
}
|
|
100
122
|
unregister() {
|
|
@@ -16,6 +16,7 @@ exports.DispatcherClient = void 0;
|
|
|
16
16
|
const dispatcher_1 = require("../../protoc/dispatcher");
|
|
17
17
|
const hatchet_error_1 = __importDefault(require("../../util/errors/hatchet-error"));
|
|
18
18
|
const logger_1 = require("../../util/logger");
|
|
19
|
+
const retrier_1 = require("../../util/retrier");
|
|
19
20
|
const action_listener_1 = require("./action-listener");
|
|
20
21
|
class DispatcherClient {
|
|
21
22
|
constructor(config, channel, factory) {
|
|
@@ -27,17 +28,13 @@ class DispatcherClient {
|
|
|
27
28
|
return __awaiter(this, void 0, void 0, function* () {
|
|
28
29
|
// Register the worker
|
|
29
30
|
const registration = yield this.client.register(Object.assign({}, options));
|
|
30
|
-
|
|
31
|
-
const listener = this.client.listen({
|
|
32
|
-
workerId: registration.workerId,
|
|
33
|
-
});
|
|
34
|
-
return new action_listener_1.ActionListener(this, listener, registration.workerId);
|
|
31
|
+
return new action_listener_1.ActionListener(this, registration.workerId);
|
|
35
32
|
});
|
|
36
33
|
}
|
|
37
34
|
sendStepActionEvent(in_) {
|
|
38
35
|
return __awaiter(this, void 0, void 0, function* () {
|
|
39
36
|
try {
|
|
40
|
-
return this.client.sendStepActionEvent(in_);
|
|
37
|
+
return (0, retrier_1.retrier)(() => __awaiter(this, void 0, void 0, function* () { return this.client.sendStepActionEvent(in_); }), this.logger);
|
|
41
38
|
}
|
|
42
39
|
catch (e) {
|
|
43
40
|
throw new hatchet_error_1.default(e.message);
|
|
@@ -47,7 +44,7 @@ class DispatcherClient {
|
|
|
47
44
|
sendGroupKeyActionEvent(in_) {
|
|
48
45
|
return __awaiter(this, void 0, void 0, function* () {
|
|
49
46
|
try {
|
|
50
|
-
return this.client.sendGroupKeyActionEvent(in_);
|
|
47
|
+
return (0, retrier_1.retrier)(() => __awaiter(this, void 0, void 0, function* () { return this.client.sendGroupKeyActionEvent(in_); }), this.logger);
|
|
51
48
|
}
|
|
52
49
|
catch (e) {
|
|
53
50
|
throw new hatchet_error_1.default(e.message);
|
|
@@ -25,7 +25,6 @@ export declare class HatchetClient {
|
|
|
25
25
|
tenantId: string;
|
|
26
26
|
logger: Logger;
|
|
27
27
|
constructor(config?: Partial<ClientConfig>, options?: HatchetClientOptions, axiosOpts?: AxiosRequestConfig);
|
|
28
|
-
static with_host_port(host: string, port: number, config?: Partial<ClientConfig>, options?: HatchetClientOptions): HatchetClient;
|
|
29
28
|
static init(config?: Partial<ClientConfig>, options?: HatchetClientOptions, axiosConfig?: AxiosRequestConfig): HatchetClient;
|
|
30
29
|
run(workflow: string | Workflow): Promise<Worker>;
|
|
31
30
|
worker(workflow: string | Workflow, maxRuns?: number): Promise<Worker>;
|
|
@@ -80,11 +80,11 @@ class HatchetClient {
|
|
|
80
80
|
// Initializes a new Client instance.
|
|
81
81
|
// Loads config in the following order: config param > yaml file > env vars
|
|
82
82
|
var _a;
|
|
83
|
-
const loaded = config_loader_1.ConfigLoader.loadClientConfig({
|
|
83
|
+
const loaded = config_loader_1.ConfigLoader.loadClientConfig(config, {
|
|
84
84
|
path: options === null || options === void 0 ? void 0 : options.config_path,
|
|
85
85
|
});
|
|
86
86
|
try {
|
|
87
|
-
const valid = client_config_1.ClientConfigSchema.parse(
|
|
87
|
+
const valid = client_config_1.ClientConfigSchema.parse(loaded);
|
|
88
88
|
this.config = valid;
|
|
89
89
|
}
|
|
90
90
|
catch (e) {
|
|
@@ -97,6 +97,12 @@ class HatchetClient {
|
|
|
97
97
|
(_a = options === null || options === void 0 ? void 0 : options.credentials) !== null && _a !== void 0 ? _a : config_loader_1.ConfigLoader.createCredentials(this.config.tls_config);
|
|
98
98
|
this.channel = (0, nice_grpc_1.createChannel)(this.config.host_port, this.credentials, {
|
|
99
99
|
'grpc.ssl_target_name_override': this.config.tls_config.server_name,
|
|
100
|
+
'grpc.keepalive_timeout_ms': 60 * 1000,
|
|
101
|
+
'grpc.client_idle_timeout_ms': 60 * 1000,
|
|
102
|
+
// Send keepalive pings every 10 seconds, default is 2 hours.
|
|
103
|
+
'grpc.keepalive_time_ms': 10 * 1000,
|
|
104
|
+
// Allow keepalive pings when there are no gRPC calls.
|
|
105
|
+
'grpc.keepalive_permit_without_calls': 1,
|
|
100
106
|
});
|
|
101
107
|
const clientFactory = (0, nice_grpc_1.createClientFactory)().use(addTokenMiddleware(this.config.token));
|
|
102
108
|
this.tenantId = this.config.tenant_id;
|
|
@@ -108,9 +114,6 @@ class HatchetClient {
|
|
|
108
114
|
this.logger = new logger_1.default('HatchetClient', this.config.log_level);
|
|
109
115
|
this.logger.info(`Initialized HatchetClient`);
|
|
110
116
|
}
|
|
111
|
-
static with_host_port(host, port, config, options) {
|
|
112
|
-
return new HatchetClient(Object.assign(Object.assign({}, config), { host_port: `${host}:${port}` }), options);
|
|
113
|
-
}
|
|
114
117
|
static init(config, options, axiosConfig) {
|
|
115
118
|
return new HatchetClient(config, options, axiosConfig);
|
|
116
119
|
}
|
|
@@ -7,7 +7,6 @@ import { Logger } from '../../util/logger';
|
|
|
7
7
|
import { Context, StepRunFunction } from '../../step';
|
|
8
8
|
export type ActionRegistry = Record<Action['actionId'], Function>;
|
|
9
9
|
export declare class Worker {
|
|
10
|
-
serviceName: string;
|
|
11
10
|
client: HatchetClient;
|
|
12
11
|
name: string;
|
|
13
12
|
killing: boolean;
|
package/clients/worker/worker.js
CHANGED
|
@@ -25,11 +25,10 @@ const dispatcher_1 = require("../../protoc/dispatcher");
|
|
|
25
25
|
const hatchet_promise_1 = __importDefault(require("../../util/hatchet-promise/hatchet-promise"));
|
|
26
26
|
const workflows_1 = require("../../protoc/workflows");
|
|
27
27
|
const logger_1 = require("../../util/logger");
|
|
28
|
-
|
|
28
|
+
// import sleep from '../../util/sleep.js';
|
|
29
29
|
const step_1 = require("../../step");
|
|
30
30
|
class Worker {
|
|
31
31
|
constructor(client, options) {
|
|
32
|
-
this.serviceName = 'default';
|
|
33
32
|
this.futures = {};
|
|
34
33
|
this.contexts = {};
|
|
35
34
|
this.client = client;
|
|
@@ -48,7 +47,7 @@ class Worker {
|
|
|
48
47
|
try {
|
|
49
48
|
const concurrency = ((_a = workflow.concurrency) === null || _a === void 0 ? void 0 : _a.name)
|
|
50
49
|
? {
|
|
51
|
-
action: `${
|
|
50
|
+
action: `${workflow.id}:${workflow.concurrency.name}`,
|
|
52
51
|
maxRuns: workflow.concurrency.maxRuns || 1,
|
|
53
52
|
limitStrategy: workflow.concurrency.limitStrategy || workflows_1.ConcurrencyLimitStrategy.CANCEL_IN_PROGRESS,
|
|
54
53
|
}
|
|
@@ -61,6 +60,7 @@ class Worker {
|
|
|
61
60
|
cronTriggers: workflow.on.cron ? [workflow.on.cron] : [],
|
|
62
61
|
scheduledTriggers: [],
|
|
63
62
|
concurrency,
|
|
63
|
+
scheduleTimeout: workflow.scheduleTimeout,
|
|
64
64
|
jobs: [
|
|
65
65
|
{
|
|
66
66
|
name: workflow.id,
|
|
@@ -70,7 +70,7 @@ class Worker {
|
|
|
70
70
|
var _a;
|
|
71
71
|
return ({
|
|
72
72
|
readableId: step.name,
|
|
73
|
-
action: `${
|
|
73
|
+
action: `${workflow.id}:${step.name}`,
|
|
74
74
|
timeout: step.timeout || '60s',
|
|
75
75
|
inputs: '{}',
|
|
76
76
|
parents: (_a = step.parents) !== null && _a !== void 0 ? _a : [],
|
|
@@ -85,12 +85,13 @@ class Worker {
|
|
|
85
85
|
catch (e) {
|
|
86
86
|
throw new hatchet_error_1.default(`Could not register workflow: ${e.message}`);
|
|
87
87
|
}
|
|
88
|
-
|
|
89
|
-
acc[`${
|
|
88
|
+
const newActions = workflow.steps.reduce((acc, step) => {
|
|
89
|
+
acc[`${workflow.id}:${step.name}`] = step.run;
|
|
90
90
|
return acc;
|
|
91
91
|
}, {});
|
|
92
|
+
this.action_registry = Object.assign(Object.assign({}, this.action_registry), newActions);
|
|
92
93
|
this.action_registry = ((_b = workflow.concurrency) === null || _b === void 0 ? void 0 : _b.name)
|
|
93
|
-
? Object.assign(Object.assign({}, this.action_registry), { [`${
|
|
94
|
+
? Object.assign(Object.assign({}, this.action_registry), { [`${workflow.id}:${workflow.concurrency.name}`]: workflow.concurrency.key }) : Object.assign({}, this.action_registry);
|
|
94
95
|
});
|
|
95
96
|
}
|
|
96
97
|
registerAction(actionId, action) {
|
|
@@ -270,58 +271,46 @@ class Worker {
|
|
|
270
271
|
start() {
|
|
271
272
|
var _a, e_1, _b, _c;
|
|
272
273
|
return __awaiter(this, void 0, void 0, function* () {
|
|
273
|
-
|
|
274
|
-
|
|
274
|
+
try {
|
|
275
|
+
this.listener = yield this.client.dispatcher.getActionListener({
|
|
276
|
+
workerName: this.name,
|
|
277
|
+
services: ['default'],
|
|
278
|
+
actions: Object.keys(this.action_registry),
|
|
279
|
+
maxRuns: this.maxRuns,
|
|
280
|
+
});
|
|
281
|
+
const generator = this.listener.actions();
|
|
282
|
+
this.logger.info(`Worker ${this.name} listening for actions`);
|
|
275
283
|
try {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
this.logger.info(`Worker ${this.name} listening for actions`);
|
|
284
|
-
try {
|
|
285
|
-
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) {
|
|
286
|
-
_c = generator_1_1.value;
|
|
287
|
-
_d = false;
|
|
288
|
-
const action = _c;
|
|
289
|
-
this.logger.info(`Worker ${this.name} received action ${action.actionId}:${action.actionType}`);
|
|
290
|
-
if (action.actionType === dispatcher_1.ActionType.START_STEP_RUN) {
|
|
291
|
-
this.handleStartStepRun(action);
|
|
292
|
-
}
|
|
293
|
-
else if (action.actionType === dispatcher_1.ActionType.CANCEL_STEP_RUN) {
|
|
294
|
-
this.handleCancelStepRun(action);
|
|
295
|
-
}
|
|
296
|
-
else if (action.actionType === dispatcher_1.ActionType.START_GET_GROUP_KEY) {
|
|
297
|
-
this.handleStartGroupKeyRun(action);
|
|
298
|
-
}
|
|
299
|
-
else {
|
|
300
|
-
this.logger.error(`Worker ${this.name} received unknown action type ${action.actionType}`);
|
|
301
|
-
}
|
|
284
|
+
for (var _d = true, generator_1 = __asyncValues(generator), generator_1_1; generator_1_1 = yield generator_1.next(), _a = generator_1_1.done, !_a; _d = true) {
|
|
285
|
+
_c = generator_1_1.value;
|
|
286
|
+
_d = false;
|
|
287
|
+
const action = _c;
|
|
288
|
+
this.logger.info(`Worker ${this.name} received action ${action.actionId}:${action.actionType}`);
|
|
289
|
+
if (action.actionType === dispatcher_1.ActionType.START_STEP_RUN) {
|
|
290
|
+
this.handleStartStepRun(action);
|
|
302
291
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
292
|
+
else if (action.actionType === dispatcher_1.ActionType.CANCEL_STEP_RUN) {
|
|
293
|
+
this.handleCancelStepRun(action);
|
|
294
|
+
}
|
|
295
|
+
else if (action.actionType === dispatcher_1.ActionType.START_GET_GROUP_KEY) {
|
|
296
|
+
this.handleStartGroupKeyRun(action);
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
this.logger.error(`Worker ${this.name} received unknown action type ${action.actionType}`);
|
|
308
300
|
}
|
|
309
|
-
finally { if (e_1) throw e_1.error; }
|
|
310
301
|
}
|
|
311
|
-
break;
|
|
312
302
|
}
|
|
313
|
-
catch (
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
303
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
304
|
+
finally {
|
|
305
|
+
try {
|
|
306
|
+
if (!_d && !_a && (_b = generator_1.return)) yield _b.call(generator_1);
|
|
307
|
+
}
|
|
308
|
+
finally { if (e_1) throw e_1.error; }
|
|
319
309
|
}
|
|
320
310
|
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
throw new hatchet_error_1.default('Could not start worker after 5 retries');
|
|
311
|
+
catch (e) {
|
|
312
|
+
this.logger.error(`Could not run worker: ${e.message}`);
|
|
313
|
+
throw new hatchet_error_1.default(`Could not run worker: ${e.message}`);
|
|
325
314
|
}
|
|
326
315
|
});
|
|
327
316
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hatchet-dev/typescript-sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.18",
|
|
4
4
|
"description": "Background task orchestration & visibility for developers",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"worker:concurrency:rr": "npm run exec -- ./examples/concurrency/group-round-robin/concurrency-worker.ts",
|
|
37
37
|
"event:concurrency:rr": "npm run exec -- ./examples/concurrency/group-round-robin/concurrency-event.ts",
|
|
38
38
|
"worker:retries": "npm run exec -- ./examples/retries-worker.ts",
|
|
39
|
+
"worker:multi-workflow": "npm run exec -- ./examples/multi-workflow.ts",
|
|
39
40
|
"api": "npm run exec -- ./examples/api.ts",
|
|
40
41
|
"prepublish": "cp package.json dist/package.json;",
|
|
41
42
|
"publish:ci": "rm -rf ./dist && npm run tsc:build && npm run prepublish && cd dist && npm publish --access public --no-git-checks",
|
|
@@ -31,6 +31,8 @@ export interface CreateWorkflowVersionOpts {
|
|
|
31
31
|
jobs: CreateWorkflowJobOpts[];
|
|
32
32
|
/** (optional) the workflow concurrency options */
|
|
33
33
|
concurrency: WorkflowConcurrencyOpts | undefined;
|
|
34
|
+
/** (optional) the timeout for the schedule */
|
|
35
|
+
scheduleTimeout?: string | undefined;
|
|
34
36
|
}
|
|
35
37
|
export interface WorkflowConcurrencyOpts {
|
|
36
38
|
/** (required) the action id for getting the concurrency group */
|
|
@@ -135,6 +135,7 @@ function createBaseCreateWorkflowVersionOpts() {
|
|
|
135
135
|
scheduledTriggers: [],
|
|
136
136
|
jobs: [],
|
|
137
137
|
concurrency: undefined,
|
|
138
|
+
scheduleTimeout: undefined,
|
|
138
139
|
};
|
|
139
140
|
}
|
|
140
141
|
exports.CreateWorkflowVersionOpts = {
|
|
@@ -163,6 +164,9 @@ exports.CreateWorkflowVersionOpts = {
|
|
|
163
164
|
if (message.concurrency !== undefined) {
|
|
164
165
|
exports.WorkflowConcurrencyOpts.encode(message.concurrency, writer.uint32(66).fork()).ldelim();
|
|
165
166
|
}
|
|
167
|
+
if (message.scheduleTimeout !== undefined) {
|
|
168
|
+
writer.uint32(74).string(message.scheduleTimeout);
|
|
169
|
+
}
|
|
166
170
|
return writer;
|
|
167
171
|
},
|
|
168
172
|
decode(input, length) {
|
|
@@ -220,6 +224,12 @@ exports.CreateWorkflowVersionOpts = {
|
|
|
220
224
|
}
|
|
221
225
|
message.concurrency = exports.WorkflowConcurrencyOpts.decode(reader, reader.uint32());
|
|
222
226
|
continue;
|
|
227
|
+
case 9:
|
|
228
|
+
if (tag !== 74) {
|
|
229
|
+
break;
|
|
230
|
+
}
|
|
231
|
+
message.scheduleTimeout = reader.string();
|
|
232
|
+
continue;
|
|
223
233
|
}
|
|
224
234
|
if ((tag & 7) === 4 || tag === 0) {
|
|
225
235
|
break;
|
|
@@ -246,6 +256,7 @@ exports.CreateWorkflowVersionOpts = {
|
|
|
246
256
|
? object.jobs.map((e) => exports.CreateWorkflowJobOpts.fromJSON(e))
|
|
247
257
|
: [],
|
|
248
258
|
concurrency: isSet(object.concurrency) ? exports.WorkflowConcurrencyOpts.fromJSON(object.concurrency) : undefined,
|
|
259
|
+
scheduleTimeout: isSet(object.scheduleTimeout) ? globalThis.String(object.scheduleTimeout) : undefined,
|
|
249
260
|
};
|
|
250
261
|
},
|
|
251
262
|
toJSON(message) {
|
|
@@ -275,13 +286,16 @@ exports.CreateWorkflowVersionOpts = {
|
|
|
275
286
|
if (message.concurrency !== undefined) {
|
|
276
287
|
obj.concurrency = exports.WorkflowConcurrencyOpts.toJSON(message.concurrency);
|
|
277
288
|
}
|
|
289
|
+
if (message.scheduleTimeout !== undefined) {
|
|
290
|
+
obj.scheduleTimeout = message.scheduleTimeout;
|
|
291
|
+
}
|
|
278
292
|
return obj;
|
|
279
293
|
},
|
|
280
294
|
create(base) {
|
|
281
295
|
return exports.CreateWorkflowVersionOpts.fromPartial(base !== null && base !== void 0 ? base : {});
|
|
282
296
|
},
|
|
283
297
|
fromPartial(object) {
|
|
284
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
298
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
285
299
|
const message = createBaseCreateWorkflowVersionOpts();
|
|
286
300
|
message.name = (_a = object.name) !== null && _a !== void 0 ? _a : "";
|
|
287
301
|
message.description = (_b = object.description) !== null && _b !== void 0 ? _b : "";
|
|
@@ -293,6 +307,7 @@ exports.CreateWorkflowVersionOpts = {
|
|
|
293
307
|
message.concurrency = (object.concurrency !== undefined && object.concurrency !== null)
|
|
294
308
|
? exports.WorkflowConcurrencyOpts.fromPartial(object.concurrency)
|
|
295
309
|
: undefined;
|
|
310
|
+
message.scheduleTimeout = (_h = object.scheduleTimeout) !== null && _h !== void 0 ? _h : undefined;
|
|
296
311
|
return message;
|
|
297
312
|
},
|
|
298
313
|
};
|
|
@@ -4,7 +4,7 @@ interface LoadClientConfigOptions {
|
|
|
4
4
|
path?: string;
|
|
5
5
|
}
|
|
6
6
|
export declare class ConfigLoader {
|
|
7
|
-
static loadClientConfig(config?: LoadClientConfigOptions): Partial<ClientConfig>;
|
|
7
|
+
static loadClientConfig(override?: Partial<ClientConfig>, config?: LoadClientConfigOptions): Partial<ClientConfig>;
|
|
8
8
|
static get default_yaml_config_path(): string;
|
|
9
9
|
static createCredentials(config: ClientConfig['tls_config']): ChannelCredentials;
|
|
10
10
|
static loadYamlConfig(path?: string): ClientConfig | undefined;
|
|
@@ -33,17 +33,17 @@ const nice_grpc_1 = require("nice-grpc");
|
|
|
33
33
|
const token_1 = require("./token");
|
|
34
34
|
const DEFAULT_CONFIG_FILE = '.hatchet.yaml';
|
|
35
35
|
class ConfigLoader {
|
|
36
|
-
static loadClientConfig(config) {
|
|
37
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
|
|
36
|
+
static loadClientConfig(override, config) {
|
|
37
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2;
|
|
38
38
|
const yaml = this.loadYamlConfig(config === null || config === void 0 ? void 0 : config.path);
|
|
39
|
-
const tlsConfig = {
|
|
40
|
-
tls_strategy: (
|
|
41
|
-
cert_file: (
|
|
42
|
-
key_file: (
|
|
43
|
-
ca_file: (
|
|
44
|
-
server_name: (
|
|
39
|
+
const tlsConfig = (_a = override === null || override === void 0 ? void 0 : override.tls_config) !== null && _a !== void 0 ? _a : {
|
|
40
|
+
tls_strategy: (_d = (_c = (_b = yaml === null || yaml === void 0 ? void 0 : yaml.tls_config) === null || _b === void 0 ? void 0 : _b.tls_strategy) !== null && _c !== void 0 ? _c : this.env('HATCHET_CLIENT_TLS_STRATEGY')) !== null && _d !== void 0 ? _d : 'tls',
|
|
41
|
+
cert_file: (_f = (_e = yaml === null || yaml === void 0 ? void 0 : yaml.tls_config) === null || _e === void 0 ? void 0 : _e.cert_file) !== null && _f !== void 0 ? _f : this.env('HATCHET_CLIENT_TLS_CERT_FILE'),
|
|
42
|
+
key_file: (_h = (_g = yaml === null || yaml === void 0 ? void 0 : yaml.tls_config) === null || _g === void 0 ? void 0 : _g.key_file) !== null && _h !== void 0 ? _h : this.env('HATCHET_CLIENT_TLS_KEY_FILE'),
|
|
43
|
+
ca_file: (_k = (_j = yaml === null || yaml === void 0 ? void 0 : yaml.tls_config) === null || _j === void 0 ? void 0 : _j.ca_file) !== null && _k !== void 0 ? _k : this.env('HATCHET_CLIENT_TLS_ROOT_CA_FILE'),
|
|
44
|
+
server_name: (_m = (_l = yaml === null || yaml === void 0 ? void 0 : yaml.tls_config) === null || _l === void 0 ? void 0 : _l.server_name) !== null && _m !== void 0 ? _m : this.env('HATCHET_CLIENT_TLS_SERVER_NAME'),
|
|
45
45
|
};
|
|
46
|
-
const token = (
|
|
46
|
+
const token = (_p = (_o = override === null || override === void 0 ? void 0 : override.token) !== null && _o !== void 0 ? _o : yaml === null || yaml === void 0 ? void 0 : yaml.token) !== null && _p !== void 0 ? _p : this.env('HATCHET_CLIENT_TOKEN');
|
|
47
47
|
let grpcBroadcastAddress;
|
|
48
48
|
let apiUrl;
|
|
49
49
|
const tenantId = (0, token_1.getTenantIdFromJWT)(token);
|
|
@@ -53,19 +53,20 @@ class ConfigLoader {
|
|
|
53
53
|
try {
|
|
54
54
|
const addresses = (0, token_1.getAddressesFromJWT)(token);
|
|
55
55
|
grpcBroadcastAddress =
|
|
56
|
-
(
|
|
57
|
-
apiUrl =
|
|
56
|
+
(_r = (_q = yaml === null || yaml === void 0 ? void 0 : yaml.host_port) !== null && _q !== void 0 ? _q : this.env('HATCHET_CLIENT_HOST_PORT')) !== null && _r !== void 0 ? _r : addresses.grpcBroadcastAddress;
|
|
57
|
+
apiUrl =
|
|
58
|
+
(_u = (_t = (_s = override === null || override === void 0 ? void 0 : override.api_url) !== null && _s !== void 0 ? _s : yaml === null || yaml === void 0 ? void 0 : yaml.api_url) !== null && _t !== void 0 ? _t : this.env('HATCHET_CLIENT_API_URL')) !== null && _u !== void 0 ? _u : addresses.serverUrl;
|
|
58
59
|
}
|
|
59
60
|
catch (e) {
|
|
60
|
-
grpcBroadcastAddress = (
|
|
61
|
-
apiUrl = (
|
|
61
|
+
grpcBroadcastAddress = (_v = yaml === null || yaml === void 0 ? void 0 : yaml.host_port) !== null && _v !== void 0 ? _v : this.env('HATCHET_CLIENT_HOST_PORT');
|
|
62
|
+
apiUrl = (_x = (_w = override === null || override === void 0 ? void 0 : override.api_url) !== null && _w !== void 0 ? _w : yaml === null || yaml === void 0 ? void 0 : yaml.api_url) !== null && _x !== void 0 ? _x : this.env('HATCHET_CLIENT_API_URL');
|
|
62
63
|
}
|
|
63
64
|
return {
|
|
64
|
-
token: (
|
|
65
|
+
token: (_z = (_y = override === null || override === void 0 ? void 0 : override.token) !== null && _y !== void 0 ? _y : yaml === null || yaml === void 0 ? void 0 : yaml.token) !== null && _z !== void 0 ? _z : this.env('HATCHET_CLIENT_TOKEN'),
|
|
65
66
|
host_port: grpcBroadcastAddress,
|
|
66
67
|
api_url: apiUrl,
|
|
67
68
|
tls_config: tlsConfig,
|
|
68
|
-
log_level: (
|
|
69
|
+
log_level: (_2 = (_1 = (_0 = override === null || override === void 0 ? void 0 : override.log_level) !== null && _0 !== void 0 ? _0 : yaml === null || yaml === void 0 ? void 0 : yaml.log_level) !== null && _1 !== void 0 ? _1 : this.env('HATCHET_CLIENT_LOG_LEVEL')) !== null && _2 !== void 0 ? _2 : 'INFO',
|
|
69
70
|
tenant_id: tenantId,
|
|
70
71
|
};
|
|
71
72
|
}
|
package/util/retrier.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
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.retrier = void 0;
|
|
16
|
+
const sleep_1 = __importDefault(require("./sleep"));
|
|
17
|
+
const DEFAULT_RETRY_INTERVAL = 5;
|
|
18
|
+
const DEFAULT_RETRY_COUNT = 5;
|
|
19
|
+
function retrier(fn, logger, retries = DEFAULT_RETRY_COUNT, interval = DEFAULT_RETRY_INTERVAL) {
|
|
20
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
21
|
+
let lastError;
|
|
22
|
+
// eslint-disable-next-line no-plusplus
|
|
23
|
+
for (let i = 0; i < retries; i++) {
|
|
24
|
+
try {
|
|
25
|
+
return yield fn();
|
|
26
|
+
}
|
|
27
|
+
catch (e) {
|
|
28
|
+
lastError = e;
|
|
29
|
+
logger.error(`Error: ${e.message}`);
|
|
30
|
+
yield (0, sleep_1.default)(interval * 1000);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
throw lastError;
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
exports.retrier = retrier;
|
package/workflow.d.ts
CHANGED
|
@@ -37,6 +37,7 @@ export declare const CreateWorkflowSchema: z.ZodObject<{
|
|
|
37
37
|
id: z.ZodString;
|
|
38
38
|
description: z.ZodString;
|
|
39
39
|
version: z.ZodOptional<z.ZodString>;
|
|
40
|
+
scheduleTimeout: z.ZodOptional<z.ZodString>;
|
|
40
41
|
timeout: z.ZodOptional<z.ZodString>;
|
|
41
42
|
on: z.ZodUnion<[z.ZodObject<{
|
|
42
43
|
cron: z.ZodString;
|
|
@@ -90,6 +91,7 @@ export declare const CreateWorkflowSchema: z.ZodObject<{
|
|
|
90
91
|
cron?: undefined;
|
|
91
92
|
};
|
|
92
93
|
version?: string | undefined;
|
|
94
|
+
scheduleTimeout?: string | undefined;
|
|
93
95
|
timeout?: string | undefined;
|
|
94
96
|
}, {
|
|
95
97
|
description: string;
|
|
@@ -108,6 +110,7 @@ export declare const CreateWorkflowSchema: z.ZodObject<{
|
|
|
108
110
|
cron?: undefined;
|
|
109
111
|
};
|
|
110
112
|
version?: string | undefined;
|
|
113
|
+
scheduleTimeout?: string | undefined;
|
|
111
114
|
timeout?: string | undefined;
|
|
112
115
|
}>;
|
|
113
116
|
export interface Workflow extends z.infer<typeof CreateWorkflowSchema> {
|
package/workflow.js
CHANGED
|
@@ -48,6 +48,7 @@ exports.CreateWorkflowSchema = z.object({
|
|
|
48
48
|
id: z.string(),
|
|
49
49
|
description: z.string(),
|
|
50
50
|
version: z.string().optional(),
|
|
51
|
+
scheduleTimeout: z.string().optional(),
|
|
51
52
|
timeout: exports.HatchetTimeoutSchema.optional(),
|
|
52
53
|
on: OnConfigSchema,
|
|
53
54
|
steps: StepsSchema,
|