@hotmeshio/hotmesh 0.0.60 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/build/modules/enums.d.ts +1 -1
- package/build/modules/enums.js +10 -2
- package/build/modules/errors.d.ts +3 -3
- package/build/modules/errors.js +8 -8
- package/build/modules/key.d.ts +1 -1
- package/build/modules/key.js +3 -3
- package/build/modules/utils.d.ts +5 -5
- package/build/modules/utils.js +20 -16
- package/build/package.json +41 -38
- package/build/services/activities/activity.js +37 -20
- package/build/services/activities/await.d.ts +1 -1
- package/build/services/activities/await.js +15 -7
- package/build/services/activities/cycle.d.ts +1 -1
- package/build/services/activities/cycle.js +16 -8
- package/build/services/activities/hook.d.ts +1 -1
- package/build/services/activities/hook.js +8 -4
- package/build/services/activities/interrupt.d.ts +1 -1
- package/build/services/activities/interrupt.js +14 -6
- package/build/services/activities/signal.d.ts +1 -1
- package/build/services/activities/signal.js +12 -4
- package/build/services/activities/trigger.d.ts +1 -1
- package/build/services/activities/trigger.js +19 -12
- package/build/services/activities/worker.d.ts +1 -1
- package/build/services/activities/worker.js +15 -7
- package/build/services/collator/index.js +12 -12
- package/build/services/compiler/deployer.js +17 -12
- package/build/services/compiler/index.js +4 -4
- package/build/services/compiler/validator.d.ts +3 -3
- package/build/services/compiler/validator.js +12 -3
- package/build/services/durable/client.d.ts +1 -1
- package/build/services/durable/client.js +18 -12
- package/build/services/durable/connection.d.ts +1 -1
- package/build/services/durable/exporter.d.ts +1 -1
- package/build/services/durable/exporter.js +3 -4
- package/build/services/durable/handle.d.ts +1 -1
- package/build/services/durable/handle.js +4 -1
- package/build/services/durable/index.d.ts +1 -1
- package/build/services/durable/index.js +2 -2
- package/build/services/durable/schemas/factory.d.ts +1 -1
- package/build/services/durable/search.js +19 -11
- package/build/services/durable/worker.js +50 -30
- package/build/services/durable/workflow.d.ts +5 -5
- package/build/services/durable/workflow.js +34 -18
- package/build/services/engine/index.js +33 -26
- package/build/services/exporter/index.d.ts +1 -1
- package/build/services/exporter/index.js +3 -3
- package/build/services/hotmesh/index.js +1 -1
- package/build/services/logger/index.js +1 -1
- package/build/services/mapper/index.js +3 -1
- package/build/services/pipe/functions/date.js +1 -1
- package/build/services/pipe/index.js +37 -10
- package/build/services/quorum/index.js +14 -11
- package/build/services/reporter/index.js +15 -12
- package/build/services/router/index.d.ts +2 -2
- package/build/services/router/index.js +73 -23
- package/build/services/serializer/index.js +48 -26
- package/build/services/store/cache.d.ts +5 -5
- package/build/services/store/cache.js +2 -2
- package/build/services/store/clients/ioredis.js +3 -3
- package/build/services/store/clients/redis.js +24 -4
- package/build/services/store/index.d.ts +9 -3
- package/build/services/store/index.js +122 -60
- package/build/services/stream/clients/ioredis.js +4 -4
- package/build/services/stream/clients/redis.js +31 -4
- package/build/services/task/index.js +8 -11
- package/build/services/telemetry/index.js +21 -14
- package/build/services/worker/index.d.ts +6 -6
- package/build/services/worker/index.js +12 -7
- package/build/types/activity.d.ts +3 -3
- package/build/types/exporter.d.ts +2 -2
- package/build/types/exporter.js +0 -6
- package/build/types/hook.d.ts +1 -1
- package/build/types/hotmesh.js +0 -1
- package/build/types/index.d.ts +12 -12
- package/build/types/job.d.ts +1 -1
- package/build/types/logger.js +0 -1
- package/build/types/quorum.d.ts +1 -1
- package/build/types/stats.d.ts +1 -1
- package/build/types/stream.d.ts +1 -2
- package/build/types/telemetry.d.ts +1 -1
- package/build/types/transition.d.ts +1 -1
- package/package.json +41 -38
- package/types/activity.ts +56 -39
- package/types/async.ts +2 -3
- package/types/collator.ts +5 -5
- package/types/durable.ts +161 -161
- package/types/error.ts +37 -37
- package/types/exporter.ts +14 -9
- package/types/hook.ts +11 -4
- package/types/hotmesh.ts +26 -25
- package/types/index.ts +53 -53
- package/types/job.ts +33 -33
- package/types/logger.ts +1 -1
- package/types/map.ts +1 -1
- package/types/pipe.ts +10 -8
- package/types/quorum.ts +20 -13
- package/types/redis.ts +70 -15
- package/types/serializer.ts +8 -6
- package/types/stats.ts +22 -6
- package/types/stream.ts +9 -9
- package/types/task.ts +7 -1
- package/types/telemetry.ts +2 -1
- package/types/transition.ts +8 -8
|
@@ -10,10 +10,10 @@ const enums_1 = require("../../modules/enums");
|
|
|
10
10
|
const errors_1 = require("../../modules/errors");
|
|
11
11
|
const storage_1 = require("../../modules/storage");
|
|
12
12
|
const utils_1 = require("../../modules/utils");
|
|
13
|
-
const factory_1 = require("./schemas/factory");
|
|
14
13
|
const hotmesh_1 = require("../hotmesh");
|
|
15
|
-
const search_1 = require("./search");
|
|
16
14
|
const stream_1 = require("../../types/stream");
|
|
15
|
+
const search_1 = require("./search");
|
|
16
|
+
const factory_1 = require("./schemas/factory");
|
|
17
17
|
class WorkerService {
|
|
18
18
|
static async activateWorkflow(hotMesh) {
|
|
19
19
|
const app = await hotMesh.engine.store.getApp(hotMesh.engine.appId);
|
|
@@ -39,12 +39,15 @@ class WorkerService {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
static registerActivities(activities) {
|
|
42
|
-
if (typeof activities === 'function' &&
|
|
42
|
+
if (typeof activities === 'function' &&
|
|
43
|
+
typeof WorkerService.activityRegistry[activities.name] !== 'function') {
|
|
43
44
|
WorkerService.activityRegistry[activities.name] = activities;
|
|
44
45
|
}
|
|
45
46
|
else {
|
|
46
|
-
Object.keys(activities).forEach(key => {
|
|
47
|
-
if (activities[key].name &&
|
|
47
|
+
Object.keys(activities).forEach((key) => {
|
|
48
|
+
if (activities[key].name &&
|
|
49
|
+
typeof WorkerService.activityRegistry[activities[key].name] !==
|
|
50
|
+
'function') {
|
|
48
51
|
WorkerService.activityRegistry[activities[key].name] = activities[key];
|
|
49
52
|
}
|
|
50
53
|
else if (typeof activities[key] === 'function') {
|
|
@@ -88,18 +91,19 @@ class WorkerService {
|
|
|
88
91
|
async initActivityWorker(config, activityTopic) {
|
|
89
92
|
const redisConfig = {
|
|
90
93
|
class: config.connection.class,
|
|
91
|
-
options: config.connection.options
|
|
94
|
+
options: config.connection.options,
|
|
92
95
|
};
|
|
93
96
|
const hotMeshWorker = await hotmesh_1.HotMeshService.init({
|
|
94
97
|
logLevel: config.options?.logLevel ?? enums_1.HMSH_LOGLEVEL,
|
|
95
98
|
appId: config.namespace ?? factory_1.APP_ID,
|
|
96
99
|
engine: { redis: redisConfig },
|
|
97
100
|
workers: [
|
|
98
|
-
{
|
|
101
|
+
{
|
|
102
|
+
topic: activityTopic,
|
|
99
103
|
redis: redisConfig,
|
|
100
|
-
callback: this.wrapActivityFunctions().bind(this)
|
|
101
|
-
}
|
|
102
|
-
]
|
|
104
|
+
callback: this.wrapActivityFunctions().bind(this),
|
|
105
|
+
},
|
|
106
|
+
],
|
|
103
107
|
});
|
|
104
108
|
WorkerService.instances.set(activityTopic, hotMeshWorker);
|
|
105
109
|
return hotMeshWorker;
|
|
@@ -116,11 +120,15 @@ class WorkerService {
|
|
|
116
120
|
return {
|
|
117
121
|
status: stream_1.StreamStatus.SUCCESS,
|
|
118
122
|
metadata: { ...data.metadata },
|
|
119
|
-
data: { response: pojoResponse }
|
|
123
|
+
data: { response: pojoResponse },
|
|
120
124
|
};
|
|
121
125
|
}
|
|
122
126
|
catch (err) {
|
|
123
|
-
this.activityRunner.engine.logger.error('durable-worker-activity-err', {
|
|
127
|
+
this.activityRunner.engine.logger.error('durable-worker-activity-err', {
|
|
128
|
+
name: err.name,
|
|
129
|
+
message: err.message,
|
|
130
|
+
stack: err.stack,
|
|
131
|
+
});
|
|
124
132
|
if (!(err instanceof errors_1.DurableTimeoutError) &&
|
|
125
133
|
!(err instanceof errors_1.DurableMaxedError) &&
|
|
126
134
|
!(err instanceof errors_1.DurableFatalError)) {
|
|
@@ -135,7 +143,7 @@ class WorkerService {
|
|
|
135
143
|
message: err.message,
|
|
136
144
|
stack: err.stack,
|
|
137
145
|
timestamp: (0, utils_1.formatISODate)(new Date()),
|
|
138
|
-
}
|
|
146
|
+
},
|
|
139
147
|
},
|
|
140
148
|
};
|
|
141
149
|
}
|
|
@@ -152,7 +160,7 @@ class WorkerService {
|
|
|
152
160
|
stack: err.stack,
|
|
153
161
|
timestamp: (0, utils_1.formatISODate)(new Date()),
|
|
154
162
|
code: err.code,
|
|
155
|
-
}
|
|
163
|
+
},
|
|
156
164
|
},
|
|
157
165
|
};
|
|
158
166
|
}
|
|
@@ -161,17 +169,19 @@ class WorkerService {
|
|
|
161
169
|
async initWorkflowWorker(config, workflowTopic, workflowFunction) {
|
|
162
170
|
const redisConfig = {
|
|
163
171
|
class: config.connection.class,
|
|
164
|
-
options: config.connection.options
|
|
172
|
+
options: config.connection.options,
|
|
165
173
|
};
|
|
166
174
|
const hotMeshWorker = await hotmesh_1.HotMeshService.init({
|
|
167
175
|
logLevel: config.options?.logLevel ?? enums_1.HMSH_LOGLEVEL,
|
|
168
176
|
appId: config.namespace ?? factory_1.APP_ID,
|
|
169
177
|
engine: { redis: redisConfig },
|
|
170
|
-
workers: [
|
|
178
|
+
workers: [
|
|
179
|
+
{
|
|
171
180
|
topic: workflowTopic,
|
|
172
181
|
redis: redisConfig,
|
|
173
|
-
callback: this.wrapWorkflowFunction(workflowFunction, workflowTopic, config).bind(this)
|
|
174
|
-
}
|
|
182
|
+
callback: this.wrapWorkflowFunction(workflowFunction, workflowTopic, config).bind(this),
|
|
183
|
+
},
|
|
184
|
+
],
|
|
175
185
|
});
|
|
176
186
|
WorkerService.instances.set(workflowTopic, hotMeshWorker);
|
|
177
187
|
return hotMeshWorker;
|
|
@@ -179,7 +189,7 @@ class WorkerService {
|
|
|
179
189
|
wrapWorkflowFunction(workflowFunction, workflowTopic, config) {
|
|
180
190
|
return async (data) => {
|
|
181
191
|
const counter = { counter: 0 };
|
|
182
|
-
const interruptionRegistry =
|
|
192
|
+
const interruptionRegistry = [];
|
|
183
193
|
let isProcessing = false;
|
|
184
194
|
try {
|
|
185
195
|
//incoming data payload has arguments and workflowId
|
|
@@ -192,7 +202,7 @@ class WorkerService {
|
|
|
192
202
|
context.set('raw', data);
|
|
193
203
|
context.set('workflowId', workflowInput.workflowId);
|
|
194
204
|
if (workflowInput.originJobId) {
|
|
195
|
-
//if present there is an origin job to which this job is subordinated;
|
|
205
|
+
//if present there is an origin job to which this job is subordinated;
|
|
196
206
|
// garbage collect (expire) this job when originJobId is expired
|
|
197
207
|
context.set('originJobId', workflowInput.originJobId);
|
|
198
208
|
}
|
|
@@ -223,14 +233,15 @@ class WorkerService {
|
|
|
223
233
|
code: 200,
|
|
224
234
|
status: stream_1.StreamStatus.SUCCESS,
|
|
225
235
|
metadata: { ...data.metadata },
|
|
226
|
-
data: { response: workflowResponse, done: true }
|
|
236
|
+
data: { response: workflowResponse, done: true },
|
|
227
237
|
};
|
|
228
238
|
}
|
|
229
239
|
catch (err) {
|
|
230
240
|
if (isProcessing) {
|
|
231
241
|
return;
|
|
232
242
|
}
|
|
233
|
-
if (err instanceof errors_1.DurableWaitForError ||
|
|
243
|
+
if (err instanceof errors_1.DurableWaitForError ||
|
|
244
|
+
interruptionRegistry.length > 1) {
|
|
234
245
|
isProcessing = true;
|
|
235
246
|
//NOTE: this type is spawned when `Promise.all` is used OR if the interruption is a `waitFor`
|
|
236
247
|
const workflowInput = data.data;
|
|
@@ -263,11 +274,15 @@ class WorkerService {
|
|
|
263
274
|
metadata: { ...data.metadata },
|
|
264
275
|
data: {
|
|
265
276
|
code: err.code,
|
|
266
|
-
message: JSON.stringify({
|
|
277
|
+
message: JSON.stringify({
|
|
278
|
+
duration: err.duration,
|
|
279
|
+
index: err.index,
|
|
280
|
+
workflowDimension: err.workflowDimension,
|
|
281
|
+
}),
|
|
267
282
|
duration: err.duration,
|
|
268
283
|
index: err.index,
|
|
269
284
|
workflowDimension: err.workflowDimension,
|
|
270
|
-
}
|
|
285
|
+
},
|
|
271
286
|
};
|
|
272
287
|
}
|
|
273
288
|
else if (err instanceof errors_1.DurableProxyError) {
|
|
@@ -279,7 +294,12 @@ class WorkerService {
|
|
|
279
294
|
metadata: { ...data.metadata },
|
|
280
295
|
data: {
|
|
281
296
|
code: err.code,
|
|
282
|
-
message: JSON.stringify({
|
|
297
|
+
message: JSON.stringify({
|
|
298
|
+
message: err.message,
|
|
299
|
+
workflowId: err.workflowId,
|
|
300
|
+
activityName: err.activityName,
|
|
301
|
+
dimension: err.workflowDimension,
|
|
302
|
+
}),
|
|
283
303
|
arguments: err.arguments,
|
|
284
304
|
workflowDimension: err.workflowDimension,
|
|
285
305
|
index: err.index,
|
|
@@ -291,7 +311,7 @@ class WorkerService {
|
|
|
291
311
|
backoffCoefficient: err.backoffCoefficient,
|
|
292
312
|
maximumAttempts: err.maximumAttempts,
|
|
293
313
|
maximumInterval: err.maximumInterval,
|
|
294
|
-
}
|
|
314
|
+
},
|
|
295
315
|
};
|
|
296
316
|
}
|
|
297
317
|
else if (err instanceof errors_1.DurableChildError) {
|
|
@@ -320,7 +340,7 @@ class WorkerService {
|
|
|
320
340
|
workflowDimension: err.workflowDimension,
|
|
321
341
|
workflowId: err.workflowId,
|
|
322
342
|
workflowTopic: err.workflowTopic,
|
|
323
|
-
}
|
|
343
|
+
},
|
|
324
344
|
};
|
|
325
345
|
}
|
|
326
346
|
// ALL other errors are actual fatal errors (598, 597, 596)
|
|
@@ -337,8 +357,8 @@ class WorkerService {
|
|
|
337
357
|
name: err.name,
|
|
338
358
|
stack: err.stack,
|
|
339
359
|
code: err.code || new errors_1.DurableRetryError(err.message).code,
|
|
340
|
-
}
|
|
341
|
-
}
|
|
360
|
+
},
|
|
361
|
+
},
|
|
342
362
|
};
|
|
343
363
|
}
|
|
344
364
|
};
|
|
@@ -359,7 +379,7 @@ WorkerService.getHotMesh = async (workflowTopic, config, options) => {
|
|
|
359
379
|
const hotMeshClient = hotmesh_1.HotMeshService.init({
|
|
360
380
|
logLevel: options?.logLevel ?? enums_1.HMSH_LOGLEVEL,
|
|
361
381
|
appId: config.namespace ?? factory_1.APP_ID,
|
|
362
|
-
engine: { redis: { ...WorkerService.connection } }
|
|
382
|
+
engine: { redis: { ...WorkerService.connection } },
|
|
363
383
|
});
|
|
364
384
|
WorkerService.instances.set(workflowTopic, hotMeshClient);
|
|
365
385
|
await WorkerService.activateWorkflow(await hotMeshClient);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Search } from './search';
|
|
2
1
|
import { HotMeshService as HotMesh } from '../hotmesh';
|
|
3
|
-
import { ActivityConfig, HookOptions, ProxyType, WorkflowContext, WorkflowOptions } from
|
|
2
|
+
import { ActivityConfig, HookOptions, ProxyType, WorkflowContext, WorkflowOptions } from '../../types/durable';
|
|
4
3
|
import { JobInterruptOptions } from '../../types/job';
|
|
5
4
|
import { DurableChildErrorType, DurableProxyErrorType } from '../../types/error';
|
|
5
|
+
import { Search } from './search';
|
|
6
6
|
export declare class WorkflowService {
|
|
7
7
|
/**
|
|
8
8
|
* Returns the synchronous output from the activity (replay)
|
|
@@ -75,9 +75,9 @@ export declare class WorkflowService {
|
|
|
75
75
|
static proxyActivities<ACT>(options?: ActivityConfig): ProxyType<ACT>;
|
|
76
76
|
static wrapActivity<T>(activityName: string, options?: ActivityConfig): T;
|
|
77
77
|
/**
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
* constructs the payload necessary to spawn a proxyActivity job
|
|
79
|
+
* @private
|
|
80
|
+
*/
|
|
81
81
|
static getProxyInterruptPayload(context: WorkflowContext, activityName: string, execIndex: number, args: any[], options?: ActivityConfig): DurableProxyErrorType;
|
|
82
82
|
/**
|
|
83
83
|
* Returns a search session for use when reading/writing to the workflow HASH.
|
|
@@ -9,11 +9,11 @@ const errors_1 = require("../../modules/errors");
|
|
|
9
9
|
const key_1 = require("../../modules/key");
|
|
10
10
|
const storage_1 = require("../../modules/storage");
|
|
11
11
|
const utils_1 = require("../../modules/utils");
|
|
12
|
-
const search_1 = require("./search");
|
|
13
|
-
const worker_1 = require("./worker");
|
|
14
12
|
const serializer_1 = require("../serializer");
|
|
15
13
|
const stream_1 = require("../../types/stream");
|
|
16
14
|
const enums_1 = require("../../modules/enums");
|
|
15
|
+
const worker_1 = require("./worker");
|
|
16
|
+
const search_1 = require("./search");
|
|
17
17
|
class WorkflowService {
|
|
18
18
|
/**
|
|
19
19
|
* Returns the synchronous output from the activity (replay)
|
|
@@ -23,7 +23,7 @@ class WorkflowService {
|
|
|
23
23
|
* @returns
|
|
24
24
|
*/
|
|
25
25
|
static async didRun(prefix) {
|
|
26
|
-
const { COUNTER, replay, workflowDimension
|
|
26
|
+
const { COUNTER, replay, workflowDimension } = WorkflowService.getContext();
|
|
27
27
|
const execIndex = COUNTER.counter = COUNTER.counter + 1;
|
|
28
28
|
const sessionId = `-${prefix}${workflowDimension}-${execIndex}-`;
|
|
29
29
|
if (sessionId in replay) {
|
|
@@ -51,10 +51,10 @@ class WorkflowService {
|
|
|
51
51
|
}
|
|
52
52
|
const keyParams = {
|
|
53
53
|
appId: hotMeshClient.appId,
|
|
54
|
-
jobId: workflowId
|
|
54
|
+
jobId: workflowId,
|
|
55
55
|
};
|
|
56
56
|
const workflowGuid = key_1.KeyService.mintKey(hotMeshClient.namespace, key_1.KeyType.JOB_STATE, keyParams);
|
|
57
|
-
const guidValue = Number(await hotMeshClient.engine.store.exec('HINCRBYFLOAT', workflowGuid, sessionId, '1'));
|
|
57
|
+
const guidValue = Number((await hotMeshClient.engine.store.exec('HINCRBYFLOAT', workflowGuid, sessionId, '1')));
|
|
58
58
|
return guidValue === 1;
|
|
59
59
|
}
|
|
60
60
|
/**
|
|
@@ -120,7 +120,9 @@ class WorkflowService {
|
|
|
120
120
|
const context = WorkflowService.getContext();
|
|
121
121
|
const { canRetry, interruptionRegistry } = context;
|
|
122
122
|
if (didRun) {
|
|
123
|
-
if (result?.$error &&
|
|
123
|
+
if (result?.$error &&
|
|
124
|
+
(!result.$error.is_stream_error ||
|
|
125
|
+
result.$error.is_stream_error && !canRetry)) {
|
|
124
126
|
if (options?.config?.throwOnError !== false) {
|
|
125
127
|
//rethrow remote execution error (simulates local failure)
|
|
126
128
|
const code = result.$error.code;
|
|
@@ -182,7 +184,8 @@ class WorkflowService {
|
|
|
182
184
|
backoffCoefficient: options?.config?.backoffCoefficient ?? enums_1.HMSH_DURABLE_EXP_BACKOFF,
|
|
183
185
|
index: execIndex,
|
|
184
186
|
maximumAttempts: options?.config?.maximumAttempts ?? enums_1.HMSH_DURABLE_MAX_ATTEMPTS,
|
|
185
|
-
maximumInterval: (0, ms_1.default)(options?.config?.maximumInterval ?? enums_1.HMSH_DURABLE_MAX_INTERVAL) /
|
|
187
|
+
maximumInterval: (0, ms_1.default)(options?.config?.maximumInterval ?? enums_1.HMSH_DURABLE_MAX_INTERVAL) /
|
|
188
|
+
1000,
|
|
186
189
|
originJobId: originJobId ?? workflowId,
|
|
187
190
|
parentWorkflowId,
|
|
188
191
|
workflowDimension: workflowDimension,
|
|
@@ -277,9 +280,9 @@ class WorkflowService {
|
|
|
277
280
|
};
|
|
278
281
|
}
|
|
279
282
|
/**
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
+
* constructs the payload necessary to spawn a proxyActivity job
|
|
284
|
+
* @private
|
|
285
|
+
*/
|
|
283
286
|
static getProxyInterruptPayload(context, activityName, execIndex, args, options) {
|
|
284
287
|
const { workflowDimension, workflowId, originJobId, workflowTopic } = context;
|
|
285
288
|
const activityTopic = `${workflowTopic}-activity`;
|
|
@@ -315,7 +318,9 @@ class WorkflowService {
|
|
|
315
318
|
const namespace = store.get('namespace');
|
|
316
319
|
const COUNTER = store.get('counter');
|
|
317
320
|
const execIndex = COUNTER.counter = COUNTER.counter + 1;
|
|
318
|
-
const hotMeshClient = await worker_1.WorkerService.getHotMesh(workflowTopic, {
|
|
321
|
+
const hotMeshClient = await worker_1.WorkerService.getHotMesh(workflowTopic, {
|
|
322
|
+
namespace,
|
|
323
|
+
});
|
|
319
324
|
//this ID is used as a item key with a hash (dash prefix ensures no collision)
|
|
320
325
|
const searchSessionId = `-search${workflowDimension}-${execIndex}`;
|
|
321
326
|
return new search_1.Search(workflowId, hotMeshClient, searchSessionId);
|
|
@@ -343,9 +348,14 @@ class WorkflowService {
|
|
|
343
348
|
const store = storage_1.asyncLocalStorage.getStore();
|
|
344
349
|
const workflowTopic = store.get('workflowTopic');
|
|
345
350
|
const namespace = store.get('namespace');
|
|
346
|
-
const hotMeshClient = await worker_1.WorkerService.getHotMesh(workflowTopic, {
|
|
351
|
+
const hotMeshClient = await worker_1.WorkerService.getHotMesh(workflowTopic, {
|
|
352
|
+
namespace,
|
|
353
|
+
});
|
|
347
354
|
if (await WorkflowService.isSideEffectAllowed(hotMeshClient, 'signal')) {
|
|
348
|
-
return await hotMeshClient.hook(`${namespace}.wfs.signal`, {
|
|
355
|
+
return await hotMeshClient.hook(`${namespace}.wfs.signal`, {
|
|
356
|
+
id: signalId,
|
|
357
|
+
data,
|
|
358
|
+
});
|
|
349
359
|
}
|
|
350
360
|
}
|
|
351
361
|
/**
|
|
@@ -355,8 +365,10 @@ class WorkflowService {
|
|
|
355
365
|
* @param {HookOptions} options - the hook options
|
|
356
366
|
*/
|
|
357
367
|
static async hook(options) {
|
|
358
|
-
const { workflowId, namespace, workflowTopic
|
|
359
|
-
const hotMeshClient = await worker_1.WorkerService.getHotMesh(workflowTopic, {
|
|
368
|
+
const { workflowId, namespace, workflowTopic } = WorkflowService.getContext();
|
|
369
|
+
const hotMeshClient = await worker_1.WorkerService.getHotMesh(workflowTopic, {
|
|
370
|
+
namespace,
|
|
371
|
+
});
|
|
360
372
|
if (await WorkflowService.isSideEffectAllowed(hotMeshClient, 'hook')) {
|
|
361
373
|
const targetWorkflowId = options.workflowId ?? workflowId;
|
|
362
374
|
let targetTopic;
|
|
@@ -389,10 +401,12 @@ class WorkflowService {
|
|
|
389
401
|
if (sessionId in replay) {
|
|
390
402
|
return serializer_1.SerializerService.fromString(replay[sessionId]).data;
|
|
391
403
|
}
|
|
392
|
-
const hotMeshClient = await worker_1.WorkerService.getHotMesh(workflowTopic, {
|
|
404
|
+
const hotMeshClient = await worker_1.WorkerService.getHotMesh(workflowTopic, {
|
|
405
|
+
namespace,
|
|
406
|
+
});
|
|
393
407
|
const keyParams = {
|
|
394
408
|
appId: hotMeshClient.appId,
|
|
395
|
-
jobId: workflowId
|
|
409
|
+
jobId: workflowId,
|
|
396
410
|
};
|
|
397
411
|
const workflowGuid = key_1.KeyService.mintKey(hotMeshClient.namespace, key_1.KeyType.JOB_STATE, keyParams);
|
|
398
412
|
const t1 = new Date();
|
|
@@ -411,7 +425,9 @@ class WorkflowService {
|
|
|
411
425
|
*/
|
|
412
426
|
static async interrupt(jobId, options = {}) {
|
|
413
427
|
const { workflowTopic, namespace } = WorkflowService.getContext();
|
|
414
|
-
const hotMeshClient = await worker_1.WorkerService.getHotMesh(workflowTopic, {
|
|
428
|
+
const hotMeshClient = await worker_1.WorkerService.getHotMesh(workflowTopic, {
|
|
429
|
+
namespace,
|
|
430
|
+
});
|
|
415
431
|
if (await WorkflowService.isSideEffectAllowed(hotMeshClient, 'interrupt')) {
|
|
416
432
|
return await hotMeshClient.interrupt(`${hotMeshClient.appId}.execute`, jobId, options);
|
|
417
433
|
}
|
|
@@ -114,7 +114,10 @@ class EngineService {
|
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
setCacheMode(cacheMode, untilVersion) {
|
|
117
|
-
this.logger.info(`engine-rule-cache-updated`, {
|
|
117
|
+
this.logger.info(`engine-rule-cache-updated`, {
|
|
118
|
+
mode: cacheMode,
|
|
119
|
+
until: untilVersion,
|
|
120
|
+
});
|
|
118
121
|
this.cacheMode = cacheMode;
|
|
119
122
|
this.untilVersion = untilVersion;
|
|
120
123
|
}
|
|
@@ -126,10 +129,10 @@ class EngineService {
|
|
|
126
129
|
}
|
|
127
130
|
}
|
|
128
131
|
async processWebHooks() {
|
|
129
|
-
this.taskService.processWebHooks(
|
|
132
|
+
this.taskService.processWebHooks(this.hook.bind(this));
|
|
130
133
|
}
|
|
131
134
|
async processTimeHooks() {
|
|
132
|
-
this.taskService.processTimeHooks(
|
|
135
|
+
this.taskService.processTimeHooks(this.hookTime.bind(this));
|
|
133
136
|
}
|
|
134
137
|
async throttle(delayInMillis) {
|
|
135
138
|
this.router.setThrottle(delayInMillis);
|
|
@@ -145,7 +148,7 @@ class EngineService {
|
|
|
145
148
|
atp: schema.type,
|
|
146
149
|
stp: schema.subtype,
|
|
147
150
|
ac: utc,
|
|
148
|
-
au: utc
|
|
151
|
+
au: utc,
|
|
149
152
|
};
|
|
150
153
|
const hook = null;
|
|
151
154
|
return new ActivityHandler(schema, data, metadata, hook, this, context);
|
|
@@ -155,7 +158,7 @@ class EngineService {
|
|
|
155
158
|
}
|
|
156
159
|
}
|
|
157
160
|
async getSchema(topic) {
|
|
158
|
-
const app = await this.store.getApp(this.appId);
|
|
161
|
+
const app = (await this.store.getApp(this.appId));
|
|
159
162
|
if (!app) {
|
|
160
163
|
throw new Error(`no app found for id ${this.appId}`);
|
|
161
164
|
}
|
|
@@ -204,7 +207,7 @@ class EngineService {
|
|
|
204
207
|
return await reporter.getIds(resolvedQuery, queryFacets);
|
|
205
208
|
}
|
|
206
209
|
async resolveQuery(topic, query) {
|
|
207
|
-
const trigger = await this.initActivity(topic, query.data);
|
|
210
|
+
const trigger = (await this.initActivity(topic, query.data));
|
|
208
211
|
await trigger.getState();
|
|
209
212
|
return {
|
|
210
213
|
end: query.end,
|
|
@@ -238,17 +241,17 @@ class EngineService {
|
|
|
238
241
|
};
|
|
239
242
|
if (streamData.type === stream_1.StreamDataType.TIMEHOOK) {
|
|
240
243
|
//TIMEHOOK AWAKEN
|
|
241
|
-
const activityHandler = await this.initActivity(`.${streamData.metadata.aid}`, context.data, context);
|
|
244
|
+
const activityHandler = (await this.initActivity(`.${streamData.metadata.aid}`, context.data, context));
|
|
242
245
|
await activityHandler.processTimeHookEvent(streamData.metadata.jid);
|
|
243
246
|
}
|
|
244
247
|
else if (streamData.type === stream_1.StreamDataType.WEBHOOK) {
|
|
245
248
|
//WEBHOOK AWAKEN (SIGNAL IN)
|
|
246
|
-
const activityHandler = await this.initActivity(`.${streamData.metadata.aid}`, context.data, context);
|
|
249
|
+
const activityHandler = (await this.initActivity(`.${streamData.metadata.aid}`, context.data, context));
|
|
247
250
|
await activityHandler.processWebHookEvent(streamData.status, streamData.code);
|
|
248
251
|
}
|
|
249
252
|
else if (streamData.type === stream_1.StreamDataType.TRANSITION) {
|
|
250
253
|
//TRANSITION (ADJACENT ACTIVITY)
|
|
251
|
-
const activityHandler = await this.initActivity(`.${streamData.metadata.aid}`, context.data, context); //todo: `as Activity` (type is more generic)
|
|
254
|
+
const activityHandler = (await this.initActivity(`.${streamData.metadata.aid}`, context.data, context)); //todo: `as Activity` (type is more generic)
|
|
252
255
|
await activityHandler.process();
|
|
253
256
|
}
|
|
254
257
|
else if (streamData.type === stream_1.StreamDataType.AWAIT) {
|
|
@@ -263,23 +266,23 @@ class EngineService {
|
|
|
263
266
|
trc: streamData.metadata.trc,
|
|
264
267
|
spn: streamData.metadata.spn,
|
|
265
268
|
};
|
|
266
|
-
const activityHandler = await this.initActivity(streamData.metadata.topic, streamData.data, context);
|
|
269
|
+
const activityHandler = (await this.initActivity(streamData.metadata.topic, streamData.data, context));
|
|
267
270
|
await activityHandler.process();
|
|
268
271
|
}
|
|
269
272
|
else if (streamData.type === stream_1.StreamDataType.RESULT) {
|
|
270
273
|
//AWAIT RESULT
|
|
271
|
-
const activityHandler = await this.initActivity(`.${context.metadata.aid}`, streamData.data, context);
|
|
274
|
+
const activityHandler = (await this.initActivity(`.${context.metadata.aid}`, streamData.data, context));
|
|
272
275
|
await activityHandler.processEvent(streamData.status, streamData.code);
|
|
273
276
|
}
|
|
274
277
|
else {
|
|
275
278
|
//WORKER RESULT
|
|
276
|
-
const activityHandler = await this.initActivity(`.${streamData.metadata.aid}`, streamData.data, context);
|
|
279
|
+
const activityHandler = (await this.initActivity(`.${streamData.metadata.aid}`, streamData.data, context));
|
|
277
280
|
await activityHandler.processEvent(streamData.status, streamData.code, 'output');
|
|
278
281
|
}
|
|
279
282
|
this.logger.debug('engine-process-stream-message-end', {
|
|
280
283
|
jid: streamData.metadata.jid,
|
|
281
284
|
gid: streamData.metadata.gid,
|
|
282
|
-
aid: streamData.metadata.aid
|
|
285
|
+
aid: streamData.metadata.aid,
|
|
283
286
|
});
|
|
284
287
|
}
|
|
285
288
|
// ***************** `AWAIT` ACTIVITY RETURN RESPONSE ****************
|
|
@@ -287,7 +290,8 @@ class EngineService {
|
|
|
287
290
|
if (this.hasParentJob(context)) {
|
|
288
291
|
//errors are stringified `StreamError` objects
|
|
289
292
|
const error = this.resolveError(jobOutput.metadata);
|
|
290
|
-
const spn = context['$self']?.output?.metadata?.l2s ||
|
|
293
|
+
const spn = context['$self']?.output?.metadata?.l2s ||
|
|
294
|
+
context['$self']?.output?.metadata?.l1s;
|
|
291
295
|
const streamData = {
|
|
292
296
|
metadata: {
|
|
293
297
|
guid: (0, utils_1.guid)(),
|
|
@@ -334,12 +338,12 @@ class EngineService {
|
|
|
334
338
|
//immediately interrupt the job, going directly to the data source
|
|
335
339
|
await this.store.interrupt(topic, jobId, options);
|
|
336
340
|
//now that the job is interrupted, we can clean up
|
|
337
|
-
const context = await this.getState(topic, jobId);
|
|
341
|
+
const context = (await this.getState(topic, jobId));
|
|
338
342
|
const completionOpts = {
|
|
339
343
|
interrupt: options.descend,
|
|
340
344
|
expire: options.expire,
|
|
341
345
|
};
|
|
342
|
-
return await this.runJobCompletionTasks(context, completionOpts);
|
|
346
|
+
return (await this.runJobCompletionTasks(context, completionOpts));
|
|
343
347
|
}
|
|
344
348
|
// ****************** `SCRUB` CLEAN COMPLETED JOBS *****************
|
|
345
349
|
async scrub(jobId) {
|
|
@@ -357,15 +361,18 @@ class EngineService {
|
|
|
357
361
|
metadata: {
|
|
358
362
|
guid: (0, utils_1.guid)(),
|
|
359
363
|
aid,
|
|
360
|
-
topic
|
|
364
|
+
topic,
|
|
361
365
|
},
|
|
362
366
|
data,
|
|
363
367
|
};
|
|
364
|
-
return await this.router.publishMessage(null, streamData);
|
|
368
|
+
return (await this.router.publishMessage(null, streamData));
|
|
365
369
|
}
|
|
366
370
|
async hookTime(jobId, gId, topicOrActivity, type) {
|
|
367
371
|
if (type === 'interrupt' || type === 'expire') {
|
|
368
|
-
return await this.interrupt(topicOrActivity, jobId, {
|
|
372
|
+
return await this.interrupt(topicOrActivity, jobId, {
|
|
373
|
+
suppress: true,
|
|
374
|
+
expire: 1,
|
|
375
|
+
});
|
|
369
376
|
}
|
|
370
377
|
const [aid, ...dimensions] = topicOrActivity.split(',');
|
|
371
378
|
const dad = `,${dimensions.join(',')}`;
|
|
@@ -392,11 +399,11 @@ class EngineService {
|
|
|
392
399
|
const workItems = await reporter.getWorkItems(resolvedQuery, queryFacets);
|
|
393
400
|
if (workItems.length) {
|
|
394
401
|
const taskService = new task_1.TaskService(this.store, this.logger);
|
|
395
|
-
await taskService.enqueueWorkItems(workItems.map(workItem => [
|
|
402
|
+
await taskService.enqueueWorkItems(workItems.map((workItem) => [
|
|
396
403
|
hookTopic,
|
|
397
404
|
workItem,
|
|
398
405
|
keyResolver.scrub || false,
|
|
399
|
-
JSON.stringify(data)
|
|
406
|
+
JSON.stringify(data),
|
|
400
407
|
].join(key_1.VALSEP)));
|
|
401
408
|
this.store.publish(key_1.KeyType.QUORUM, { type: 'work', originator: this.guid }, this.appId);
|
|
402
409
|
}
|
|
@@ -445,8 +452,8 @@ class EngineService {
|
|
|
445
452
|
metadata: {
|
|
446
453
|
ngn: this.guid,
|
|
447
454
|
trc: context?.metadata?.trc,
|
|
448
|
-
spn: context?.metadata?.spn
|
|
449
|
-
}
|
|
455
|
+
spn: context?.metadata?.spn,
|
|
456
|
+
},
|
|
450
457
|
};
|
|
451
458
|
const jobId = await this.pub(topic, data, context);
|
|
452
459
|
return new Promise((resolve, reject) => {
|
|
@@ -468,7 +475,7 @@ class EngineService {
|
|
|
468
475
|
reject({
|
|
469
476
|
code: enums_1.HMSH_CODE_TIMEOUT,
|
|
470
477
|
message: 'timeout',
|
|
471
|
-
job_id: jobId
|
|
478
|
+
job_id: jobId,
|
|
472
479
|
});
|
|
473
480
|
}, timeout);
|
|
474
481
|
});
|
|
@@ -502,7 +509,7 @@ class EngineService {
|
|
|
502
509
|
}
|
|
503
510
|
}
|
|
504
511
|
async add(streamData) {
|
|
505
|
-
return await this.router.publishMessage(null, streamData);
|
|
512
|
+
return (await this.router.publishMessage(null, streamData));
|
|
506
513
|
}
|
|
507
514
|
registerJobCallback(jobId, jobCallback) {
|
|
508
515
|
this.jobCallbacks[jobId] = jobCallback;
|
|
@@ -556,7 +563,7 @@ class EngineService {
|
|
|
556
563
|
async getState(topic, jobId) {
|
|
557
564
|
const jobSymbols = await this.store.getSymbols(`$${topic}`);
|
|
558
565
|
const consumes = {
|
|
559
|
-
[`$${topic}`]: Object.keys(jobSymbols)
|
|
566
|
+
[`$${topic}`]: Object.keys(jobSymbols),
|
|
560
567
|
};
|
|
561
568
|
//job data exists at the 'zero' dimension; pass an empty object
|
|
562
569
|
const dIds = {};
|
|
@@ -2,7 +2,7 @@ import { ILogger } from '../logger';
|
|
|
2
2
|
import { StoreService } from '../store';
|
|
3
3
|
import { DependencyExport, ExportOptions, JobActionExport, JobExport } from '../../types/exporter';
|
|
4
4
|
import { RedisClient, RedisMulti } from '../../types/redis';
|
|
5
|
-
import { StringStringType, Symbols } from
|
|
5
|
+
import { StringStringType, Symbols } from '../../types/serializer';
|
|
6
6
|
/**
|
|
7
7
|
* Downloads job data from Redis (hscan, hmget, hgetall)
|
|
8
8
|
* Expands process data and includes dependency list
|
|
@@ -35,7 +35,7 @@ class ExporterService {
|
|
|
35
35
|
* tree-like structure of the unidimensional Hash
|
|
36
36
|
*/
|
|
37
37
|
inflateKey(key) {
|
|
38
|
-
return
|
|
38
|
+
return key in this.symbols ? this.symbols[key] : key;
|
|
39
39
|
}
|
|
40
40
|
/**
|
|
41
41
|
* Inflates the job data from Redis into a JobExport object
|
|
@@ -49,8 +49,8 @@ class ExporterService {
|
|
|
49
49
|
hooks: {},
|
|
50
50
|
main: {
|
|
51
51
|
cursor: -1,
|
|
52
|
-
items: []
|
|
53
|
-
}
|
|
52
|
+
items: [],
|
|
53
|
+
},
|
|
54
54
|
};
|
|
55
55
|
const process = {};
|
|
56
56
|
const dependencies = this.inflateDependencyData(dependencyList, actions);
|
|
@@ -87,7 +87,7 @@ class HotMeshService {
|
|
|
87
87
|
return await this.engine?.pubsub(topic, data, context, timeout);
|
|
88
88
|
}
|
|
89
89
|
async add(streamData) {
|
|
90
|
-
return await this.engine.add(streamData);
|
|
90
|
+
return (await this.engine.add(streamData));
|
|
91
91
|
}
|
|
92
92
|
// ************* QUORUM METHODS *************
|
|
93
93
|
async rollCall(delay) {
|
|
@@ -17,7 +17,7 @@ class LoggerService {
|
|
|
17
17
|
const { timestamp, level, message } = info;
|
|
18
18
|
// Extract the object from the `info` object's `Symbol(splat)` field
|
|
19
19
|
const symbols = Object.getOwnPropertySymbols(info);
|
|
20
|
-
const splatSymbol = symbols.find(symbol => symbol.toString() === 'Symbol(splat)');
|
|
20
|
+
const splatSymbol = symbols.find((symbol) => symbol.toString() === 'Symbol(splat)');
|
|
21
21
|
let splatData = {};
|
|
22
22
|
if (splatSymbol) {
|
|
23
23
|
splatData = info[splatSymbol][0] || {};
|
|
@@ -53,7 +53,9 @@ class MapperService {
|
|
|
53
53
|
if (typeof transitionRule === 'boolean') {
|
|
54
54
|
return transitionRule;
|
|
55
55
|
}
|
|
56
|
-
if ((Array.isArray(transitionRule.code) &&
|
|
56
|
+
if ((Array.isArray(transitionRule.code) &&
|
|
57
|
+
transitionRule.code.includes(code || 200)) ||
|
|
58
|
+
code.toString() === (transitionRule.code || 200).toString()) {
|
|
57
59
|
if (!transitionRule.match) {
|
|
58
60
|
return true;
|
|
59
61
|
}
|