@hatchet-dev/typescript-sdk 0.1.31 → 0.2.1

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.
@@ -39,7 +39,12 @@ export declare class AdminClient {
39
39
  * @param input an object containing the input to the workflow
40
40
  * @returns the ID of the new workflow run
41
41
  */
42
- run_workflow(workflowName: string, input: object): Promise<string>;
42
+ run_workflow<T = object>(workflowName: string, input: T, options?: {
43
+ parentId?: string | undefined;
44
+ parentStepRunId?: string | undefined;
45
+ childIndex?: number | undefined;
46
+ childKey?: string | undefined;
47
+ }): Promise<string>;
43
48
  /**
44
49
  * List workflows in the tenant associated with the API token.
45
50
  * @returns a list of all workflows in the tenant
@@ -63,14 +63,11 @@ class AdminClient {
63
63
  * @param input an object containing the input to the workflow
64
64
  * @returns the ID of the new workflow run
65
65
  */
66
- run_workflow(workflowName, input) {
66
+ run_workflow(workflowName, input, options) {
67
67
  return __awaiter(this, void 0, void 0, function* () {
68
68
  try {
69
69
  const inputStr = JSON.stringify(input);
70
- const resp = yield this.client.triggerWorkflow({
71
- name: workflowName,
72
- input: inputStr,
73
- });
70
+ const resp = yield this.client.triggerWorkflow(Object.assign({ name: workflowName, input: inputStr }, options));
74
71
  return resp.workflowRunId;
75
72
  }
76
73
  catch (e) {
@@ -2,6 +2,10 @@ import { DispatcherClient as PbDispatcherClient, AssignedAction } from '../../pr
2
2
  import { ClientConfig } from '../hatchet-client/client-config';
3
3
  import { Logger } from '../../util/logger';
4
4
  import { DispatcherClient } from './dispatcher-client';
5
+ declare enum ListenStrategy {
6
+ LISTEN_STRATEGY_V1 = 1,
7
+ LISTEN_STRATEGY_V2 = 2
8
+ }
5
9
  export interface Action {
6
10
  tenantId: string;
7
11
  jobId: string;
@@ -26,9 +30,16 @@ export declare class ActionListener {
26
30
  retryInterval: number;
27
31
  retryCount: number;
28
32
  done: boolean;
33
+ listenStrategy: ListenStrategy;
34
+ heartbeatInterval: any;
29
35
  constructor(client: DispatcherClient, workerId: string, retryInterval?: number, retryCount?: number);
30
36
  actions: () => AsyncGenerator<Action, void, unknown>;
37
+ setListenStrategy(strategy: ListenStrategy): Promise<void>;
38
+ getListenStrategy(): Promise<ListenStrategy>;
31
39
  incrementRetries(): Promise<void>;
40
+ heartbeat(): Promise<void>;
41
+ closeHeartbeat(): void;
32
42
  getListenClient(): Promise<AsyncIterable<AssignedAction>>;
33
43
  unregister(): Promise<import("../../protoc/dispatcher").WorkerUnsubscribeResponse>;
34
44
  }
45
+ export {};
@@ -39,6 +39,12 @@ const hatchet_error_1 = __importDefault(require("../../util/errors/hatchet-error
39
39
  const logger_1 = require("../../util/logger");
40
40
  const DEFAULT_ACTION_LISTENER_RETRY_INTERVAL = 5000; // milliseconds
41
41
  const DEFAULT_ACTION_LISTENER_RETRY_COUNT = 5;
42
+ // eslint-disable-next-line no-shadow
43
+ var ListenStrategy;
44
+ (function (ListenStrategy) {
45
+ ListenStrategy[ListenStrategy["LISTEN_STRATEGY_V1"] = 1] = "LISTEN_STRATEGY_V1";
46
+ ListenStrategy[ListenStrategy["LISTEN_STRATEGY_V2"] = 2] = "LISTEN_STRATEGY_V2";
47
+ })(ListenStrategy || (ListenStrategy = {}));
42
48
  class ActionListener {
43
49
  constructor(client, workerId, retryInterval = DEFAULT_ACTION_LISTENER_RETRY_INTERVAL, retryCount = DEFAULT_ACTION_LISTENER_RETRY_COUNT) {
44
50
  this.lastConnectionAttempt = 0;
@@ -46,6 +52,7 @@ class ActionListener {
46
52
  this.retryInterval = DEFAULT_ACTION_LISTENER_RETRY_INTERVAL;
47
53
  this.retryCount = DEFAULT_ACTION_LISTENER_RETRY_COUNT;
48
54
  this.done = false;
55
+ this.listenStrategy = ListenStrategy.LISTEN_STRATEGY_V2;
49
56
  this.actions = () => (function gen(client) {
50
57
  return __asyncGenerator(this, arguments, function* gen_1() {
51
58
  var _a, e_1, _b, _c;
@@ -79,6 +86,10 @@ class ActionListener {
79
86
  if (e.code === nice_grpc_1.Status.CANCELLED) {
80
87
  break;
81
88
  }
89
+ if ((yield __await(client.getListenStrategy())) === ListenStrategy.LISTEN_STRATEGY_V2 &&
90
+ e.code === nice_grpc_1.Status.UNIMPLEMENTED) {
91
+ client.setListenStrategy(ListenStrategy.LISTEN_STRATEGY_V1);
92
+ }
82
93
  client.incrementRetries();
83
94
  }
84
95
  }
@@ -91,11 +102,62 @@ class ActionListener {
91
102
  this.retryInterval = retryInterval;
92
103
  this.retryCount = retryCount;
93
104
  }
105
+ setListenStrategy(strategy) {
106
+ return __awaiter(this, void 0, void 0, function* () {
107
+ this.listenStrategy = strategy;
108
+ });
109
+ }
110
+ getListenStrategy() {
111
+ return __awaiter(this, void 0, void 0, function* () {
112
+ return this.listenStrategy;
113
+ });
114
+ }
94
115
  incrementRetries() {
95
116
  return __awaiter(this, void 0, void 0, function* () {
96
117
  this.retries += 1;
97
118
  });
98
119
  }
120
+ heartbeat() {
121
+ return __awaiter(this, void 0, void 0, function* () {
122
+ if (this.heartbeatInterval) {
123
+ return;
124
+ }
125
+ // start with a heartbeat
126
+ try {
127
+ yield this.client.heartbeat({
128
+ workerId: this.workerId,
129
+ heartbeatAt: new Date(),
130
+ });
131
+ }
132
+ catch (e) {
133
+ this.logger.error(`Failed to send heartbeat: ${e.message}`);
134
+ if (e.code === nice_grpc_1.Status.UNIMPLEMENTED) {
135
+ return;
136
+ }
137
+ }
138
+ this.heartbeatInterval = setInterval(() => __awaiter(this, void 0, void 0, function* () {
139
+ try {
140
+ yield this.client.heartbeat({
141
+ workerId: this.workerId,
142
+ heartbeatAt: new Date(),
143
+ });
144
+ }
145
+ catch (e) {
146
+ if (e.code === nice_grpc_1.Status.UNIMPLEMENTED) {
147
+ // break out of interval
148
+ this.closeHeartbeat();
149
+ return;
150
+ }
151
+ this.logger.error(`Failed to send heartbeat: ${e.message}`);
152
+ }
153
+ }), 4000);
154
+ });
155
+ }
156
+ closeHeartbeat() {
157
+ if (this.heartbeatInterval) {
158
+ clearInterval(this.heartbeatInterval);
159
+ }
160
+ }
99
161
  getListenClient() {
100
162
  return __awaiter(this, void 0, void 0, function* () {
101
163
  const currentTime = Math.floor(Date.now());
@@ -112,9 +174,16 @@ class ActionListener {
112
174
  yield (0, sleep_1.default)(DEFAULT_ACTION_LISTENER_RETRY_INTERVAL);
113
175
  }
114
176
  try {
115
- return this.client.listen({
177
+ if (this.listenStrategy === ListenStrategy.LISTEN_STRATEGY_V1) {
178
+ return this.client.listen({
179
+ workerId: this.workerId,
180
+ });
181
+ }
182
+ const res = this.client.listenV2({
116
183
  workerId: this.workerId,
117
184
  });
185
+ this.heartbeat();
186
+ return res;
118
187
  }
119
188
  catch (e) {
120
189
  this.retries += 1;
@@ -126,6 +195,7 @@ class ActionListener {
126
195
  unregister() {
127
196
  return __awaiter(this, void 0, void 0, function* () {
128
197
  this.done = true;
198
+ this.closeHeartbeat();
129
199
  try {
130
200
  return this.client.unsubscribe({
131
201
  workerId: this.workerId,
@@ -110,7 +110,7 @@ class HatchetClient {
110
110
  this.event = new event_client_1.EventClient(this.config, this.channel, clientFactory);
111
111
  this.dispatcher = new dispatcher_client_1.DispatcherClient(this.config, this.channel, clientFactory);
112
112
  this.admin = new admin_client_1.AdminClient(this.config, this.channel, clientFactory, this.api, this.tenantId);
113
- this.listener = new listener_client_1.ListenerClient(this.config, this.channel, clientFactory);
113
+ this.listener = new listener_client_1.ListenerClient(this.config, this.channel, clientFactory, this.api);
114
114
  this.logger = new logger_1.default('HatchetClient', this.config.log_level);
115
115
  this.logger.info(`Initialized HatchetClient`);
116
116
  }
@@ -1,26 +1,49 @@
1
+ /// <reference types="node" />
1
2
  import { Channel, ClientFactory } from 'nice-grpc';
3
+ import { EventEmitter } from 'events';
2
4
  import { DispatcherClient as PbDispatcherClient } from '../../protoc/dispatcher';
3
5
  import { ClientConfig } from '../hatchet-client/client-config';
4
6
  import { Logger } from '../../util/logger';
5
- export declare enum StepRunEventType {
7
+ import { Api } from '../rest';
8
+ export declare enum RunEventType {
6
9
  STEP_RUN_EVENT_TYPE_STARTED = "STEP_RUN_EVENT_TYPE_STARTED",
7
10
  STEP_RUN_EVENT_TYPE_COMPLETED = "STEP_RUN_EVENT_TYPE_COMPLETED",
8
11
  STEP_RUN_EVENT_TYPE_FAILED = "STEP_RUN_EVENT_TYPE_FAILED",
9
12
  STEP_RUN_EVENT_TYPE_CANCELLED = "STEP_RUN_EVENT_TYPE_CANCELLED",
10
- STEP_RUN_EVENT_TYPE_TIMED_OUT = "STEP_RUN_EVENT_TYPE_TIMED_OUT"
13
+ STEP_RUN_EVENT_TYPE_TIMED_OUT = "STEP_RUN_EVENT_TYPE_TIMED_OUT",
14
+ WORKFLOW_RUN_EVENT_TYPE_STARTED = "WORKFLOW_RUN_EVENT_TYPE_STARTED",
15
+ WORKFLOW_RUN_EVENT_TYPE_COMPLETED = "WORKFLOW_RUN_EVENT_TYPE_COMPLETED",
16
+ WORKFLOW_RUN_EVENT_TYPE_FAILED = "WORKFLOW_RUN_EVENT_TYPE_FAILED",
17
+ WORKFLOW_RUN_EVENT_TYPE_CANCELLED = "WORKFLOW_RUN_EVENT_TYPE_CANCELLED",
18
+ WORKFLOW_RUN_EVENT_TYPE_TIMED_OUT = "WORKFLOW_RUN_EVENT_TYPE_TIMED_OUT"
11
19
  }
12
20
  export interface StepRunEvent {
13
- type: StepRunEventType;
21
+ type: RunEventType;
14
22
  payload: string;
15
23
  }
24
+ export declare class PollingAsyncListener {
25
+ client: ListenerClient;
26
+ q: Array<StepRunEvent>;
27
+ eventEmitter: EventEmitter;
28
+ pollInterval: any;
29
+ constructor(workflowRunid: string, client: ListenerClient);
30
+ emit(event: StepRunEvent): void;
31
+ listen(workflowRunId: string): Promise<void>;
32
+ retrySubscribe(workflowRunId: string): Promise<AsyncIterable<import("../../protoc/dispatcher").WorkflowEvent>>;
33
+ getWorkflowRun(workflowRunId: string): Promise<{
34
+ type: RunEventType;
35
+ payload: string;
36
+ } | undefined>;
37
+ polling(workflowRunId: string): Promise<void>;
38
+ close(): void;
39
+ stream(): AsyncGenerator<StepRunEvent, void, unknown>;
40
+ }
16
41
  export declare class ListenerClient {
17
42
  config: ClientConfig;
18
43
  client: PbDispatcherClient;
19
44
  logger: Logger;
20
- constructor(config: ClientConfig, channel: Channel, factory: ClientFactory);
21
- stream(workflowRunId: string): AsyncGenerator<{
22
- type: StepRunEventType;
23
- payload: string;
24
- }, void, unknown>;
25
- retrySubscribe(workflowRunId: string): Promise<AsyncIterable<import("../../protoc/dispatcher").WorkflowEvent>>;
45
+ api: Api;
46
+ constructor(config: ClientConfig, channel: Channel, factory: ClientFactory, api: Api);
47
+ get(workflowRunId: string): PollingAsyncListener;
48
+ stream(workflowRunId: string): Promise<AsyncGenerator<StepRunEvent, void, unknown>>;
26
49
  }
@@ -32,94 +32,137 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
32
32
  return (mod && mod.__esModule) ? mod : { "default": mod };
33
33
  };
34
34
  Object.defineProperty(exports, "__esModule", { value: true });
35
- exports.ListenerClient = exports.StepRunEventType = void 0;
35
+ exports.ListenerClient = exports.PollingAsyncListener = exports.RunEventType = void 0;
36
+ // eslint-disable-next-line max-classes-per-file
36
37
  const nice_grpc_1 = require("nice-grpc");
38
+ const events_1 = require("events");
37
39
  const dispatcher_1 = require("../../protoc/dispatcher");
38
40
  const hatchet_error_1 = __importDefault(require("../../util/errors/hatchet-error"));
39
41
  const logger_1 = require("../../util/logger");
40
42
  const sleep_1 = __importDefault(require("../../util/sleep"));
41
- const DEFAULT_ACTION_LISTENER_RETRY_INTERVAL = 5; // seconds
42
- const DEFAULT_ACTION_LISTENER_RETRY_COUNT = 5;
43
+ const data_contracts_1 = require("../rest/generated/data-contracts");
44
+ const DEFAULT_EVENT_LISTENER_RETRY_INTERVAL = 5; // seconds
45
+ const DEFAULT_EVENT_LISTENER_RETRY_COUNT = 5;
46
+ const DEFAULT_EVENT_LISTENER_POLL_INTERVAL = 5000; // milliseconds
43
47
  // eslint-disable-next-line no-shadow
44
- var StepRunEventType;
45
- (function (StepRunEventType) {
46
- StepRunEventType["STEP_RUN_EVENT_TYPE_STARTED"] = "STEP_RUN_EVENT_TYPE_STARTED";
47
- StepRunEventType["STEP_RUN_EVENT_TYPE_COMPLETED"] = "STEP_RUN_EVENT_TYPE_COMPLETED";
48
- StepRunEventType["STEP_RUN_EVENT_TYPE_FAILED"] = "STEP_RUN_EVENT_TYPE_FAILED";
49
- StepRunEventType["STEP_RUN_EVENT_TYPE_CANCELLED"] = "STEP_RUN_EVENT_TYPE_CANCELLED";
50
- StepRunEventType["STEP_RUN_EVENT_TYPE_TIMED_OUT"] = "STEP_RUN_EVENT_TYPE_TIMED_OUT";
51
- })(StepRunEventType || (exports.StepRunEventType = StepRunEventType = {}));
52
- class ListenerClient {
53
- constructor(config, channel, factory) {
54
- this.config = config;
55
- this.client = factory.create(dispatcher_1.DispatcherDefinition, channel);
56
- this.logger = new logger_1.Logger(`Listener`, config.log_level);
48
+ var RunEventType;
49
+ (function (RunEventType) {
50
+ RunEventType["STEP_RUN_EVENT_TYPE_STARTED"] = "STEP_RUN_EVENT_TYPE_STARTED";
51
+ RunEventType["STEP_RUN_EVENT_TYPE_COMPLETED"] = "STEP_RUN_EVENT_TYPE_COMPLETED";
52
+ RunEventType["STEP_RUN_EVENT_TYPE_FAILED"] = "STEP_RUN_EVENT_TYPE_FAILED";
53
+ RunEventType["STEP_RUN_EVENT_TYPE_CANCELLED"] = "STEP_RUN_EVENT_TYPE_CANCELLED";
54
+ RunEventType["STEP_RUN_EVENT_TYPE_TIMED_OUT"] = "STEP_RUN_EVENT_TYPE_TIMED_OUT";
55
+ RunEventType["WORKFLOW_RUN_EVENT_TYPE_STARTED"] = "WORKFLOW_RUN_EVENT_TYPE_STARTED";
56
+ RunEventType["WORKFLOW_RUN_EVENT_TYPE_COMPLETED"] = "WORKFLOW_RUN_EVENT_TYPE_COMPLETED";
57
+ RunEventType["WORKFLOW_RUN_EVENT_TYPE_FAILED"] = "WORKFLOW_RUN_EVENT_TYPE_FAILED";
58
+ RunEventType["WORKFLOW_RUN_EVENT_TYPE_CANCELLED"] = "WORKFLOW_RUN_EVENT_TYPE_CANCELLED";
59
+ RunEventType["WORKFLOW_RUN_EVENT_TYPE_TIMED_OUT"] = "WORKFLOW_RUN_EVENT_TYPE_TIMED_OUT";
60
+ })(RunEventType || (exports.RunEventType = RunEventType = {}));
61
+ const stepEventTypeMap = {
62
+ [dispatcher_1.ResourceEventType.RESOURCE_EVENT_TYPE_STARTED]: RunEventType.STEP_RUN_EVENT_TYPE_STARTED,
63
+ [dispatcher_1.ResourceEventType.RESOURCE_EVENT_TYPE_COMPLETED]: RunEventType.STEP_RUN_EVENT_TYPE_COMPLETED,
64
+ [dispatcher_1.ResourceEventType.RESOURCE_EVENT_TYPE_FAILED]: RunEventType.STEP_RUN_EVENT_TYPE_FAILED,
65
+ [dispatcher_1.ResourceEventType.RESOURCE_EVENT_TYPE_CANCELLED]: RunEventType.STEP_RUN_EVENT_TYPE_CANCELLED,
66
+ [dispatcher_1.ResourceEventType.RESOURCE_EVENT_TYPE_TIMED_OUT]: RunEventType.STEP_RUN_EVENT_TYPE_TIMED_OUT,
67
+ [dispatcher_1.ResourceEventType.RESOURCE_EVENT_TYPE_UNKNOWN]: undefined,
68
+ [dispatcher_1.ResourceEventType.UNRECOGNIZED]: undefined,
69
+ };
70
+ const workflowEventTypeMap = {
71
+ [dispatcher_1.ResourceEventType.RESOURCE_EVENT_TYPE_STARTED]: RunEventType.WORKFLOW_RUN_EVENT_TYPE_STARTED,
72
+ [dispatcher_1.ResourceEventType.RESOURCE_EVENT_TYPE_COMPLETED]: RunEventType.WORKFLOW_RUN_EVENT_TYPE_COMPLETED,
73
+ [dispatcher_1.ResourceEventType.RESOURCE_EVENT_TYPE_FAILED]: RunEventType.WORKFLOW_RUN_EVENT_TYPE_FAILED,
74
+ [dispatcher_1.ResourceEventType.RESOURCE_EVENT_TYPE_CANCELLED]: RunEventType.WORKFLOW_RUN_EVENT_TYPE_CANCELLED,
75
+ [dispatcher_1.ResourceEventType.RESOURCE_EVENT_TYPE_TIMED_OUT]: RunEventType.WORKFLOW_RUN_EVENT_TYPE_TIMED_OUT,
76
+ [dispatcher_1.ResourceEventType.RESOURCE_EVENT_TYPE_UNKNOWN]: undefined,
77
+ [dispatcher_1.ResourceEventType.UNRECOGNIZED]: undefined,
78
+ };
79
+ const resourceTypeMap = {
80
+ [dispatcher_1.ResourceType.RESOURCE_TYPE_STEP_RUN]: stepEventTypeMap,
81
+ [dispatcher_1.ResourceType.RESOURCE_TYPE_WORKFLOW_RUN]: workflowEventTypeMap,
82
+ [dispatcher_1.ResourceType.RESOURCE_TYPE_UNKNOWN]: undefined,
83
+ [dispatcher_1.ResourceType.UNRECOGNIZED]: undefined,
84
+ };
85
+ const workflowStatusMap = {
86
+ [data_contracts_1.WorkflowRunStatus.SUCCEEDED]: RunEventType.WORKFLOW_RUN_EVENT_TYPE_COMPLETED,
87
+ [data_contracts_1.WorkflowRunStatus.FAILED]: RunEventType.WORKFLOW_RUN_EVENT_TYPE_FAILED,
88
+ [data_contracts_1.WorkflowRunStatus.CANCELLED]: RunEventType.WORKFLOW_RUN_EVENT_TYPE_CANCELLED,
89
+ [data_contracts_1.WorkflowRunStatus.PENDING]: undefined,
90
+ [data_contracts_1.WorkflowRunStatus.RUNNING]: undefined,
91
+ };
92
+ class PollingAsyncListener {
93
+ constructor(workflowRunid, client) {
94
+ this.q = [];
95
+ this.eventEmitter = new events_1.EventEmitter();
96
+ this.client = client;
97
+ this.listen(workflowRunid);
98
+ this.polling(workflowRunid);
57
99
  }
58
- stream(workflowRunId) {
59
- return __asyncGenerator(this, arguments, function* stream_1() {
60
- var _a, e_1, _b, _c;
61
- let listener = this.client.subscribeToWorkflowEvents({
100
+ emit(event) {
101
+ this.q.push(event);
102
+ this.eventEmitter.emit('event');
103
+ }
104
+ listen(workflowRunId) {
105
+ var _a, e_1, _b, _c;
106
+ var _d;
107
+ return __awaiter(this, void 0, void 0, function* () {
108
+ let listener = this.client.client.subscribeToWorkflowEvents({
62
109
  workflowRunId,
63
110
  });
111
+ const res = yield this.getWorkflowRun(workflowRunId);
112
+ if (res) {
113
+ this.emit(res);
114
+ this.close();
115
+ }
64
116
  try {
65
117
  try {
66
- for (var _d = true, listener_1 = __asyncValues(listener), listener_1_1; listener_1_1 = yield __await(listener_1.next()), _a = listener_1_1.done, !_a; _d = true) {
118
+ 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) {
67
119
  _c = listener_1_1.value;
68
- _d = false;
120
+ _e = false;
69
121
  const workflowEvent = _c;
70
- let eventType;
71
- switch (workflowEvent.eventType) {
72
- case dispatcher_1.ResourceEventType.RESOURCE_EVENT_TYPE_STARTED:
73
- eventType = StepRunEventType.STEP_RUN_EVENT_TYPE_STARTED;
74
- break;
75
- case dispatcher_1.ResourceEventType.RESOURCE_EVENT_TYPE_COMPLETED:
76
- eventType = StepRunEventType.STEP_RUN_EVENT_TYPE_COMPLETED;
77
- break;
78
- case dispatcher_1.ResourceEventType.RESOURCE_EVENT_TYPE_FAILED:
79
- eventType = StepRunEventType.STEP_RUN_EVENT_TYPE_FAILED;
80
- break;
81
- case dispatcher_1.ResourceEventType.RESOURCE_EVENT_TYPE_CANCELLED:
82
- eventType = StepRunEventType.STEP_RUN_EVENT_TYPE_CANCELLED;
83
- break;
84
- case dispatcher_1.ResourceEventType.RESOURCE_EVENT_TYPE_TIMED_OUT:
85
- eventType = StepRunEventType.STEP_RUN_EVENT_TYPE_TIMED_OUT;
86
- break;
87
- default:
88
- // no nothing
89
- }
122
+ const eventType = (_d = resourceTypeMap[workflowEvent.resourceType]) === null || _d === void 0 ? void 0 : _d[workflowEvent.eventType];
90
123
  if (eventType) {
91
- yield yield __await({
92
- type: eventType,
93
- payload: workflowEvent.eventPayload,
94
- });
124
+ if (eventType === RunEventType.WORKFLOW_RUN_EVENT_TYPE_COMPLETED) {
125
+ // OPTIMZATION - consider including the workflow run data in the event?
126
+ const data = yield this.getWorkflowRun(workflowRunId);
127
+ if (data) {
128
+ this.emit(data);
129
+ }
130
+ }
131
+ else {
132
+ this.emit({
133
+ type: eventType,
134
+ payload: workflowEvent.eventPayload,
135
+ });
136
+ }
95
137
  }
96
138
  }
97
139
  }
98
140
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
99
141
  finally {
100
142
  try {
101
- if (!_d && !_a && (_b = listener_1.return)) yield __await(_b.call(listener_1));
143
+ if (!_e && !_a && (_b = listener_1.return)) yield _b.call(listener_1);
102
144
  }
103
145
  finally { if (e_1) throw e_1.error; }
104
146
  }
105
147
  }
106
148
  catch (e) {
107
149
  if (e.code === nice_grpc_1.Status.CANCELLED) {
108
- return yield __await(void 0);
150
+ return;
109
151
  }
110
152
  if (e.code === nice_grpc_1.Status.UNAVAILABLE) {
111
- listener = yield __await(this.retrySubscribe(workflowRunId));
153
+ listener = yield this.retrySubscribe(workflowRunId);
112
154
  }
113
155
  }
156
+ setTimeout(() => this.close(), DEFAULT_EVENT_LISTENER_POLL_INTERVAL * 5);
114
157
  });
115
158
  }
116
159
  retrySubscribe(workflowRunId) {
117
160
  return __awaiter(this, void 0, void 0, function* () {
118
161
  let retries = 0;
119
- while (retries < DEFAULT_ACTION_LISTENER_RETRY_COUNT) {
162
+ while (retries < DEFAULT_EVENT_LISTENER_RETRY_COUNT) {
120
163
  try {
121
- yield (0, sleep_1.default)(DEFAULT_ACTION_LISTENER_RETRY_INTERVAL);
122
- const listener = this.client.subscribeToWorkflowEvents({
164
+ yield (0, sleep_1.default)(DEFAULT_EVENT_LISTENER_RETRY_INTERVAL);
165
+ const listener = this.client.client.subscribeToWorkflowEvents({
123
166
  workflowRunId,
124
167
  });
125
168
  return listener;
@@ -128,7 +171,98 @@ class ListenerClient {
128
171
  retries += 1;
129
172
  }
130
173
  }
131
- throw new hatchet_error_1.default(`Could not subscribe to the worker after ${DEFAULT_ACTION_LISTENER_RETRY_COUNT} retries`);
174
+ throw new hatchet_error_1.default(`Could not subscribe to the worker after ${DEFAULT_EVENT_LISTENER_RETRY_COUNT} retries`);
175
+ });
176
+ }
177
+ getWorkflowRun(workflowRunId) {
178
+ var _a, _b, _c;
179
+ return __awaiter(this, void 0, void 0, function* () {
180
+ try {
181
+ const res = yield this.client.api.workflowRunGet(this.client.config.tenant_id, workflowRunId);
182
+ const stepRuns = (_c = (_b = (_a = res.data.jobRuns) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.stepRuns) !== null && _c !== void 0 ? _c : [];
183
+ const stepRunOutput = stepRuns.reduce((acc, stepRun) => {
184
+ var _a;
185
+ acc[((_a = stepRun.step) === null || _a === void 0 ? void 0 : _a.readableId) || ''] = JSON.parse(stepRun.output || '{}');
186
+ return acc;
187
+ }, {});
188
+ if (Object.keys(workflowStatusMap).includes(res.data.status)) {
189
+ const type = workflowStatusMap[res.data.status];
190
+ if (!type)
191
+ return undefined;
192
+ return {
193
+ type,
194
+ payload: JSON.stringify(stepRunOutput),
195
+ };
196
+ }
197
+ return undefined;
198
+ }
199
+ catch (e) {
200
+ throw new hatchet_error_1.default(e.message);
201
+ }
202
+ });
203
+ }
204
+ polling(workflowRunId) {
205
+ return __awaiter(this, void 0, void 0, function* () {
206
+ this.pollInterval = setInterval(() => __awaiter(this, void 0, void 0, function* () {
207
+ try {
208
+ const result = yield this.getWorkflowRun(workflowRunId);
209
+ if (result) {
210
+ this.emit(result);
211
+ this.close();
212
+ }
213
+ }
214
+ catch (e) {
215
+ // TODO error handling
216
+ }
217
+ }), DEFAULT_EVENT_LISTENER_POLL_INTERVAL);
218
+ });
219
+ }
220
+ close() {
221
+ if (this.pollInterval) {
222
+ clearInterval(this.pollInterval);
223
+ }
224
+ }
225
+ stream() {
226
+ return __asyncGenerator(this, arguments, function* stream_1() {
227
+ var _a, e_2, _b, _c;
228
+ try {
229
+ for (var _d = true, _e = __asyncValues((0, events_1.on)(this.eventEmitter, 'event')), _f; _f = yield __await(_e.next()), _a = _f.done, !_a; _d = true) {
230
+ _c = _f.value;
231
+ _d = false;
232
+ const _ = _c;
233
+ while (this.q.length > 0) {
234
+ const r = this.q.shift();
235
+ if (r) {
236
+ yield yield __await(r);
237
+ }
238
+ }
239
+ }
240
+ }
241
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
242
+ finally {
243
+ try {
244
+ if (!_d && !_a && (_b = _e.return)) yield __await(_b.call(_e));
245
+ }
246
+ finally { if (e_2) throw e_2.error; }
247
+ }
248
+ });
249
+ }
250
+ }
251
+ exports.PollingAsyncListener = PollingAsyncListener;
252
+ class ListenerClient {
253
+ constructor(config, channel, factory, api) {
254
+ this.config = config;
255
+ this.client = factory.create(dispatcher_1.DispatcherDefinition, channel);
256
+ this.logger = new logger_1.Logger(`Listener`, config.log_level);
257
+ this.api = api;
258
+ }
259
+ get(workflowRunId) {
260
+ const listener = new PollingAsyncListener(workflowRunId, this);
261
+ return listener;
262
+ }
263
+ stream(workflowRunId) {
264
+ return __awaiter(this, void 0, void 0, function* () {
265
+ return this.get(workflowRunId).stream();
132
266
  });
133
267
  }
134
268
  }
@@ -104,7 +104,7 @@ class Worker {
104
104
  handleStartStepRun(action) {
105
105
  const { actionId } = action;
106
106
  try {
107
- const context = new step_1.Context(action, this.client.dispatcher, this.client.event);
107
+ const context = new step_1.Context(action, this.client);
108
108
  this.contexts[action.stepRunId] = context;
109
109
  const step = this.action_registry[actionId];
110
110
  if (!step) {
@@ -153,7 +153,7 @@ class Worker {
153
153
  handleStartGroupKeyRun(action) {
154
154
  const { actionId } = action;
155
155
  try {
156
- const context = new step_1.Context(action, this.client.dispatcher, this.client.event);
156
+ const context = new step_1.Context(action, this.client);
157
157
  const key = action.getGroupKeyRunId;
158
158
  this.contexts[key] = context;
159
159
  this.logger.debug(`Starting group key run ${key}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hatchet-dev/typescript-sdk",
3
- "version": "0.1.31",
3
+ "version": "0.2.1",
4
4
  "description": "Background task orchestration & visibility for developers",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [
@@ -26,14 +26,15 @@
26
26
  "generate-protoc": "./generate-protoc.sh",
27
27
  "lint:check": "npm run eslint:check && npm run prettier:check",
28
28
  "lint:fix": "npm run eslint:fix && npm run prettier:fix",
29
- "eslint:check": "eslint \"{hatchet,tests}/**/*.{ts,tsx,js}\"",
30
- "eslint:fix": "eslint \"{hatchet,tests}/**/*.{ts,tsx,js}\" --fix",
31
- "prettier:check": "prettier \"hatchet/**/*.{ts,tsx}\" --list-different",
32
- "prettier:fix": "prettier \"hatchet/**/*.{ts,tsx}\" --write",
29
+ "eslint:check": "eslint \"{src,tests}/**/*.{ts,tsx,js}\"",
30
+ "eslint:fix": "eslint \"{src,tests}/**/*.{ts,tsx,js}\" --fix",
31
+ "prettier:check": "prettier \"src/**/*.{ts,tsx}\" --list-different",
32
+ "prettier:fix": "prettier \"src/**/*.{ts,tsx}\" --write",
33
33
  "exec": "npx dotenv -- ts-node -r tsconfig-paths/register --project tsconfig.json",
34
34
  "example:event": "npm run exec -- ./examples/example-event.ts",
35
35
  "example:event-listen": "npm run exec -- ./examples/example-event-with-results.ts",
36
36
  "worker:namespaced": "npm run exec -- ./examples/namespaced-worker.ts",
37
+ "worker:fanout": "npm run exec -- ./examples/fanout-worker.ts",
37
38
  "worker:simple": "npm run exec -- ./examples/simple-worker.ts",
38
39
  "manual:trigger": "npm run exec -- ./examples/manual-trigger.ts",
39
40
  "worker:dag": "npm run exec -- ./examples/dag-worker.ts",
@@ -54,8 +55,8 @@
54
55
  "author": "",
55
56
  "license": "MIT",
56
57
  "devDependencies": {
57
- "@types/node": "^20.11.16",
58
58
  "@types/jest": "^29.5.11",
59
+ "@types/node": "^20.11.16",
59
60
  "@typescript-eslint/eslint-plugin": "^6.4.0",
60
61
  "autoprefixer": "^10.4.16",
61
62
  "dotenv-cli": "^7.3.0",
@@ -69,6 +70,9 @@
69
70
  "eslint-plugin-n": "^15.0.0 || ^16.0.0 ",
70
71
  "eslint-plugin-prettier": "^5.0.1",
71
72
  "eslint-plugin-promise": "^6.0.0",
73
+ "eslint-plugin-react": "^7.34.1",
74
+ "eslint-plugin-react-hooks": "^4.6.0",
75
+ "eslint-plugin-react-refresh": "^0.4.6",
72
76
  "eslint-plugin-unused-imports": "^3.0.0",
73
77
  "grpc-tools": "^1.12.4",
74
78
  "jest": "^29.7.0",