@hotmeshio/hotmesh 0.1.9 → 0.1.11
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/modules/errors.d.ts +3 -0
- package/build/modules/errors.js +3 -0
- package/build/package.json +1 -1
- package/build/services/activities/activity.d.ts +7 -1
- package/build/services/activities/activity.js +33 -2
- package/build/services/collator/index.d.ts +1 -1
- package/build/services/collator/index.js +2 -2
- package/build/services/durable/client.d.ts +6 -1
- package/build/services/durable/client.js +19 -7
- package/build/services/durable/schemas/factory.d.ts +1 -1
- package/build/services/durable/schemas/factory.js +63 -1
- package/build/services/durable/worker.js +3 -0
- package/build/services/durable/workflow.js +3 -0
- package/build/services/pipe/functions/conditional.d.ts +2 -0
- package/build/services/pipe/functions/conditional.js +6 -0
- package/build/types/activity.d.ts +2 -0
- package/build/types/durable.d.ts +6 -0
- package/build/types/error.d.ts +3 -0
- package/package.json +1 -1
- package/types/activity.ts +2 -0
- package/types/durable.ts +8 -0
- package/types/error.ts +3 -0
|
@@ -27,6 +27,7 @@ declare class DurableProxyError extends Error {
|
|
|
27
27
|
maximumInterval: number;
|
|
28
28
|
originJobId: string | null;
|
|
29
29
|
parentWorkflowId: string;
|
|
30
|
+
expire: number;
|
|
30
31
|
workflowDimension: string;
|
|
31
32
|
workflowId: string;
|
|
32
33
|
workflowTopic: string;
|
|
@@ -37,6 +38,8 @@ declare class DurableChildError extends Error {
|
|
|
37
38
|
arguments: string[];
|
|
38
39
|
backoffCoefficient: number;
|
|
39
40
|
code: number;
|
|
41
|
+
expire: number;
|
|
42
|
+
signalIn: boolean;
|
|
40
43
|
workflowDimension: string;
|
|
41
44
|
index: number;
|
|
42
45
|
maximumAttempts: number;
|
package/build/modules/errors.js
CHANGED
|
@@ -33,6 +33,7 @@ class DurableProxyError extends Error {
|
|
|
33
33
|
this.workflowId = params.workflowId;
|
|
34
34
|
this.workflowTopic = params.workflowTopic;
|
|
35
35
|
this.parentWorkflowId = params.parentWorkflowId;
|
|
36
|
+
this.expire = params.expire;
|
|
36
37
|
this.originJobId = params.originJobId;
|
|
37
38
|
this.index = params.index;
|
|
38
39
|
this.activityName = params.activityName;
|
|
@@ -51,6 +52,8 @@ class DurableChildError extends Error {
|
|
|
51
52
|
this.workflowId = params.workflowId;
|
|
52
53
|
this.workflowTopic = params.workflowTopic;
|
|
53
54
|
this.parentWorkflowId = params.parentWorkflowId;
|
|
55
|
+
this.expire = params.expire;
|
|
56
|
+
this.signalIn = params.signalIn;
|
|
54
57
|
this.originJobId = params.originJobId;
|
|
55
58
|
this.index = params.index;
|
|
56
59
|
this.workflowDimension = params.workflowDimension;
|
package/build/package.json
CHANGED
|
@@ -26,6 +26,12 @@ declare class Activity {
|
|
|
26
26
|
adjacentIndex: number;
|
|
27
27
|
constructor(config: ActivityType, data: ActivityData, metadata: ActivityMetadata, hook: ActivityData | null, engine: EngineService, context?: JobState);
|
|
28
28
|
setLeg(leg: ActivityLeg): void;
|
|
29
|
+
/**
|
|
30
|
+
* A job is assumed to be complete when its status (a semaphore)
|
|
31
|
+
* reaches `0`. A different threshold can be set in the
|
|
32
|
+
* activity YAML, in support of Dynamic Activation Control.
|
|
33
|
+
*/
|
|
34
|
+
mapStatusThreshold(): number;
|
|
29
35
|
/**
|
|
30
36
|
* Upon entering leg 1 of a duplexed activity
|
|
31
37
|
*/
|
|
@@ -55,7 +61,7 @@ declare class Activity {
|
|
|
55
61
|
bindJobError(data: Record<string, unknown>): void;
|
|
56
62
|
getTriggerConfig(): Promise<ActivityType>;
|
|
57
63
|
getJobStatus(): null | number;
|
|
58
|
-
setStatus(amount: number, multi?: RedisMulti): Promise<void>;
|
|
64
|
+
setStatus(amount: number, multi?: RedisMulti): Promise<void | any>;
|
|
59
65
|
authorizeEntry(state: StringAnyType): string[];
|
|
60
66
|
bindDimensionalAddress(state: StringAnyType): void;
|
|
61
67
|
setState(multi?: RedisMulti): Promise<string>;
|
|
@@ -30,13 +30,44 @@ class Activity {
|
|
|
30
30
|
setLeg(leg) {
|
|
31
31
|
this.leg = leg;
|
|
32
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* A job is assumed to be complete when its status (a semaphore)
|
|
35
|
+
* reaches `0`. A different threshold can be set in the
|
|
36
|
+
* activity YAML, in support of Dynamic Activation Control.
|
|
37
|
+
*/
|
|
38
|
+
mapStatusThreshold() {
|
|
39
|
+
if (this.config.statusThreshold !== undefined) {
|
|
40
|
+
const threshold = pipe_1.Pipe.resolve(this.config.statusThreshold, this.context);
|
|
41
|
+
if (threshold !== undefined && !isNaN(Number(threshold))) {
|
|
42
|
+
return threshold;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return 0;
|
|
46
|
+
}
|
|
33
47
|
/**
|
|
34
48
|
* Upon entering leg 1 of a duplexed activity
|
|
35
49
|
*/
|
|
36
50
|
async verifyEntry() {
|
|
37
51
|
this.setLeg(1);
|
|
38
52
|
await this.getState();
|
|
39
|
-
|
|
53
|
+
const threshold = this.mapStatusThreshold();
|
|
54
|
+
try {
|
|
55
|
+
collator_1.CollatorService.assertJobActive(this.context.metadata.js, this.context.metadata.jid, this.metadata.aid, threshold);
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
if (threshold > 0) {
|
|
59
|
+
if (this.context.metadata.js === threshold) {
|
|
60
|
+
//conclude job EXACTLY ONCE
|
|
61
|
+
const status = await this.setStatus(-threshold);
|
|
62
|
+
if (Number(status) === 0) {
|
|
63
|
+
await this.engine.runJobCompletionTasks(this.context);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
40
71
|
await collator_1.CollatorService.notarizeEntry(this);
|
|
41
72
|
}
|
|
42
73
|
/**
|
|
@@ -247,7 +278,7 @@ class Activity {
|
|
|
247
278
|
}
|
|
248
279
|
async setStatus(amount, multi) {
|
|
249
280
|
const { id: appId } = await this.engine.getVID();
|
|
250
|
-
await this.store.setStatus(amount, this.context.metadata.jid, appId, multi);
|
|
281
|
+
return await this.store.setStatus(amount, this.context.metadata.jid, appId, multi);
|
|
251
282
|
}
|
|
252
283
|
authorizeEntry(state) {
|
|
253
284
|
//pre-authorize activity state to allow entry for adjacent activities
|
|
@@ -9,7 +9,7 @@ declare class CollatorService {
|
|
|
9
9
|
/**
|
|
10
10
|
* Upon re/entry, verify that the job status is active
|
|
11
11
|
*/
|
|
12
|
-
static assertJobActive(status: number, jobId: string, activityId: string): void;
|
|
12
|
+
static assertJobActive(status: number, jobId: string, activityId: string, threshold?: number): void;
|
|
13
13
|
/**
|
|
14
14
|
* returns the dimensional address (dad) for the target; due
|
|
15
15
|
* to the nature of the notary system, the dad for leg 2 entry
|
|
@@ -7,8 +7,8 @@ class CollatorService {
|
|
|
7
7
|
/**
|
|
8
8
|
* Upon re/entry, verify that the job status is active
|
|
9
9
|
*/
|
|
10
|
-
static assertJobActive(status, jobId, activityId) {
|
|
11
|
-
if (status <=
|
|
10
|
+
static assertJobActive(status, jobId, activityId, threshold = 0) {
|
|
11
|
+
if (status <= threshold) {
|
|
12
12
|
throw new errors_1.InactiveJobError(jobId, status, activityId);
|
|
13
13
|
}
|
|
14
14
|
}
|
|
@@ -7,7 +7,7 @@ export declare class ClientService {
|
|
|
7
7
|
static topics: string[];
|
|
8
8
|
static instances: Map<string, HotMesh | Promise<HotMesh>>;
|
|
9
9
|
constructor(config: ClientConfig);
|
|
10
|
-
getHotMeshClient: (workflowTopic: string, namespace?: string) => Promise<HotMesh>;
|
|
10
|
+
getHotMeshClient: (workflowTopic: string | null, namespace?: string) => Promise<HotMesh>;
|
|
11
11
|
/**
|
|
12
12
|
* Creates a stream (Redis `XGROUP.CREATE`) where events can be published (XADD).
|
|
13
13
|
* It is possible that the worker that will read from this stream channel
|
|
@@ -38,6 +38,11 @@ export declare class ClientService {
|
|
|
38
38
|
getHandle: (taskQueue: string, workflowName: string, workflowId: string, namespace?: string) => Promise<WorkflowHandleService>;
|
|
39
39
|
search: (taskQueue: string, workflowName: string, namespace: null | string, index: string, ...query: string[]) => Promise<string[]>;
|
|
40
40
|
};
|
|
41
|
+
/**
|
|
42
|
+
* Any point of presence can be used to deploy and activate the HotMesh
|
|
43
|
+
* distributed executable to the active quorum.
|
|
44
|
+
*/
|
|
45
|
+
deployAndActivate(namespace?: string, version?: string): Promise<void>;
|
|
41
46
|
verifyWorkflowActive(hotMesh: HotMesh, appId?: string, count?: number): Promise<boolean>;
|
|
42
47
|
activateWorkflow(hotMesh: HotMesh, appId?: string, version?: string): Promise<void>;
|
|
43
48
|
static shutdown(): Promise<void>;
|
|
@@ -78,6 +78,7 @@ class ClientService {
|
|
|
78
78
|
arguments: [...options.args],
|
|
79
79
|
originJobId: options.originJobId,
|
|
80
80
|
expire: options.expire ?? enums_1.HMSH_EXPIRE_JOB_SECONDS,
|
|
81
|
+
signalIn: options.signalIn,
|
|
81
82
|
parentWorkflowId: options.parentWorkflowId,
|
|
82
83
|
workflowId: options.workflowId || hotmesh_1.HotMeshService.guid(),
|
|
83
84
|
workflowTopic: workflowTopic,
|
|
@@ -150,6 +151,17 @@ class ClientService {
|
|
|
150
151
|
};
|
|
151
152
|
this.connection = config.connection;
|
|
152
153
|
}
|
|
154
|
+
/**
|
|
155
|
+
* Any point of presence can be used to deploy and activate the HotMesh
|
|
156
|
+
* distributed executable to the active quorum.
|
|
157
|
+
*/
|
|
158
|
+
async deployAndActivate(namespace = factory_1.APP_ID, version = factory_1.APP_VERSION) {
|
|
159
|
+
if (isNaN(Number(version))) {
|
|
160
|
+
throw new Error('Invalid version number');
|
|
161
|
+
}
|
|
162
|
+
const hotMesh = await this.getHotMeshClient('', namespace);
|
|
163
|
+
await this.activateWorkflow(hotMesh, namespace, version);
|
|
164
|
+
}
|
|
153
165
|
async verifyWorkflowActive(hotMesh, appId = factory_1.APP_ID, count = 0) {
|
|
154
166
|
const app = await hotMesh.engine.store.getApp(appId);
|
|
155
167
|
const appVersion = app?.version;
|
|
@@ -165,24 +177,24 @@ class ClientService {
|
|
|
165
177
|
async activateWorkflow(hotMesh, appId = factory_1.APP_ID, version = factory_1.APP_VERSION) {
|
|
166
178
|
const app = await hotMesh.engine.store.getApp(appId);
|
|
167
179
|
const appVersion = app?.version;
|
|
168
|
-
if (
|
|
180
|
+
if (appVersion === version && !app.active) {
|
|
169
181
|
try {
|
|
170
|
-
await hotMesh.deploy((0, factory_1.getWorkflowYAML)(appId, version));
|
|
171
182
|
await hotMesh.activate(version);
|
|
172
183
|
}
|
|
173
184
|
catch (error) {
|
|
174
|
-
hotMesh.engine.logger.error('durable-client-
|
|
175
|
-
...error,
|
|
176
|
-
});
|
|
185
|
+
hotMesh.engine.logger.error('durable-client-activate-err', { error });
|
|
177
186
|
throw error;
|
|
178
187
|
}
|
|
179
188
|
}
|
|
180
|
-
else if (
|
|
189
|
+
else if (isNaN(Number(appVersion)) || appVersion <= version) {
|
|
181
190
|
try {
|
|
191
|
+
await hotMesh.deploy((0, factory_1.getWorkflowYAML)(appId, version));
|
|
182
192
|
await hotMesh.activate(version);
|
|
183
193
|
}
|
|
184
194
|
catch (error) {
|
|
185
|
-
hotMesh.engine.logger.error('durable-client-activate-err', {
|
|
195
|
+
hotMesh.engine.logger.error('durable-client-deploy-activate-err', {
|
|
196
|
+
...error,
|
|
197
|
+
});
|
|
186
198
|
throw error;
|
|
187
199
|
}
|
|
188
200
|
}
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
*/
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
26
|
exports.APP_ID = exports.APP_VERSION = exports.getWorkflowYAML = void 0;
|
|
27
|
-
const APP_VERSION = '
|
|
27
|
+
const APP_VERSION = '2';
|
|
28
28
|
exports.APP_VERSION = APP_VERSION;
|
|
29
29
|
const APP_ID = 'durable';
|
|
30
30
|
exports.APP_ID = APP_ID;
|
|
@@ -81,6 +81,9 @@ const getWorkflowYAML = (app, version) => {
|
|
|
81
81
|
expire:
|
|
82
82
|
description: the time in seconds to expire the workflow in Redis once it completes
|
|
83
83
|
type: number
|
|
84
|
+
signalIn:
|
|
85
|
+
description: if false, the job will not support subordinated hooks
|
|
86
|
+
type: boolean
|
|
84
87
|
|
|
85
88
|
output:
|
|
86
89
|
schema:
|
|
@@ -232,6 +235,10 @@ const getWorkflowYAML = (app, version) => {
|
|
|
232
235
|
type: number
|
|
233
236
|
maximumInterval:
|
|
234
237
|
type: number
|
|
238
|
+
expire:
|
|
239
|
+
type: number
|
|
240
|
+
signalIn:
|
|
241
|
+
type: boolean
|
|
235
242
|
await:
|
|
236
243
|
type: string
|
|
237
244
|
description: when set to false, do not await the child flow's completion
|
|
@@ -335,6 +342,8 @@ const getWorkflowYAML = (app, version) => {
|
|
|
335
342
|
type: number
|
|
336
343
|
expire:
|
|
337
344
|
type: number
|
|
345
|
+
signalIn:
|
|
346
|
+
type: boolean
|
|
338
347
|
parentWorkflowId:
|
|
339
348
|
type: string
|
|
340
349
|
description: used to forge the cleanup key
|
|
@@ -355,6 +364,8 @@ const getWorkflowYAML = (app, version) => {
|
|
|
355
364
|
index: '{worker.output.data.index}'
|
|
356
365
|
originJobId: '{worker.output.data.originJobId}'
|
|
357
366
|
parentWorkflowId: '{worker.output.data.parentWorkflowId}'
|
|
367
|
+
expire: '{worker.output.data.expire}'
|
|
368
|
+
signalIn: '{worker.output.data.signalIn}'
|
|
358
369
|
workflowId: '{worker.output.data.workflowId}'
|
|
359
370
|
workflowName: '{worker.output.data.workflowName}'
|
|
360
371
|
workflowTopic: '{worker.output.data.workflowTopic}'
|
|
@@ -512,6 +523,8 @@ const getWorkflowYAML = (app, version) => {
|
|
|
512
523
|
description: the arguments to pass to the activity
|
|
513
524
|
items:
|
|
514
525
|
type: string
|
|
526
|
+
expire:
|
|
527
|
+
type: number
|
|
515
528
|
backoffCoefficient:
|
|
516
529
|
type: number
|
|
517
530
|
maximumAttempts:
|
|
@@ -527,6 +540,7 @@ const getWorkflowYAML = (app, version) => {
|
|
|
527
540
|
parentWorkflowId: '{worker.output.data.workflowId}'
|
|
528
541
|
workflowId: '{worker.output.data.workflowId}'
|
|
529
542
|
workflowTopic: '{worker.output.data.workflowTopic}'
|
|
543
|
+
expire: '{worker.output.data.expire}'
|
|
530
544
|
backoffCoefficient:
|
|
531
545
|
'@pipe':
|
|
532
546
|
- ['{worker.output.data.backoffCoefficient}','{trigger.output.data.backoffCoefficient}']
|
|
@@ -754,6 +768,17 @@ const getWorkflowYAML = (app, version) => {
|
|
|
754
768
|
- ['{trigger.output.data.maximumInterval}', 120]
|
|
755
769
|
- ['{@logical.or}']
|
|
756
770
|
- ['{@math.min}']
|
|
771
|
+
ender:
|
|
772
|
+
title: Sets job data; ignores the \`Signal In\` Hook Channel which was suppressed
|
|
773
|
+
type: hook
|
|
774
|
+
job:
|
|
775
|
+
maps:
|
|
776
|
+
done: true
|
|
777
|
+
$error: '{worker.output.data.$error}'
|
|
778
|
+
jc: '{$job.metadata.jc}'
|
|
779
|
+
ju:
|
|
780
|
+
'@pipe':
|
|
781
|
+
- ['{@date.toISOXString}']
|
|
757
782
|
|
|
758
783
|
closer:
|
|
759
784
|
title: Closes the \`Signal In\` Hook Channel, so the workflow can exit
|
|
@@ -806,6 +831,7 @@ const getWorkflowYAML = (app, version) => {
|
|
|
806
831
|
signaler:
|
|
807
832
|
title: Signal-In Reentry point for subordinated hook flows
|
|
808
833
|
type: hook
|
|
834
|
+
statusThreshold: 1
|
|
809
835
|
hook:
|
|
810
836
|
type: object
|
|
811
837
|
properties:
|
|
@@ -938,6 +964,11 @@ const getWorkflowYAML = (app, version) => {
|
|
|
938
964
|
maximumInterval:
|
|
939
965
|
type: number
|
|
940
966
|
description: the maximum time in seconds to wait between retries; provides a fixed limit to exponential backoff growth
|
|
967
|
+
expire:
|
|
968
|
+
type: number
|
|
969
|
+
signalIn:
|
|
970
|
+
type: boolean
|
|
971
|
+
description: if false, the spawned child will not support subordinated hooks
|
|
941
972
|
await:
|
|
942
973
|
type: string
|
|
943
974
|
description: when set to false, do not await the child flow's completion
|
|
@@ -965,6 +996,8 @@ const getWorkflowYAML = (app, version) => {
|
|
|
965
996
|
type: string
|
|
966
997
|
originJobId:
|
|
967
998
|
type: string
|
|
999
|
+
expire:
|
|
1000
|
+
type: number
|
|
968
1001
|
backoffCoefficient:
|
|
969
1002
|
type: number
|
|
970
1003
|
maximumAttempts:
|
|
@@ -1038,6 +1071,8 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1038
1071
|
type: number
|
|
1039
1072
|
expire:
|
|
1040
1073
|
type: number
|
|
1074
|
+
signalIn:
|
|
1075
|
+
type: boolean
|
|
1041
1076
|
parentWorkflowId:
|
|
1042
1077
|
type: string
|
|
1043
1078
|
description: used to forge the cleanup key
|
|
@@ -1058,6 +1093,8 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1058
1093
|
index: '{signaler_worker.output.data.index}'
|
|
1059
1094
|
originJobId: '{signaler_worker.output.data.originJobId}'
|
|
1060
1095
|
parentWorkflowId: '{signaler_worker.output.data.parentWorkflowId}'
|
|
1096
|
+
expire: '{signaler_worker.output.data.expire}'
|
|
1097
|
+
signalIn: '{signaler_worker.output.data.signalIn}'
|
|
1061
1098
|
workflowId: '{signaler_worker.output.data.workflowId}'
|
|
1062
1099
|
workflowName: '{signaler_worker.output.data.workflowName}'
|
|
1063
1100
|
workflowTopic: '{signaler_worker.output.data.workflowTopic}'
|
|
@@ -1215,6 +1252,8 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1215
1252
|
description: the arguments to pass to the activity
|
|
1216
1253
|
items:
|
|
1217
1254
|
type: string
|
|
1255
|
+
expire:
|
|
1256
|
+
type: number
|
|
1218
1257
|
backoffCoefficient:
|
|
1219
1258
|
type: number
|
|
1220
1259
|
maximumAttempts:
|
|
@@ -1230,6 +1269,7 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1230
1269
|
parentWorkflowId: '{signaler_worker.output.data.workflowId}'
|
|
1231
1270
|
workflowId: '{signaler_worker.output.data.workflowId}'
|
|
1232
1271
|
workflowTopic: '{signaler_worker.output.data.workflowTopic}'
|
|
1272
|
+
expire: '{signaler_worker.output.data.expire}'
|
|
1233
1273
|
backoffCoefficient:
|
|
1234
1274
|
'@pipe':
|
|
1235
1275
|
- ['{signaler_worker.output.data.backoffCoefficient}','{trigger.output.data.backoffCoefficient}']
|
|
@@ -1462,15 +1502,37 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1462
1502
|
trigger:
|
|
1463
1503
|
- to: cycle_hook
|
|
1464
1504
|
- to: signaler
|
|
1505
|
+
conditions:
|
|
1506
|
+
match:
|
|
1507
|
+
- expected: true
|
|
1508
|
+
actual:
|
|
1509
|
+
'@pipe':
|
|
1510
|
+
- ['{$self.output.data.signalIn}', true]
|
|
1511
|
+
- ['{@conditional.nullish}']
|
|
1465
1512
|
## MAIN PROCESS TRANSITIONS ##
|
|
1466
1513
|
cycle_hook:
|
|
1467
1514
|
- to: throttler
|
|
1468
1515
|
throttler:
|
|
1469
1516
|
- to: worker
|
|
1470
1517
|
worker:
|
|
1518
|
+
- to: ender
|
|
1519
|
+
conditions:
|
|
1520
|
+
code: [200, 596, 597, 598]
|
|
1521
|
+
match:
|
|
1522
|
+
- expected: false
|
|
1523
|
+
actual:
|
|
1524
|
+
'@pipe':
|
|
1525
|
+
- ['{trigger.output.data.signalIn}', true]
|
|
1526
|
+
- ['{@conditional.nullish}']
|
|
1471
1527
|
- to: closer
|
|
1472
1528
|
conditions:
|
|
1473
1529
|
code: [200, 596, 597, 598]
|
|
1530
|
+
match:
|
|
1531
|
+
- expected: true
|
|
1532
|
+
actual:
|
|
1533
|
+
'@pipe':
|
|
1534
|
+
- ['{trigger.output.data.signalIn}', true]
|
|
1535
|
+
- ['{@conditional.nullish}']
|
|
1474
1536
|
- to: sleeper
|
|
1475
1537
|
conditions:
|
|
1476
1538
|
code: 588
|
|
@@ -310,6 +310,7 @@ class WorkerService {
|
|
|
310
310
|
index: err.index,
|
|
311
311
|
originJobId: err.originJobId,
|
|
312
312
|
parentWorkflowId: err.parentWorkflowId,
|
|
313
|
+
expire: err.expire,
|
|
313
314
|
workflowId: err.workflowId,
|
|
314
315
|
workflowTopic: err.workflowTopic,
|
|
315
316
|
activityName: err.activityName,
|
|
@@ -342,6 +343,8 @@ class WorkerService {
|
|
|
342
343
|
maximumInterval: err.maximumInterval || (0, ms_1.default)(enums_1.HMSH_DURABLE_MAX_INTERVAL) / 1000,
|
|
343
344
|
originJobId: err.originJobId,
|
|
344
345
|
parentWorkflowId: err.parentWorkflowId,
|
|
346
|
+
expire: err.expire,
|
|
347
|
+
signalIn: err.signalIn,
|
|
345
348
|
workflowDimension: err.workflowDimension,
|
|
346
349
|
workflowId: err.workflowId,
|
|
347
350
|
workflowTopic: err.workflowTopic,
|
|
@@ -190,6 +190,8 @@ class WorkflowService {
|
|
|
190
190
|
maximumInterval: (0, ms_1.default)(options?.config?.maximumInterval ?? enums_1.HMSH_DURABLE_MAX_INTERVAL) /
|
|
191
191
|
1000,
|
|
192
192
|
originJobId: originJobId ?? workflowId,
|
|
193
|
+
expire: options.expire,
|
|
194
|
+
signalIn: options.signalIn,
|
|
193
195
|
parentWorkflowId,
|
|
194
196
|
workflowDimension: workflowDimension,
|
|
195
197
|
workflowId: childJobId,
|
|
@@ -303,6 +305,7 @@ class WorkflowService {
|
|
|
303
305
|
workflowId: activityJobId,
|
|
304
306
|
workflowTopic: activityTopic,
|
|
305
307
|
activityName,
|
|
308
|
+
expire: options.expire,
|
|
306
309
|
backoffCoefficient: options?.retryPolicy?.backoffCoefficient ?? undefined,
|
|
307
310
|
maximumAttempts: options?.retryPolicy?.maximumAttempts ?? undefined,
|
|
308
311
|
maximumInterval: maximumInterval ?? undefined,
|
|
@@ -2,6 +2,8 @@ declare class ConditionalHandler {
|
|
|
2
2
|
ternary(condition: boolean, valueIfTrue: any, valueIfFalse: any): any;
|
|
3
3
|
equality(value1: any, value2: any): boolean;
|
|
4
4
|
strict_equality(value1: any, value2: any): boolean;
|
|
5
|
+
inequality(value1: any, value2: any): boolean;
|
|
6
|
+
strict_inequality(value1: any, value2: any): boolean;
|
|
5
7
|
greater_than(value1: number, value2: number): boolean;
|
|
6
8
|
less_than(value1: number, value2: number): boolean;
|
|
7
9
|
greater_than_or_equal(value1: number, value2: number): boolean;
|
|
@@ -11,6 +11,12 @@ class ConditionalHandler {
|
|
|
11
11
|
strict_equality(value1, value2) {
|
|
12
12
|
return value1 === value2;
|
|
13
13
|
}
|
|
14
|
+
inequality(value1, value2) {
|
|
15
|
+
return value1 != value2;
|
|
16
|
+
}
|
|
17
|
+
strict_inequality(value1, value2) {
|
|
18
|
+
return value1 !== value2;
|
|
19
|
+
}
|
|
14
20
|
greater_than(value1, value2) {
|
|
15
21
|
return value1 > value2;
|
|
16
22
|
}
|
|
@@ -6,6 +6,8 @@ interface BaseActivity {
|
|
|
6
6
|
title?: string;
|
|
7
7
|
type?: ActivityExecutionType;
|
|
8
8
|
subtype?: string;
|
|
9
|
+
statusThreshold?: number;
|
|
10
|
+
statusThresholdType?: 'stop' | 'throw' | 'stall';
|
|
9
11
|
input?: Record<string, any>;
|
|
10
12
|
output?: Record<string, any>;
|
|
11
13
|
settings?: Record<string, any>;
|
package/build/types/durable.d.ts
CHANGED
|
@@ -260,6 +260,10 @@ type WorkflowOptions = {
|
|
|
260
260
|
* sets the number of seconds a workflow may exist after completion. As the process engine is an in-memory cache, the default policy is to expire and scrub the job hash as soon as it completes.
|
|
261
261
|
*/
|
|
262
262
|
expire?: number;
|
|
263
|
+
/**
|
|
264
|
+
* default is true; set to false to optimize workflows that do not require a `signal in`
|
|
265
|
+
*/
|
|
266
|
+
signalIn?: boolean;
|
|
263
267
|
/**
|
|
264
268
|
* default is true; if false, will not await the execution
|
|
265
269
|
*/
|
|
@@ -422,6 +426,8 @@ type ProxyType<ACT> = {
|
|
|
422
426
|
* Configuration settings for activities within a workflow.
|
|
423
427
|
*/
|
|
424
428
|
type ActivityConfig = {
|
|
429
|
+
/** place holder setting; unused at this time (re: activity workflow expire configuration) */
|
|
430
|
+
expire?: number;
|
|
425
431
|
/** Start to close timeout for the activity; not yet implemented */
|
|
426
432
|
startToCloseTimeout?: string;
|
|
427
433
|
/** Configuration for specific activities, type not yet specified */
|
package/build/types/error.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ export type DurableChildErrorType = {
|
|
|
3
3
|
await?: boolean;
|
|
4
4
|
backoffCoefficient?: number;
|
|
5
5
|
index: number;
|
|
6
|
+
expire?: number;
|
|
7
|
+
signalIn?: boolean;
|
|
6
8
|
maximumAttempts?: number;
|
|
7
9
|
maximumInterval?: number;
|
|
8
10
|
originJobId: string | null;
|
|
@@ -26,6 +28,7 @@ export type DurableProxyErrorType = {
|
|
|
26
28
|
activityName: string;
|
|
27
29
|
backoffCoefficient?: number;
|
|
28
30
|
index: number;
|
|
31
|
+
expire?: number;
|
|
29
32
|
maximumAttempts?: number;
|
|
30
33
|
maximumInterval?: number;
|
|
31
34
|
originJobId: string | null;
|
package/package.json
CHANGED
package/types/activity.ts
CHANGED
|
@@ -18,6 +18,8 @@ interface BaseActivity {
|
|
|
18
18
|
title?: string;
|
|
19
19
|
type?: ActivityExecutionType;
|
|
20
20
|
subtype?: string;
|
|
21
|
+
statusThreshold?: number; //default is 0; set to 1 to ensure not last standing; message will be ignored as if too late to process
|
|
22
|
+
statusThresholdType?: 'stop' | 'throw' | 'stall'; //default is stop; must explicitly set to throw to throw an error or stall to stall
|
|
21
23
|
input?: Record<string, any>;
|
|
22
24
|
output?: Record<string, any>;
|
|
23
25
|
settings?: Record<string, any>;
|
package/types/durable.ts
CHANGED
|
@@ -314,6 +314,11 @@ type WorkflowOptions = {
|
|
|
314
314
|
*/
|
|
315
315
|
expire?: number;
|
|
316
316
|
|
|
317
|
+
/**
|
|
318
|
+
* default is true; set to false to optimize workflows that do not require a `signal in`
|
|
319
|
+
*/
|
|
320
|
+
signalIn?: boolean;
|
|
321
|
+
|
|
317
322
|
/**
|
|
318
323
|
* default is true; if false, will not await the execution
|
|
319
324
|
*/
|
|
@@ -516,6 +521,9 @@ type ProxyType<ACT> = {
|
|
|
516
521
|
* Configuration settings for activities within a workflow.
|
|
517
522
|
*/
|
|
518
523
|
type ActivityConfig = {
|
|
524
|
+
/** place holder setting; unused at this time (re: activity workflow expire configuration) */
|
|
525
|
+
expire?: number;
|
|
526
|
+
|
|
519
527
|
/** Start to close timeout for the activity; not yet implemented */
|
|
520
528
|
startToCloseTimeout?: string;
|
|
521
529
|
|
package/types/error.ts
CHANGED
|
@@ -3,6 +3,8 @@ export type DurableChildErrorType = {
|
|
|
3
3
|
await?: boolean;
|
|
4
4
|
backoffCoefficient?: number;
|
|
5
5
|
index: number;
|
|
6
|
+
expire?: number;
|
|
7
|
+
signalIn?: boolean;
|
|
6
8
|
maximumAttempts?: number;
|
|
7
9
|
maximumInterval?: number;
|
|
8
10
|
originJobId: string | null;
|
|
@@ -28,6 +30,7 @@ export type DurableProxyErrorType = {
|
|
|
28
30
|
activityName: string;
|
|
29
31
|
backoffCoefficient?: number;
|
|
30
32
|
index: number;
|
|
33
|
+
expire?: number;
|
|
31
34
|
maximumAttempts?: number;
|
|
32
35
|
maximumInterval?: number;
|
|
33
36
|
originJobId: string | null;
|