@hotmeshio/hotmesh 0.0.16 → 0.0.17
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/build/package.json +1 -1
- package/build/services/activities/activity.js +6 -1
- package/build/services/activities/trigger.js +1 -1
- package/build/services/durable/client.js +1 -0
- package/build/services/durable/factory.js +78 -2
- package/build/services/durable/workflow.js +2 -0
- package/build/types/durable.d.ts +1 -0
- package/package.json +1 -1
- package/services/activities/activity.ts +6 -1
- package/services/activities/trigger.ts +1 -1
- package/services/durable/client.ts +1 -0
- package/services/durable/factory.ts +78 -2
- package/services/durable/workflow.ts +2 -0
- package/types/durable.ts +1 -0
package/build/package.json
CHANGED
|
@@ -496,7 +496,12 @@ class Activity {
|
|
|
496
496
|
}
|
|
497
497
|
async transition(adjacencyList, jobStatus) {
|
|
498
498
|
let mIds = [];
|
|
499
|
-
|
|
499
|
+
//emit can be a mapping (allows emissions to be driven by the job state)
|
|
500
|
+
let emit = false;
|
|
501
|
+
if (this.config.emit) {
|
|
502
|
+
emit = pipe_1.Pipe.resolve(this.config.emit, this.context);
|
|
503
|
+
}
|
|
504
|
+
if (jobStatus <= 0 || emit) {
|
|
500
505
|
//activity should not send 'emit' if the job is truly over
|
|
501
506
|
const isTrueEmit = jobStatus > 0;
|
|
502
507
|
await this.engine.runJobCompletionTasks(this.context, isTrueEmit);
|
|
@@ -151,7 +151,7 @@ class Trigger extends activity_1.Activity {
|
|
|
151
151
|
}
|
|
152
152
|
async setStats(multi) {
|
|
153
153
|
const md = this.context.metadata;
|
|
154
|
-
if (this.config.stats?.measures) {
|
|
154
|
+
if (md.key && this.config.stats?.measures) {
|
|
155
155
|
const config = await this.engine.getVID();
|
|
156
156
|
const reporter = new reporter_1.ReporterService(config, this.store, this.logger);
|
|
157
157
|
await this.store.setStats(md.key, md.jid, md.ts, reporter.resolveTriggerStatistics(this.config, this.context), config, multi);
|
|
@@ -87,6 +87,7 @@ class ClientService {
|
|
|
87
87
|
const hotMeshClient = await this.getHotMeshClient(workflowTopic);
|
|
88
88
|
const payload = {
|
|
89
89
|
arguments: [...options.args],
|
|
90
|
+
parentWorkflowId: options.parentWorkflowId,
|
|
90
91
|
workflowId: options.workflowId || (0, nanoid_1.nanoid)(),
|
|
91
92
|
workflowTopic: workflowTopic,
|
|
92
93
|
backoffCoefficient: options.config?.backoffCoefficient || factory_1.DEFAULT_COEFFICIENT,
|
|
@@ -25,6 +25,8 @@ const getWorkflowYAML = (app, version) => {
|
|
|
25
25
|
schema:
|
|
26
26
|
type: object
|
|
27
27
|
properties:
|
|
28
|
+
parentWorkflowId:
|
|
29
|
+
type: string
|
|
28
30
|
workflowId:
|
|
29
31
|
type: string
|
|
30
32
|
arguments:
|
|
@@ -47,6 +49,11 @@ const getWorkflowYAML = (app, version) => {
|
|
|
47
49
|
type: trigger
|
|
48
50
|
stats:
|
|
49
51
|
id: '{$self.input.data.workflowId}'
|
|
52
|
+
key: '{$self.input.data.parentWorkflowId}'
|
|
53
|
+
granularity: infinity
|
|
54
|
+
measures:
|
|
55
|
+
- measure: index
|
|
56
|
+
target: '{$self.input.data.parentWorkflowId}'
|
|
50
57
|
job:
|
|
51
58
|
maps:
|
|
52
59
|
done: false
|
|
@@ -66,6 +73,7 @@ const getWorkflowYAML = (app, version) => {
|
|
|
66
73
|
w1:
|
|
67
74
|
type: worker
|
|
68
75
|
topic: '{t1.output.data.workflowTopic}'
|
|
76
|
+
emit: '{$job.data.done}'
|
|
69
77
|
retry:
|
|
70
78
|
'599': [2]
|
|
71
79
|
input:
|
|
@@ -123,6 +131,19 @@ const getWorkflowYAML = (app, version) => {
|
|
|
123
131
|
response: '{$self.output.data.response}'
|
|
124
132
|
done: '{$self.output.data.done}'
|
|
125
133
|
|
|
134
|
+
a2:
|
|
135
|
+
type: activity
|
|
136
|
+
title: Wait for cleanup signal
|
|
137
|
+
hook:
|
|
138
|
+
type: object
|
|
139
|
+
properties:
|
|
140
|
+
done:
|
|
141
|
+
type: boolean
|
|
142
|
+
job:
|
|
143
|
+
maps:
|
|
144
|
+
workflowId: '{t1.output.data.workflowId}'
|
|
145
|
+
|
|
146
|
+
|
|
126
147
|
a594:
|
|
127
148
|
title: Wait for signals
|
|
128
149
|
type: await
|
|
@@ -280,7 +301,7 @@ const getWorkflowYAML = (app, version) => {
|
|
|
280
301
|
done: true
|
|
281
302
|
|
|
282
303
|
s2:
|
|
283
|
-
title: Awaken
|
|
304
|
+
title: Awaken sleeping flows so they end and self-clean
|
|
284
305
|
type: signal
|
|
285
306
|
subtype: all
|
|
286
307
|
key_name: parentWorkflowId
|
|
@@ -352,10 +373,55 @@ const getWorkflowYAML = (app, version) => {
|
|
|
352
373
|
type: boolean
|
|
353
374
|
maps:
|
|
354
375
|
done: true
|
|
376
|
+
|
|
377
|
+
s4:
|
|
378
|
+
title: Awaken child FLOWS so they end and self-clean
|
|
379
|
+
type: signal
|
|
380
|
+
subtype: all
|
|
381
|
+
key_name: parentWorkflowId
|
|
382
|
+
key_value:
|
|
383
|
+
'@pipe':
|
|
384
|
+
- ['{$job.metadata.jid}', '-f']
|
|
385
|
+
- ['{@string.concat}']
|
|
386
|
+
topic: ${app}.childflow.awaken
|
|
387
|
+
resolver:
|
|
388
|
+
schema:
|
|
389
|
+
type: object
|
|
390
|
+
properties:
|
|
391
|
+
data:
|
|
392
|
+
type: object
|
|
393
|
+
properties:
|
|
394
|
+
parentWorkflowId:
|
|
395
|
+
type: string
|
|
396
|
+
scrub:
|
|
397
|
+
type: boolean
|
|
398
|
+
maps:
|
|
399
|
+
data:
|
|
400
|
+
parentWorkflowId:
|
|
401
|
+
'@pipe':
|
|
402
|
+
- ['{$job.metadata.jid}', '-f']
|
|
403
|
+
- ['{@string.concat}']
|
|
404
|
+
scrub: true
|
|
405
|
+
signal:
|
|
406
|
+
schema:
|
|
407
|
+
type: object
|
|
408
|
+
properties:
|
|
409
|
+
done:
|
|
410
|
+
type: boolean
|
|
411
|
+
maps:
|
|
412
|
+
done: true
|
|
355
413
|
|
|
356
414
|
transitions:
|
|
357
415
|
t1:
|
|
358
416
|
- to: a1
|
|
417
|
+
- to: a2
|
|
418
|
+
conditions:
|
|
419
|
+
match:
|
|
420
|
+
- expected: true
|
|
421
|
+
actual:
|
|
422
|
+
'@pipe':
|
|
423
|
+
- ['{$job.metadata.key}', true, false]
|
|
424
|
+
- ['{@conditional.ternary}']
|
|
359
425
|
a1:
|
|
360
426
|
- to: w1
|
|
361
427
|
w1:
|
|
@@ -377,11 +443,13 @@ const getWorkflowYAML = (app, version) => {
|
|
|
377
443
|
- to: s3
|
|
378
444
|
conditions:
|
|
379
445
|
code: [200, 598, 597, 596]
|
|
446
|
+
- to: s4
|
|
447
|
+
conditions:
|
|
448
|
+
code: [200, 598, 597, 596]
|
|
380
449
|
a594:
|
|
381
450
|
- to: c594
|
|
382
451
|
conditions:
|
|
383
452
|
code: 202
|
|
384
|
-
|
|
385
453
|
a595:
|
|
386
454
|
- to: c595
|
|
387
455
|
conditions:
|
|
@@ -389,6 +457,14 @@ const getWorkflowYAML = (app, version) => {
|
|
|
389
457
|
a599:
|
|
390
458
|
- to: c599
|
|
391
459
|
|
|
460
|
+
hooks:
|
|
461
|
+
${app}.childflow.awaken:
|
|
462
|
+
- to: a2
|
|
463
|
+
conditions:
|
|
464
|
+
match:
|
|
465
|
+
- expected: '{t1.output.data.workflowId}'
|
|
466
|
+
actual: '{$self.hook.data.id}'
|
|
467
|
+
|
|
392
468
|
- subscribes: ${app}.activity.execute
|
|
393
469
|
publishes: ${app}.activity.executed
|
|
394
470
|
|
|
@@ -54,6 +54,7 @@ class WorkflowService {
|
|
|
54
54
|
const COUNTER = store.get('counter');
|
|
55
55
|
const execIndex = COUNTER.counter = COUNTER.counter + 1;
|
|
56
56
|
const childJobId = `${workflowId}-$${options.workflowName}-${execIndex}`;
|
|
57
|
+
const parentWorkflowId = `${workflowId}-f`;
|
|
57
58
|
const client = new client_1.ClientService({
|
|
58
59
|
connection: await connection_1.ConnectionService.connect(worker_1.WorkerService.connection),
|
|
59
60
|
});
|
|
@@ -65,6 +66,7 @@ class WorkflowService {
|
|
|
65
66
|
handle = await client.workflow.start({
|
|
66
67
|
...options,
|
|
67
68
|
workflowId: childJobId,
|
|
69
|
+
parentWorkflowId,
|
|
68
70
|
workflowTrace,
|
|
69
71
|
workflowSpan,
|
|
70
72
|
});
|
package/build/types/durable.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -584,7 +584,12 @@ class Activity {
|
|
|
584
584
|
|
|
585
585
|
async transition(adjacencyList: StreamData[], jobStatus: JobStatus): Promise<string[]> {
|
|
586
586
|
let mIds: string[] = [];
|
|
587
|
-
|
|
587
|
+
//emit can be a mapping (allows emissions to be driven by the job state)
|
|
588
|
+
let emit: boolean = false;
|
|
589
|
+
if (this.config.emit) {
|
|
590
|
+
emit = Pipe.resolve(this.config.emit, this.context);
|
|
591
|
+
}
|
|
592
|
+
if (jobStatus <= 0 || emit) {
|
|
588
593
|
//activity should not send 'emit' if the job is truly over
|
|
589
594
|
const isTrueEmit = jobStatus > 0;
|
|
590
595
|
await this.engine.runJobCompletionTasks(this.context, isTrueEmit);
|
|
@@ -178,7 +178,7 @@ class Trigger extends Activity {
|
|
|
178
178
|
|
|
179
179
|
async setStats(multi?: RedisMulti): Promise<void> {
|
|
180
180
|
const md = this.context.metadata;
|
|
181
|
-
if (this.config.stats?.measures) {
|
|
181
|
+
if (md.key && this.config.stats?.measures) {
|
|
182
182
|
const config = await this.engine.getVID();
|
|
183
183
|
const reporter = new ReporterService(config, this.store, this.logger);
|
|
184
184
|
await this.store.setStats(
|
|
@@ -101,6 +101,7 @@ export class ClientService {
|
|
|
101
101
|
const hotMeshClient = await this.getHotMeshClient(workflowTopic);
|
|
102
102
|
const payload = {
|
|
103
103
|
arguments: [...options.args],
|
|
104
|
+
parentWorkflowId: options.parentWorkflowId,
|
|
104
105
|
workflowId: options.workflowId || nanoid(),
|
|
105
106
|
workflowTopic: workflowTopic,
|
|
106
107
|
backoffCoefficient: options.config?.backoffCoefficient || DEFAULT_COEFFICIENT,
|
|
@@ -24,6 +24,8 @@ const getWorkflowYAML = (app: string, version: string) => {
|
|
|
24
24
|
schema:
|
|
25
25
|
type: object
|
|
26
26
|
properties:
|
|
27
|
+
parentWorkflowId:
|
|
28
|
+
type: string
|
|
27
29
|
workflowId:
|
|
28
30
|
type: string
|
|
29
31
|
arguments:
|
|
@@ -46,6 +48,11 @@ const getWorkflowYAML = (app: string, version: string) => {
|
|
|
46
48
|
type: trigger
|
|
47
49
|
stats:
|
|
48
50
|
id: '{$self.input.data.workflowId}'
|
|
51
|
+
key: '{$self.input.data.parentWorkflowId}'
|
|
52
|
+
granularity: infinity
|
|
53
|
+
measures:
|
|
54
|
+
- measure: index
|
|
55
|
+
target: '{$self.input.data.parentWorkflowId}'
|
|
49
56
|
job:
|
|
50
57
|
maps:
|
|
51
58
|
done: false
|
|
@@ -65,6 +72,7 @@ const getWorkflowYAML = (app: string, version: string) => {
|
|
|
65
72
|
w1:
|
|
66
73
|
type: worker
|
|
67
74
|
topic: '{t1.output.data.workflowTopic}'
|
|
75
|
+
emit: '{$job.data.done}'
|
|
68
76
|
retry:
|
|
69
77
|
'599': [2]
|
|
70
78
|
input:
|
|
@@ -122,6 +130,19 @@ const getWorkflowYAML = (app: string, version: string) => {
|
|
|
122
130
|
response: '{$self.output.data.response}'
|
|
123
131
|
done: '{$self.output.data.done}'
|
|
124
132
|
|
|
133
|
+
a2:
|
|
134
|
+
type: activity
|
|
135
|
+
title: Wait for cleanup signal
|
|
136
|
+
hook:
|
|
137
|
+
type: object
|
|
138
|
+
properties:
|
|
139
|
+
done:
|
|
140
|
+
type: boolean
|
|
141
|
+
job:
|
|
142
|
+
maps:
|
|
143
|
+
workflowId: '{t1.output.data.workflowId}'
|
|
144
|
+
|
|
145
|
+
|
|
125
146
|
a594:
|
|
126
147
|
title: Wait for signals
|
|
127
148
|
type: await
|
|
@@ -279,7 +300,7 @@ const getWorkflowYAML = (app: string, version: string) => {
|
|
|
279
300
|
done: true
|
|
280
301
|
|
|
281
302
|
s2:
|
|
282
|
-
title: Awaken
|
|
303
|
+
title: Awaken sleeping flows so they end and self-clean
|
|
283
304
|
type: signal
|
|
284
305
|
subtype: all
|
|
285
306
|
key_name: parentWorkflowId
|
|
@@ -351,10 +372,55 @@ const getWorkflowYAML = (app: string, version: string) => {
|
|
|
351
372
|
type: boolean
|
|
352
373
|
maps:
|
|
353
374
|
done: true
|
|
375
|
+
|
|
376
|
+
s4:
|
|
377
|
+
title: Awaken child FLOWS so they end and self-clean
|
|
378
|
+
type: signal
|
|
379
|
+
subtype: all
|
|
380
|
+
key_name: parentWorkflowId
|
|
381
|
+
key_value:
|
|
382
|
+
'@pipe':
|
|
383
|
+
- ['{$job.metadata.jid}', '-f']
|
|
384
|
+
- ['{@string.concat}']
|
|
385
|
+
topic: ${app}.childflow.awaken
|
|
386
|
+
resolver:
|
|
387
|
+
schema:
|
|
388
|
+
type: object
|
|
389
|
+
properties:
|
|
390
|
+
data:
|
|
391
|
+
type: object
|
|
392
|
+
properties:
|
|
393
|
+
parentWorkflowId:
|
|
394
|
+
type: string
|
|
395
|
+
scrub:
|
|
396
|
+
type: boolean
|
|
397
|
+
maps:
|
|
398
|
+
data:
|
|
399
|
+
parentWorkflowId:
|
|
400
|
+
'@pipe':
|
|
401
|
+
- ['{$job.metadata.jid}', '-f']
|
|
402
|
+
- ['{@string.concat}']
|
|
403
|
+
scrub: true
|
|
404
|
+
signal:
|
|
405
|
+
schema:
|
|
406
|
+
type: object
|
|
407
|
+
properties:
|
|
408
|
+
done:
|
|
409
|
+
type: boolean
|
|
410
|
+
maps:
|
|
411
|
+
done: true
|
|
354
412
|
|
|
355
413
|
transitions:
|
|
356
414
|
t1:
|
|
357
415
|
- to: a1
|
|
416
|
+
- to: a2
|
|
417
|
+
conditions:
|
|
418
|
+
match:
|
|
419
|
+
- expected: true
|
|
420
|
+
actual:
|
|
421
|
+
'@pipe':
|
|
422
|
+
- ['{$job.metadata.key}', true, false]
|
|
423
|
+
- ['{@conditional.ternary}']
|
|
358
424
|
a1:
|
|
359
425
|
- to: w1
|
|
360
426
|
w1:
|
|
@@ -376,11 +442,13 @@ const getWorkflowYAML = (app: string, version: string) => {
|
|
|
376
442
|
- to: s3
|
|
377
443
|
conditions:
|
|
378
444
|
code: [200, 598, 597, 596]
|
|
445
|
+
- to: s4
|
|
446
|
+
conditions:
|
|
447
|
+
code: [200, 598, 597, 596]
|
|
379
448
|
a594:
|
|
380
449
|
- to: c594
|
|
381
450
|
conditions:
|
|
382
451
|
code: 202
|
|
383
|
-
|
|
384
452
|
a595:
|
|
385
453
|
- to: c595
|
|
386
454
|
conditions:
|
|
@@ -388,6 +456,14 @@ const getWorkflowYAML = (app: string, version: string) => {
|
|
|
388
456
|
a599:
|
|
389
457
|
- to: c599
|
|
390
458
|
|
|
459
|
+
hooks:
|
|
460
|
+
${app}.childflow.awaken:
|
|
461
|
+
- to: a2
|
|
462
|
+
conditions:
|
|
463
|
+
match:
|
|
464
|
+
- expected: '{t1.output.data.workflowId}'
|
|
465
|
+
actual: '{$self.hook.data.id}'
|
|
466
|
+
|
|
391
467
|
- subscribes: ${app}.activity.execute
|
|
392
468
|
publishes: ${app}.activity.executed
|
|
393
469
|
|
|
@@ -54,6 +54,7 @@ export class WorkflowService {
|
|
|
54
54
|
const COUNTER = store.get('counter');
|
|
55
55
|
const execIndex = COUNTER.counter = COUNTER.counter + 1;
|
|
56
56
|
const childJobId = `${workflowId}-$${options.workflowName}-${execIndex}`;
|
|
57
|
+
const parentWorkflowId = `${workflowId}-f`;
|
|
57
58
|
|
|
58
59
|
const client = new Client({
|
|
59
60
|
connection: await Connection.connect(WorkerService.connection),
|
|
@@ -71,6 +72,7 @@ export class WorkflowService {
|
|
|
71
72
|
handle = await client.workflow.start({
|
|
72
73
|
...options,
|
|
73
74
|
workflowId: childJobId,
|
|
75
|
+
parentWorkflowId,
|
|
74
76
|
workflowTrace,
|
|
75
77
|
workflowSpan,
|
|
76
78
|
});
|
package/types/durable.ts
CHANGED
|
@@ -12,6 +12,7 @@ type WorkflowOptions = {
|
|
|
12
12
|
args: any[]; //input arguments to pass in
|
|
13
13
|
workflowId: string; //execution id (the job id)
|
|
14
14
|
workflowName?: string; //the name of the user's workflow function
|
|
15
|
+
parentWorkflowId?: string; //system reserved; the id of the parent; if present the flow will not self-clean until the parent that spawned it self-cleans
|
|
15
16
|
workflowTrace?: string;
|
|
16
17
|
workflowSpan?: string;
|
|
17
18
|
config?: WorkflowConfig;
|