@hotmeshio/hotmesh 0.1.9 → 0.1.10
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.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.js +1 -0
- package/build/services/durable/schemas/factory.d.ts +1 -1
- package/build/services/durable/schemas/factory.js +12 -1
- 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 +4 -0
- package/package.json +1 -1
- package/types/activity.ts +2 -0
- package/types/durable.ts +5 -0
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
|
}
|
|
@@ -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,
|
|
@@ -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:
|
|
@@ -806,6 +809,7 @@ const getWorkflowYAML = (app, version) => {
|
|
|
806
809
|
signaler:
|
|
807
810
|
title: Signal-In Reentry point for subordinated hook flows
|
|
808
811
|
type: hook
|
|
812
|
+
statusThreshold: 1
|
|
809
813
|
hook:
|
|
810
814
|
type: object
|
|
811
815
|
properties:
|
|
@@ -1462,6 +1466,13 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1462
1466
|
trigger:
|
|
1463
1467
|
- to: cycle_hook
|
|
1464
1468
|
- to: signaler
|
|
1469
|
+
conditions:
|
|
1470
|
+
match:
|
|
1471
|
+
- expected: true
|
|
1472
|
+
actual:
|
|
1473
|
+
'@pipe':
|
|
1474
|
+
- ['{$self.output.data.signalIn}', true]
|
|
1475
|
+
- ['{@conditional.nullish}']
|
|
1465
1476
|
## MAIN PROCESS TRANSITIONS ##
|
|
1466
1477
|
cycle_hook:
|
|
1467
1478
|
- to: throttler
|
|
@@ -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
|
*/
|
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
|
*/
|