@hotmeshio/hotmesh 0.2.3 → 0.3.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 +14 -14
- package/build/modules/enums.d.ts +1 -0
- package/build/modules/enums.js +2 -1
- package/build/modules/errors.d.ts +1 -0
- package/build/modules/errors.js +1 -0
- package/build/modules/utils.d.ts +1 -0
- package/build/modules/utils.js +6 -10
- package/build/package.json +1 -1
- package/build/services/activities/activity.d.ts +3 -0
- package/build/services/activities/activity.js +24 -7
- package/build/services/activities/hook.js +3 -2
- package/build/services/activities/trigger.js +15 -5
- package/build/services/collator/index.d.ts +2 -0
- package/build/services/collator/index.js +12 -0
- package/build/services/compiler/deployer.js +1 -0
- package/build/services/engine/index.js +1 -0
- package/build/services/exporter/index.js +1 -1
- package/build/services/meshcall/index.d.ts +5 -5
- package/build/services/meshcall/index.js +45 -32
- package/build/services/meshcall/schemas/factory.js +2 -2
- package/build/services/meshdata/index.d.ts +2 -2
- package/build/services/meshdata/index.js +25 -20
- package/build/services/meshflow/client.js +3 -8
- package/build/services/meshflow/schemas/factory.d.ts +1 -1
- package/build/services/meshflow/schemas/factory.js +56 -10
- package/build/services/meshflow/worker.js +3 -5
- package/build/services/meshflow/workflow.js +10 -12
- package/build/services/router/index.js +3 -1
- package/build/services/store/clients/ioredis.d.ts +1 -0
- package/build/services/store/clients/ioredis.js +4 -0
- package/build/services/store/clients/redis.d.ts +1 -0
- package/build/services/store/clients/redis.js +5 -0
- package/build/services/store/index.d.ts +2 -3
- package/build/services/store/index.js +5 -36
- package/build/services/task/index.d.ts +1 -1
- package/build/services/task/index.js +3 -6
- package/build/types/activity.d.ts +2 -0
- package/build/types/error.d.ts +1 -0
- package/build/types/hook.d.ts +1 -0
- package/build/types/hotmesh.d.ts +1 -0
- package/build/types/job.d.ts +1 -1
- package/build/types/meshcall.d.ts +6 -2
- package/build/types/meshdata.d.ts +1 -1
- package/build/types/meshflow.d.ts +3 -0
- package/package.json +1 -1
- package/types/activity.ts +3 -1
- package/types/error.ts +1 -0
- package/types/hook.ts +6 -1
- package/types/hotmesh.ts +35 -0
- package/types/job.ts +4 -14
- package/types/meshcall.ts +19 -2
- package/types/meshdata.ts +9 -5
- package/types/meshflow.ts +12 -1
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
var _a;
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.MeshData = void 0;
|
|
5
|
+
const utils_1 = require("../../modules/utils");
|
|
5
6
|
const meshflow_1 = require("../meshflow");
|
|
6
7
|
const hotmesh_1 = require("../hotmesh");
|
|
7
8
|
const hotmesh_2 = require("../../types/hotmesh");
|
|
9
|
+
const enums_1 = require("../../modules/enums");
|
|
8
10
|
class MeshData {
|
|
9
11
|
constructor(redisClass, redisOptions, search) {
|
|
10
12
|
this.connectionSignatures = {};
|
|
@@ -161,7 +163,7 @@ class MeshData {
|
|
|
161
163
|
this.connectionSignatures[entity] = target.toString();
|
|
162
164
|
const targetFunction = {
|
|
163
165
|
[entity]: async (...args) => {
|
|
164
|
-
const { callOptions } = this.bindCallOptions(args
|
|
166
|
+
const { callOptions } = this.bindCallOptions(args);
|
|
165
167
|
const result = (await target.apply(target, args));
|
|
166
168
|
await this.pauseForTTL(result, callOptions);
|
|
167
169
|
return result;
|
|
@@ -177,19 +179,11 @@ class MeshData {
|
|
|
177
179
|
});
|
|
178
180
|
return true;
|
|
179
181
|
}
|
|
180
|
-
bindCallOptions(args,
|
|
182
|
+
bindCallOptions(args, callOptions = {}) {
|
|
181
183
|
if (args.length) {
|
|
182
184
|
const lastArg = args[args.length - 1];
|
|
183
185
|
if (lastArg instanceof Object && lastArg?.$type === 'exec') {
|
|
184
186
|
callOptions = args.pop();
|
|
185
|
-
if (options.ttl === 'infinity') {
|
|
186
|
-
if (!callOptions) {
|
|
187
|
-
callOptions = { ttl: 'infinity' };
|
|
188
|
-
}
|
|
189
|
-
else {
|
|
190
|
-
callOptions.ttl = 'infinity';
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
187
|
}
|
|
194
188
|
else if (lastArg instanceof Object && lastArg.$type === 'hook') {
|
|
195
189
|
callOptions = args.pop();
|
|
@@ -215,13 +209,6 @@ class MeshData {
|
|
|
215
209
|
});
|
|
216
210
|
const jobResponse = ['aAa', '/t', 'aBa', this.toString(result)];
|
|
217
211
|
await store?.exec('HSET', jobKey, ...jobResponse);
|
|
218
|
-
await this.publishDone(result, hotMesh, options);
|
|
219
|
-
if (options.ttl === 'infinity') {
|
|
220
|
-
await MeshData.workflow.waitFor(`flush-${options.$guid}`);
|
|
221
|
-
}
|
|
222
|
-
else {
|
|
223
|
-
await MeshData.workflow.sleepFor(options.ttl);
|
|
224
|
-
}
|
|
225
212
|
}
|
|
226
213
|
}
|
|
227
214
|
async publishDone(result, hotMesh, options) {
|
|
@@ -278,9 +265,13 @@ class MeshData {
|
|
|
278
265
|
async hook({ entity, id, hookEntity, hookArgs, options = {}, }) {
|
|
279
266
|
const workflowId = MeshData.mintGuid(entity, id);
|
|
280
267
|
this.validate(workflowId);
|
|
268
|
+
const args = [
|
|
269
|
+
...hookArgs,
|
|
270
|
+
{ ...options, $guid: workflowId, $type: 'hook' },
|
|
271
|
+
];
|
|
281
272
|
return await this.getClient().workflow.hook({
|
|
282
273
|
namespace: options.namespace,
|
|
283
|
-
args
|
|
274
|
+
args,
|
|
284
275
|
taskQueue: options.taskQueue ?? hookEntity,
|
|
285
276
|
workflowName: hookEntity,
|
|
286
277
|
workflowId: options.workflowId ?? workflowId,
|
|
@@ -301,6 +292,19 @@ class MeshData {
|
|
|
301
292
|
}
|
|
302
293
|
catch (e) {
|
|
303
294
|
const optionsClone = { ...options };
|
|
295
|
+
let seconds;
|
|
296
|
+
if (optionsClone.ttl) {
|
|
297
|
+
if (optionsClone.signalIn !== false) {
|
|
298
|
+
optionsClone.signalIn = true;
|
|
299
|
+
}
|
|
300
|
+
if (optionsClone.ttl === 'infinity') {
|
|
301
|
+
delete optionsClone.ttl;
|
|
302
|
+
seconds = enums_1.MAX_DELAY;
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
seconds = (0, utils_1.s)(optionsClone.ttl);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
304
308
|
delete optionsClone.search;
|
|
305
309
|
delete optionsClone.config;
|
|
306
310
|
const handle = await client.workflow.start({
|
|
@@ -316,8 +320,9 @@ class MeshData {
|
|
|
316
320
|
await: options.await,
|
|
317
321
|
marker: options.marker,
|
|
318
322
|
pending: options.pending,
|
|
319
|
-
expire: options.expire,
|
|
320
|
-
|
|
323
|
+
expire: seconds ?? options.expire,
|
|
324
|
+
persistent: options.signalIn == false ? undefined : seconds && true,
|
|
325
|
+
signalIn: optionsClone.signalIn,
|
|
321
326
|
});
|
|
322
327
|
if (options.await === false) {
|
|
323
328
|
return handle.workflowId;
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
var _a;
|
|
6
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
4
|
exports.ClientService = void 0;
|
|
8
|
-
const ms_1 = __importDefault(require("ms"));
|
|
9
5
|
const enums_1 = require("../../modules/enums");
|
|
10
6
|
const utils_1 = require("../../modules/utils");
|
|
11
7
|
const hotmesh_1 = require("../hotmesh");
|
|
@@ -68,14 +64,14 @@ class ClientService {
|
|
|
68
64
|
arguments: [...options.args],
|
|
69
65
|
originJobId: options.originJobId,
|
|
70
66
|
expire: options.expire ?? enums_1.HMSH_EXPIRE_JOB_SECONDS,
|
|
67
|
+
persistent: options.persistent,
|
|
71
68
|
signalIn: options.signalIn,
|
|
72
69
|
parentWorkflowId: options.parentWorkflowId,
|
|
73
70
|
workflowId: options.workflowId || hotmesh_1.HotMesh.guid(),
|
|
74
71
|
workflowTopic: workflowTopic,
|
|
75
72
|
backoffCoefficient: options.config?.backoffCoefficient || enums_1.HMSH_MESHFLOW_EXP_BACKOFF,
|
|
76
73
|
maximumAttempts: options.config?.maximumAttempts || enums_1.HMSH_MESHFLOW_MAX_ATTEMPTS,
|
|
77
|
-
maximumInterval: (0,
|
|
78
|
-
1000,
|
|
74
|
+
maximumInterval: (0, utils_1.s)(options.config?.maximumInterval || enums_1.HMSH_MESHFLOW_MAX_INTERVAL),
|
|
79
75
|
};
|
|
80
76
|
const context = { metadata: { trc, spn }, data: {} };
|
|
81
77
|
const jobId = await hotMeshClient.pub(`${options.namespace ?? factory_1.APP_ID}.execute`, payload, context, {
|
|
@@ -97,8 +93,7 @@ class ClientService {
|
|
|
97
93
|
workflowTopic,
|
|
98
94
|
backoffCoefficient: options.config?.backoffCoefficient || enums_1.HMSH_MESHFLOW_EXP_BACKOFF,
|
|
99
95
|
maximumAttempts: options.config?.maximumAttempts || enums_1.HMSH_MESHFLOW_MAX_ATTEMPTS,
|
|
100
|
-
maximumInterval: (0,
|
|
101
|
-
1000,
|
|
96
|
+
maximumInterval: (0, utils_1.s)(options.config?.maximumInterval || enums_1.HMSH_MESHFLOW_MAX_INTERVAL),
|
|
102
97
|
};
|
|
103
98
|
const hotMeshClient = await this.getHotMeshClient(workflowTopic, options.namespace);
|
|
104
99
|
const msgId = await hotMeshClient.hook(`${hotMeshClient.appId}.flow.signal`, payload, types_1.StreamStatus.PENDING, 202);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.APP_ID = exports.APP_VERSION = exports.getWorkflowYAML = void 0;
|
|
4
|
-
const APP_VERSION = '
|
|
4
|
+
const APP_VERSION = '4';
|
|
5
5
|
exports.APP_VERSION = APP_VERSION;
|
|
6
6
|
const APP_ID = 'durable';
|
|
7
7
|
exports.APP_ID = APP_ID;
|
|
@@ -12,14 +12,17 @@ const getWorkflowYAML = (app, version) => {
|
|
|
12
12
|
graphs:
|
|
13
13
|
|
|
14
14
|
###################################################
|
|
15
|
-
# THE MESHFLOW-REENTRANT-WORKFLOW
|
|
15
|
+
# THE MESHFLOW-REENTRANT-WORKFLOW #
|
|
16
16
|
# #
|
|
17
17
|
- subscribes: ${app}.execute
|
|
18
18
|
publishes: ${app}.executed
|
|
19
19
|
|
|
20
|
+
persistent: '{trigger.output.data.persistent}'
|
|
20
21
|
expire:
|
|
21
22
|
'@pipe':
|
|
22
|
-
- ['{trigger.output.data.
|
|
23
|
+
- ['{trigger.output.data.persistent}']
|
|
24
|
+
- ['{@number.isNaN}', '{trigger.output.data.originJobId}']
|
|
25
|
+
- ['{@logical.and}', 1,'{trigger.output.data.expire}']
|
|
23
26
|
- ['{@conditional.ternary}']
|
|
24
27
|
|
|
25
28
|
input:
|
|
@@ -52,6 +55,9 @@ const getWorkflowYAML = (app, version) => {
|
|
|
52
55
|
expire:
|
|
53
56
|
description: the time in seconds to expire the workflow in Redis once it completes
|
|
54
57
|
type: number
|
|
58
|
+
persistent:
|
|
59
|
+
description: if true, the workflow emit the 'job completed' event while remaining open to outside signals
|
|
60
|
+
type: boolean
|
|
55
61
|
signalIn:
|
|
56
62
|
description: if false, the job will not support subordinated hooks
|
|
57
63
|
type: boolean
|
|
@@ -136,11 +142,14 @@ const getWorkflowYAML = (app, version) => {
|
|
|
136
142
|
type: string
|
|
137
143
|
canRetry:
|
|
138
144
|
type: boolean
|
|
145
|
+
expire:
|
|
146
|
+
type: number
|
|
139
147
|
maps:
|
|
140
148
|
originJobId: '{trigger.output.data.originJobId}'
|
|
141
149
|
workflowId: '{trigger.output.data.workflowId}'
|
|
142
150
|
arguments: '{trigger.output.data.arguments}'
|
|
143
151
|
workflowTopic: '{trigger.output.data.workflowTopic}'
|
|
152
|
+
expire: '{trigger.output.data.expire}'
|
|
144
153
|
canRetry:
|
|
145
154
|
'@pipe':
|
|
146
155
|
- '@pipe':
|
|
@@ -208,6 +217,8 @@ const getWorkflowYAML = (app, version) => {
|
|
|
208
217
|
type: number
|
|
209
218
|
expire:
|
|
210
219
|
type: number
|
|
220
|
+
persistent:
|
|
221
|
+
type: boolean
|
|
211
222
|
signalIn:
|
|
212
223
|
type: boolean
|
|
213
224
|
await:
|
|
@@ -313,6 +324,8 @@ const getWorkflowYAML = (app, version) => {
|
|
|
313
324
|
type: number
|
|
314
325
|
expire:
|
|
315
326
|
type: number
|
|
327
|
+
persistent:
|
|
328
|
+
type: boolean
|
|
316
329
|
signalIn:
|
|
317
330
|
type: boolean
|
|
318
331
|
parentWorkflowId:
|
|
@@ -336,6 +349,7 @@ const getWorkflowYAML = (app, version) => {
|
|
|
336
349
|
originJobId: '{worker.output.data.originJobId}'
|
|
337
350
|
parentWorkflowId: '{worker.output.data.parentWorkflowId}'
|
|
338
351
|
expire: '{worker.output.data.expire}'
|
|
352
|
+
persistent: '{worker.output.data.persistent}'
|
|
339
353
|
signalIn: '{worker.output.data.signalIn}'
|
|
340
354
|
workflowId: '{worker.output.data.workflowId}'
|
|
341
355
|
workflowName: '{worker.output.data.workflowName}'
|
|
@@ -643,6 +657,8 @@ const getWorkflowYAML = (app, version) => {
|
|
|
643
657
|
type: number
|
|
644
658
|
data:
|
|
645
659
|
type: object
|
|
660
|
+
expire:
|
|
661
|
+
type: number
|
|
646
662
|
maps:
|
|
647
663
|
items: '{worker.output.data.items}'
|
|
648
664
|
size: '{worker.output.data.size}'
|
|
@@ -652,6 +668,7 @@ const getWorkflowYAML = (app, version) => {
|
|
|
652
668
|
parentWorkflowId: '{worker.output.data.workflowId}'
|
|
653
669
|
workflowId: '{worker.output.data.workflowId}'
|
|
654
670
|
workflowTopic: '{worker.output.data.workflowTopic}'
|
|
671
|
+
expire: '{worker.output.data.expire}'
|
|
655
672
|
output:
|
|
656
673
|
schema:
|
|
657
674
|
type: object
|
|
@@ -740,8 +757,9 @@ const getWorkflowYAML = (app, version) => {
|
|
|
740
757
|
- ['{@logical.or}']
|
|
741
758
|
- ['{@math.min}']
|
|
742
759
|
ender:
|
|
743
|
-
title: Sets job data; ignores the \`Signal In\` Hook Channel which was suppressed
|
|
760
|
+
title: Sets job data; ignores the \`Signal In\` Hook Channel which was suppressed; sends the final response
|
|
744
761
|
type: hook
|
|
762
|
+
persist: '{trigger.output.data.signalIn}'
|
|
745
763
|
job:
|
|
746
764
|
maps:
|
|
747
765
|
done: true
|
|
@@ -854,11 +872,14 @@ const getWorkflowYAML = (app, version) => {
|
|
|
854
872
|
type: array
|
|
855
873
|
canRetry:
|
|
856
874
|
type: boolean
|
|
875
|
+
expire:
|
|
876
|
+
type: number
|
|
857
877
|
maps:
|
|
858
878
|
workflowId: '{trigger.output.data.workflowId}'
|
|
859
879
|
originJobId: '{trigger.output.data.originJobId}'
|
|
860
880
|
workflowDimension: '{signaler.output.metadata.dad}'
|
|
861
881
|
arguments: '{signaler.hook.data.arguments}'
|
|
882
|
+
expire: '{trigger.output.data.expire}'
|
|
862
883
|
canRetry:
|
|
863
884
|
'@pipe':
|
|
864
885
|
- '@pipe':
|
|
@@ -938,6 +959,8 @@ const getWorkflowYAML = (app, version) => {
|
|
|
938
959
|
description: the maximum time in seconds to wait between retries; provides a fixed limit to exponential backoff growth
|
|
939
960
|
expire:
|
|
940
961
|
type: number
|
|
962
|
+
persistent:
|
|
963
|
+
type: boolean
|
|
941
964
|
signalIn:
|
|
942
965
|
type: boolean
|
|
943
966
|
description: if false, the spawned child will not support subordinated hooks
|
|
@@ -1043,6 +1066,8 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1043
1066
|
type: number
|
|
1044
1067
|
expire:
|
|
1045
1068
|
type: number
|
|
1069
|
+
persistent:
|
|
1070
|
+
type: boolean
|
|
1046
1071
|
signalIn:
|
|
1047
1072
|
type: boolean
|
|
1048
1073
|
parentWorkflowId:
|
|
@@ -1066,6 +1091,7 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1066
1091
|
originJobId: '{signaler_worker.output.data.originJobId}'
|
|
1067
1092
|
parentWorkflowId: '{signaler_worker.output.data.parentWorkflowId}'
|
|
1068
1093
|
expire: '{signaler_worker.output.data.expire}'
|
|
1094
|
+
persistent: '{signaler_worker.output.data.persistent}'
|
|
1069
1095
|
signalIn: '{signaler_worker.output.data.signalIn}'
|
|
1070
1096
|
workflowId: '{signaler_worker.output.data.workflowId}'
|
|
1071
1097
|
workflowName: '{signaler_worker.output.data.workflowName}'
|
|
@@ -1373,6 +1399,8 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1373
1399
|
type: number
|
|
1374
1400
|
data:
|
|
1375
1401
|
type: object
|
|
1402
|
+
expire:
|
|
1403
|
+
type: number
|
|
1376
1404
|
maps:
|
|
1377
1405
|
items: '{signaler_worker.output.data.items}'
|
|
1378
1406
|
size: '{signaler_worker.output.data.size}'
|
|
@@ -1382,6 +1410,7 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1382
1410
|
parentWorkflowId: '{signaler_worker.output.data.workflowId}'
|
|
1383
1411
|
workflowId: '{signaler_worker.output.data.workflowId}'
|
|
1384
1412
|
workflowTopic: '{signaler_worker.output.data.workflowTopic}'
|
|
1413
|
+
expire: '{signaler_worker.output.data.expire}'
|
|
1385
1414
|
output:
|
|
1386
1415
|
schema:
|
|
1387
1416
|
type: object
|
|
@@ -1494,8 +1523,8 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1494
1523
|
- expected: false
|
|
1495
1524
|
actual:
|
|
1496
1525
|
'@pipe':
|
|
1497
|
-
- ['{trigger.output.data.signalIn}',
|
|
1498
|
-
- ['{@conditional.
|
|
1526
|
+
- ['{trigger.output.data.signalIn}', '{@symbol.undefined}']
|
|
1527
|
+
- ['{@conditional.strict_equality}']
|
|
1499
1528
|
- to: closer
|
|
1500
1529
|
conditions:
|
|
1501
1530
|
code: [200, 596, 597, 598]
|
|
@@ -1503,8 +1532,8 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1503
1532
|
- expected: true
|
|
1504
1533
|
actual:
|
|
1505
1534
|
'@pipe':
|
|
1506
|
-
- ['{trigger.output.data.signalIn}',
|
|
1507
|
-
- ['{@conditional.
|
|
1535
|
+
- ['{trigger.output.data.signalIn}', '{@symbol.undefined}']
|
|
1536
|
+
- ['{@conditional.strict_equality}']
|
|
1508
1537
|
- to: sleeper
|
|
1509
1538
|
conditions:
|
|
1510
1539
|
code: 588
|
|
@@ -1631,7 +1660,10 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1631
1660
|
- subscribes: ${app}.collator.execute
|
|
1632
1661
|
publishes: ${app}.collator.executed
|
|
1633
1662
|
|
|
1634
|
-
expire:
|
|
1663
|
+
expire:
|
|
1664
|
+
'@pipe':
|
|
1665
|
+
- ['{collator_trigger.output.data.expire}', 1]
|
|
1666
|
+
- ['{@conditional.nullish}']
|
|
1635
1667
|
|
|
1636
1668
|
input:
|
|
1637
1669
|
schema:
|
|
@@ -1658,6 +1690,8 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1658
1690
|
type: index
|
|
1659
1691
|
data:
|
|
1660
1692
|
type: object
|
|
1693
|
+
expire:
|
|
1694
|
+
type: number
|
|
1661
1695
|
output:
|
|
1662
1696
|
schema:
|
|
1663
1697
|
type: object
|
|
@@ -1799,6 +1833,8 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1799
1833
|
type: number
|
|
1800
1834
|
expire:
|
|
1801
1835
|
type: number
|
|
1836
|
+
persistent:
|
|
1837
|
+
type: boolean
|
|
1802
1838
|
signalIn:
|
|
1803
1839
|
type: boolean
|
|
1804
1840
|
parentWorkflowId:
|
|
@@ -1840,6 +1876,11 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1840
1876
|
- ['{collator_trigger.output.data.items}', '{collator_cycle_hook.output.data.cur_index}']
|
|
1841
1877
|
- ['{@array.get}', expire]
|
|
1842
1878
|
- ['{@object.get}']
|
|
1879
|
+
persistent:
|
|
1880
|
+
'@pipe':
|
|
1881
|
+
- ['{collator_trigger.output.data.items}', '{collator_cycle_hook.output.data.cur_index}']
|
|
1882
|
+
- ['{@array.get}', persistent]
|
|
1883
|
+
- ['{@object.get}']
|
|
1843
1884
|
signalIn:
|
|
1844
1885
|
'@pipe':
|
|
1845
1886
|
- ['{collator_trigger.output.data.items}', '{collator_cycle_hook.output.data.cur_index}']
|
|
@@ -2230,7 +2271,10 @@ const getWorkflowYAML = (app, version) => {
|
|
|
2230
2271
|
- subscribes: ${app}.activity.execute
|
|
2231
2272
|
publishes: ${app}.activity.executed
|
|
2232
2273
|
|
|
2233
|
-
expire:
|
|
2274
|
+
expire:
|
|
2275
|
+
'@pipe':
|
|
2276
|
+
- ['{activity_trigger.output.data.expire}', 1]
|
|
2277
|
+
- ['{@conditional.nullish}']
|
|
2234
2278
|
|
|
2235
2279
|
input:
|
|
2236
2280
|
schema:
|
|
@@ -2254,6 +2298,8 @@ const getWorkflowYAML = (app, version) => {
|
|
|
2254
2298
|
type: number
|
|
2255
2299
|
maximumInterval:
|
|
2256
2300
|
type: number
|
|
2301
|
+
expire:
|
|
2302
|
+
type: number
|
|
2257
2303
|
output:
|
|
2258
2304
|
schema:
|
|
2259
2305
|
type: object
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
var _a;
|
|
6
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
4
|
exports.WorkerService = void 0;
|
|
8
|
-
const ms_1 = __importDefault(require("ms"));
|
|
9
5
|
const enums_1 = require("../../modules/enums");
|
|
10
6
|
const errors_1 = require("../../modules/errors");
|
|
11
7
|
const storage_1 = require("../../modules/storage");
|
|
@@ -196,6 +192,7 @@ class WorkerService {
|
|
|
196
192
|
const workflowInput = data.data;
|
|
197
193
|
const context = new Map();
|
|
198
194
|
context.set('canRetry', workflowInput.canRetry);
|
|
195
|
+
context.set('expire', workflowInput.expire);
|
|
199
196
|
context.set('counter', counter);
|
|
200
197
|
context.set('interruptionRegistry', interruptionRegistry);
|
|
201
198
|
context.set('connection', config.connection);
|
|
@@ -326,10 +323,11 @@ class WorkerService {
|
|
|
326
323
|
index: err.index,
|
|
327
324
|
message: JSON.stringify(msg),
|
|
328
325
|
maximumAttempts: err.maximumAttempts || enums_1.HMSH_MESHFLOW_MAX_ATTEMPTS,
|
|
329
|
-
maximumInterval: err.maximumInterval || (0,
|
|
326
|
+
maximumInterval: err.maximumInterval || (0, utils_1.s)(enums_1.HMSH_MESHFLOW_MAX_INTERVAL),
|
|
330
327
|
originJobId: err.originJobId,
|
|
331
328
|
parentWorkflowId: err.parentWorkflowId,
|
|
332
329
|
expire: err.expire,
|
|
330
|
+
persistent: err.persistent,
|
|
333
331
|
signalIn: err.signalIn,
|
|
334
332
|
workflowDimension: err.workflowDimension,
|
|
335
333
|
workflowId: err.workflowId,
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.WorkflowService = void 0;
|
|
7
|
-
const ms_1 = __importDefault(require("ms"));
|
|
8
4
|
const errors_1 = require("../../modules/errors");
|
|
9
5
|
const key_1 = require("../../modules/key");
|
|
10
6
|
const storage_1 = require("../../modules/storage");
|
|
@@ -59,6 +55,7 @@ class WorkflowService {
|
|
|
59
55
|
const workflowTrace = store.get('workflowTrace');
|
|
60
56
|
const canRetry = store.get('canRetry');
|
|
61
57
|
const workflowSpan = store.get('workflowSpan');
|
|
58
|
+
const expire = store.get('expire');
|
|
62
59
|
const COUNTER = store.get('counter');
|
|
63
60
|
const raw = store.get('raw');
|
|
64
61
|
return {
|
|
@@ -68,6 +65,7 @@ class WorkflowService {
|
|
|
68
65
|
cursor,
|
|
69
66
|
interruptionRegistry,
|
|
70
67
|
connection,
|
|
68
|
+
expire,
|
|
71
69
|
namespace,
|
|
72
70
|
originJobId,
|
|
73
71
|
raw,
|
|
@@ -131,7 +129,7 @@ class WorkflowService {
|
|
|
131
129
|
throw new errors_1.MeshFlowChildError(interruptionMessage);
|
|
132
130
|
}
|
|
133
131
|
static getChildInterruptPayload(context, options, execIndex) {
|
|
134
|
-
const { workflowId, originJobId, workflowDimension } = context;
|
|
132
|
+
const { workflowId, originJobId, workflowDimension, expire } = context;
|
|
135
133
|
let childJobId;
|
|
136
134
|
if (options.workflowId) {
|
|
137
135
|
childJobId = options.workflowId;
|
|
@@ -152,10 +150,10 @@ class WorkflowService {
|
|
|
152
150
|
backoffCoefficient: options?.config?.backoffCoefficient ?? enums_1.HMSH_MESHFLOW_EXP_BACKOFF,
|
|
153
151
|
index: execIndex,
|
|
154
152
|
maximumAttempts: options?.config?.maximumAttempts ?? enums_1.HMSH_MESHFLOW_MAX_ATTEMPTS,
|
|
155
|
-
maximumInterval: (0,
|
|
156
|
-
1000,
|
|
153
|
+
maximumInterval: (0, utils_1.s)(options?.config?.maximumInterval ?? enums_1.HMSH_MESHFLOW_MAX_INTERVAL),
|
|
157
154
|
originJobId: originJobId ?? workflowId,
|
|
158
|
-
expire: options.expire,
|
|
155
|
+
expire: options.expire ?? expire,
|
|
156
|
+
persistent: options.persistent,
|
|
159
157
|
signalIn: options.signalIn,
|
|
160
158
|
parentWorkflowId,
|
|
161
159
|
workflowDimension: workflowDimension,
|
|
@@ -215,12 +213,12 @@ class WorkflowService {
|
|
|
215
213
|
};
|
|
216
214
|
}
|
|
217
215
|
static getProxyInterruptPayload(context, activityName, execIndex, args, options) {
|
|
218
|
-
const { workflowDimension, workflowId, originJobId, workflowTopic } = context;
|
|
216
|
+
const { workflowDimension, workflowId, originJobId, workflowTopic, expire, } = context;
|
|
219
217
|
const activityTopic = `${workflowTopic}-activity`;
|
|
220
218
|
const activityJobId = `-${workflowId}-$${activityName}${workflowDimension}-${execIndex}`;
|
|
221
219
|
let maximumInterval;
|
|
222
220
|
if (options.retryPolicy?.maximumInterval) {
|
|
223
|
-
maximumInterval = (0,
|
|
221
|
+
maximumInterval = (0, utils_1.s)(options.retryPolicy.maximumInterval);
|
|
224
222
|
}
|
|
225
223
|
return {
|
|
226
224
|
arguments: args,
|
|
@@ -231,7 +229,7 @@ class WorkflowService {
|
|
|
231
229
|
workflowId: activityJobId,
|
|
232
230
|
workflowTopic: activityTopic,
|
|
233
231
|
activityName,
|
|
234
|
-
expire: options.expire,
|
|
232
|
+
expire: options.expire ?? expire,
|
|
235
233
|
backoffCoefficient: options?.retryPolicy?.backoffCoefficient ?? undefined,
|
|
236
234
|
maximumAttempts: options?.retryPolicy?.maximumAttempts ?? undefined,
|
|
237
235
|
maximumInterval: maximumInterval ?? undefined,
|
|
@@ -351,7 +349,7 @@ class WorkflowService {
|
|
|
351
349
|
const workflowDimension = store.get('workflowDimension') ?? '';
|
|
352
350
|
const interruptionMessage = {
|
|
353
351
|
workflowId,
|
|
354
|
-
duration: (0,
|
|
352
|
+
duration: (0, utils_1.s)(duration),
|
|
355
353
|
index: execIndex,
|
|
356
354
|
workflowDimension,
|
|
357
355
|
};
|
|
@@ -74,8 +74,10 @@ class Router {
|
|
|
74
74
|
});
|
|
75
75
|
}
|
|
76
76
|
async consumeMessages(stream, group, consumer, callback) {
|
|
77
|
-
if (this.readonly)
|
|
77
|
+
if (this.readonly) {
|
|
78
|
+
this.logger.info(`router-stream-readonly`, { group, consumer, stream });
|
|
78
79
|
return;
|
|
80
|
+
}
|
|
79
81
|
this.logger.info(`router-stream-starting`, { group, consumer, stream });
|
|
80
82
|
Router.instances.add(this);
|
|
81
83
|
this.shouldConsume = true;
|
|
@@ -15,6 +15,7 @@ declare class IORedisStoreService extends StoreService<RedisClientType, RedisMul
|
|
|
15
15
|
constructor(redisClient: RedisClientType);
|
|
16
16
|
getMulti(): RedisMultiType;
|
|
17
17
|
exec(...args: any[]): Promise<string | string[] | string[][]>;
|
|
18
|
+
setnxex(key: string, value: string, expireSeconds: number): Promise<boolean>;
|
|
18
19
|
hGetAllResult(result: any): any;
|
|
19
20
|
addTaskQueues(keys: string[]): Promise<void>;
|
|
20
21
|
publish(keyType: KeyType.QUORUM, message: Record<string, any>, appId: string, engineId?: string): Promise<boolean>;
|
|
@@ -122,6 +122,10 @@ class IORedisStoreService extends index_1.StoreService {
|
|
|
122
122
|
}
|
|
123
123
|
return response;
|
|
124
124
|
}
|
|
125
|
+
async setnxex(key, value, expireSeconds) {
|
|
126
|
+
const status = await this.redisClient[this.commands.set](key, value, 'NX', 'EX', expireSeconds.toString());
|
|
127
|
+
return this.isSuccessful(status);
|
|
128
|
+
}
|
|
125
129
|
hGetAllResult(result) {
|
|
126
130
|
return result[1];
|
|
127
131
|
}
|
|
@@ -16,6 +16,7 @@ declare class RedisStoreService extends StoreService<RedisClientType, RedisMulti
|
|
|
16
16
|
constructor(redisClient: RedisClientType);
|
|
17
17
|
getMulti(): RedisMultiType;
|
|
18
18
|
exec(...args: any[]): Promise<string | string[] | string[][]>;
|
|
19
|
+
setnxex(key: string, value: string, expireSeconds: number): Promise<boolean>;
|
|
19
20
|
publish(keyType: KeyType.QUORUM, message: Record<string, any>, appId: string, engineId?: string): Promise<boolean>;
|
|
20
21
|
zAdd(key: string, score: number | string, value: string | number, redisMulti?: RedisMultiType): Promise<any>;
|
|
21
22
|
zRangeByScoreWithScores(key: string, score: number | string, value: string | number): Promise<string | null>;
|
|
@@ -7,6 +7,7 @@ class RedisStoreService extends index_1.StoreService {
|
|
|
7
7
|
constructor(redisClient) {
|
|
8
8
|
super(redisClient);
|
|
9
9
|
this.commands = {
|
|
10
|
+
get: 'GET',
|
|
10
11
|
set: 'SET',
|
|
11
12
|
setnx: 'SETNX',
|
|
12
13
|
del: 'DEL',
|
|
@@ -172,6 +173,10 @@ class RedisStoreService extends index_1.StoreService {
|
|
|
172
173
|
async exec(...args) {
|
|
173
174
|
return await this.redisClient.sendCommand(args);
|
|
174
175
|
}
|
|
176
|
+
async setnxex(key, value, expireSeconds) {
|
|
177
|
+
const status = await this.redisClient[this.commands.set](key, value, { NX: true, EX: expireSeconds });
|
|
178
|
+
return this.isSuccessful(status);
|
|
179
|
+
}
|
|
175
180
|
async publish(keyType, message, appId, engineId) {
|
|
176
181
|
const topic = this.mintKey(keyType, { appId, engineId });
|
|
177
182
|
const status = await this.redisClient.publish(topic, JSON.stringify(message));
|
|
@@ -9,7 +9,7 @@ import { SymbolSets, StringStringType, StringAnyType, Symbols } from '../../type
|
|
|
9
9
|
import { IdsData, JobStatsRange, StatsType } from '../../types/stats';
|
|
10
10
|
import { Transitions } from '../../types/transition';
|
|
11
11
|
import { ReclaimedMessageType } from '../../types/stream';
|
|
12
|
-
import {
|
|
12
|
+
import { JobInterruptOptions } from '../../types/job';
|
|
13
13
|
import { WorkListTaskType } from '../../types/task';
|
|
14
14
|
import { ThrottleOptions } from '../../types/quorum';
|
|
15
15
|
import { Cache } from './cache';
|
|
@@ -26,6 +26,7 @@ declare abstract class StoreService<T, U extends AbstractRedisClient> {
|
|
|
26
26
|
commands: Record<string, string>;
|
|
27
27
|
abstract getMulti(): U;
|
|
28
28
|
abstract exec(...args: any[]): Promise<string | string[] | string[][]>;
|
|
29
|
+
abstract setnxex(key: string, value: string, expireSeconds: number): Promise<boolean>;
|
|
29
30
|
abstract publish(keyType: KeyType.QUORUM, message: Record<string, any>, appId: string, engineId?: string): Promise<boolean>;
|
|
30
31
|
abstract xgroup(command: 'CREATE', key: string, groupName: string, id: string, mkStream?: 'MKSTREAM'): Promise<boolean>;
|
|
31
32
|
abstract xadd(key: string, id: string, messageId: string, messageValue: string, multi?: U): Promise<string | U>;
|
|
@@ -61,7 +62,6 @@ declare abstract class StoreService<T, U extends AbstractRedisClient> {
|
|
|
61
62
|
activateAppVersion(id: string, version: string): Promise<boolean>;
|
|
62
63
|
registerAppVersion(appId: string, version: string): Promise<any>;
|
|
63
64
|
registerJobDependency(depType: WorkListTaskType, originJobId: string, topic: string, jobId: string, gId: string, pd?: string, multi?: U): Promise<any>;
|
|
64
|
-
registerSignalDependency(jobId: string, signalKey: string, dad: string, multi?: U): Promise<any>;
|
|
65
65
|
setStats(jobKey: string, jobId: string, dateTime: string, stats: StatsType, appVersion: AppVID, multi?: U): Promise<any>;
|
|
66
66
|
hGetAllResult(result: any): any;
|
|
67
67
|
getJobStats(jobKeys: string[]): Promise<JobStatsRange>;
|
|
@@ -93,7 +93,6 @@ declare abstract class StoreService<T, U extends AbstractRedisClient> {
|
|
|
93
93
|
deleteProcessedTaskQueue(workItemKey: string, key: string, processedKey: string, scrub?: boolean): Promise<void>;
|
|
94
94
|
processTaskQueue(sourceKey: string, destinationKey: string): Promise<any>;
|
|
95
95
|
expireJob(jobId: string, inSeconds: number, redisMulti?: U): Promise<void>;
|
|
96
|
-
registerDependenciesForCleanup(jobId: string, deletionTime: number, options: JobCompletionOptions): Promise<void>;
|
|
97
96
|
getDependencies(jobId: string): Promise<string[]>;
|
|
98
97
|
registerTimeHook(jobId: string, gId: string, activityId: string, type: WorkListTaskType, deletionTime: number, dad: string, multi?: U): Promise<void>;
|
|
99
98
|
getNextTask(listKey?: string): Promise<[
|