@hotmeshio/hotmesh 0.0.54 → 0.0.56
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 +0 -3
- package/build/modules/enums.js +1 -10
- package/build/modules/key.d.ts +0 -38
- package/build/modules/key.js +4 -46
- package/build/modules/utils.d.ts +0 -8
- package/build/modules/utils.js +0 -14
- package/build/package.json +11 -4
- package/build/services/activities/activity.d.ts +0 -28
- package/build/services/activities/activity.js +1 -46
- package/build/services/activities/await.js +0 -4
- package/build/services/activities/cycle.d.ts +0 -7
- package/build/services/activities/cycle.js +1 -16
- package/build/services/activities/hook.d.ts +0 -6
- package/build/services/activities/hook.js +2 -12
- package/build/services/activities/interrupt.js +0 -8
- package/build/services/activities/signal.d.ts +0 -6
- package/build/services/activities/signal.js +0 -15
- package/build/services/activities/trigger.d.ts +0 -4
- package/build/services/activities/trigger.js +1 -7
- package/build/services/activities/worker.js +0 -4
- package/build/services/collator/index.d.ts +0 -70
- package/build/services/collator/index.js +1 -91
- package/build/services/compiler/deployer.js +6 -38
- package/build/services/compiler/index.d.ts +0 -15
- package/build/services/compiler/index.js +0 -20
- package/build/services/compiler/validator.d.ts +0 -3
- package/build/services/compiler/validator.js +0 -25
- package/build/services/connector/clients/ioredis.d.ts +2 -2
- package/build/services/connector/clients/ioredis.js +0 -2
- package/build/services/connector/clients/redis.d.ts +4 -4
- package/build/services/connector/clients/redis.js +1 -3
- package/build/services/connector/index.d.ts +1 -1
- package/build/services/connector/index.js +0 -2
- package/build/services/durable/client.d.ts +1 -26
- package/build/services/durable/client.js +0 -56
- package/build/services/durable/exporter.d.ts +0 -22
- package/build/services/durable/exporter.js +1 -30
- package/build/services/durable/handle.d.ts +0 -36
- package/build/services/durable/handle.js +0 -46
- package/build/services/durable/index.d.ts +0 -4
- package/build/services/durable/index.js +0 -4
- package/build/services/durable/schemas/factory.d.ts +0 -29
- package/build/services/durable/schemas/factory.js +0 -29
- package/build/services/durable/search.d.ts +1 -36
- package/build/services/durable/search.js +57 -56
- package/build/services/durable/worker.js +2 -22
- package/build/services/durable/workflow.d.ts +0 -114
- package/build/services/durable/workflow.js +4 -144
- package/build/services/engine/index.d.ts +1 -6
- package/build/services/engine/index.js +1 -43
- package/build/services/exporter/index.d.ts +0 -27
- package/build/services/exporter/index.js +0 -33
- package/build/services/hotmesh/index.d.ts +2 -2
- package/build/services/hotmesh/index.js +1 -9
- package/build/services/logger/index.js +0 -2
- package/build/services/mapper/index.d.ts +0 -14
- package/build/services/mapper/index.js +0 -14
- package/build/services/pipe/functions/date.d.ts +0 -7
- package/build/services/pipe/functions/date.js +0 -7
- package/build/services/pipe/functions/math.js +0 -2
- package/build/services/pipe/index.d.ts +0 -15
- package/build/services/pipe/index.js +2 -23
- package/build/services/quorum/index.d.ts +0 -7
- package/build/services/quorum/index.js +0 -21
- package/build/services/reporter/index.d.ts +0 -5
- package/build/services/reporter/index.js +0 -9
- package/build/services/router/index.d.ts +0 -9
- package/build/services/router/index.js +2 -38
- package/build/services/serializer/index.js +7 -26
- package/build/services/store/cache.d.ts +0 -18
- package/build/services/store/cache.js +0 -18
- package/build/services/store/clients/ioredis.d.ts +1 -1
- package/build/services/store/clients/ioredis.js +0 -1
- package/build/services/store/clients/redis.d.ts +1 -1
- package/build/services/store/index.d.ts +0 -55
- package/build/services/store/index.js +5 -81
- package/build/services/stream/clients/ioredis.d.ts +1 -1
- package/build/services/stream/clients/ioredis.js +1 -4
- package/build/services/stream/clients/redis.d.ts +1 -1
- package/build/services/sub/clients/ioredis.d.ts +1 -1
- package/build/services/sub/clients/redis.d.ts +1 -1
- package/build/services/task/index.d.ts +0 -9
- package/build/services/task/index.js +0 -31
- package/build/services/telemetry/index.d.ts +0 -7
- package/build/services/telemetry/index.js +1 -13
- package/build/services/worker/index.d.ts +0 -4
- package/build/services/worker/index.js +2 -6
- package/build/types/activity.d.ts +0 -81
- package/build/types/durable.d.ts +25 -177
- package/build/types/exporter.d.ts +0 -13
- package/build/types/hotmesh.d.ts +4 -16
- package/build/types/hotmesh.js +0 -3
- package/build/types/index.d.ts +4 -6
- package/build/types/index.js +4 -3
- package/build/types/job.d.ts +1 -86
- package/build/types/pipe.d.ts +0 -65
- package/build/types/quorum.d.ts +15 -10
- package/build/types/redis.d.ts +225 -7
- package/build/types/redis.js +9 -0
- package/build/types/stream.d.ts +0 -58
- package/build/types/stream.js +0 -4
- package/package.json +11 -4
- package/types/durable.ts +121 -3
- package/types/hotmesh.ts +3 -6
- package/types/index.ts +23 -10
- package/types/job.ts +1 -1
- package/types/quorum.ts +22 -0
- package/types/redis.ts +267 -18
- package/build/types/ioredisclient.d.ts +0 -5
- package/build/types/ioredisclient.js +0 -5
- package/build/types/redisclient.d.ts +0 -26
- package/build/types/redisclient.js +0 -2
- package/modules/enums.ts +0 -62
- package/modules/errors.ts +0 -280
- package/modules/key.ts +0 -101
- package/modules/storage.ts +0 -3
- package/modules/utils.ts +0 -242
- package/services/activities/activity.ts +0 -589
- package/services/activities/await.ts +0 -113
- package/services/activities/cycle.ts +0 -115
- package/services/activities/hook.ts +0 -197
- package/services/activities/index.ts +0 -19
- package/services/activities/interrupt.ts +0 -172
- package/services/activities/signal.ts +0 -148
- package/services/activities/trigger.ts +0 -295
- package/services/activities/worker.ts +0 -107
- package/services/collator/README.md +0 -102
- package/services/collator/index.ts +0 -291
- package/services/compiler/deployer.ts +0 -504
- package/services/compiler/index.ts +0 -98
- package/services/compiler/validator.ts +0 -158
- package/services/connector/clients/ioredis.ts +0 -57
- package/services/connector/clients/redis.ts +0 -72
- package/services/connector/index.ts +0 -42
- package/services/durable/client.ts +0 -266
- package/services/durable/connection.ts +0 -10
- package/services/durable/exporter.ts +0 -232
- package/services/durable/handle.ts +0 -160
- package/services/durable/index.ts +0 -27
- package/services/durable/schemas/factory.ts +0 -2358
- package/services/durable/search.ts +0 -196
- package/services/durable/worker.ts +0 -401
- package/services/durable/workflow.ts +0 -557
- package/services/engine/index.ts +0 -761
- package/services/exporter/index.ts +0 -146
- package/services/hotmesh/index.ts +0 -237
- package/services/logger/index.ts +0 -79
- package/services/mapper/index.ts +0 -89
- package/services/pipe/functions/array.ts +0 -78
- package/services/pipe/functions/bitwise.ts +0 -27
- package/services/pipe/functions/conditional.ts +0 -35
- package/services/pipe/functions/date.ts +0 -220
- package/services/pipe/functions/index.ts +0 -27
- package/services/pipe/functions/json.ts +0 -11
- package/services/pipe/functions/logical.ts +0 -11
- package/services/pipe/functions/math.ts +0 -217
- package/services/pipe/functions/number.ts +0 -75
- package/services/pipe/functions/object.ts +0 -98
- package/services/pipe/functions/string.ts +0 -86
- package/services/pipe/functions/symbol.ts +0 -39
- package/services/pipe/functions/unary.ts +0 -19
- package/services/pipe/index.ts +0 -216
- package/services/quorum/index.ts +0 -319
- package/services/reporter/index.ts +0 -387
- package/services/router/index.ts +0 -426
- package/services/serializer/README.md +0 -10
- package/services/serializer/index.ts +0 -285
- package/services/store/cache.ts +0 -172
- package/services/store/clients/ioredis.ts +0 -145
- package/services/store/clients/redis.ts +0 -191
- package/services/store/index.ts +0 -1091
- package/services/stream/clients/ioredis.ts +0 -157
- package/services/stream/clients/redis.ts +0 -158
- package/services/stream/index.ts +0 -58
- package/services/sub/clients/ioredis.ts +0 -83
- package/services/sub/clients/redis.ts +0 -74
- package/services/sub/index.ts +0 -25
- package/services/task/index.ts +0 -250
- package/services/telemetry/index.ts +0 -273
- package/services/worker/index.ts +0 -248
- package/types/ioredisclient.ts +0 -10
- package/types/redisclient.ts +0 -30
package/README.md
CHANGED
|
@@ -19,9 +19,6 @@ HotMesh inverts the relationship to Redis: those functions that once used Redis
|
|
|
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
|
|
|
22
|
-
<img src="./docs/img/hotmesh_emergent_properties.png" alt="HotMesh elevates Redis to a Service Mesh, Message Router, Integration Bus, and Business Process Engine." style="max-width:100%;width:600px;">
|
|
23
|
-
|
|
24
|
-
|
|
25
22
|
## Design
|
|
26
23
|
HotMesh uses your existing Redis installation. If you already have an instance available, you have all the infrastructure you'll ever need.
|
|
27
24
|
|
package/build/modules/enums.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.HMSH_SCOUT_INTERVAL_SECONDS = exports.HMSH_FIDELITY_SECONDS = exports.HMSH_EXPIRE_DURATION = exports.HMSH_XPENDING_COUNT = exports.HMSH_XCLAIM_COUNT = exports.HMSH_XCLAIM_DELAY_MS = exports.HMSH_BLOCK_TIME_MS = exports.HMSH_DURABLE_EXP_BACKOFF = exports.HMSH_DURABLE_MAX_INTERVAL = exports.HMSH_DURABLE_MAX_ATTEMPTS = exports.HMSH_GRADUATED_INTERVAL_MS = exports.HMSH_MAX_TIMEOUT_MS = exports.HMSH_MAX_RETRIES = exports.HMSH_EXPIRE_JOB_SECONDS = exports.HMSH_OTT_WAIT_TIME = exports.HMSH_ACTIVATION_MAX_RETRY = exports.HMSH_QUORUM_DELAY_MS = exports.HMSH_QUORUM_ROLLCALL_CYCLES = exports.HMSH_STATUS_UNKNOWN = exports.HMSH_CODE_DURABLE_RETRYABLE = exports.HMSH_CODE_DURABLE_FATAL = exports.HMSH_CODE_DURABLE_MAXED = exports.HMSH_CODE_DURABLE_TIMEOUT = exports.HMSH_CODE_DURABLE_WAIT = exports.HMSH_CODE_DURABLE_PROXY = exports.HMSH_CODE_DURABLE_CHILD = exports.HMSH_CODE_DURABLE_ALL = exports.HMSH_CODE_DURABLE_SLEEP = exports.HMSH_CODE_UNACKED = exports.HMSH_CODE_TIMEOUT = exports.HMSH_CODE_UNKNOWN = exports.HMSH_CODE_INTERRUPT = exports.HMSH_CODE_NOTFOUND = exports.HMSH_CODE_PENDING = exports.HMSH_CODE_SUCCESS = exports.HMSH_LOGLEVEL = void 0;
|
|
4
|
-
// HOTMESH SYSTEM
|
|
5
4
|
exports.HMSH_LOGLEVEL = process.env.HMSH_LOGLEVEL || 'info';
|
|
6
|
-
// HOTMESH STATUS CODES
|
|
7
5
|
exports.HMSH_CODE_SUCCESS = 200;
|
|
8
6
|
exports.HMSH_CODE_PENDING = 202;
|
|
9
7
|
exports.HMSH_CODE_NOTFOUND = 404;
|
|
@@ -11,7 +9,6 @@ exports.HMSH_CODE_INTERRUPT = 410;
|
|
|
11
9
|
exports.HMSH_CODE_UNKNOWN = 500;
|
|
12
10
|
exports.HMSH_CODE_TIMEOUT = 504;
|
|
13
11
|
exports.HMSH_CODE_UNACKED = 999;
|
|
14
|
-
// DURABLE STATUS CODES
|
|
15
12
|
exports.HMSH_CODE_DURABLE_SLEEP = 588;
|
|
16
13
|
exports.HMSH_CODE_DURABLE_ALL = 589;
|
|
17
14
|
exports.HMSH_CODE_DURABLE_CHILD = 590;
|
|
@@ -21,20 +18,15 @@ exports.HMSH_CODE_DURABLE_TIMEOUT = 596;
|
|
|
21
18
|
exports.HMSH_CODE_DURABLE_MAXED = 597;
|
|
22
19
|
exports.HMSH_CODE_DURABLE_FATAL = 598;
|
|
23
20
|
exports.HMSH_CODE_DURABLE_RETRYABLE = 599;
|
|
24
|
-
// HOTMESH MESSAGES
|
|
25
21
|
exports.HMSH_STATUS_UNKNOWN = 'unknown';
|
|
26
|
-
|
|
27
|
-
exports.HMSH_QUORUM_ROLLCALL_CYCLES = 12; //max iterations
|
|
22
|
+
exports.HMSH_QUORUM_ROLLCALL_CYCLES = 12;
|
|
28
23
|
exports.HMSH_QUORUM_DELAY_MS = 250;
|
|
29
24
|
exports.HMSH_ACTIVATION_MAX_RETRY = 3;
|
|
30
|
-
// ENGINE
|
|
31
25
|
exports.HMSH_OTT_WAIT_TIME = parseInt(process.env.HMSH_OTT_WAIT_TIME, 10) || 1000;
|
|
32
26
|
exports.HMSH_EXPIRE_JOB_SECONDS = parseInt(process.env.HMSH_EXPIRE_JOB_SECONDS, 10) || 1;
|
|
33
|
-
// STREAM ROUTER
|
|
34
27
|
exports.HMSH_MAX_RETRIES = parseInt(process.env.HMSH_MAX_RETRIES, 10) || 3;
|
|
35
28
|
exports.HMSH_MAX_TIMEOUT_MS = parseInt(process.env.HMSH_MAX_TIMEOUT_MS, 10) || 60000;
|
|
36
29
|
exports.HMSH_GRADUATED_INTERVAL_MS = parseInt(process.env.HMSH_GRADUATED_INTERVAL_MS, 10) || 5000;
|
|
37
|
-
// DURABLE
|
|
38
30
|
exports.HMSH_DURABLE_MAX_ATTEMPTS = 3;
|
|
39
31
|
exports.HMSH_DURABLE_MAX_INTERVAL = '120s';
|
|
40
32
|
exports.HMSH_DURABLE_EXP_BACKOFF = 10;
|
|
@@ -44,7 +36,6 @@ exports.HMSH_BLOCK_TIME_MS = process.env.HMSH_BLOCK_TIME_MS ? parseInt(process.e
|
|
|
44
36
|
exports.HMSH_XCLAIM_DELAY_MS = parseInt(process.env.HMSH_XCLAIM_DELAY_MS, 10) || 1000 * 60;
|
|
45
37
|
exports.HMSH_XCLAIM_COUNT = parseInt(process.env.HMSH_XCLAIM_COUNT, 10) || 3;
|
|
46
38
|
exports.HMSH_XPENDING_COUNT = parseInt(process.env.HMSH_XPENDING_COUNT, 10) || 10;
|
|
47
|
-
// TASK WORKER
|
|
48
39
|
exports.HMSH_EXPIRE_DURATION = parseInt(process.env.HMSH_EXPIRE_DURATION, 10) || 1;
|
|
49
40
|
const BASE_FIDELITY_SECONDS = 5;
|
|
50
41
|
const TEST_FIDELITY_SECONDS = 1;
|
package/build/modules/key.d.ts
CHANGED
|
@@ -1,48 +1,10 @@
|
|
|
1
1
|
import { KeyStoreParams, KeyType } from '../types/hotmesh';
|
|
2
|
-
/**
|
|
3
|
-
* Keys
|
|
4
|
-
*
|
|
5
|
-
* hmsh -> {hash} hotmesh config {version: "0.0.1", namespace: "hmsh"}
|
|
6
|
-
* hmsh:a:<appid> -> {hash} app profile { "id": "appid", "version": "2", "versions/1": "GMT", "versions/2": "GMT"}
|
|
7
|
-
* hmsh:<appid>:e:<engineId> -> {string} setnx to ensure only one engine of given id
|
|
8
|
-
* hmsh:<appid>:w: -> {zset} work items/tasks an engine must do like garbage collect or hook a set of matching records (hookAll)
|
|
9
|
-
* hmsh:<appid>:t: -> {zset} an ordered set of list (work lists) ids
|
|
10
|
-
* hmsh:<appid>:t:<timeValue?> -> {list} a worklist of `jobId+activityId` items that should be awakened
|
|
11
|
-
* hmsh:<appid>:q: -> {hash} quorum-wide messages
|
|
12
|
-
* hmsh:<appid>:q:<ngnid> -> {hash} engine-targeted messages (targeted quorum-oriented message)
|
|
13
|
-
* hmsh:<appid>:j:<jobid> -> {hash} job data
|
|
14
|
-
* hmsh:<appid>:j:<jobid>:<activityid> -> {hash} job activity data (a1)
|
|
15
|
-
* hmsh:<appid>:s:<jobkey>:<dateTime> -> {hash} job stats (general)
|
|
16
|
-
* hmsh:<appid>:s:<jobkey>:<dateTime>:mdn:<field/path>:<fieldvalue> -> {zset} job stats (median)
|
|
17
|
-
* hmsh:<appid>:s:<jobkey>:<dateTime>:index:<field/path>:<fieldvalue> -> {list} job stats (index of jobid[])
|
|
18
|
-
* hmsh:<appid>:v:<version>:activities -> {hash} schemas [cache]
|
|
19
|
-
* hmsh:<appid>:v:<version>:transitions -> {hash} transitions [cache]
|
|
20
|
-
* hmsh:<appid>:v:<version>:subscriptions -> {hash} subscriptions [cache]
|
|
21
|
-
* hmsh:<appid>:x: -> {xstream} when an engine is sent or reads a buffered task (engines read from their custom topic)
|
|
22
|
-
* hmsh:<appid>:x:<topic> -> {xstream} when a worker is sent or reads a buffered task (workers read from their custom topic)
|
|
23
|
-
* hmsh:<appid>:hooks -> {hash} hook patterns/rules; set at compile time
|
|
24
|
-
* hmsh:<appid>:signals -> {hash} dynamic hook signals (hget/hdel) when resolving (always self-clean); added/removed at runtime
|
|
25
|
-
* hmsh:<appid>:sym:keys: -> {hash} list of symbol ranges and :cursor assigned at version deploy time for job keys
|
|
26
|
-
* hmsh:<appid>:sym:keys:<activityid|$subscribes> -> {hash} list of symbols based upon schema enums (initially) and adaptively optimized (later) during runtime; if '$subscribes' is used as the activityid, it is a top-level `job` symbol set (for job keys)
|
|
27
|
-
* hmsh:<appid>:sym:vals: -> {hash} list of symbols for job values across all app versions
|
|
28
|
-
*/
|
|
29
2
|
declare const HMNS = "hmsh";
|
|
30
3
|
declare const KEYSEP = ":";
|
|
31
4
|
declare const VALSEP = "::";
|
|
32
5
|
declare const WEBSEP = "::";
|
|
33
6
|
declare const TYPSEP = "::";
|
|
34
7
|
declare class KeyService {
|
|
35
|
-
/**
|
|
36
|
-
* returns a key that can be used to access a value in the key/value store
|
|
37
|
-
* appropriate for the given key type; the keys have an implicit hierarchy
|
|
38
|
-
* and are used to organize data in the store in a tree-like structure
|
|
39
|
-
* via the use of colons as separators. The top-level entity is the hmsh manifest.
|
|
40
|
-
* This file will reveal the full scope of what is on the server (apps, versions, etc)
|
|
41
|
-
* @param namespace
|
|
42
|
-
* @param keyType
|
|
43
|
-
* @param params
|
|
44
|
-
* @returns {string}
|
|
45
|
-
*/
|
|
46
8
|
static mintKey(namespace: string, keyType: KeyType, params: KeyStoreParams): string;
|
|
47
9
|
}
|
|
48
10
|
export { KeyService, KeyType, KeyStoreParams, HMNS, KEYSEP, TYPSEP, WEBSEP, VALSEP };
|
package/build/modules/key.js
CHANGED
|
@@ -3,55 +3,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.VALSEP = exports.WEBSEP = exports.TYPSEP = exports.KEYSEP = exports.HMNS = exports.KeyType = exports.KeyService = void 0;
|
|
4
4
|
const hotmesh_1 = require("../types/hotmesh");
|
|
5
5
|
Object.defineProperty(exports, "KeyType", { enumerable: true, get: function () { return hotmesh_1.KeyType; } });
|
|
6
|
-
/**
|
|
7
|
-
* Keys
|
|
8
|
-
*
|
|
9
|
-
* hmsh -> {hash} hotmesh config {version: "0.0.1", namespace: "hmsh"}
|
|
10
|
-
* hmsh:a:<appid> -> {hash} app profile { "id": "appid", "version": "2", "versions/1": "GMT", "versions/2": "GMT"}
|
|
11
|
-
* hmsh:<appid>:e:<engineId> -> {string} setnx to ensure only one engine of given id
|
|
12
|
-
* hmsh:<appid>:w: -> {zset} work items/tasks an engine must do like garbage collect or hook a set of matching records (hookAll)
|
|
13
|
-
* hmsh:<appid>:t: -> {zset} an ordered set of list (work lists) ids
|
|
14
|
-
* hmsh:<appid>:t:<timeValue?> -> {list} a worklist of `jobId+activityId` items that should be awakened
|
|
15
|
-
* hmsh:<appid>:q: -> {hash} quorum-wide messages
|
|
16
|
-
* hmsh:<appid>:q:<ngnid> -> {hash} engine-targeted messages (targeted quorum-oriented message)
|
|
17
|
-
* hmsh:<appid>:j:<jobid> -> {hash} job data
|
|
18
|
-
* hmsh:<appid>:j:<jobid>:<activityid> -> {hash} job activity data (a1)
|
|
19
|
-
* hmsh:<appid>:s:<jobkey>:<dateTime> -> {hash} job stats (general)
|
|
20
|
-
* hmsh:<appid>:s:<jobkey>:<dateTime>:mdn:<field/path>:<fieldvalue> -> {zset} job stats (median)
|
|
21
|
-
* hmsh:<appid>:s:<jobkey>:<dateTime>:index:<field/path>:<fieldvalue> -> {list} job stats (index of jobid[])
|
|
22
|
-
* hmsh:<appid>:v:<version>:activities -> {hash} schemas [cache]
|
|
23
|
-
* hmsh:<appid>:v:<version>:transitions -> {hash} transitions [cache]
|
|
24
|
-
* hmsh:<appid>:v:<version>:subscriptions -> {hash} subscriptions [cache]
|
|
25
|
-
* hmsh:<appid>:x: -> {xstream} when an engine is sent or reads a buffered task (engines read from their custom topic)
|
|
26
|
-
* hmsh:<appid>:x:<topic> -> {xstream} when a worker is sent or reads a buffered task (workers read from their custom topic)
|
|
27
|
-
* hmsh:<appid>:hooks -> {hash} hook patterns/rules; set at compile time
|
|
28
|
-
* hmsh:<appid>:signals -> {hash} dynamic hook signals (hget/hdel) when resolving (always self-clean); added/removed at runtime
|
|
29
|
-
* hmsh:<appid>:sym:keys: -> {hash} list of symbol ranges and :cursor assigned at version deploy time for job keys
|
|
30
|
-
* hmsh:<appid>:sym:keys:<activityid|$subscribes> -> {hash} list of symbols based upon schema enums (initially) and adaptively optimized (later) during runtime; if '$subscribes' is used as the activityid, it is a top-level `job` symbol set (for job keys)
|
|
31
|
-
* hmsh:<appid>:sym:vals: -> {hash} list of symbols for job values across all app versions
|
|
32
|
-
*/
|
|
33
6
|
const HMNS = "hmsh";
|
|
34
7
|
exports.HMNS = HMNS;
|
|
35
|
-
const KEYSEP = ':';
|
|
8
|
+
const KEYSEP = ':';
|
|
36
9
|
exports.KEYSEP = KEYSEP;
|
|
37
|
-
const VALSEP = '::';
|
|
10
|
+
const VALSEP = '::';
|
|
38
11
|
exports.VALSEP = VALSEP;
|
|
39
|
-
const WEBSEP = '::';
|
|
12
|
+
const WEBSEP = '::';
|
|
40
13
|
exports.WEBSEP = WEBSEP;
|
|
41
|
-
const TYPSEP = '::';
|
|
14
|
+
const TYPSEP = '::';
|
|
42
15
|
exports.TYPSEP = TYPSEP;
|
|
43
16
|
class KeyService {
|
|
44
|
-
/**
|
|
45
|
-
* returns a key that can be used to access a value in the key/value store
|
|
46
|
-
* appropriate for the given key type; the keys have an implicit hierarchy
|
|
47
|
-
* and are used to organize data in the store in a tree-like structure
|
|
48
|
-
* via the use of colons as separators. The top-level entity is the hmsh manifest.
|
|
49
|
-
* This file will reveal the full scope of what is on the server (apps, versions, etc)
|
|
50
|
-
* @param namespace
|
|
51
|
-
* @param keyType
|
|
52
|
-
* @param params
|
|
53
|
-
* @returns {string}
|
|
54
|
-
*/
|
|
55
17
|
static mintKey(namespace, keyType, params) {
|
|
56
18
|
switch (keyType) {
|
|
57
19
|
case hotmesh_1.KeyType.HOTMESH:
|
|
@@ -83,16 +45,12 @@ class KeyService {
|
|
|
83
45
|
case hotmesh_1.KeyType.SUBSCRIPTION_PATTERNS:
|
|
84
46
|
return `${namespace}:${params.appId}:v:${params.appVersion}:transitions`;
|
|
85
47
|
case hotmesh_1.KeyType.HOOKS:
|
|
86
|
-
//`hooks` provide the pattern to resolve a value
|
|
87
48
|
return `${namespace}:${params.appId}:hooks`;
|
|
88
49
|
case hotmesh_1.KeyType.SIGNALS:
|
|
89
|
-
//`signals` provide the registry of resolved values that link back to paused jobs
|
|
90
50
|
return `${namespace}:${params.appId}:signals`;
|
|
91
51
|
case hotmesh_1.KeyType.SYMKEYS:
|
|
92
|
-
//`symbol keys` provide the registry of replacement values for job keys
|
|
93
52
|
return `${namespace}:${params.appId}:sym:keys:${params.activityId || ''}`;
|
|
94
53
|
case hotmesh_1.KeyType.SYMVALS:
|
|
95
|
-
//`symbol vals` provide the registry of replacement values for job vals
|
|
96
54
|
return `${namespace}:${params.appId}:sym:vals:`;
|
|
97
55
|
case hotmesh_1.KeyType.STREAMS:
|
|
98
56
|
return `${namespace}:${params.appId || ''}:x:${params.topic || ''}`;
|
package/build/modules/utils.d.ts
CHANGED
|
@@ -22,15 +22,7 @@ export declare function XSleepFor(ms: number): {
|
|
|
22
22
|
};
|
|
23
23
|
export declare function findTopKey(obj: AppTransitions, input: string): string | null;
|
|
24
24
|
export declare function findSubscriptionForTrigger(obj: AppSubscriptions, value: string): string | null;
|
|
25
|
-
/**
|
|
26
|
-
* Get the subscription topic for the flow to which @activityId belongs.
|
|
27
|
-
* TODO: resolve this value in the compiler...do not call this at runtime
|
|
28
|
-
*/
|
|
29
25
|
export declare function getSubscriptionTopic(activityId: string, store: StoreService<RedisClient, RedisMulti>, appVID: AppVID): Promise<string | undefined>;
|
|
30
|
-
/**
|
|
31
|
-
* returns the 12-digit format of the iso timestamp (e.g, 202101010000); returns
|
|
32
|
-
* an empty string if overridden by the user to not segment by time (infinity).
|
|
33
|
-
*/
|
|
34
26
|
export declare function getTimeSeries(granularity: string): string;
|
|
35
27
|
export declare function formatISODate(input: Date | string): string;
|
|
36
28
|
export declare function getSymKey(number: number): string;
|
package/build/modules/utils.js
CHANGED
|
@@ -21,16 +21,13 @@ async function getSystemHealth() {
|
|
|
21
21
|
const freeMemory = os_1.default.freemem();
|
|
22
22
|
const usedMemory = totalMemory - freeMemory;
|
|
23
23
|
const cpus = os_1.default.cpus();
|
|
24
|
-
// CPU load calculation remains unchanged
|
|
25
24
|
const cpuLoad = cpus.map((cpu, i) => {
|
|
26
25
|
const total = Object.values(cpu.times).reduce((acc, tv) => acc + tv, 0);
|
|
27
26
|
const idle = cpu.times.idle;
|
|
28
27
|
const usage = ((total - idle) / total) * 100;
|
|
29
28
|
return { [`CPU ${i} Usage`]: `${usage.toFixed(2)}%` };
|
|
30
29
|
});
|
|
31
|
-
// Wrap each systeminformation call with safeExecute
|
|
32
30
|
const networkStats = await safeExecute(systeminformation_1.default.networkStats(), []);
|
|
33
|
-
// Construct the system health object with error handling in mind
|
|
34
31
|
const systemHealth = {
|
|
35
32
|
TotalMemoryGB: `${(totalMemory / 1024 / 1024 / 1024).toFixed(2)} GB`,
|
|
36
33
|
FreeMemoryGB: `${(freeMemory / 1024 / 1024 / 1024).toFixed(2)} GB`,
|
|
@@ -77,7 +74,6 @@ function identifyRedisType(redisInstance) {
|
|
|
77
74
|
return null;
|
|
78
75
|
}
|
|
79
76
|
exports.identifyRedisType = identifyRedisType;
|
|
80
|
-
//todo: the polyfill methods will all be deleted in the `beta` release.
|
|
81
77
|
exports.polyfill = {
|
|
82
78
|
resolveActivityType(activityType) {
|
|
83
79
|
if (activityType === 'activity') {
|
|
@@ -98,7 +94,6 @@ function identifyRedisTypeFromClass(redisClass) {
|
|
|
98
94
|
exports.identifyRedisTypeFromClass = identifyRedisTypeFromClass;
|
|
99
95
|
function matchesStatusCode(code, pattern) {
|
|
100
96
|
if (typeof pattern === 'string') {
|
|
101
|
-
// Convert '*' wildcard to its regex equivalent (\d)
|
|
102
97
|
const regexPattern = `^${pattern.replace(/\*/g, "\\d")}$`;
|
|
103
98
|
return new RegExp(regexPattern).test(code.toString());
|
|
104
99
|
}
|
|
@@ -110,7 +105,6 @@ function matchesStatus(status, targetStatus) {
|
|
|
110
105
|
}
|
|
111
106
|
exports.matchesStatus = matchesStatus;
|
|
112
107
|
function XSleepFor(ms) {
|
|
113
|
-
//can be interrupted with `clearTimeout`
|
|
114
108
|
let timerId;
|
|
115
109
|
let promise = new Promise((resolve) => {
|
|
116
110
|
timerId = setTimeout(resolve, ms);
|
|
@@ -137,10 +131,6 @@ function findSubscriptionForTrigger(obj, value) {
|
|
|
137
131
|
return null;
|
|
138
132
|
}
|
|
139
133
|
exports.findSubscriptionForTrigger = findSubscriptionForTrigger;
|
|
140
|
-
/**
|
|
141
|
-
* Get the subscription topic for the flow to which @activityId belongs.
|
|
142
|
-
* TODO: resolve this value in the compiler...do not call this at runtime
|
|
143
|
-
*/
|
|
144
134
|
async function getSubscriptionTopic(activityId, store, appVID) {
|
|
145
135
|
const appTransitions = await store.getTransitions(appVID);
|
|
146
136
|
const appSubscriptions = await store.getSubscriptions(appVID);
|
|
@@ -149,10 +139,6 @@ async function getSubscriptionTopic(activityId, store, appVID) {
|
|
|
149
139
|
return topic;
|
|
150
140
|
}
|
|
151
141
|
exports.getSubscriptionTopic = getSubscriptionTopic;
|
|
152
|
-
/**
|
|
153
|
-
* returns the 12-digit format of the iso timestamp (e.g, 202101010000); returns
|
|
154
|
-
* an empty string if overridden by the user to not segment by time (infinity).
|
|
155
|
-
*/
|
|
156
142
|
function getTimeSeries(granularity) {
|
|
157
143
|
if (granularity.toString() === 'infinity') {
|
|
158
144
|
return '0';
|
package/build/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hotmeshio/hotmesh",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.56",
|
|
4
4
|
"description": "Unbreakable Workflows",
|
|
5
5
|
"main": "./build/index.js",
|
|
6
6
|
"types": "./build/index.d.ts",
|
|
@@ -65,11 +65,14 @@
|
|
|
65
65
|
},
|
|
66
66
|
"keywords": [
|
|
67
67
|
"durable workflow",
|
|
68
|
-
"
|
|
68
|
+
"HotMesh",
|
|
69
69
|
"service mesh",
|
|
70
70
|
"workflows",
|
|
71
71
|
"operational data",
|
|
72
|
-
"
|
|
72
|
+
"Redis",
|
|
73
|
+
"OLAP",
|
|
74
|
+
"OLTP",
|
|
75
|
+
"HTAP"
|
|
73
76
|
],
|
|
74
77
|
"author": "luke.birdeau@gmail.com",
|
|
75
78
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -90,11 +93,15 @@
|
|
|
90
93
|
"eslint": "^8.36.0",
|
|
91
94
|
"ioredis": "^5.3.2",
|
|
92
95
|
"jest": "^29.5.0",
|
|
93
|
-
"redis": "^4.6.
|
|
96
|
+
"redis": "^4.6.13",
|
|
94
97
|
"rimraf": "^4.4.1",
|
|
95
98
|
"ts-jest": "^29.0.5",
|
|
96
99
|
"ts-node": "^10.9.1",
|
|
97
100
|
"ts-node-dev": "^2.0.0",
|
|
98
101
|
"typescript": "^5.0.4"
|
|
102
|
+
},
|
|
103
|
+
"peerDependencies": {
|
|
104
|
+
"redis": "^4.0.0",
|
|
105
|
+
"ioredis": "^4.0.0 || ^5.0.0"
|
|
99
106
|
}
|
|
100
107
|
}
|
|
@@ -7,9 +7,6 @@ import { JobState, JobStatus } from '../../types/job';
|
|
|
7
7
|
import { MultiResponseFlags, RedisClient, RedisMulti } from '../../types/redis';
|
|
8
8
|
import { StringAnyType } from '../../types/serializer';
|
|
9
9
|
import { StreamCode, StreamData, StreamStatus } from '../../types/stream';
|
|
10
|
-
/**
|
|
11
|
-
* The base class for all activities
|
|
12
|
-
*/
|
|
13
10
|
declare class Activity {
|
|
14
11
|
config: ActivityType;
|
|
15
12
|
data: ActivityData;
|
|
@@ -26,15 +23,7 @@ declare class Activity {
|
|
|
26
23
|
adjacentIndex: number;
|
|
27
24
|
constructor(config: ActivityType, data: ActivityData, metadata: ActivityMetadata, hook: ActivityData | null, engine: EngineService, context?: JobState);
|
|
28
25
|
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
26
|
verifyEntry(): Promise<void>;
|
|
34
|
-
/**
|
|
35
|
-
* Upon entering leg 2 of a duplexed activty, verify
|
|
36
|
-
* all aspects of the re-entry including job and activty state
|
|
37
|
-
*/
|
|
38
27
|
verifyReentry(): Promise<number>;
|
|
39
28
|
processEvent(status?: StreamStatus, code?: StreamCode, type?: 'hook' | 'output'): Promise<void>;
|
|
40
29
|
processPending(telemetry: TelemetryService, type: 'hook' | 'output'): Promise<MultiResponseFlags>;
|
|
@@ -46,14 +35,7 @@ declare class Activity {
|
|
|
46
35
|
mapInputData(): void;
|
|
47
36
|
mapOutputData(): void;
|
|
48
37
|
registerTimeout(): Promise<void>;
|
|
49
|
-
/**
|
|
50
|
-
* Any StreamMessage with a status of ERROR is bound to the activity
|
|
51
|
-
*/
|
|
52
38
|
bindActivityError(data: Record<string, unknown>): void;
|
|
53
|
-
/**
|
|
54
|
-
* unhandled activity errors (activities that return an ERROR StreamMessage
|
|
55
|
-
* status and have no adjacent children to transition to) are bound to the job
|
|
56
|
-
*/
|
|
57
39
|
bindJobError(data: Record<string, unknown>): void;
|
|
58
40
|
getTriggerConfig(): Promise<ActivityType>;
|
|
59
41
|
getJobStatus(): null | number;
|
|
@@ -68,12 +50,6 @@ declare class Activity {
|
|
|
68
50
|
bindJobMetadataPaths(): string[];
|
|
69
51
|
bindActivityMetadataPaths(): string[];
|
|
70
52
|
getState(): Promise<void>;
|
|
71
|
-
/**
|
|
72
|
-
* if the job is created/deleted/created with the same key,
|
|
73
|
-
* the 'gid' ensures no stale messages (such as sleep delays)
|
|
74
|
-
* enter the workstream. Any message with a mismatched gid
|
|
75
|
-
* belongs to a prior job and can safely be ignored/dropped.
|
|
76
|
-
*/
|
|
77
53
|
assertGenerationalId(jobGID: string, msgGID?: string): void;
|
|
78
54
|
initDimensionalAddress(dad: string): void;
|
|
79
55
|
initSelf(context: StringAnyType): JobState;
|
|
@@ -83,10 +59,6 @@ declare class Activity {
|
|
|
83
59
|
resolveAdjacentDad(): string;
|
|
84
60
|
filterAdjacent(): Promise<StreamData[]>;
|
|
85
61
|
transition(adjacencyList: StreamData[], jobStatus: JobStatus): Promise<string[]>;
|
|
86
|
-
/**
|
|
87
|
-
* A job with a vale < -100_000_000 is considered interrupted,
|
|
88
|
-
* as the interruption event decrements the job status by 1billion.
|
|
89
|
-
*/
|
|
90
62
|
jobWasInterrupted(jobStatus: JobStatus): boolean;
|
|
91
63
|
}
|
|
92
64
|
export { Activity, ActivityType };
|
|
@@ -10,9 +10,6 @@ const pipe_1 = require("../pipe");
|
|
|
10
10
|
const serializer_1 = require("../serializer");
|
|
11
11
|
const telemetry_1 = require("../telemetry");
|
|
12
12
|
const stream_1 = require("../../types/stream");
|
|
13
|
-
/**
|
|
14
|
-
* The base class for all activities
|
|
15
|
-
*/
|
|
16
13
|
class Activity {
|
|
17
14
|
constructor(config, data, metadata, hook, engine, context) {
|
|
18
15
|
this.status = stream_1.StreamStatus.SUCCESS;
|
|
@@ -30,20 +27,12 @@ class Activity {
|
|
|
30
27
|
setLeg(leg) {
|
|
31
28
|
this.leg = leg;
|
|
32
29
|
}
|
|
33
|
-
/**
|
|
34
|
-
* Upon entering leg 1 of a duplexed activty, verify
|
|
35
|
-
* all aspects of the entry including job and activty state
|
|
36
|
-
*/
|
|
37
30
|
async verifyEntry() {
|
|
38
31
|
this.setLeg(1);
|
|
39
32
|
await this.getState();
|
|
40
33
|
collator_1.CollatorService.assertJobActive(this.context.metadata.js, this.context.metadata.jid, this.metadata.aid);
|
|
41
34
|
await collator_1.CollatorService.notarizeEntry(this);
|
|
42
35
|
}
|
|
43
|
-
/**
|
|
44
|
-
* Upon entering leg 2 of a duplexed activty, verify
|
|
45
|
-
* all aspects of the re-entry including job and activty state
|
|
46
|
-
*/
|
|
47
36
|
async verifyReentry() {
|
|
48
37
|
const guid = this.context.metadata.guid;
|
|
49
38
|
this.setLeg(2);
|
|
@@ -51,7 +40,6 @@ class Activity {
|
|
|
51
40
|
collator_1.CollatorService.assertJobActive(this.context.metadata.js, this.context.metadata.jid, this.metadata.aid);
|
|
52
41
|
return await collator_1.CollatorService.notarizeReentry(this, guid);
|
|
53
42
|
}
|
|
54
|
-
//******** DUPLEX RE-ENTRY POINT ********//
|
|
55
43
|
async processEvent(status = stream_1.StreamStatus.SUCCESS, code = 200, type = 'output') {
|
|
56
44
|
this.setLeg(2);
|
|
57
45
|
const jid = this.context.metadata.jid;
|
|
@@ -144,7 +132,6 @@ class Activity {
|
|
|
144
132
|
telemetry.mapActivityAttributes();
|
|
145
133
|
const jobStatus = this.resolveStatus(multiResponse);
|
|
146
134
|
const attrs = { 'app.job.jss': jobStatus };
|
|
147
|
-
//adjacencyList membership has already been set at this point (according to activity status)
|
|
148
135
|
const messageIds = await this.transition(this.adjacencyList, jobStatus);
|
|
149
136
|
if (messageIds?.length) {
|
|
150
137
|
attrs['app.activity.mids'] = messageIds.join(',');
|
|
@@ -167,10 +154,6 @@ class Activity {
|
|
|
167
154
|
if (output) {
|
|
168
155
|
for (const key in output) {
|
|
169
156
|
const f1 = key.indexOf('[');
|
|
170
|
-
//keys with array notation suffix `somekey[]` represent
|
|
171
|
-
//dynamically-keyed mappings whose `value` must be moved to the output.
|
|
172
|
-
//The `value` must be an object with keys appropriate to the
|
|
173
|
-
//notation type: `somekey[0] (array)`, `somekey[-] (mark)`, OR `somekey[_] (search)`
|
|
174
157
|
if (f1 > -1) {
|
|
175
158
|
const amount = key.substring(f1 + 1).split(']')[0];
|
|
176
159
|
if (!isNaN(Number(amount))) {
|
|
@@ -197,7 +180,6 @@ class Activity {
|
|
|
197
180
|
}
|
|
198
181
|
}
|
|
199
182
|
mapOutputData() {
|
|
200
|
-
//activity YAML may include output map data that produces/extends activity output data.
|
|
201
183
|
if (this.config.output?.maps) {
|
|
202
184
|
const mapper = new mapper_1.MapperService(this.config.output.maps, this.context);
|
|
203
185
|
const actOutData = mapper.mapRules();
|
|
@@ -207,21 +189,12 @@ class Activity {
|
|
|
207
189
|
}
|
|
208
190
|
}
|
|
209
191
|
async registerTimeout() {
|
|
210
|
-
//set timeout in support of hook and/or duplex
|
|
211
192
|
}
|
|
212
|
-
/**
|
|
213
|
-
* Any StreamMessage with a status of ERROR is bound to the activity
|
|
214
|
-
*/
|
|
215
193
|
bindActivityError(data) {
|
|
216
194
|
const md = this.context[this.metadata.aid].output.metadata;
|
|
217
195
|
md.err = JSON.stringify(this.data);
|
|
218
|
-
//(temporary...useful for mapping error parts in the app.yaml)
|
|
219
196
|
md.$error = { ...data, is_stream_error: true };
|
|
220
197
|
}
|
|
221
|
-
/**
|
|
222
|
-
* unhandled activity errors (activities that return an ERROR StreamMessage
|
|
223
|
-
* status and have no adjacent children to transition to) are bound to the job
|
|
224
|
-
*/
|
|
225
198
|
bindJobError(data) {
|
|
226
199
|
this.context.metadata.err = JSON.stringify({ ...data, is_stream_error: true });
|
|
227
200
|
}
|
|
@@ -236,7 +209,6 @@ class Activity {
|
|
|
236
209
|
await this.store.setStatus(amount, this.context.metadata.jid, appId, multi);
|
|
237
210
|
}
|
|
238
211
|
authorizeEntry(state) {
|
|
239
|
-
//pre-authorize activity state to allow entry for adjacent activities
|
|
240
212
|
return this.adjacencyList?.map((streamData) => {
|
|
241
213
|
const { metadata: { aid } } = streamData;
|
|
242
214
|
state[`${aid}/output/metadata/as`] = collator_1.CollatorService.getSeed();
|
|
@@ -256,7 +228,6 @@ class Activity {
|
|
|
256
228
|
const presets = this.authorizeEntry(state);
|
|
257
229
|
this.bindDimensionalAddress(state);
|
|
258
230
|
this.bindActivityState(state);
|
|
259
|
-
//symbolNames holds symkeys
|
|
260
231
|
const symbolNames = [
|
|
261
232
|
`$${this.config.subscribes}`,
|
|
262
233
|
this.metadata.aid,
|
|
@@ -266,7 +237,6 @@ class Activity {
|
|
|
266
237
|
return await this.store.setState(state, this.getJobStatus(), jobId, symbolNames, dIds, multi);
|
|
267
238
|
}
|
|
268
239
|
bindJobMetadata() {
|
|
269
|
-
//both legs of the most recently run activity (1 and 2) modify ju (job_updated)
|
|
270
240
|
this.context.metadata.ju = (0, utils_1.formatISODate)(new Date());
|
|
271
241
|
}
|
|
272
242
|
bindActivityMetadata() {
|
|
@@ -353,7 +323,6 @@ class Activity {
|
|
|
353
323
|
telemetry_1.TelemetryService.addTargetTelemetryPaths(consumes, this.config, this.metadata, this.leg);
|
|
354
324
|
let { dad, jid } = this.context.metadata;
|
|
355
325
|
const dIds = collator_1.CollatorService.getDimensionsById([...this.config.ancestors, this.metadata.aid], dad || '');
|
|
356
|
-
//`state` is a unidimensional hash; context is a tree
|
|
357
326
|
const [state, _status] = await this.store.getState(jid, consumes, dIds);
|
|
358
327
|
this.context = (0, utils_1.restoreHierarchy)(state);
|
|
359
328
|
this.assertGenerationalId(this.context?.metadata?.gid, gid);
|
|
@@ -361,12 +330,6 @@ class Activity {
|
|
|
361
330
|
this.initSelf(this.context);
|
|
362
331
|
this.initPolicies(this.context);
|
|
363
332
|
}
|
|
364
|
-
/**
|
|
365
|
-
* if the job is created/deleted/created with the same key,
|
|
366
|
-
* the 'gid' ensures no stale messages (such as sleep delays)
|
|
367
|
-
* enter the workstream. Any message with a mismatched gid
|
|
368
|
-
* belongs to a prior job and can safely be ignored/dropped.
|
|
369
|
-
*/
|
|
370
333
|
assertGenerationalId(jobGID, msgGID) {
|
|
371
334
|
if (msgGID !== jobGID) {
|
|
372
335
|
throw new errors_1.GenerationalError(jobGID, msgGID, this.context?.metadata?.jid ?? '', this.context?.metadata?.aid ?? '', this.context?.metadata?.dad ?? '');
|
|
@@ -393,10 +356,9 @@ class Activity {
|
|
|
393
356
|
if (!self.output.metadata) {
|
|
394
357
|
self.output.metadata = {};
|
|
395
358
|
}
|
|
396
|
-
//prebind the updated timestamp (mappings need the time)
|
|
397
359
|
self.output.metadata.au = (0, utils_1.formatISODate)(new Date());
|
|
398
360
|
context['$self'] = self;
|
|
399
|
-
context['$job'] = context;
|
|
361
|
+
context['$job'] = context;
|
|
400
362
|
return context;
|
|
401
363
|
}
|
|
402
364
|
initPolicies(context) {
|
|
@@ -409,13 +371,11 @@ class Activity {
|
|
|
409
371
|
resolveDad() {
|
|
410
372
|
let dad = this.metadata.dad;
|
|
411
373
|
if (this.adjacentIndex > 0) {
|
|
412
|
-
//if adjacent index > 0 the activity is cycling; replace last index with cycle index
|
|
413
374
|
dad = `${dad.substring(0, dad.lastIndexOf(','))},${this.adjacentIndex}`;
|
|
414
375
|
}
|
|
415
376
|
return dad;
|
|
416
377
|
}
|
|
417
378
|
resolveAdjacentDad() {
|
|
418
|
-
//concat self and child dimension (all children (leg 1) begin life at 0)
|
|
419
379
|
return `${this.resolveDad()}${collator_1.CollatorService.getDimensionalSeed(0)}`;
|
|
420
380
|
}
|
|
421
381
|
;
|
|
@@ -423,7 +383,6 @@ class Activity {
|
|
|
423
383
|
const adjacencyList = [];
|
|
424
384
|
const transitions = await this.store.getTransitions(await this.engine.getVID());
|
|
425
385
|
const transition = transitions[`.${this.metadata.aid}`];
|
|
426
|
-
//resolve the dimensional address for adjacent children
|
|
427
386
|
const adjacentDad = this.resolveAdjacentDad();
|
|
428
387
|
if (transition) {
|
|
429
388
|
for (const toActivityId in transition) {
|
|
@@ -468,10 +427,6 @@ class Activity {
|
|
|
468
427
|
}
|
|
469
428
|
return mIds;
|
|
470
429
|
}
|
|
471
|
-
/**
|
|
472
|
-
* A job with a vale < -100_000_000 is considered interrupted,
|
|
473
|
-
* as the interruption event decrements the job status by 1billion.
|
|
474
|
-
*/
|
|
475
430
|
jobWasInterrupted(jobStatus) {
|
|
476
431
|
return jobStatus < -100000000;
|
|
477
432
|
}
|
|
@@ -12,7 +12,6 @@ class Await extends activity_1.Activity {
|
|
|
12
12
|
constructor(config, data, metadata, hook, engine, context) {
|
|
13
13
|
super(config, data, metadata, hook, engine, context);
|
|
14
14
|
}
|
|
15
|
-
//******** INITIAL ENTRY POINT (A) ********//
|
|
16
15
|
async process() {
|
|
17
16
|
this.logger.debug('await-process', { jid: this.context.metadata.jid, gid: this.context.metadata.gid, aid: this.metadata.aid });
|
|
18
17
|
let telemetry;
|
|
@@ -21,15 +20,12 @@ class Await extends activity_1.Activity {
|
|
|
21
20
|
telemetry = new telemetry_1.TelemetryService(this.engine.appId, this.config, this.metadata, this.context);
|
|
22
21
|
telemetry.startActivitySpan(this.leg);
|
|
23
22
|
this.mapInputData();
|
|
24
|
-
//save state and authorize reentry
|
|
25
23
|
const multi = this.store.getMulti();
|
|
26
|
-
//todo: await this.registerTimeout();
|
|
27
24
|
const messageId = await this.execActivity(multi);
|
|
28
25
|
await collator_1.CollatorService.authorizeReentry(this, multi);
|
|
29
26
|
await this.setState(multi);
|
|
30
27
|
await this.setStatus(0, multi);
|
|
31
28
|
const multiResponse = await multi.exec();
|
|
32
|
-
//telemetry
|
|
33
29
|
telemetry.mapActivityAttributes();
|
|
34
30
|
const jobStatus = this.resolveStatus(multiResponse);
|
|
35
31
|
telemetry.setActivityAttributes({
|
|
@@ -7,13 +7,6 @@ declare class Cycle extends Activity {
|
|
|
7
7
|
config: CycleActivity;
|
|
8
8
|
constructor(config: ActivityType, data: ActivityData, metadata: ActivityMetadata, hook: ActivityData | null, engine: EngineService, context?: JobState);
|
|
9
9
|
process(): Promise<string>;
|
|
10
|
-
/**
|
|
11
|
-
* Trigger the target ancestor to execute in a cycle,
|
|
12
|
-
* without violating the constraints of the DAG. Immutable
|
|
13
|
-
* `individual activity state` will execute in a new dimensional
|
|
14
|
-
* thread while `shared job state` can change. This
|
|
15
|
-
* pattern allows for retries without violating the DAG.
|
|
16
|
-
*/
|
|
17
10
|
cycleAncestorActivity(multi: RedisMulti): Promise<string>;
|
|
18
11
|
}
|
|
19
12
|
export { Cycle };
|
|
@@ -10,7 +10,6 @@ class Cycle extends activity_1.Activity {
|
|
|
10
10
|
constructor(config, data, metadata, hook, engine, context) {
|
|
11
11
|
super(config, data, metadata, hook, engine, context);
|
|
12
12
|
}
|
|
13
|
-
//******** LEG 1 ENTRY ********//
|
|
14
13
|
async process() {
|
|
15
14
|
this.logger.debug('cycle-process', { jid: this.context.metadata.jid, gid: this.context.metadata.gid, aid: this.metadata.aid });
|
|
16
15
|
let telemetry;
|
|
@@ -19,21 +18,18 @@ class Cycle extends activity_1.Activity {
|
|
|
19
18
|
telemetry = new telemetry_1.TelemetryService(this.engine.appId, this.config, this.metadata, this.context);
|
|
20
19
|
telemetry.startActivitySpan(this.leg);
|
|
21
20
|
this.mapInputData();
|
|
22
|
-
//set state/status
|
|
23
21
|
let multi = this.store.getMulti();
|
|
24
22
|
await this.setState(multi);
|
|
25
|
-
await this.setStatus(0, multi);
|
|
23
|
+
await this.setStatus(0, multi);
|
|
26
24
|
const multiResponse = await multi.exec();
|
|
27
25
|
telemetry.mapActivityAttributes();
|
|
28
26
|
const jobStatus = this.resolveStatus(multiResponse);
|
|
29
|
-
//cycle the target ancestor
|
|
30
27
|
multi = this.store.getMulti();
|
|
31
28
|
const messageId = await this.cycleAncestorActivity(multi);
|
|
32
29
|
telemetry.setActivityAttributes({
|
|
33
30
|
'app.activity.mid': messageId,
|
|
34
31
|
'app.job.jss': jobStatus
|
|
35
32
|
});
|
|
36
|
-
//exit early (`Cycle` activities only execute Leg 1)
|
|
37
33
|
await collator_1.CollatorService.notarizeEarlyExit(this, multi);
|
|
38
34
|
await multi.exec();
|
|
39
35
|
return this.context.metadata.aid;
|
|
@@ -62,18 +58,7 @@ class Cycle extends activity_1.Activity {
|
|
|
62
58
|
this.logger.debug('cycle-process-end', { jid: this.context.metadata.jid, gid: this.context.metadata.gid, aid: this.metadata.aid });
|
|
63
59
|
}
|
|
64
60
|
}
|
|
65
|
-
/**
|
|
66
|
-
* Trigger the target ancestor to execute in a cycle,
|
|
67
|
-
* without violating the constraints of the DAG. Immutable
|
|
68
|
-
* `individual activity state` will execute in a new dimensional
|
|
69
|
-
* thread while `shared job state` can change. This
|
|
70
|
-
* pattern allows for retries without violating the DAG.
|
|
71
|
-
*/
|
|
72
61
|
async cycleAncestorActivity(multi) {
|
|
73
|
-
//Cycle activity L1 is a standin for the target ancestor L1.
|
|
74
|
-
//Input data mapping (mapInputData) allows for the
|
|
75
|
-
//next dimensonal thread to execute with different
|
|
76
|
-
//input data than the current dimensional thread
|
|
77
62
|
this.mapInputData();
|
|
78
63
|
const streamData = {
|
|
79
64
|
metadata: {
|
|
@@ -6,16 +6,10 @@ import { HookRule } from '../../types/hook';
|
|
|
6
6
|
import { JobState, JobStatus } from '../../types/job';
|
|
7
7
|
import { RedisMulti } from '../../types/redis';
|
|
8
8
|
import { StreamCode, StreamStatus } from '../../types/stream';
|
|
9
|
-
/**
|
|
10
|
-
* Supports `signal hook`, `time hook`, and `cycle hook` patterns
|
|
11
|
-
*/
|
|
12
9
|
declare class Hook extends Activity {
|
|
13
10
|
config: HookActivity;
|
|
14
11
|
constructor(config: ActivityType, data: ActivityData, metadata: ActivityMetadata, hook: ActivityData | null, engine: EngineService, context?: JobState);
|
|
15
12
|
process(): Promise<string>;
|
|
16
|
-
/**
|
|
17
|
-
* does this activity use a time-hook or web-hook
|
|
18
|
-
*/
|
|
19
13
|
doesHook(): boolean;
|
|
20
14
|
doHook(telemetry: TelemetryService): Promise<void>;
|
|
21
15
|
doPassThrough(telemetry: TelemetryService): Promise<void>;
|