@hotmeshio/hotmesh 0.0.36 → 0.0.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -11
- package/build/modules/enums.d.ts +1 -0
- package/build/modules/enums.js +3 -1
- package/build/modules/errors.d.ts +9 -1
- package/build/modules/errors.js +12 -1
- package/build/modules/key.d.ts +20 -19
- package/build/modules/key.js +20 -20
- package/build/package.json +1 -1
- package/build/services/activities/activity.d.ts +10 -0
- package/build/services/activities/activity.js +28 -3
- package/build/services/activities/await.js +10 -9
- package/build/services/activities/cycle.js +10 -9
- package/build/services/activities/hook.d.ts +7 -1
- package/build/services/activities/hook.js +61 -44
- package/build/services/activities/interrupt.js +10 -9
- package/build/services/activities/signal.js +7 -7
- package/build/services/activities/trigger.js +4 -2
- package/build/services/activities/worker.js +9 -8
- package/build/services/durable/meshos.js +2 -2
- package/build/services/durable/worker.js +2 -2
- package/build/services/durable/workflow.js +17 -17
- package/build/services/engine/index.d.ts +5 -7
- package/build/services/engine/index.js +53 -47
- package/build/services/hotmesh/index.d.ts +2 -2
- package/build/services/hotmesh/index.js +6 -7
- package/build/services/quorum/index.d.ts +6 -6
- package/build/services/quorum/index.js +47 -11
- package/build/services/{signaler/stream.d.ts → router/index.d.ts} +3 -3
- package/build/services/{signaler/stream.js → router/index.js} +6 -6
- package/build/services/serializer/index.js +1 -1
- package/build/services/store/clients/ioredis.d.ts +1 -0
- package/build/services/store/clients/ioredis.js +9 -0
- package/build/services/store/clients/redis.d.ts +1 -0
- package/build/services/store/clients/redis.js +16 -0
- package/build/services/store/index.d.ts +10 -4
- package/build/services/store/index.js +21 -10
- package/build/services/stream/clients/ioredis.d.ts +1 -0
- package/build/services/stream/clients/ioredis.js +33 -24
- package/build/services/stream/clients/redis.d.ts +1 -0
- package/build/services/stream/clients/redis.js +15 -0
- package/build/services/stream/index.d.ts +1 -0
- package/build/services/task/index.d.ts +13 -4
- package/build/services/task/index.js +115 -17
- package/build/services/telemetry/index.js +6 -6
- package/build/services/worker/index.d.ts +4 -3
- package/build/services/worker/index.js +32 -8
- package/build/types/job.d.ts +2 -0
- package/build/types/quorum.d.ts +11 -1
- package/build/types/redisclient.d.ts +1 -0
- package/build/types/stream.d.ts +1 -0
- package/modules/enums.ts +3 -0
- package/modules/errors.ts +18 -0
- package/modules/key.ts +21 -20
- package/package.json +1 -1
- package/services/activities/activity.ts +44 -4
- package/services/activities/await.ts +14 -10
- package/services/activities/cycle.ts +14 -10
- package/services/activities/hook.ts +70 -47
- package/services/activities/interrupt.ts +13 -10
- package/services/activities/signal.ts +11 -8
- package/services/activities/trigger.ts +5 -1
- package/services/activities/worker.ts +13 -9
- package/services/durable/meshos.ts +1 -1
- package/services/durable/worker.ts +1 -1
- package/services/durable/workflow.ts +1 -1
- package/services/engine/index.ts +82 -44
- package/services/hotmesh/index.ts +7 -8
- package/services/quorum/index.ts +48 -12
- package/services/{signaler/stream.ts → router/index.ts} +5 -5
- package/services/serializer/index.ts +1 -1
- package/services/store/clients/ioredis.ts +9 -0
- package/services/store/clients/redis.ts +16 -0
- package/services/store/index.ts +27 -12
- package/services/stream/clients/ioredis.ts +33 -24
- package/services/stream/clients/redis.ts +14 -0
- package/services/stream/index.ts +1 -0
- package/services/task/index.ts +120 -21
- package/services/telemetry/index.ts +6 -6
- package/services/worker/index.ts +37 -7
- package/types/job.ts +2 -0
- package/types/quorum.ts +15 -4
- package/types/redisclient.ts +1 -0
- package/types/stream.ts +6 -5
- package/build/services/signaler/store.d.ts +0 -15
- package/build/services/signaler/store.js +0 -68
- package/services/signaler/store.ts +0 -76
- /package/build/{services/durable/asyncLocalStorage.d.ts → modules/storage.d.ts} +0 -0
- /package/build/{services/durable/asyncLocalStorage.js → modules/storage.js} +0 -0
- /package/{services/durable/asyncLocalStorage.ts → modules/storage.ts} +0 -0
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ npm install @hotmeshio/hotmesh
|
|
|
15
15
|
## Understanding HotMesh
|
|
16
16
|
HotMesh inverts the relationship to Redis: those functions that once used Redis as a cache, are instead *cached and governed* by Redis. Consider the following. It's a typical microservices network, with a tangled mess of services and functions. There's important business logic in there (functions *A*, *B* and *C* are critical!), but they're hard to find and access.
|
|
17
17
|
|
|
18
|
-
<img src="
|
|
18
|
+
<img src="./docs/img/operational_data_layer.png" alt="A Tangled Microservices Network with 3 valuable functions buried within" style="max-width:100%;width:600px;">
|
|
19
19
|
|
|
20
20
|
HotMesh creates an *ad hoc*, Redis-backed network of functions and organizes them into a unified service mesh. *Any service with access to Redis can join in the network, bypassing the legacy clutter.*
|
|
21
21
|
|
|
@@ -285,31 +285,31 @@ const hotMesh = await HotMesh.init({
|
|
|
285
285
|
```
|
|
286
286
|
|
|
287
287
|
### Observability
|
|
288
|
-
Workflows and activities are run according to the rules you define, offering [Graph-Oriented](https://github.com/hotmeshio/sdk-typescript/
|
|
288
|
+
Workflows and activities are run according to the rules you define, offering [Graph-Oriented](https://github.com/hotmeshio/sdk-typescript/tree/main/docs/system_lifecycle.md#telemetry) telemetry insights into your legacy function executions.
|
|
289
289
|
|
|
290
290
|
## FAQ
|
|
291
|
-
Refer to the [FAQ](https://github.com/hotmeshio/sdk-typescript/
|
|
291
|
+
Refer to the [FAQ](https://github.com/hotmeshio/sdk-typescript/tree/main/docs/faq.md) for terminology, definitions, and an exploration of how HotMesh facilitates orchestration use cases.
|
|
292
292
|
|
|
293
293
|
## Quick Start
|
|
294
|
-
Refer to the [Quick Start](https://github.com/hotmeshio/sdk-typescript/
|
|
294
|
+
Refer to the [Quick Start](https://github.com/hotmeshio/sdk-typescript/tree/main/docs/quickstart.md) for sample flows you can easily copy, paste, and modify to get started.
|
|
295
295
|
|
|
296
296
|
## Developer Guide
|
|
297
|
-
For more details on the complete development process, including information about schemas, APIs, and deployment, consult the [Developer Guide](https://github.com/hotmeshio/sdk-typescript/
|
|
297
|
+
For more details on the complete development process, including information about schemas, APIs, and deployment, consult the [Developer Guide](https://github.com/hotmeshio/sdk-typescript/tree/main/docs/developer_guide.md).
|
|
298
298
|
|
|
299
299
|
## Model Driven Development
|
|
300
|
-
[Model Driven Development](https://github.com/hotmeshio/sdk-typescript/
|
|
300
|
+
[Model Driven Development](https://github.com/hotmeshio/sdk-typescript/tree/main/docs/model_driven_development.md) is an established strategy for managing process-oriented tasks. Check out this guide to understand its foundational principles.
|
|
301
301
|
|
|
302
302
|
## Data Mapping
|
|
303
|
-
Exchanging data between activities is central to HotMesh. For detailed information on supported functions and the functional mapping syntax (@pipes), see the [Data Mapping Overview](https://github.com/hotmeshio/sdk-typescript/
|
|
303
|
+
Exchanging data between activities is central to HotMesh. For detailed information on supported functions and the functional mapping syntax (@pipes), see the [Data Mapping Overview](https://github.com/hotmeshio/sdk-typescript/tree/main/docs/data_mapping.md).
|
|
304
304
|
|
|
305
305
|
## Composition
|
|
306
|
-
While the simplest graphs are linear, detailing a consistent sequence of non-cyclical activities, graphs can be layered to represent intricate business scenarios. Some can even be designed to accommodate long-lasting workflows that span months. For more details, check out the [Composable Workflow Guide](https://github.com/hotmeshio/sdk-typescript/
|
|
306
|
+
While the simplest graphs are linear, detailing a consistent sequence of non-cyclical activities, graphs can be layered to represent intricate business scenarios. Some can even be designed to accommodate long-lasting workflows that span months. For more details, check out the [Composable Workflow Guide](https://github.com/hotmeshio/sdk-typescript/tree/main/docs/composable_workflow.md).
|
|
307
307
|
|
|
308
308
|
## Distributed Orchestration
|
|
309
|
-
HotMesh is a distributed orchestration engine. Refer to the [Distributed Orchestration Guide](https://github.com/hotmeshio/sdk-typescript/
|
|
309
|
+
HotMesh is a distributed orchestration engine. Refer to the [Distributed Orchestration Guide](https://github.com/hotmeshio/sdk-typescript/tree/main/docs/distributed_orchestration.md) for a detailed breakdown of the approach.
|
|
310
310
|
|
|
311
311
|
## System Lifecycle
|
|
312
|
-
Gain insight into HotMesh's monitoring, exception handling, and alarm configurations via the [System Lifecycle Guide](https://github.com/hotmeshio/sdk-typescript/
|
|
312
|
+
Gain insight into HotMesh's monitoring, exception handling, and alarm configurations via the [System Lifecycle Guide](https://github.com/hotmeshio/sdk-typescript/tree/main/docs/system_lifecycle.md).
|
|
313
313
|
|
|
314
314
|
## Alpha Release
|
|
315
|
-
So what exacty is an [alpha release](https://github.com/hotmeshio/sdk-typescript/
|
|
315
|
+
So what exacty is an [alpha release](https://github.com/hotmeshio/sdk-typescript/tree/main/docs/alpha.md)?
|
package/build/modules/enums.d.ts
CHANGED
package/build/modules/enums.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DURABLE_EXPIRE_SECONDS = exports.FIDELITY_SECONDS = exports.TEST_FIDELITY_SECONDS = exports.BASE_FIDELITY_SECONDS = exports.EXPIRE_DURATION = exports.STATUS_MESSAGE_UNKNOWN = exports.STATUS_CODE_UNKNOWN = exports.STATUS_CODE_UNACKED = exports.XPENDING_COUNT = exports.XCLAIM_COUNT = exports.XCLAIM_DELAY_MS = exports.BLOCK_TIME_MS = exports.TEST_BLOCK_DURATION = exports.BLOCK_DURATION = exports.GRADUATED_INTERVAL_MS = exports.MAX_TIMEOUT_MS = exports.MAX_RETRIES = exports.OTT_WAIT_TIME = exports.STATUS_CODE_INTERRUPT = exports.STATUS_CODE_TIMEOUT = exports.STATUS_CODE_PENDING = exports.STATUS_CODE_SUCCESS = void 0;
|
|
3
|
+
exports.SCOUT_INTERVAL_SECONDS = exports.DURABLE_EXPIRE_SECONDS = exports.FIDELITY_SECONDS = exports.TEST_FIDELITY_SECONDS = exports.BASE_FIDELITY_SECONDS = exports.EXPIRE_DURATION = exports.STATUS_MESSAGE_UNKNOWN = exports.STATUS_CODE_UNKNOWN = exports.STATUS_CODE_UNACKED = exports.XPENDING_COUNT = exports.XCLAIM_COUNT = exports.XCLAIM_DELAY_MS = exports.BLOCK_TIME_MS = exports.TEST_BLOCK_DURATION = exports.BLOCK_DURATION = exports.GRADUATED_INTERVAL_MS = exports.MAX_TIMEOUT_MS = exports.MAX_RETRIES = exports.OTT_WAIT_TIME = exports.STATUS_CODE_INTERRUPT = exports.STATUS_CODE_TIMEOUT = exports.STATUS_CODE_PENDING = exports.STATUS_CODE_SUCCESS = void 0;
|
|
4
4
|
// Engine Constants
|
|
5
5
|
exports.STATUS_CODE_SUCCESS = 200;
|
|
6
6
|
exports.STATUS_CODE_PENDING = 202;
|
|
@@ -27,3 +27,5 @@ exports.TEST_FIDELITY_SECONDS = 5;
|
|
|
27
27
|
exports.FIDELITY_SECONDS = process.env.NODE_ENV === 'test' ? exports.TEST_FIDELITY_SECONDS : exports.BASE_FIDELITY_SECONDS;
|
|
28
28
|
// DURABLE CONSTANTS
|
|
29
29
|
exports.DURABLE_EXPIRE_SECONDS = 1;
|
|
30
|
+
// TASK CONSTANTS
|
|
31
|
+
exports.SCOUT_INTERVAL_SECONDS = 60;
|
|
@@ -68,6 +68,14 @@ declare class InactiveJobError extends Error {
|
|
|
68
68
|
status: number;
|
|
69
69
|
constructor(jobId: string, status: number, activityId: string);
|
|
70
70
|
}
|
|
71
|
+
declare class GenerationalError extends Error {
|
|
72
|
+
expected: string;
|
|
73
|
+
actual: string;
|
|
74
|
+
jobId: string;
|
|
75
|
+
activityId: string;
|
|
76
|
+
dimensionalAddress: string;
|
|
77
|
+
constructor(expected: string, actual: string, jobId: string, activityId: string, dimensionalAddress: string);
|
|
78
|
+
}
|
|
71
79
|
declare class ExecActivityError extends Error {
|
|
72
80
|
constructor();
|
|
73
81
|
}
|
|
@@ -78,4 +86,4 @@ declare class CollationError extends Error {
|
|
|
78
86
|
fault: CollationFaultType;
|
|
79
87
|
constructor(status: number, leg: ActivityDuplex, stage: CollationStage, fault?: CollationFaultType);
|
|
80
88
|
}
|
|
81
|
-
export { CollationError, DurableFatalError, DurableIncompleteSignalError, DurableMaxedError, DurableRetryError, DurableSleepError, DurableSleepForError, DurableTimeoutError, DurableWaitForSignalError, DuplicateJobError, ExecActivityError, GetStateError, InactiveJobError, MapDataError, RegisterTimeoutError, SetStateError, };
|
|
89
|
+
export { CollationError, DurableFatalError, DurableIncompleteSignalError, DurableMaxedError, DurableRetryError, DurableSleepError, DurableSleepForError, DurableTimeoutError, DurableWaitForSignalError, DuplicateJobError, ExecActivityError, GenerationalError, GetStateError, InactiveJobError, MapDataError, RegisterTimeoutError, SetStateError, };
|
package/build/modules/errors.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SetStateError = exports.RegisterTimeoutError = exports.MapDataError = exports.InactiveJobError = exports.GetStateError = exports.ExecActivityError = exports.DuplicateJobError = exports.DurableWaitForSignalError = exports.DurableTimeoutError = exports.DurableSleepForError = exports.DurableSleepError = exports.DurableRetryError = exports.DurableMaxedError = exports.DurableIncompleteSignalError = exports.DurableFatalError = exports.CollationError = void 0;
|
|
3
|
+
exports.SetStateError = exports.RegisterTimeoutError = exports.MapDataError = exports.InactiveJobError = exports.GetStateError = exports.GenerationalError = exports.ExecActivityError = exports.DuplicateJobError = exports.DurableWaitForSignalError = exports.DurableTimeoutError = exports.DurableSleepForError = exports.DurableSleepError = exports.DurableRetryError = exports.DurableMaxedError = exports.DurableIncompleteSignalError = exports.DurableFatalError = exports.CollationError = void 0;
|
|
4
4
|
class GetStateError extends Error {
|
|
5
5
|
constructor(jobId) {
|
|
6
6
|
super(`${jobId} Not Found`);
|
|
@@ -110,6 +110,17 @@ class InactiveJobError extends Error {
|
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
exports.InactiveJobError = InactiveJobError;
|
|
113
|
+
class GenerationalError extends Error {
|
|
114
|
+
constructor(expected, actual, jobId, activityId, dimensionalAddress) {
|
|
115
|
+
super("Generational Error");
|
|
116
|
+
this.expected = expected;
|
|
117
|
+
this.actual = actual;
|
|
118
|
+
this.jobId = jobId;
|
|
119
|
+
this.activityId = activityId;
|
|
120
|
+
this.dimensionalAddress = dimensionalAddress;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
exports.GenerationalError = GenerationalError;
|
|
113
124
|
class ExecActivityError extends Error {
|
|
114
125
|
constructor() {
|
|
115
126
|
super("Error occurred while executing activity");
|
package/build/modules/key.d.ts
CHANGED
|
@@ -27,25 +27,25 @@
|
|
|
27
27
|
*/
|
|
28
28
|
declare const HMNS = "hmsh";
|
|
29
29
|
declare enum KeyType {
|
|
30
|
-
APP =
|
|
31
|
-
ENGINE_ID =
|
|
32
|
-
HOOKS =
|
|
33
|
-
JOB_DEPENDENTS =
|
|
34
|
-
JOB_STATE =
|
|
35
|
-
JOB_STATS_GENERAL =
|
|
36
|
-
JOB_STATS_MEDIAN =
|
|
37
|
-
JOB_STATS_INDEX =
|
|
38
|
-
HOTMESH =
|
|
39
|
-
QUORUM =
|
|
40
|
-
SCHEMAS =
|
|
41
|
-
SIGNALS =
|
|
42
|
-
STREAMS =
|
|
43
|
-
SUBSCRIPTIONS =
|
|
44
|
-
SUBSCRIPTION_PATTERNS =
|
|
45
|
-
SYMKEYS =
|
|
46
|
-
SYMVALS =
|
|
47
|
-
TIME_RANGE =
|
|
48
|
-
WORK_ITEMS =
|
|
30
|
+
APP = "APP",
|
|
31
|
+
ENGINE_ID = "ENGINE",
|
|
32
|
+
HOOKS = "HOOKS",
|
|
33
|
+
JOB_DEPENDENTS = "JOB_DEPENDENTS",
|
|
34
|
+
JOB_STATE = "JOB_STATE",
|
|
35
|
+
JOB_STATS_GENERAL = "JOB_STATS_GENERAL",
|
|
36
|
+
JOB_STATS_MEDIAN = "JOB_STATS_MEDIAN",
|
|
37
|
+
JOB_STATS_INDEX = "JOB_STATS_INDEX",
|
|
38
|
+
HOTMESH = "HOTMESH",
|
|
39
|
+
QUORUM = "QUORUM",
|
|
40
|
+
SCHEMAS = "SCHEMAS",
|
|
41
|
+
SIGNALS = "SIGNALS",
|
|
42
|
+
STREAMS = "STREAMS",
|
|
43
|
+
SUBSCRIPTIONS = "SUBSCRIPTIONS",
|
|
44
|
+
SUBSCRIPTION_PATTERNS = "SUBSCRIPTION_PATTERNS",
|
|
45
|
+
SYMKEYS = "SYMKEYS",
|
|
46
|
+
SYMVALS = "SYMVALS",
|
|
47
|
+
TIME_RANGE = "TIME_RANGE",
|
|
48
|
+
WORK_ITEMS = "WORK_ITEMS"
|
|
49
49
|
}
|
|
50
50
|
type KeyStoreParams = {
|
|
51
51
|
appId?: string;
|
|
@@ -58,6 +58,7 @@ type KeyStoreParams = {
|
|
|
58
58
|
facet?: string;
|
|
59
59
|
topic?: string;
|
|
60
60
|
timeValue?: number;
|
|
61
|
+
scoutType?: 'signal' | 'time';
|
|
61
62
|
};
|
|
62
63
|
declare class KeyService {
|
|
63
64
|
/**
|
package/build/modules/key.js
CHANGED
|
@@ -34,25 +34,25 @@ exports.HMNS = HMNS;
|
|
|
34
34
|
//these are the entity types that are stored in the key/value store
|
|
35
35
|
var KeyType;
|
|
36
36
|
(function (KeyType) {
|
|
37
|
-
KeyType[
|
|
38
|
-
KeyType[
|
|
39
|
-
KeyType[
|
|
40
|
-
KeyType[
|
|
41
|
-
KeyType[
|
|
42
|
-
KeyType[
|
|
43
|
-
KeyType[
|
|
44
|
-
KeyType[
|
|
45
|
-
KeyType[
|
|
46
|
-
KeyType[
|
|
47
|
-
KeyType[
|
|
48
|
-
KeyType[
|
|
49
|
-
KeyType[
|
|
50
|
-
KeyType[
|
|
51
|
-
KeyType[
|
|
52
|
-
KeyType[
|
|
53
|
-
KeyType[
|
|
54
|
-
KeyType[
|
|
55
|
-
KeyType[
|
|
37
|
+
KeyType["APP"] = "APP";
|
|
38
|
+
KeyType["ENGINE_ID"] = "ENGINE";
|
|
39
|
+
KeyType["HOOKS"] = "HOOKS";
|
|
40
|
+
KeyType["JOB_DEPENDENTS"] = "JOB_DEPENDENTS";
|
|
41
|
+
KeyType["JOB_STATE"] = "JOB_STATE";
|
|
42
|
+
KeyType["JOB_STATS_GENERAL"] = "JOB_STATS_GENERAL";
|
|
43
|
+
KeyType["JOB_STATS_MEDIAN"] = "JOB_STATS_MEDIAN";
|
|
44
|
+
KeyType["JOB_STATS_INDEX"] = "JOB_STATS_INDEX";
|
|
45
|
+
KeyType["HOTMESH"] = "HOTMESH";
|
|
46
|
+
KeyType["QUORUM"] = "QUORUM";
|
|
47
|
+
KeyType["SCHEMAS"] = "SCHEMAS";
|
|
48
|
+
KeyType["SIGNALS"] = "SIGNALS";
|
|
49
|
+
KeyType["STREAMS"] = "STREAMS";
|
|
50
|
+
KeyType["SUBSCRIPTIONS"] = "SUBSCRIPTIONS";
|
|
51
|
+
KeyType["SUBSCRIPTION_PATTERNS"] = "SUBSCRIPTION_PATTERNS";
|
|
52
|
+
KeyType["SYMKEYS"] = "SYMKEYS";
|
|
53
|
+
KeyType["SYMVALS"] = "SYMVALS";
|
|
54
|
+
KeyType["TIME_RANGE"] = "TIME_RANGE";
|
|
55
|
+
KeyType["WORK_ITEMS"] = "WORK_ITEMS";
|
|
56
56
|
})(KeyType || (KeyType = {}));
|
|
57
57
|
exports.KeyType = KeyType;
|
|
58
58
|
class KeyService {
|
|
@@ -74,7 +74,7 @@ class KeyService {
|
|
|
74
74
|
case KeyType.ENGINE_ID:
|
|
75
75
|
return `${namespace}:${params.appId}:e:${params.engineId}`;
|
|
76
76
|
case KeyType.WORK_ITEMS:
|
|
77
|
-
return `${namespace}:${params.appId}:w
|
|
77
|
+
return `${namespace}:${params.appId}:w:${params.scoutType || ''}`;
|
|
78
78
|
case KeyType.TIME_RANGE:
|
|
79
79
|
return `${namespace}:${params.appId}:t:${params.timeValue || ''}`;
|
|
80
80
|
case KeyType.APP:
|
package/build/package.json
CHANGED
|
@@ -26,6 +26,11 @@ 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
|
+
* Upon entering leg 1 of a duplexed activty, verify
|
|
31
|
+
* all aspects of the entry including job and activty state
|
|
32
|
+
*/
|
|
33
|
+
verifyEntry(): Promise<void>;
|
|
29
34
|
processEvent(status?: StreamStatus, code?: StreamCode, type?: 'hook' | 'output'): Promise<void>;
|
|
30
35
|
processPending(telemetry: TelemetryService, type: 'hook' | 'output'): Promise<MultiResponseFlags>;
|
|
31
36
|
processSuccess(telemetry: TelemetryService, type: 'hook' | 'output'): Promise<MultiResponseFlags>;
|
|
@@ -50,6 +55,11 @@ declare class Activity {
|
|
|
50
55
|
bindJobMetadataPaths(): string[];
|
|
51
56
|
bindActivityMetadataPaths(): string[];
|
|
52
57
|
getState(): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* if the job is created/deleted/created with the same key,
|
|
60
|
+
* the 'gid' ensures no stale messages enter the stream
|
|
61
|
+
*/
|
|
62
|
+
assertGenerationalId(jobGID: string, msgGID?: string): void;
|
|
53
63
|
initDimensionalAddress(dad: string): void;
|
|
54
64
|
initSelf(context: StringAnyType): JobState;
|
|
55
65
|
initPolicies(context: JobState): void;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Activity = void 0;
|
|
4
|
+
const enums_1 = require("../../modules/enums");
|
|
4
5
|
const errors_1 = require("../../modules/errors");
|
|
5
6
|
const utils_1 = require("../../modules/utils");
|
|
6
7
|
const collator_1 = require("../collator");
|
|
@@ -9,7 +10,6 @@ const pipe_1 = require("../pipe");
|
|
|
9
10
|
const serializer_1 = require("../serializer");
|
|
10
11
|
const telemetry_1 = require("../telemetry");
|
|
11
12
|
const stream_1 = require("../../types/stream");
|
|
12
|
-
const enums_1 = require("../../modules/enums");
|
|
13
13
|
/**
|
|
14
14
|
* The base class for all activities
|
|
15
15
|
*/
|
|
@@ -30,6 +30,16 @@ class Activity {
|
|
|
30
30
|
setLeg(leg) {
|
|
31
31
|
this.leg = leg;
|
|
32
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Upon entering leg 1 of a duplexed activty, verify
|
|
35
|
+
* all aspects of the entry including job and activty state
|
|
36
|
+
*/
|
|
37
|
+
async verifyEntry() {
|
|
38
|
+
this.setLeg(1);
|
|
39
|
+
await this.getState();
|
|
40
|
+
collator_1.CollatorService.assertJobActive(this.context.metadata.js, this.context.metadata.jid, this.metadata.aid);
|
|
41
|
+
await collator_1.CollatorService.notarizeEntry(this);
|
|
42
|
+
}
|
|
33
43
|
//******** DUPLEX RE-ENTRY POINT ********//
|
|
34
44
|
async processEvent(status = stream_1.StreamStatus.SUCCESS, code = 200, type = 'output') {
|
|
35
45
|
this.setLeg(2);
|
|
@@ -77,6 +87,10 @@ class Activity {
|
|
|
77
87
|
this.logger.info('process-event-inactive-job-error', { error });
|
|
78
88
|
return;
|
|
79
89
|
}
|
|
90
|
+
else if (error instanceof errors_1.GenerationalError) {
|
|
91
|
+
this.logger.info('process-event-generational-job-error', { error });
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
80
94
|
else if (error instanceof errors_1.GetStateError) {
|
|
81
95
|
this.logger.info('process-event-get-job-error', { error });
|
|
82
96
|
return;
|
|
@@ -266,7 +280,7 @@ class Activity {
|
|
|
266
280
|
return serializer_1.MDATA_SYMBOLS[keys_to_save].KEYS.map((key) => `output/metadata/${key}`);
|
|
267
281
|
}
|
|
268
282
|
async getState() {
|
|
269
|
-
|
|
283
|
+
const gid = this.context.metadata.gid;
|
|
270
284
|
const jobSymbolHashName = `$${this.config.subscribes}`;
|
|
271
285
|
const consumes = {
|
|
272
286
|
[jobSymbolHashName]: serializer_1.MDATA_SYMBOLS.JOB.KEYS.map((key) => `metadata/${key}`)
|
|
@@ -295,10 +309,20 @@ class Activity {
|
|
|
295
309
|
//`state` is a flat hash; context is a tree
|
|
296
310
|
const [state, status] = await this.store.getState(jid, consumes, dIds);
|
|
297
311
|
this.context = (0, utils_1.restoreHierarchy)(state);
|
|
312
|
+
this.assertGenerationalId(this.context.metadata.gid, gid);
|
|
298
313
|
this.initDimensionalAddress(dad);
|
|
299
314
|
this.initSelf(this.context);
|
|
300
315
|
this.initPolicies(this.context);
|
|
301
316
|
}
|
|
317
|
+
/**
|
|
318
|
+
* if the job is created/deleted/created with the same key,
|
|
319
|
+
* the 'gid' ensures no stale messages enter the stream
|
|
320
|
+
*/
|
|
321
|
+
assertGenerationalId(jobGID, msgGID) {
|
|
322
|
+
if (msgGID !== jobGID) {
|
|
323
|
+
throw new errors_1.GenerationalError(jobGID, msgGID, this.context.metadata.jid, this.context.metadata.aid, this.context.metadata.dad);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
302
326
|
initDimensionalAddress(dad) {
|
|
303
327
|
this.metadata.dad = dad;
|
|
304
328
|
}
|
|
@@ -355,6 +379,7 @@ class Activity {
|
|
|
355
379
|
metadata: {
|
|
356
380
|
guid: (0, utils_1.guid)(),
|
|
357
381
|
jid: this.context.metadata.jid,
|
|
382
|
+
gid: this.context.metadata.gid,
|
|
358
383
|
dad: adjacentDad,
|
|
359
384
|
aid: toActivityId,
|
|
360
385
|
spn: this.context['$self'].output.metadata?.l2s,
|
|
@@ -383,7 +408,7 @@ class Activity {
|
|
|
383
408
|
if (adjacencyList.length && jobStatus > 0) {
|
|
384
409
|
const multi = this.store.getMulti();
|
|
385
410
|
for (const execSignal of adjacencyList) {
|
|
386
|
-
await this.engine.
|
|
411
|
+
await this.engine.router?.publishMessage(null, execSignal, multi);
|
|
387
412
|
}
|
|
388
413
|
mIds = (await multi.exec());
|
|
389
414
|
}
|
|
@@ -4,8 +4,8 @@ exports.Await = void 0;
|
|
|
4
4
|
const errors_1 = require("../../modules/errors");
|
|
5
5
|
const activity_1 = require("./activity");
|
|
6
6
|
const collator_1 = require("../collator");
|
|
7
|
-
const stream_1 = require("../../types/stream");
|
|
8
7
|
const telemetry_1 = require("../telemetry");
|
|
8
|
+
const stream_1 = require("../../types/stream");
|
|
9
9
|
const pipe_1 = require("../pipe");
|
|
10
10
|
const utils_1 = require("../../modules/utils");
|
|
11
11
|
class Await extends activity_1.Activity {
|
|
@@ -14,14 +14,10 @@ class Await extends activity_1.Activity {
|
|
|
14
14
|
}
|
|
15
15
|
//******** INITIAL ENTRY POINT (A) ********//
|
|
16
16
|
async process() {
|
|
17
|
-
this.logger.debug('await-process', { jid: this.context.metadata.jid, aid: this.metadata.aid });
|
|
17
|
+
this.logger.debug('await-process', { jid: this.context.metadata.jid, gid: this.context.metadata.gid, aid: this.metadata.aid });
|
|
18
18
|
let telemetry;
|
|
19
19
|
try {
|
|
20
|
-
|
|
21
|
-
this.setLeg(1);
|
|
22
|
-
await collator_1.CollatorService.notarizeEntry(this);
|
|
23
|
-
await this.getState();
|
|
24
|
-
collator_1.CollatorService.assertJobActive(this.context.metadata.js, this.context.metadata.jid, this.metadata.aid);
|
|
20
|
+
await this.verifyEntry();
|
|
25
21
|
telemetry = new telemetry_1.TelemetryService(this.engine.appId, this.config, this.metadata, this.context);
|
|
26
22
|
telemetry.startActivitySpan(this.leg);
|
|
27
23
|
this.mapInputData();
|
|
@@ -47,6 +43,10 @@ class Await extends activity_1.Activity {
|
|
|
47
43
|
this.logger.error('await-inactive-job-error', { error });
|
|
48
44
|
return;
|
|
49
45
|
}
|
|
46
|
+
else if (error instanceof errors_1.GenerationalError) {
|
|
47
|
+
this.logger.info('process-event-generational-job-error', { error });
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
50
|
else if (error instanceof errors_1.GetStateError) {
|
|
51
51
|
this.logger.error('await-get-state-error', { error });
|
|
52
52
|
return;
|
|
@@ -59,7 +59,7 @@ class Await extends activity_1.Activity {
|
|
|
59
59
|
}
|
|
60
60
|
finally {
|
|
61
61
|
telemetry?.endActivitySpan();
|
|
62
|
-
this.logger.debug('await-process-end', { jid: this.context.metadata.jid, aid: this.metadata.aid });
|
|
62
|
+
this.logger.debug('await-process-end', { jid: this.context.metadata.jid, gid: this.context.metadata.gid, aid: this.metadata.aid });
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
async execActivity(multi) {
|
|
@@ -68,6 +68,7 @@ class Await extends activity_1.Activity {
|
|
|
68
68
|
metadata: {
|
|
69
69
|
guid: (0, utils_1.guid)(),
|
|
70
70
|
jid: this.context.metadata.jid,
|
|
71
|
+
gid: this.context.metadata.gid,
|
|
71
72
|
dad: this.metadata.dad,
|
|
72
73
|
aid: this.metadata.aid,
|
|
73
74
|
topic,
|
|
@@ -82,7 +83,7 @@ class Await extends activity_1.Activity {
|
|
|
82
83
|
retry: this.config.retry
|
|
83
84
|
};
|
|
84
85
|
}
|
|
85
|
-
return (await this.engine.
|
|
86
|
+
return (await this.engine.router?.publishMessage(null, streamData, multi));
|
|
86
87
|
}
|
|
87
88
|
}
|
|
88
89
|
exports.Await = Await;
|
|
@@ -12,14 +12,10 @@ class Cycle extends activity_1.Activity {
|
|
|
12
12
|
}
|
|
13
13
|
//******** LEG 1 ENTRY ********//
|
|
14
14
|
async process() {
|
|
15
|
-
this.logger.debug('cycle-process', { jid: this.context.metadata.jid, aid: this.metadata.aid });
|
|
15
|
+
this.logger.debug('cycle-process', { jid: this.context.metadata.jid, gid: this.context.metadata.gid, aid: this.metadata.aid });
|
|
16
16
|
let telemetry;
|
|
17
17
|
try {
|
|
18
|
-
|
|
19
|
-
this.setLeg(1);
|
|
20
|
-
await collator_1.CollatorService.notarizeEntry(this);
|
|
21
|
-
await this.getState();
|
|
22
|
-
collator_1.CollatorService.assertJobActive(this.context.metadata.js, this.context.metadata.jid, this.metadata.aid);
|
|
18
|
+
await this.verifyEntry();
|
|
23
19
|
telemetry = new telemetry_1.TelemetryService(this.engine.appId, this.config, this.metadata, this.context);
|
|
24
20
|
telemetry.startActivitySpan(this.leg);
|
|
25
21
|
this.mapInputData();
|
|
@@ -47,6 +43,10 @@ class Cycle extends activity_1.Activity {
|
|
|
47
43
|
this.logger.error('cycle-inactive-job-error', { error });
|
|
48
44
|
return;
|
|
49
45
|
}
|
|
46
|
+
else if (error instanceof errors_1.GenerationalError) {
|
|
47
|
+
this.logger.info('process-event-generational-job-error', { error });
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
50
|
else if (error instanceof errors_1.GetStateError) {
|
|
51
51
|
this.logger.error('cycle-get-state-error', { error });
|
|
52
52
|
return;
|
|
@@ -59,7 +59,7 @@ class Cycle extends activity_1.Activity {
|
|
|
59
59
|
}
|
|
60
60
|
finally {
|
|
61
61
|
telemetry?.endActivitySpan();
|
|
62
|
-
this.logger.debug('cycle-process-end', { jid: this.context.metadata.jid, aid: this.metadata.aid });
|
|
62
|
+
this.logger.debug('cycle-process-end', { jid: this.context.metadata.jid, gid: this.context.metadata.gid, aid: this.metadata.aid });
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
/**
|
|
@@ -78,15 +78,16 @@ class Cycle extends activity_1.Activity {
|
|
|
78
78
|
const streamData = {
|
|
79
79
|
metadata: {
|
|
80
80
|
guid: (0, utils_1.guid)(),
|
|
81
|
-
dad: collator_1.CollatorService.resolveReentryDimension(this),
|
|
82
81
|
jid: this.context.metadata.jid,
|
|
82
|
+
gid: this.context.metadata.gid,
|
|
83
|
+
dad: collator_1.CollatorService.resolveReentryDimension(this),
|
|
83
84
|
aid: this.config.ancestor,
|
|
84
85
|
spn: this.context['$self'].output.metadata?.l1s,
|
|
85
86
|
trc: this.context.metadata.trc,
|
|
86
87
|
},
|
|
87
88
|
data: this.context.data
|
|
88
89
|
};
|
|
89
|
-
return (await this.engine.
|
|
90
|
+
return (await this.engine.router?.publishMessage(null, streamData, multi));
|
|
90
91
|
}
|
|
91
92
|
}
|
|
92
93
|
exports.Cycle = Cycle;
|
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
import { Activity } from './activity';
|
|
2
2
|
import { EngineService } from '../engine';
|
|
3
|
+
import { TelemetryService } from '../telemetry';
|
|
3
4
|
import { ActivityData, ActivityMetadata, ActivityType, HookActivity } from '../../types/activity';
|
|
4
5
|
import { HookRule } from '../../types/hook';
|
|
5
6
|
import { JobState, JobStatus } from '../../types/job';
|
|
6
7
|
import { RedisMulti } from '../../types/redis';
|
|
7
8
|
import { StreamCode, StreamStatus } from '../../types/stream';
|
|
8
9
|
/**
|
|
9
|
-
*
|
|
10
|
+
* Supports `signal hook`, `time hook`, and `cycle hook` patterns
|
|
10
11
|
*/
|
|
11
12
|
declare class Hook extends Activity {
|
|
12
13
|
config: HookActivity;
|
|
13
14
|
constructor(config: ActivityType, data: ActivityData, metadata: ActivityMetadata, hook: ActivityData | null, engine: EngineService, context?: JobState);
|
|
14
15
|
process(): Promise<string>;
|
|
16
|
+
/**
|
|
17
|
+
* does this activity use a time-hook or web-hook
|
|
18
|
+
*/
|
|
15
19
|
doesHook(): boolean;
|
|
20
|
+
doHook(telemetry: TelemetryService): Promise<void>;
|
|
21
|
+
doPassThrough(telemetry: TelemetryService): Promise<void>;
|
|
16
22
|
getHookRule(topic: string): Promise<HookRule | undefined>;
|
|
17
23
|
registerHook(multi?: RedisMulti): Promise<string | void>;
|
|
18
24
|
processWebHookEvent(status?: StreamStatus, code?: StreamCode): Promise<JobStatus | void>;
|