@hotmeshio/hotmesh 0.14.7 → 0.14.8
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/worker.js +14 -0
- package/build/services/durable/exporter.js +2 -2
- package/build/services/durable/schemas/factory.d.ts +1 -19
- package/build/services/durable/schemas/factory.js +122 -524
- package/build/services/durable/worker.js +25 -14
- package/build/services/router/consumption/index.js +14 -5
- package/build/services/router/error-handling/index.d.ts +1 -1
- package/build/services/router/error-handling/index.js +12 -11
- package/build/services/store/providers/postgres/exporter-sql.d.ts +4 -0
- package/build/services/store/providers/postgres/exporter-sql.js +11 -1
- package/build/services/store/providers/postgres/postgres.js +24 -0
- package/build/services/stream/providers/postgres/postgres.d.ts +6 -0
- package/build/services/stream/providers/postgres/postgres.js +25 -0
- package/package.json +1 -1
package/build/package.json
CHANGED
|
@@ -181,6 +181,20 @@ class Worker extends activity_1.Activity {
|
|
|
181
181
|
retry: this.config.retry,
|
|
182
182
|
};
|
|
183
183
|
}
|
|
184
|
+
// Propagate per-activity retry config as _streamRetryConfig so
|
|
185
|
+
// the engine-level retry mechanism uses it for exponential backoff.
|
|
186
|
+
// The durable module's maximumAttempts means max retries
|
|
187
|
+
// (total executions = 1 + maximumAttempts), while the engine's
|
|
188
|
+
// max_retry_attempts means total attempts. Add 1 to align.
|
|
189
|
+
if (jobData?.maximumAttempts || jobData?.backoffCoefficient || jobData?.maximumInterval || jobData?.initialInterval) {
|
|
190
|
+
const durableMaxAttempts = jobData.maximumAttempts ?? 50;
|
|
191
|
+
streamData._streamRetryConfig = {
|
|
192
|
+
max_retry_attempts: durableMaxAttempts + 1,
|
|
193
|
+
backoff_coefficient: jobData.backoffCoefficient ?? 10,
|
|
194
|
+
maximum_interval_seconds: jobData.maximumInterval ?? 120,
|
|
195
|
+
initialInterval: jobData.initialInterval ?? 1,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
184
198
|
return (await this.engine.router?.publishMessage(topic, streamData, transaction));
|
|
185
199
|
}
|
|
186
200
|
}
|
|
@@ -474,10 +474,10 @@ class ExporterService {
|
|
|
474
474
|
const activityArgsField = this.resolveSymbolField(symbolSets, 'activity_trigger', 'activity_trigger/output/data/arguments');
|
|
475
475
|
const workflowArgsField = this.resolveSymbolField(symbolSets, 'trigger', 'trigger/output/data/arguments');
|
|
476
476
|
// ── 1. Enrich activity inputs ──
|
|
477
|
-
|
|
477
|
+
{
|
|
478
478
|
const activityEvents = execution.events.filter((e) => e.event_type === 'activity_task_scheduled' || e.event_type === 'activity_task_completed' || e.event_type === 'activity_task_failed');
|
|
479
479
|
if (activityEvents.length > 0) {
|
|
480
|
-
const { byJobId, byNameIndex } = await this.store.getActivityInputs(workflowId, activityArgsField);
|
|
480
|
+
const { byJobId, byNameIndex } = await this.store.getActivityInputs(workflowId, activityArgsField || '');
|
|
481
481
|
for (const evt of activityEvents) {
|
|
482
482
|
const attrs = evt.attributes;
|
|
483
483
|
let input = attrs.timeline_key ? byJobId.get(attrs.timeline_key) : undefined;
|
|
@@ -1,22 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
*********** HOTMESH 'DURABLE' MODULE APPLICATION GRAPH **********
|
|
3
|
-
*
|
|
4
|
-
* This HotMesh application spec uses 50 activities and 25 transitions
|
|
5
|
-
* to model a durable workflow engine using a pluggable backend.
|
|
6
|
-
*
|
|
7
|
-
* This YAML file can also serve as a useful starting point for building
|
|
8
|
-
* Integration/BPM/Workflow servers in general (MuleSoft, etc) without the need
|
|
9
|
-
* for a physical application server.
|
|
10
|
-
*
|
|
11
|
-
* Possible use cases include:
|
|
12
|
-
* * Orchestration servers
|
|
13
|
-
* * Integration servers
|
|
14
|
-
* * BPMN engines
|
|
15
|
-
* * Reentrant process servers
|
|
16
|
-
* * Service Meshes
|
|
17
|
-
* * Master Data Management systems
|
|
18
|
-
*/
|
|
19
|
-
declare const APP_VERSION = "11";
|
|
1
|
+
declare const APP_VERSION = "12";
|
|
20
2
|
declare const APP_ID = "durable";
|
|
21
3
|
/**
|
|
22
4
|
* returns a new durable workflow schema
|
|
@@ -1,25 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
*********** HOTMESH 'DURABLE' MODULE APPLICATION GRAPH **********
|
|
4
|
-
*
|
|
5
|
-
* This HotMesh application spec uses 50 activities and 25 transitions
|
|
6
|
-
* to model a durable workflow engine using a pluggable backend.
|
|
7
|
-
*
|
|
8
|
-
* This YAML file can also serve as a useful starting point for building
|
|
9
|
-
* Integration/BPM/Workflow servers in general (MuleSoft, etc) without the need
|
|
10
|
-
* for a physical application server.
|
|
11
|
-
*
|
|
12
|
-
* Possible use cases include:
|
|
13
|
-
* * Orchestration servers
|
|
14
|
-
* * Integration servers
|
|
15
|
-
* * BPMN engines
|
|
16
|
-
* * Reentrant process servers
|
|
17
|
-
* * Service Meshes
|
|
18
|
-
* * Master Data Management systems
|
|
19
|
-
*/
|
|
20
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
3
|
exports.APP_ID = exports.APP_VERSION = exports.getWorkflowYAML = void 0;
|
|
22
|
-
const APP_VERSION = '
|
|
4
|
+
const APP_VERSION = '12';
|
|
23
5
|
exports.APP_VERSION = APP_VERSION;
|
|
24
6
|
const APP_ID = 'durable';
|
|
25
7
|
exports.APP_ID = APP_ID;
|
|
@@ -153,12 +135,10 @@ const getWorkflowYAML = (app, version) => {
|
|
|
153
135
|
type: number
|
|
154
136
|
maps:
|
|
155
137
|
retryCount: 0
|
|
156
|
-
throttleSeconds: 0
|
|
157
138
|
|
|
158
139
|
throttler:
|
|
159
|
-
title:
|
|
140
|
+
title: Pass-through hook between cycle_hook and worker
|
|
160
141
|
type: hook
|
|
161
|
-
sleep: '{cycle_hook.output.data.throttleSeconds}'
|
|
162
142
|
|
|
163
143
|
worker:
|
|
164
144
|
title: Main Worker - Calls linked Workflow functions
|
|
@@ -202,6 +182,22 @@ const getWorkflowYAML = (app, version) => {
|
|
|
202
182
|
- ['{trigger.output.data.maximumAttempts}', 5]
|
|
203
183
|
- ['{@conditional.nullish}']
|
|
204
184
|
- ['{@conditional.less_than}']
|
|
185
|
+
maximumAttempts:
|
|
186
|
+
'@pipe':
|
|
187
|
+
- ['{trigger.output.data.maximumAttempts}', 5]
|
|
188
|
+
- ['{@conditional.nullish}']
|
|
189
|
+
backoffCoefficient:
|
|
190
|
+
'@pipe':
|
|
191
|
+
- ['{trigger.output.data.backoffCoefficient}', 10]
|
|
192
|
+
- ['{@conditional.nullish}']
|
|
193
|
+
maximumInterval:
|
|
194
|
+
'@pipe':
|
|
195
|
+
- ['{trigger.output.data.maximumInterval}', 120]
|
|
196
|
+
- ['{@conditional.nullish}']
|
|
197
|
+
initialInterval:
|
|
198
|
+
'@pipe':
|
|
199
|
+
- ['{trigger.output.data.initialInterval}', 1]
|
|
200
|
+
- ['{@conditional.nullish}']
|
|
205
201
|
output:
|
|
206
202
|
schema:
|
|
207
203
|
type: object
|
|
@@ -364,7 +360,6 @@ const getWorkflowYAML = (app, version) => {
|
|
|
364
360
|
input:
|
|
365
361
|
maps:
|
|
366
362
|
retryCount: 0
|
|
367
|
-
throttleSeconds: 0
|
|
368
363
|
continueGeneration: '{cycle_hook.output.data.continueGeneration}'
|
|
369
364
|
continueArgs: '{cycle_hook.output.data.continueArgs}'
|
|
370
365
|
|
|
@@ -540,38 +535,13 @@ const getWorkflowYAML = (app, version) => {
|
|
|
540
535
|
- '@pipe':
|
|
541
536
|
- [0]
|
|
542
537
|
- ['{@conditional.ternary}']
|
|
543
|
-
throttleSeconds:
|
|
544
|
-
'@pipe':
|
|
545
|
-
- '@pipe':
|
|
546
|
-
- ['{childer.output.metadata.err}']
|
|
547
|
-
- '@pipe':
|
|
548
|
-
- '@pipe':
|
|
549
|
-
- '@pipe':
|
|
550
|
-
- '@pipe':
|
|
551
|
-
- ['{trigger.output.data.backoffCoefficient}', 10]
|
|
552
|
-
- ['{@conditional.nullish}']
|
|
553
|
-
- '@pipe':
|
|
554
|
-
- ['{cycle_hook.output.data.retryCount}', 0]
|
|
555
|
-
- ['{@conditional.nullish}']
|
|
556
|
-
- ['{@math.pow}']
|
|
557
|
-
- '@pipe':
|
|
558
|
-
- ['{trigger.output.data.initialInterval}', 1]
|
|
559
|
-
- ['{@conditional.nullish}']
|
|
560
|
-
- ['{@math.multiply}']
|
|
561
|
-
- '@pipe':
|
|
562
|
-
- ['{trigger.output.data.maximumInterval}', 120]
|
|
563
|
-
- ['{@logical.or}']
|
|
564
|
-
- ['{@math.min}']
|
|
565
|
-
- '@pipe':
|
|
566
|
-
- [0]
|
|
567
|
-
- ['{@conditional.ternary}']
|
|
568
538
|
continueGeneration: '{cycle_hook.output.data.continueGeneration}'
|
|
569
539
|
continueArgs: '{cycle_hook.output.data.continueArgs}'
|
|
570
540
|
|
|
571
541
|
proxyer:
|
|
572
|
-
title:
|
|
573
|
-
type:
|
|
574
|
-
topic:
|
|
542
|
+
title: Calls the activity function directly via worker topic
|
|
543
|
+
type: worker
|
|
544
|
+
topic: '{worker.output.data.workflowTopic}'
|
|
575
545
|
input:
|
|
576
546
|
schema:
|
|
577
547
|
type: object
|
|
@@ -637,6 +607,12 @@ const getWorkflowYAML = (app, version) => {
|
|
|
637
607
|
- ['{worker.output.data.maximumInterval}','{trigger.output.data.maximumInterval}']
|
|
638
608
|
- ['{@conditional.nullish}', 120]
|
|
639
609
|
- ['{@conditional.nullish}']
|
|
610
|
+
output:
|
|
611
|
+
schema:
|
|
612
|
+
type: object
|
|
613
|
+
properties:
|
|
614
|
+
response:
|
|
615
|
+
type: any
|
|
640
616
|
job:
|
|
641
617
|
maps:
|
|
642
618
|
idempotentcy-marker[-]:
|
|
@@ -646,24 +622,26 @@ const getWorkflowYAML = (app, version) => {
|
|
|
646
622
|
- ['{@string.concat}']
|
|
647
623
|
- '@pipe':
|
|
648
624
|
- '@pipe':
|
|
649
|
-
- ['{$self.output.data.$error}']
|
|
625
|
+
- ['{$self.output.data.$error}', '{$self.output.metadata.err}']
|
|
626
|
+
- ['{@logical.or}']
|
|
650
627
|
- '@pipe':
|
|
651
628
|
- '@pipe':
|
|
652
629
|
- [$error]
|
|
653
630
|
- '@pipe':
|
|
654
|
-
- ['{$self.output.data.$error}']
|
|
631
|
+
- ['{$self.output.data.$error}', '{$self.output.metadata.$error}']
|
|
632
|
+
- ['{@conditional.nullish}']
|
|
655
633
|
- '@pipe':
|
|
656
634
|
- [ac]
|
|
657
635
|
- '@pipe':
|
|
658
|
-
- ['{$self.output.
|
|
636
|
+
- ['{$self.output.metadata.ac}']
|
|
659
637
|
- '@pipe':
|
|
660
638
|
- [au]
|
|
661
639
|
- '@pipe':
|
|
662
|
-
- ['{$self.output.
|
|
640
|
+
- ['{$self.output.metadata.au}']
|
|
663
641
|
- '@pipe':
|
|
664
642
|
- ['job_id']
|
|
665
643
|
- '@pipe':
|
|
666
|
-
- ['{
|
|
644
|
+
- ['{worker.output.data.workflowId}']
|
|
667
645
|
- ['{@object.create}']
|
|
668
646
|
- '@pipe':
|
|
669
647
|
- '@pipe':
|
|
@@ -673,15 +651,15 @@ const getWorkflowYAML = (app, version) => {
|
|
|
673
651
|
- '@pipe':
|
|
674
652
|
- [ac]
|
|
675
653
|
- '@pipe':
|
|
676
|
-
- ['{$self.output.
|
|
654
|
+
- ['{$self.output.metadata.ac}']
|
|
677
655
|
- '@pipe':
|
|
678
656
|
- [au]
|
|
679
657
|
- '@pipe':
|
|
680
|
-
- ['{$self.output.
|
|
658
|
+
- ['{$self.output.metadata.au}']
|
|
681
659
|
- '@pipe':
|
|
682
660
|
- ['job_id']
|
|
683
661
|
- '@pipe':
|
|
684
|
-
- ['{
|
|
662
|
+
- ['{worker.output.data.workflowId}']
|
|
685
663
|
- ['{@object.create}']
|
|
686
664
|
- ['{@conditional.ternary}']
|
|
687
665
|
- ['{@object.create}']
|
|
@@ -692,42 +670,7 @@ const getWorkflowYAML = (app, version) => {
|
|
|
692
670
|
ancestor: cycle_hook
|
|
693
671
|
input:
|
|
694
672
|
maps:
|
|
695
|
-
retryCount:
|
|
696
|
-
'@pipe':
|
|
697
|
-
- '@pipe':
|
|
698
|
-
- ['{proxyer.output.metadata.err}']
|
|
699
|
-
- '@pipe':
|
|
700
|
-
- ['{cycle_hook.output.data.retryCount}', 0]
|
|
701
|
-
- ['{@logical.or}', 1]
|
|
702
|
-
- ['{@math.add}']
|
|
703
|
-
- '@pipe':
|
|
704
|
-
- [0]
|
|
705
|
-
- ['{@conditional.ternary}']
|
|
706
|
-
throttleSeconds:
|
|
707
|
-
'@pipe':
|
|
708
|
-
- '@pipe':
|
|
709
|
-
- ['{proxyer.output.metadata.err}']
|
|
710
|
-
- '@pipe':
|
|
711
|
-
- '@pipe':
|
|
712
|
-
- '@pipe':
|
|
713
|
-
- '@pipe':
|
|
714
|
-
- ['{trigger.output.data.backoffCoefficient}', 10]
|
|
715
|
-
- ['{@conditional.nullish}']
|
|
716
|
-
- '@pipe':
|
|
717
|
-
- ['{cycle_hook.output.data.retryCount}', 0]
|
|
718
|
-
- ['{@conditional.nullish}']
|
|
719
|
-
- ['{@math.pow}']
|
|
720
|
-
- '@pipe':
|
|
721
|
-
- ['{trigger.output.data.initialInterval}', 1]
|
|
722
|
-
- ['{@conditional.nullish}']
|
|
723
|
-
- ['{@math.multiply}']
|
|
724
|
-
- '@pipe':
|
|
725
|
-
- ['{trigger.output.data.maximumInterval}', 120]
|
|
726
|
-
- ['{@logical.or}']
|
|
727
|
-
- ['{@math.min}']
|
|
728
|
-
- '@pipe':
|
|
729
|
-
- [0]
|
|
730
|
-
- ['{@conditional.ternary}']
|
|
673
|
+
retryCount: 0
|
|
731
674
|
continueGeneration: '{cycle_hook.output.data.continueGeneration}'
|
|
732
675
|
continueArgs: '{cycle_hook.output.data.continueArgs}'
|
|
733
676
|
|
|
@@ -832,35 +775,6 @@ const getWorkflowYAML = (app, version) => {
|
|
|
832
775
|
input:
|
|
833
776
|
maps:
|
|
834
777
|
retryCount: 0
|
|
835
|
-
throttleSeconds: 0
|
|
836
|
-
continueGeneration: '{cycle_hook.output.data.continueGeneration}'
|
|
837
|
-
continueArgs: '{cycle_hook.output.data.continueArgs}'
|
|
838
|
-
|
|
839
|
-
retryer:
|
|
840
|
-
title: Cycles back to the cycle_hook pivot, increasing the retryCount (the exponential)
|
|
841
|
-
type: cycle
|
|
842
|
-
ancestor: cycle_hook
|
|
843
|
-
input:
|
|
844
|
-
maps:
|
|
845
|
-
retryCount:
|
|
846
|
-
'@pipe':
|
|
847
|
-
- ['{cycle_hook.output.data.retryCount}', 0]
|
|
848
|
-
- ['{@logical.or}', 1]
|
|
849
|
-
- ['{@math.add}']
|
|
850
|
-
throttleSeconds:
|
|
851
|
-
'@pipe':
|
|
852
|
-
- '@pipe':
|
|
853
|
-
- '@pipe':
|
|
854
|
-
- ['{trigger.output.data.backoffCoefficient}', 10]
|
|
855
|
-
- ['{@conditional.nullish}']
|
|
856
|
-
- '@pipe':
|
|
857
|
-
- ['{cycle_hook.output.data.retryCount}', 0]
|
|
858
|
-
- ['{@conditional.nullish}']
|
|
859
|
-
- ['{@math.pow}']
|
|
860
|
-
- '@pipe':
|
|
861
|
-
- ['{trigger.output.data.maximumInterval}', 120]
|
|
862
|
-
- ['{@logical.or}']
|
|
863
|
-
- ['{@math.min}']
|
|
864
778
|
continueGeneration: '{cycle_hook.output.data.continueGeneration}'
|
|
865
779
|
continueArgs: '{cycle_hook.output.data.continueArgs}'
|
|
866
780
|
|
|
@@ -871,7 +785,6 @@ const getWorkflowYAML = (app, version) => {
|
|
|
871
785
|
input:
|
|
872
786
|
maps:
|
|
873
787
|
retryCount: 0
|
|
874
|
-
throttleSeconds: 0
|
|
875
788
|
continueArgs: '{worker.output.data.arguments}'
|
|
876
789
|
continueGeneration:
|
|
877
790
|
'@pipe':
|
|
@@ -886,18 +799,20 @@ const getWorkflowYAML = (app, version) => {
|
|
|
886
799
|
job:
|
|
887
800
|
maps:
|
|
888
801
|
done: true
|
|
889
|
-
$error:
|
|
802
|
+
$error:
|
|
803
|
+
'@pipe':
|
|
804
|
+
- ['{worker.output.data.$error}', '{worker.output.metadata.$error}']
|
|
805
|
+
- ['{@conditional.nullish}']
|
|
890
806
|
jc: '{$job.metadata.jc}'
|
|
891
807
|
ju:
|
|
892
808
|
'@pipe':
|
|
893
809
|
- ['{@date.toISOXString}']
|
|
894
810
|
|
|
895
|
-
|
|
896
|
-
title:
|
|
811
|
+
stopper:
|
|
812
|
+
title: Stops 'Signal In' when retryCount is exceeded (and as a result ends the job)
|
|
897
813
|
type: signal
|
|
898
814
|
subtype: one
|
|
899
815
|
topic: ${app}.flow.signal
|
|
900
|
-
statusThreshold: 1
|
|
901
816
|
signal:
|
|
902
817
|
schema:
|
|
903
818
|
type: object
|
|
@@ -909,17 +824,26 @@ const getWorkflowYAML = (app, version) => {
|
|
|
909
824
|
job:
|
|
910
825
|
maps:
|
|
911
826
|
done: true
|
|
912
|
-
$error:
|
|
827
|
+
$error:
|
|
828
|
+
'@pipe':
|
|
829
|
+
- '@pipe':
|
|
830
|
+
- ['{worker.output.data.$error}', '{worker.output.metadata.$error}']
|
|
831
|
+
- ['{@conditional.nullish}']
|
|
832
|
+
- '@pipe':
|
|
833
|
+
- [message, 'maximum retry attempts exceeded', code, 597]
|
|
834
|
+
- ['{@object.create}']
|
|
835
|
+
- ['{@conditional.nullish}']
|
|
913
836
|
jc: '{$job.metadata.jc}'
|
|
914
837
|
ju:
|
|
915
838
|
'@pipe':
|
|
916
839
|
- ['{@date.toISOXString}']
|
|
917
840
|
|
|
918
|
-
|
|
919
|
-
title:
|
|
841
|
+
closer:
|
|
842
|
+
title: Closes the \`Signal In\` Hook Channel, so the workflow can exit
|
|
920
843
|
type: signal
|
|
921
844
|
subtype: one
|
|
922
845
|
topic: ${app}.flow.signal
|
|
846
|
+
statusThreshold: 1
|
|
923
847
|
signal:
|
|
924
848
|
schema:
|
|
925
849
|
type: object
|
|
@@ -933,8 +857,8 @@ const getWorkflowYAML = (app, version) => {
|
|
|
933
857
|
done: true
|
|
934
858
|
$error:
|
|
935
859
|
'@pipe':
|
|
936
|
-
- ['{worker.output.data.$error}', '
|
|
937
|
-
- ['{@
|
|
860
|
+
- ['{worker.output.data.$error}', '{worker.output.metadata.$error}']
|
|
861
|
+
- ['{@conditional.nullish}']
|
|
938
862
|
jc: '{$job.metadata.jc}'
|
|
939
863
|
ju:
|
|
940
864
|
'@pipe':
|
|
@@ -970,13 +894,11 @@ const getWorkflowYAML = (app, version) => {
|
|
|
970
894
|
type: number
|
|
971
895
|
maps:
|
|
972
896
|
retryCount: 0
|
|
973
|
-
throttleSeconds: 0
|
|
974
897
|
|
|
975
898
|
signaler_throttler:
|
|
976
|
-
title:
|
|
899
|
+
title: Pass-through hook between signaler_cycle_hook and signaler_worker
|
|
977
900
|
type: hook
|
|
978
|
-
|
|
979
|
-
|
|
901
|
+
|
|
980
902
|
signaler_worker:
|
|
981
903
|
title: Signal In - Worker
|
|
982
904
|
type: worker
|
|
@@ -1014,6 +936,22 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1014
936
|
- ['{trigger.output.data.maximumAttempts}', 5]
|
|
1015
937
|
- ['{@conditional.nullish}']
|
|
1016
938
|
- ['{@conditional.less_than}']
|
|
939
|
+
maximumAttempts:
|
|
940
|
+
'@pipe':
|
|
941
|
+
- ['{trigger.output.data.maximumAttempts}', 5]
|
|
942
|
+
- ['{@conditional.nullish}']
|
|
943
|
+
backoffCoefficient:
|
|
944
|
+
'@pipe':
|
|
945
|
+
- ['{trigger.output.data.backoffCoefficient}', 10]
|
|
946
|
+
- ['{@conditional.nullish}']
|
|
947
|
+
maximumInterval:
|
|
948
|
+
'@pipe':
|
|
949
|
+
- ['{trigger.output.data.maximumInterval}', 120]
|
|
950
|
+
- ['{@conditional.nullish}']
|
|
951
|
+
initialInterval:
|
|
952
|
+
'@pipe':
|
|
953
|
+
- ['{trigger.output.data.initialInterval}', 1]
|
|
954
|
+
- ['{@conditional.nullish}']
|
|
1017
955
|
|
|
1018
956
|
output:
|
|
1019
957
|
schema:
|
|
@@ -1174,7 +1112,6 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1174
1112
|
input:
|
|
1175
1113
|
maps:
|
|
1176
1114
|
retryCount: 0
|
|
1177
|
-
throttleSeconds: 0
|
|
1178
1115
|
|
|
1179
1116
|
signaler_childer:
|
|
1180
1117
|
title: Awaits a child flow to be executed/started
|
|
@@ -1344,36 +1281,11 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1344
1281
|
- '@pipe':
|
|
1345
1282
|
- [0]
|
|
1346
1283
|
- ['{@conditional.ternary}']
|
|
1347
|
-
|
|
1348
|
-
'@pipe':
|
|
1349
|
-
- '@pipe':
|
|
1350
|
-
- ['{signaler_childer.output.metadata.err}']
|
|
1351
|
-
- '@pipe':
|
|
1352
|
-
- '@pipe':
|
|
1353
|
-
- '@pipe':
|
|
1354
|
-
- '@pipe':
|
|
1355
|
-
- ['{trigger.output.data.backoffCoefficient}', 10]
|
|
1356
|
-
- ['{@conditional.nullish}']
|
|
1357
|
-
- '@pipe':
|
|
1358
|
-
- ['{signaler_cycle_hook.output.data.retryCount}', 0]
|
|
1359
|
-
- ['{@conditional.nullish}']
|
|
1360
|
-
- ['{@math.pow}']
|
|
1361
|
-
- '@pipe':
|
|
1362
|
-
- ['{trigger.output.data.initialInterval}', 1]
|
|
1363
|
-
- ['{@conditional.nullish}']
|
|
1364
|
-
- ['{@math.multiply}']
|
|
1365
|
-
- '@pipe':
|
|
1366
|
-
- ['{trigger.output.data.maximumInterval}', 120]
|
|
1367
|
-
- ['{@logical.or}']
|
|
1368
|
-
- ['{@math.min}']
|
|
1369
|
-
- '@pipe':
|
|
1370
|
-
- [0]
|
|
1371
|
-
- ['{@conditional.ternary}']
|
|
1372
|
-
|
|
1284
|
+
|
|
1373
1285
|
signaler_proxyer:
|
|
1374
|
-
title:
|
|
1375
|
-
type:
|
|
1376
|
-
topic:
|
|
1286
|
+
title: Calls the activity function directly via worker topic
|
|
1287
|
+
type: worker
|
|
1288
|
+
topic: '{signaler_worker.output.data.workflowTopic}'
|
|
1377
1289
|
input:
|
|
1378
1290
|
schema:
|
|
1379
1291
|
type: object
|
|
@@ -1439,6 +1351,12 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1439
1351
|
- ['{signaler_worker.output.data.maximumInterval}','{trigger.output.data.maximumInterval}']
|
|
1440
1352
|
- ['{@conditional.nullish}', 120]
|
|
1441
1353
|
- ['{@conditional.nullish}']
|
|
1354
|
+
output:
|
|
1355
|
+
schema:
|
|
1356
|
+
type: object
|
|
1357
|
+
properties:
|
|
1358
|
+
response:
|
|
1359
|
+
type: any
|
|
1442
1360
|
job:
|
|
1443
1361
|
maps:
|
|
1444
1362
|
idempotentcy-marker[-]:
|
|
@@ -1448,24 +1366,26 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1448
1366
|
- ['{@string.concat}']
|
|
1449
1367
|
- '@pipe':
|
|
1450
1368
|
- '@pipe':
|
|
1451
|
-
- ['{$self.output.data.$error}']
|
|
1369
|
+
- ['{$self.output.data.$error}', '{$self.output.metadata.err}']
|
|
1370
|
+
- ['{@logical.or}']
|
|
1452
1371
|
- '@pipe':
|
|
1453
1372
|
- '@pipe':
|
|
1454
1373
|
- [$error]
|
|
1455
1374
|
- '@pipe':
|
|
1456
|
-
- ['{$self.output.data.$error}']
|
|
1375
|
+
- ['{$self.output.data.$error}', '{$self.output.metadata.$error}']
|
|
1376
|
+
- ['{@conditional.nullish}']
|
|
1457
1377
|
- '@pipe':
|
|
1458
1378
|
- [ac]
|
|
1459
1379
|
- '@pipe':
|
|
1460
|
-
- ['{$self.output.
|
|
1380
|
+
- ['{$self.output.metadata.ac}']
|
|
1461
1381
|
- '@pipe':
|
|
1462
1382
|
- [au]
|
|
1463
1383
|
- '@pipe':
|
|
1464
|
-
- ['{$self.output.
|
|
1384
|
+
- ['{$self.output.metadata.au}']
|
|
1465
1385
|
- '@pipe':
|
|
1466
1386
|
- ['job_id']
|
|
1467
1387
|
- '@pipe':
|
|
1468
|
-
- ['{
|
|
1388
|
+
- ['{signaler_worker.output.data.workflowId}']
|
|
1469
1389
|
- ['{@object.create}']
|
|
1470
1390
|
- '@pipe':
|
|
1471
1391
|
- '@pipe':
|
|
@@ -1475,15 +1395,15 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1475
1395
|
- '@pipe':
|
|
1476
1396
|
- [ac]
|
|
1477
1397
|
- '@pipe':
|
|
1478
|
-
- ['{$self.output.
|
|
1398
|
+
- ['{$self.output.metadata.ac}']
|
|
1479
1399
|
- '@pipe':
|
|
1480
1400
|
- [au]
|
|
1481
1401
|
- '@pipe':
|
|
1482
|
-
- ['{$self.output.
|
|
1402
|
+
- ['{$self.output.metadata.au}']
|
|
1483
1403
|
- '@pipe':
|
|
1484
1404
|
- ['job_id']
|
|
1485
1405
|
- '@pipe':
|
|
1486
|
-
- ['{
|
|
1406
|
+
- ['{signaler_worker.output.data.workflowId}']
|
|
1487
1407
|
- ['{@object.create}']
|
|
1488
1408
|
- ['{@conditional.ternary}']
|
|
1489
1409
|
- ['{@object.create}']
|
|
@@ -1494,42 +1414,7 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1494
1414
|
ancestor: signaler_cycle_hook
|
|
1495
1415
|
input:
|
|
1496
1416
|
maps:
|
|
1497
|
-
retryCount:
|
|
1498
|
-
'@pipe':
|
|
1499
|
-
- '@pipe':
|
|
1500
|
-
- ['{signaler_proxyer.output.metadata.err}']
|
|
1501
|
-
- '@pipe':
|
|
1502
|
-
- ['{signaler_cycle_hook.output.data.retryCount}', 0]
|
|
1503
|
-
- ['{@logical.or}', 1]
|
|
1504
|
-
- ['{@math.add}']
|
|
1505
|
-
- '@pipe':
|
|
1506
|
-
- [0]
|
|
1507
|
-
- ['{@conditional.ternary}']
|
|
1508
|
-
throttleSeconds:
|
|
1509
|
-
'@pipe':
|
|
1510
|
-
- '@pipe':
|
|
1511
|
-
- ['{signaler_proxyer.output.metadata.err}']
|
|
1512
|
-
- '@pipe':
|
|
1513
|
-
- '@pipe':
|
|
1514
|
-
- '@pipe':
|
|
1515
|
-
- '@pipe':
|
|
1516
|
-
- ['{trigger.output.data.backoffCoefficient}', 10]
|
|
1517
|
-
- ['{@conditional.nullish}']
|
|
1518
|
-
- '@pipe':
|
|
1519
|
-
- ['{signaler_cycle_hook.output.data.retryCount}', 0]
|
|
1520
|
-
- ['{@conditional.nullish}']
|
|
1521
|
-
- ['{@math.pow}']
|
|
1522
|
-
- '@pipe':
|
|
1523
|
-
- ['{trigger.output.data.initialInterval}', 1]
|
|
1524
|
-
- ['{@conditional.nullish}']
|
|
1525
|
-
- ['{@math.multiply}']
|
|
1526
|
-
- '@pipe':
|
|
1527
|
-
- ['{trigger.output.data.maximumInterval}', 120]
|
|
1528
|
-
- ['{@logical.or}']
|
|
1529
|
-
- ['{@math.min}']
|
|
1530
|
-
- '@pipe':
|
|
1531
|
-
- [0]
|
|
1532
|
-
- ['{@conditional.ternary}']
|
|
1417
|
+
retryCount: 0
|
|
1533
1418
|
|
|
1534
1419
|
signaler_collator:
|
|
1535
1420
|
title: Awaits the collator to resolve the idempotent items as a sequential set
|
|
@@ -1632,34 +1517,7 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1632
1517
|
input:
|
|
1633
1518
|
maps:
|
|
1634
1519
|
retryCount: 0
|
|
1635
|
-
throttleSeconds: 0
|
|
1636
1520
|
|
|
1637
|
-
signaler_retryer:
|
|
1638
|
-
title: Cycles back to the signaler_cycle_hook pivot, increasing the retryCount (the exponential)
|
|
1639
|
-
type: cycle
|
|
1640
|
-
ancestor: signaler_cycle_hook
|
|
1641
|
-
input:
|
|
1642
|
-
maps:
|
|
1643
|
-
retryCount:
|
|
1644
|
-
'@pipe':
|
|
1645
|
-
- ['{signaler_cycle_hook.output.data.retryCount}', 0]
|
|
1646
|
-
- ['{@logical.or}', 1]
|
|
1647
|
-
- ['{@math.add}']
|
|
1648
|
-
throttleSeconds:
|
|
1649
|
-
'@pipe':
|
|
1650
|
-
- '@pipe':
|
|
1651
|
-
- '@pipe':
|
|
1652
|
-
- ['{trigger.output.data.backoffCoefficient}', 10]
|
|
1653
|
-
- ['{@conditional.nullish}']
|
|
1654
|
-
- '@pipe':
|
|
1655
|
-
- ['{signaler_cycle_hook.output.data.retryCount}', 0]
|
|
1656
|
-
- ['{@conditional.nullish}']
|
|
1657
|
-
- ['{@math.pow}']
|
|
1658
|
-
- '@pipe':
|
|
1659
|
-
- ['{trigger.output.data.maximumInterval}', 120]
|
|
1660
|
-
- ['{@logical.or}']
|
|
1661
|
-
- ['{@math.min}']
|
|
1662
|
-
|
|
1663
1521
|
transitions:
|
|
1664
1522
|
trigger:
|
|
1665
1523
|
- to: cycle_hook
|
|
@@ -1720,22 +1578,9 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1720
1578
|
- to: continuer
|
|
1721
1579
|
conditions:
|
|
1722
1580
|
code: 592
|
|
1723
|
-
- to: retryer
|
|
1724
|
-
conditions:
|
|
1725
|
-
code: 599
|
|
1726
|
-
match:
|
|
1727
|
-
- expected: true
|
|
1728
|
-
actual:
|
|
1729
|
-
'@pipe':
|
|
1730
|
-
- '@pipe':
|
|
1731
|
-
- ['{cycle_hook.output.data.retryCount}']
|
|
1732
|
-
- '@pipe':
|
|
1733
|
-
- ['{trigger.output.data.maximumAttempts}', 5]
|
|
1734
|
-
- ['{@conditional.nullish}']
|
|
1735
|
-
- ['{@conditional.less_than}']
|
|
1736
1581
|
- to: stopper
|
|
1737
1582
|
conditions:
|
|
1738
|
-
code: [590, 591, 596, 597, 598
|
|
1583
|
+
code: [590, 591, 596, 597, 598]
|
|
1739
1584
|
match:
|
|
1740
1585
|
- expected: true
|
|
1741
1586
|
actual:
|
|
@@ -1786,19 +1631,6 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1786
1631
|
- to: signaler_proxyer
|
|
1787
1632
|
conditions:
|
|
1788
1633
|
code: 591
|
|
1789
|
-
- to: signaler_retryer
|
|
1790
|
-
conditions:
|
|
1791
|
-
code: 599
|
|
1792
|
-
match:
|
|
1793
|
-
- expected: true
|
|
1794
|
-
actual:
|
|
1795
|
-
'@pipe':
|
|
1796
|
-
- '@pipe':
|
|
1797
|
-
- ['{signaler_cycle_hook.output.data.retryCount}']
|
|
1798
|
-
- '@pipe':
|
|
1799
|
-
- ['{trigger.output.data.maximumAttempts}', 5]
|
|
1800
|
-
- ['{@conditional.nullish}']
|
|
1801
|
-
- ['{@conditional.less_than}']
|
|
1802
1634
|
signaler_collator:
|
|
1803
1635
|
- to: signaler_collate_cycler
|
|
1804
1636
|
signaler_childer:
|
|
@@ -2215,9 +2047,13 @@ const getWorkflowYAML = (app, version) => {
|
|
|
2215
2047
|
- ['{@object.create}']
|
|
2216
2048
|
|
|
2217
2049
|
collator_proxyer:
|
|
2218
|
-
title:
|
|
2219
|
-
type:
|
|
2220
|
-
topic:
|
|
2050
|
+
title: Calls the activity function directly via worker topic
|
|
2051
|
+
type: worker
|
|
2052
|
+
topic:
|
|
2053
|
+
'@pipe':
|
|
2054
|
+
- ['{collator_trigger.output.data.items}', '{collator_cycle_hook.output.data.cur_index}']
|
|
2055
|
+
- ['{@array.get}', workflowTopic]
|
|
2056
|
+
- ['{@object.get}']
|
|
2221
2057
|
input:
|
|
2222
2058
|
schema:
|
|
2223
2059
|
type: object
|
|
@@ -2327,23 +2163,6 @@ const getWorkflowYAML = (app, version) => {
|
|
|
2327
2163
|
properties:
|
|
2328
2164
|
response:
|
|
2329
2165
|
type: any
|
|
2330
|
-
$error:
|
|
2331
|
-
type: object
|
|
2332
|
-
properties:
|
|
2333
|
-
code:
|
|
2334
|
-
type: number
|
|
2335
|
-
message:
|
|
2336
|
-
type: string
|
|
2337
|
-
stack:
|
|
2338
|
-
type: string
|
|
2339
|
-
done:
|
|
2340
|
-
type: boolean
|
|
2341
|
-
workflowId:
|
|
2342
|
-
type: string
|
|
2343
|
-
jc:
|
|
2344
|
-
type: string
|
|
2345
|
-
ju:
|
|
2346
|
-
type: string
|
|
2347
2166
|
job:
|
|
2348
2167
|
maps:
|
|
2349
2168
|
response[25]:
|
|
@@ -2352,46 +2171,44 @@ const getWorkflowYAML = (app, version) => {
|
|
|
2352
2171
|
- ['{collator_cycle_hook.output.data.cur_index}']
|
|
2353
2172
|
- '@pipe':
|
|
2354
2173
|
- '@pipe':
|
|
2355
|
-
- ['{$self.output.data.
|
|
2174
|
+
- ['{$self.output.data.$error}', '{$self.output.metadata.err}']
|
|
2175
|
+
- ['{@logical.or}']
|
|
2356
2176
|
- '@pipe':
|
|
2357
2177
|
- '@pipe':
|
|
2358
2178
|
- [type]
|
|
2359
2179
|
- '@pipe':
|
|
2360
2180
|
- ['proxy']
|
|
2361
2181
|
- '@pipe':
|
|
2362
|
-
- [
|
|
2182
|
+
- [$error]
|
|
2363
2183
|
- '@pipe':
|
|
2364
|
-
- ['{$self.output.data.
|
|
2184
|
+
- ['{$self.output.data.$error}', '{$self.output.metadata.$error}']
|
|
2185
|
+
- ['{@conditional.nullish}']
|
|
2365
2186
|
- '@pipe':
|
|
2366
2187
|
- [ac]
|
|
2367
2188
|
- '@pipe':
|
|
2368
|
-
- ['{$
|
|
2189
|
+
- ['{$self.output.metadata.ac}']
|
|
2369
2190
|
- '@pipe':
|
|
2370
2191
|
- [au]
|
|
2371
2192
|
- '@pipe':
|
|
2372
|
-
- ['{
|
|
2373
|
-
- '@pipe':
|
|
2374
|
-
- [job_id]
|
|
2375
|
-
- '@pipe':
|
|
2376
|
-
- ['{$self.output.data.workflowId}']
|
|
2193
|
+
- ['{$self.output.metadata.au}']
|
|
2377
2194
|
- ['{@object.create}']
|
|
2378
2195
|
- '@pipe':
|
|
2379
2196
|
- '@pipe':
|
|
2380
|
-
- [
|
|
2197
|
+
- [type]
|
|
2381
2198
|
- '@pipe':
|
|
2382
|
-
- ['
|
|
2199
|
+
- ['proxy']
|
|
2383
2200
|
- '@pipe':
|
|
2384
|
-
- [
|
|
2201
|
+
- [data]
|
|
2385
2202
|
- '@pipe':
|
|
2386
|
-
- ['{$
|
|
2203
|
+
- ['{$self.output.data.response}']
|
|
2387
2204
|
- '@pipe':
|
|
2388
|
-
- [
|
|
2205
|
+
- [ac]
|
|
2389
2206
|
- '@pipe':
|
|
2390
|
-
- ['{
|
|
2207
|
+
- ['{$self.output.metadata.ac}']
|
|
2391
2208
|
- '@pipe':
|
|
2392
|
-
- [
|
|
2209
|
+
- [au]
|
|
2393
2210
|
- '@pipe':
|
|
2394
|
-
- ['{$self.output.
|
|
2211
|
+
- ['{$self.output.metadata.au}']
|
|
2395
2212
|
- ['{@object.create}']
|
|
2396
2213
|
- ['{@conditional.ternary}']
|
|
2397
2214
|
- ['{@object.create}']
|
|
@@ -2453,6 +2270,8 @@ const getWorkflowYAML = (app, version) => {
|
|
|
2453
2270
|
- ['{collator_trigger.output.data.items}', '{collator_cycle_hook.output.data.cur_index}']
|
|
2454
2271
|
- ['{@array.get}', code]
|
|
2455
2272
|
- ['{@object.get}']
|
|
2273
|
+
collator_proxyer:
|
|
2274
|
+
- to: collator_cycler
|
|
2456
2275
|
|
|
2457
2276
|
hooks:
|
|
2458
2277
|
${app}.wfs.signal:
|
|
@@ -2465,227 +2284,6 @@ const getWorkflowYAML = (app, version) => {
|
|
|
2465
2284
|
- ['{@array.get}', signalId]
|
|
2466
2285
|
- ['{@object.get}']
|
|
2467
2286
|
actual: '{$self.hook.data.id}'
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
###################################################
|
|
2472
|
-
# THE REENTRANT ACTIVITY FLOW #
|
|
2473
|
-
# #
|
|
2474
|
-
- subscribes: ${app}.activity.execute
|
|
2475
|
-
publishes: ${app}.activity.executed
|
|
2476
|
-
|
|
2477
|
-
expire:
|
|
2478
|
-
'@pipe':
|
|
2479
|
-
- '@pipe':
|
|
2480
|
-
- ['{activity_trigger.output.data.startToCloseTimeout}']
|
|
2481
|
-
- '@pipe':
|
|
2482
|
-
- ['{activity_trigger.output.data.expire}', 1]
|
|
2483
|
-
- ['{@conditional.nullish}']
|
|
2484
|
-
- ['{@conditional.nullish}']
|
|
2485
|
-
|
|
2486
|
-
input:
|
|
2487
|
-
schema:
|
|
2488
|
-
type: object
|
|
2489
|
-
properties:
|
|
2490
|
-
parentWorkflowId:
|
|
2491
|
-
type: string
|
|
2492
|
-
originJobId:
|
|
2493
|
-
type: string
|
|
2494
|
-
workflowId:
|
|
2495
|
-
type: string
|
|
2496
|
-
workflowTopic:
|
|
2497
|
-
type: string
|
|
2498
|
-
activityName:
|
|
2499
|
-
type: string
|
|
2500
|
-
arguments:
|
|
2501
|
-
type: array
|
|
2502
|
-
headers:
|
|
2503
|
-
type: object
|
|
2504
|
-
backoffCoefficient:
|
|
2505
|
-
type: number
|
|
2506
|
-
initialInterval:
|
|
2507
|
-
type: number
|
|
2508
|
-
maximumAttempts:
|
|
2509
|
-
type: number
|
|
2510
|
-
maximumInterval:
|
|
2511
|
-
type: number
|
|
2512
|
-
startToCloseTimeout:
|
|
2513
|
-
type: number
|
|
2514
|
-
expire:
|
|
2515
|
-
type: number
|
|
2516
|
-
output:
|
|
2517
|
-
schema:
|
|
2518
|
-
type: object
|
|
2519
|
-
properties:
|
|
2520
|
-
response:
|
|
2521
|
-
type: any
|
|
2522
|
-
done:
|
|
2523
|
-
type: boolean
|
|
2524
|
-
workflowId:
|
|
2525
|
-
type: string
|
|
2526
|
-
jc:
|
|
2527
|
-
type: string
|
|
2528
|
-
ju:
|
|
2529
|
-
type: string
|
|
2530
|
-
|
|
2531
|
-
activities:
|
|
2532
|
-
activity_trigger:
|
|
2533
|
-
title: Activity Flow Trigger
|
|
2534
|
-
type: trigger
|
|
2535
|
-
stats:
|
|
2536
|
-
id: '{$self.input.data.workflowId}'
|
|
2537
|
-
key: '{$self.input.data.parentWorkflowId}'
|
|
2538
|
-
parent: '{$self.input.data.originJobId}'
|
|
2539
|
-
adjacent: '{$self.input.data.parentWorkflowId}'
|
|
2540
|
-
job:
|
|
2541
|
-
maps:
|
|
2542
|
-
workflowId: '{$self.input.data.workflowId}'
|
|
2543
|
-
|
|
2544
|
-
activity_cycle_hook:
|
|
2545
|
-
title: Activity Flow Pivot - Cycling Descendants Point Here
|
|
2546
|
-
type: hook
|
|
2547
|
-
cycle: true
|
|
2548
|
-
output:
|
|
2549
|
-
schema:
|
|
2550
|
-
type: object
|
|
2551
|
-
properties:
|
|
2552
|
-
retryCount:
|
|
2553
|
-
type: number
|
|
2554
|
-
maps:
|
|
2555
|
-
retryCount: 0
|
|
2556
|
-
|
|
2557
|
-
activity_worker:
|
|
2558
|
-
title: Activity Worker - Calls Activity Functions
|
|
2559
|
-
type: worker
|
|
2560
|
-
topic: '{activity_trigger.output.data.workflowTopic}'
|
|
2561
|
-
input:
|
|
2562
|
-
schema:
|
|
2563
|
-
type: object
|
|
2564
|
-
properties:
|
|
2565
|
-
parentWorkflowId:
|
|
2566
|
-
type: string
|
|
2567
|
-
workflowId:
|
|
2568
|
-
type: string
|
|
2569
|
-
workflowTopic:
|
|
2570
|
-
type: string
|
|
2571
|
-
activityName:
|
|
2572
|
-
type: string
|
|
2573
|
-
arguments:
|
|
2574
|
-
type: array
|
|
2575
|
-
headers:
|
|
2576
|
-
type: object
|
|
2577
|
-
startToCloseTimeout:
|
|
2578
|
-
type: number
|
|
2579
|
-
maps:
|
|
2580
|
-
parentWorkflowId: '{activity_trigger.output.data.parentWorkflowId}'
|
|
2581
|
-
workflowId: '{activity_trigger.output.data.workflowId}'
|
|
2582
|
-
workflowTopic: '{activity_trigger.output.data.workflowTopic}'
|
|
2583
|
-
activityName: '{activity_trigger.output.data.activityName}'
|
|
2584
|
-
arguments: '{activity_trigger.output.data.arguments}'
|
|
2585
|
-
headers: '{activity_trigger.output.data.headers}'
|
|
2586
|
-
startToCloseTimeout: '{activity_trigger.output.data.startToCloseTimeout}'
|
|
2587
|
-
output:
|
|
2588
|
-
schema:
|
|
2589
|
-
type: object
|
|
2590
|
-
properties:
|
|
2591
|
-
response:
|
|
2592
|
-
type: any
|
|
2593
|
-
job:
|
|
2594
|
-
maps:
|
|
2595
|
-
response: '{$self.output.data.response}'
|
|
2596
|
-
|
|
2597
|
-
activity_retryer:
|
|
2598
|
-
title: Pauses for an exponentially-throttled amount of time after a 599 (retryable) error
|
|
2599
|
-
type: hook
|
|
2600
|
-
sleep:
|
|
2601
|
-
'@pipe':
|
|
2602
|
-
- '@pipe':
|
|
2603
|
-
- '@pipe':
|
|
2604
|
-
- ['{activity_trigger.output.data.backoffCoefficient}', 10]
|
|
2605
|
-
- ['{@logical.or}', '{activity_cycle_hook.output.data.retryCount}']
|
|
2606
|
-
- ['{@math.pow}']
|
|
2607
|
-
- '@pipe':
|
|
2608
|
-
- ['{activity_trigger.output.data.initialInterval}', 1]
|
|
2609
|
-
- ['{@conditional.nullish}']
|
|
2610
|
-
- ['{@math.multiply}']
|
|
2611
|
-
- '@pipe':
|
|
2612
|
-
- ['{activity_trigger.output.data.maximumInterval}', 120]
|
|
2613
|
-
- ['{@math.min}']
|
|
2614
|
-
- ['{@math.min}']
|
|
2615
|
-
|
|
2616
|
-
activity_retry_cycler:
|
|
2617
|
-
title: Cycles back to the activity_cycle_hook pivot, incrementing the \`retryCount\` (the exponential)
|
|
2618
|
-
type: cycle
|
|
2619
|
-
ancestor: activity_cycle_hook
|
|
2620
|
-
input:
|
|
2621
|
-
maps:
|
|
2622
|
-
retryCount:
|
|
2623
|
-
'@pipe':
|
|
2624
|
-
- ['{activity_cycle_hook.output.data.retryCount}', 1]
|
|
2625
|
-
- ['{@math.add}']
|
|
2626
|
-
|
|
2627
|
-
activity_closer:
|
|
2628
|
-
title: Marks the activity workflow as done
|
|
2629
|
-
type: hook
|
|
2630
|
-
job:
|
|
2631
|
-
maps:
|
|
2632
|
-
done: true
|
|
2633
|
-
$error: '{activity_worker.output.data.$error}'
|
|
2634
|
-
jc: '{$job.metadata.jc}'
|
|
2635
|
-
ju:
|
|
2636
|
-
'@pipe':
|
|
2637
|
-
- ['{@date.toISOXString}']
|
|
2638
|
-
|
|
2639
|
-
activity_stopper:
|
|
2640
|
-
title: Stops the activity after retry count has been maxed
|
|
2641
|
-
type: hook
|
|
2642
|
-
job:
|
|
2643
|
-
maps:
|
|
2644
|
-
done: true
|
|
2645
|
-
$error: '{activity_worker.output.data.$error}'
|
|
2646
|
-
jc: '{$job.metadata.jc}'
|
|
2647
|
-
ju:
|
|
2648
|
-
'@pipe':
|
|
2649
|
-
- ['{@date.toISOXString}']
|
|
2650
|
-
|
|
2651
|
-
transitions:
|
|
2652
|
-
activity_trigger:
|
|
2653
|
-
- to: activity_cycle_hook
|
|
2654
|
-
activity_cycle_hook:
|
|
2655
|
-
- to: activity_worker
|
|
2656
|
-
activity_worker:
|
|
2657
|
-
- to: activity_closer
|
|
2658
|
-
conditions:
|
|
2659
|
-
code: [200, 598, 597, 596]
|
|
2660
|
-
- to: activity_stopper
|
|
2661
|
-
conditions:
|
|
2662
|
-
code: 599
|
|
2663
|
-
match:
|
|
2664
|
-
- expected: true
|
|
2665
|
-
actual:
|
|
2666
|
-
'@pipe':
|
|
2667
|
-
- '@pipe':
|
|
2668
|
-
- ['{activity_cycle_hook.output.data.retryCount}']
|
|
2669
|
-
- '@pipe':
|
|
2670
|
-
- ['{activity_trigger.output.data.maximumAttempts}', 50]
|
|
2671
|
-
- ['{@conditional.nullish}']
|
|
2672
|
-
- ['{@conditional.greater_than_or_equal}']
|
|
2673
|
-
|
|
2674
|
-
- to: activity_retryer
|
|
2675
|
-
conditions:
|
|
2676
|
-
code: 599
|
|
2677
|
-
match:
|
|
2678
|
-
- expected: true
|
|
2679
|
-
actual:
|
|
2680
|
-
'@pipe':
|
|
2681
|
-
- '@pipe':
|
|
2682
|
-
- ['{activity_cycle_hook.output.data.retryCount}']
|
|
2683
|
-
- '@pipe':
|
|
2684
|
-
- ['{activity_trigger.output.data.maximumAttempts}', 50]
|
|
2685
|
-
- ['{@conditional.nullish}']
|
|
2686
|
-
- ['{@conditional.less_than}']
|
|
2687
|
-
activity_retryer:
|
|
2688
|
-
- to: activity_retry_cycler
|
|
2689
2287
|
`;
|
|
2690
2288
|
};
|
|
2691
2289
|
exports.getWorkflowYAML = getWorkflowYAML;
|
|
@@ -377,15 +377,13 @@ class WorkerService {
|
|
|
377
377
|
//use code 599 as a proxy for all retryable errors
|
|
378
378
|
// (basically anything not 596, 597, 598)
|
|
379
379
|
return {
|
|
380
|
-
status: stream_1.StreamStatus.
|
|
380
|
+
status: stream_1.StreamStatus.ERROR,
|
|
381
381
|
code: 599,
|
|
382
382
|
metadata: { ...data.metadata },
|
|
383
383
|
data: {
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
code: enums_1.HMSH_CODE_DURABLE_RETRYABLE,
|
|
388
|
-
},
|
|
384
|
+
message: err.message,
|
|
385
|
+
stack: err.stack,
|
|
386
|
+
code: enums_1.HMSH_CODE_DURABLE_RETRYABLE,
|
|
389
387
|
},
|
|
390
388
|
};
|
|
391
389
|
}
|
|
@@ -607,15 +605,13 @@ class WorkerService {
|
|
|
607
605
|
//use code 599 as a proxy for all retryable errors
|
|
608
606
|
// (basically anything not 596, 597, 598)
|
|
609
607
|
return {
|
|
610
|
-
status: stream_1.StreamStatus.
|
|
608
|
+
status: stream_1.StreamStatus.ERROR,
|
|
611
609
|
code: enums_1.HMSH_CODE_DURABLE_RETRYABLE,
|
|
612
610
|
metadata: { ...data.metadata },
|
|
613
611
|
data: {
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
timestamp: (0, utils_1.formatISODate)(new Date()),
|
|
618
|
-
},
|
|
612
|
+
message: err.message,
|
|
613
|
+
stack: err.stack,
|
|
614
|
+
code: enums_1.HMSH_CODE_DURABLE_RETRYABLE,
|
|
619
615
|
},
|
|
620
616
|
};
|
|
621
617
|
}
|
|
@@ -963,9 +959,24 @@ class WorkerService {
|
|
|
963
959
|
}, telemetry_3.SpanStatusCode.ERROR, err.message);
|
|
964
960
|
}
|
|
965
961
|
isProcessing = true;
|
|
962
|
+
const errorCode = err.code || new errors_1.DurableRetryError(err.message).code;
|
|
963
|
+
if (errorCode === enums_1.HMSH_CODE_DURABLE_RETRYABLE) {
|
|
964
|
+
// Retryable errors use status: ERROR so the engine-level
|
|
965
|
+
// retry mechanism (handleRetry + _streamRetryConfig) kicks in
|
|
966
|
+
return withPatchMarkers({
|
|
967
|
+
status: stream_1.StreamStatus.ERROR,
|
|
968
|
+
code: errorCode,
|
|
969
|
+
metadata: { ...data.metadata },
|
|
970
|
+
data: {
|
|
971
|
+
message: err.message,
|
|
972
|
+
stack: err.stack,
|
|
973
|
+
code: errorCode,
|
|
974
|
+
},
|
|
975
|
+
});
|
|
976
|
+
}
|
|
966
977
|
return withPatchMarkers({
|
|
967
978
|
status: stream_1.StreamStatus.SUCCESS,
|
|
968
|
-
code:
|
|
979
|
+
code: errorCode,
|
|
969
980
|
metadata: { ...data.metadata },
|
|
970
981
|
data: {
|
|
971
982
|
$error: {
|
|
@@ -973,7 +984,7 @@ class WorkerService {
|
|
|
973
984
|
type: err.name,
|
|
974
985
|
name: err.name,
|
|
975
986
|
stack: err.stack,
|
|
976
|
-
code:
|
|
987
|
+
code: errorCode,
|
|
977
988
|
},
|
|
978
989
|
},
|
|
979
990
|
});
|
|
@@ -585,14 +585,23 @@ class ConsumptionManager {
|
|
|
585
585
|
// Extract retry policy with priority:
|
|
586
586
|
// 1. Use message-level _streamRetryConfig (from database columns or previous retry)
|
|
587
587
|
// 2. Fall back to router-level retry (from worker config)
|
|
588
|
-
const
|
|
588
|
+
const streamRetryConfig = input._streamRetryConfig;
|
|
589
|
+
const retry = streamRetryConfig
|
|
589
590
|
? {
|
|
590
|
-
maximumAttempts:
|
|
591
|
-
backoffCoefficient:
|
|
592
|
-
maximumInterval:
|
|
591
|
+
maximumAttempts: streamRetryConfig.max_retry_attempts,
|
|
592
|
+
backoffCoefficient: streamRetryConfig.backoff_coefficient,
|
|
593
|
+
maximumInterval: streamRetryConfig.maximum_interval_seconds,
|
|
594
|
+
initialInterval: streamRetryConfig.initialInterval ?? input.data?.initialInterval ?? 1,
|
|
593
595
|
}
|
|
594
596
|
: this.retry;
|
|
595
|
-
return await this.errorHandler.handleRetry(input, output, this.publishMessage.bind(this), retry)
|
|
597
|
+
return await this.errorHandler.handleRetry(input, output, this.publishMessage.bind(this), retry, (topic, delayMs) => {
|
|
598
|
+
// Schedule a targeted NOTIFY so the consumer wakes up
|
|
599
|
+
// when the visibility-delayed retry message becomes visible
|
|
600
|
+
if (typeof this.stream.scheduleStreamNotify === 'function') {
|
|
601
|
+
const streamKey = this.stream.mintKey(key_1.KeyType.STREAMS, { topic });
|
|
602
|
+
this.stream.scheduleStreamNotify(streamKey, delayMs);
|
|
603
|
+
}
|
|
604
|
+
});
|
|
596
605
|
}
|
|
597
606
|
else if (typeof output.metadata !== 'object') {
|
|
598
607
|
output.metadata = { ...input.metadata, guid: (0, utils_1.guid)() };
|
|
@@ -4,5 +4,5 @@ export declare class ErrorHandler {
|
|
|
4
4
|
structureUnhandledError(input: StreamData, err: Error): StreamDataResponse;
|
|
5
5
|
structureUnacknowledgedError(input: StreamData): StreamDataResponse;
|
|
6
6
|
structureError(input: StreamData, output: StreamDataResponse): StreamDataResponse;
|
|
7
|
-
handleRetry(input: StreamData, output: StreamDataResponse, publishMessage: (topic: string, streamData: StreamData | StreamDataResponse) => Promise<string>, retry?: RetryPolicy): Promise<string>;
|
|
7
|
+
handleRetry(input: StreamData, output: StreamDataResponse, publishMessage: (topic: string, streamData: StreamData | StreamDataResponse) => Promise<string>, retry?: RetryPolicy, onRetryScheduled?: (topic: string, delayMs: number) => void): Promise<string>;
|
|
8
8
|
}
|
|
@@ -14,16 +14,11 @@ class ErrorHandler {
|
|
|
14
14
|
const maxInterval = typeof retry.maximumInterval === 'string'
|
|
15
15
|
? parseInt(retry.maximumInterval)
|
|
16
16
|
: (retry.maximumInterval || 120);
|
|
17
|
-
|
|
18
|
-
// tryCount=0 is 1st attempt, tryCount=1 is 2nd attempt, etc.
|
|
19
|
-
// So after tryCount, we've made (tryCount + 1) attempts
|
|
20
|
-
// We can retry if (tryCount + 1) < maxAttempts
|
|
17
|
+
const initialIntervalS = retry.initialInterval || 1;
|
|
21
18
|
if ((tryCount + 1) < maxAttempts) {
|
|
22
|
-
// Exponential backoff: min(coefficient^(try+1), maxInterval)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const backoffSeconds = Math.min(Math.pow(backoffCoeff, tryCount + 1), maxInterval);
|
|
26
|
-
return [true, backoffSeconds * 1000]; // Convert to milliseconds
|
|
19
|
+
// Exponential backoff: min(initialInterval * coefficient^(try+1), maxInterval)
|
|
20
|
+
const backoffSeconds = Math.min(initialIntervalS * Math.pow(backoffCoeff, tryCount + 1), maxInterval);
|
|
21
|
+
return [true, backoffSeconds * 1000];
|
|
27
22
|
}
|
|
28
23
|
return [false, 0];
|
|
29
24
|
}
|
|
@@ -101,7 +96,7 @@ class ErrorHandler {
|
|
|
101
96
|
data,
|
|
102
97
|
};
|
|
103
98
|
}
|
|
104
|
-
async handleRetry(input, output, publishMessage, retry) {
|
|
99
|
+
async handleRetry(input, output, publishMessage, retry, onRetryScheduled) {
|
|
105
100
|
const [shouldRetry, timeout] = this.shouldRetry(input, output, retry);
|
|
106
101
|
if (shouldRetry) {
|
|
107
102
|
// Only sleep if no retry (legacy behavior for backward compatibility)
|
|
@@ -126,7 +121,13 @@ class ErrorHandler {
|
|
|
126
121
|
// Track retry attempt count in database
|
|
127
122
|
const currentAttempt = input._retryAttempt || 0;
|
|
128
123
|
newMessage._retryAttempt = currentAttempt + 1;
|
|
129
|
-
|
|
124
|
+
const messageId = (await publishMessage(input.metadata.topic, newMessage));
|
|
125
|
+
// Schedule a targeted NOTIFY so the consumer wakes up when
|
|
126
|
+
// the visibility-delayed message becomes visible
|
|
127
|
+
if (retry && timeout > 0 && onRetryScheduled) {
|
|
128
|
+
onRetryScheduled(input.metadata.topic, timeout);
|
|
129
|
+
}
|
|
130
|
+
return messageId;
|
|
130
131
|
}
|
|
131
132
|
else {
|
|
132
133
|
const structuredError = this.structureError(input, output);
|
|
@@ -15,6 +15,10 @@ export declare const GET_JOB_ATTRIBUTES = "\n SELECT symbol || dimension AS fie
|
|
|
15
15
|
* Matches all activity jobs for the given workflow and extracts their input arguments.
|
|
16
16
|
*/
|
|
17
17
|
export declare const GET_ACTIVITY_INPUTS = "\n SELECT j.key, ja.value\n FROM {schema}.jobs j\n JOIN {schema}.jobs_attributes ja ON ja.job_id = j.id\n WHERE j.key LIKE $1\n AND ja.symbol = $2 AND ja.dimension = $3\n";
|
|
18
|
+
/**
|
|
19
|
+
* Fetch activity inputs from worker_streams for direct worker proxyer activities.
|
|
20
|
+
*/
|
|
21
|
+
export declare const GET_PROXYER_STREAM_INPUTS = "\n SELECT message\n FROM {schema}.worker_streams\n WHERE jid = $1\n AND aid IN ('proxyer', 'collator_proxyer', 'signaler_proxyer')\n ORDER BY created_at, id\n";
|
|
18
22
|
/**
|
|
19
23
|
* Fetch all worker stream messages for a job AND its child activities.
|
|
20
24
|
* Child activity jobs use the pattern: -{parentJobId}-$activityName-N
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* These queries support the exporter's input enrichment and direct query features.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.buildChildWorkflowInputsQuery = exports.GET_STREAM_HISTORY_BY_JID_AND_AID = exports.GET_STREAM_HISTORY_BY_JID_AND_TYPE = exports.GET_STREAM_HISTORY_BY_JID = exports.GET_ACTIVITY_INPUTS = exports.GET_JOB_ATTRIBUTES = exports.GET_JOB_BY_KEY = void 0;
|
|
7
|
+
exports.buildChildWorkflowInputsQuery = exports.GET_STREAM_HISTORY_BY_JID_AND_AID = exports.GET_STREAM_HISTORY_BY_JID_AND_TYPE = exports.GET_STREAM_HISTORY_BY_JID = exports.GET_PROXYER_STREAM_INPUTS = exports.GET_ACTIVITY_INPUTS = exports.GET_JOB_ATTRIBUTES = exports.GET_JOB_BY_KEY = void 0;
|
|
8
8
|
/**
|
|
9
9
|
* Fetch job record by key.
|
|
10
10
|
*/
|
|
@@ -34,6 +34,16 @@ exports.GET_ACTIVITY_INPUTS = `
|
|
|
34
34
|
WHERE j.key LIKE $1
|
|
35
35
|
AND ja.symbol = $2 AND ja.dimension = $3
|
|
36
36
|
`;
|
|
37
|
+
/**
|
|
38
|
+
* Fetch activity inputs from worker_streams for direct worker proxyer activities.
|
|
39
|
+
*/
|
|
40
|
+
exports.GET_PROXYER_STREAM_INPUTS = `
|
|
41
|
+
SELECT message
|
|
42
|
+
FROM {schema}.worker_streams
|
|
43
|
+
WHERE jid = $1
|
|
44
|
+
AND aid IN ('proxyer', 'collator_proxyer', 'signaler_proxyer')
|
|
45
|
+
ORDER BY created_at, id
|
|
46
|
+
`;
|
|
37
47
|
/**
|
|
38
48
|
* Fetch all worker stream messages for a job AND its child activities.
|
|
39
49
|
* Child activity jobs use the pattern: -{parentJobId}-$activityName-N
|
|
@@ -1442,6 +1442,30 @@ class PostgresStoreService extends __1.StoreService {
|
|
|
1442
1442
|
// Skip unparseable values
|
|
1443
1443
|
}
|
|
1444
1444
|
}
|
|
1445
|
+
// If no results from legacy approach, try direct worker approach:
|
|
1446
|
+
// extract arguments from proxyer messages in worker_streams
|
|
1447
|
+
if (byNameIndex.size === 0) {
|
|
1448
|
+
const { GET_PROXYER_STREAM_INPUTS } = await Promise.resolve().then(() => __importStar(require('./exporter-sql')));
|
|
1449
|
+
const streamSql = GET_PROXYER_STREAM_INPUTS.replace(/{schema}/g, schemaName);
|
|
1450
|
+
const streamResult = await this.pgClient.query(streamSql, [workflowId]);
|
|
1451
|
+
for (const row of streamResult.rows) {
|
|
1452
|
+
try {
|
|
1453
|
+
const msg = typeof row.message === 'string' ? JSON.parse(row.message) : row.message;
|
|
1454
|
+
const data = msg?.data;
|
|
1455
|
+
if (data?.activityName && data?.arguments) {
|
|
1456
|
+
const activityName = data.activityName;
|
|
1457
|
+
const wfId = data.workflowId || '';
|
|
1458
|
+
const idxMatch = wfId.match(/-(\d+)$/);
|
|
1459
|
+
const execIndex = idxMatch ? idxMatch[1] : '0';
|
|
1460
|
+
byNameIndex.set(`${activityName}:${execIndex}`, data.arguments);
|
|
1461
|
+
byJobId.set(wfId, data.arguments);
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
catch {
|
|
1465
|
+
// Skip unparseable messages
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1445
1469
|
return { byJobId, byNameIndex };
|
|
1446
1470
|
}
|
|
1447
1471
|
/**
|
|
@@ -58,6 +58,12 @@ declare class PostgresStreamService extends StreamService<PostgresClientType & P
|
|
|
58
58
|
* added to the transaction for atomic execution.
|
|
59
59
|
*/
|
|
60
60
|
publishMessages(streamName: string, messages: string[], options?: PublishMessageConfig): Promise<string[] | ProviderTransaction>;
|
|
61
|
+
/**
|
|
62
|
+
* Schedule a NOTIFY for a worker stream after a delay. Used to wake up
|
|
63
|
+
* consumers when a visibility-delayed retry message becomes visible,
|
|
64
|
+
* avoiding the need to wait for the scout's fallback poll.
|
|
65
|
+
*/
|
|
66
|
+
scheduleStreamNotify(streamName: string, delayMs: number): void;
|
|
61
67
|
_publishMessages(streamName: string, messages: string[], options?: PublishMessageConfig): {
|
|
62
68
|
sql: string;
|
|
63
69
|
params: any[];
|
|
@@ -174,6 +174,31 @@ class PostgresStreamService extends index_1.StreamService {
|
|
|
174
174
|
const target = this.resolveStreamTarget(streamName);
|
|
175
175
|
return Messages.publishMessages(this.streamClient, target.tableName, target.streamName, target.isEngine, messages, options, this.logger);
|
|
176
176
|
}
|
|
177
|
+
/**
|
|
178
|
+
* Schedule a NOTIFY for a worker stream after a delay. Used to wake up
|
|
179
|
+
* consumers when a visibility-delayed retry message becomes visible,
|
|
180
|
+
* avoiding the need to wait for the scout's fallback poll.
|
|
181
|
+
*/
|
|
182
|
+
scheduleStreamNotify(streamName, delayMs) {
|
|
183
|
+
const target = this.resolveStreamTarget(streamName);
|
|
184
|
+
const prefix = target.isEngine ? 'eng_' : 'wrk_';
|
|
185
|
+
let channelName = `${prefix}${target.streamName}`;
|
|
186
|
+
if (channelName.length > 63) {
|
|
187
|
+
channelName = channelName.substring(0, 63);
|
|
188
|
+
}
|
|
189
|
+
const payload = JSON.stringify({
|
|
190
|
+
stream_name: target.streamName,
|
|
191
|
+
table_type: target.isEngine ? 'engine' : 'worker',
|
|
192
|
+
});
|
|
193
|
+
setTimeout(async () => {
|
|
194
|
+
try {
|
|
195
|
+
await this.streamClient.query(`SELECT pg_notify($1, $2)`, [channelName, payload]);
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
// Best-effort; the scout fallback will pick it up
|
|
199
|
+
}
|
|
200
|
+
}, delayMs);
|
|
201
|
+
}
|
|
177
202
|
_publishMessages(streamName, messages, options) {
|
|
178
203
|
const target = this.resolveStreamTarget(streamName);
|
|
179
204
|
return Messages.buildPublishSQL(target.tableName, target.streamName, target.isEngine, messages, options);
|