@hotmeshio/hotmesh 0.12.1 → 0.14.0
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 +18 -22
- package/build/modules/enums.d.ts +60 -5
- package/build/modules/enums.js +62 -7
- package/build/modules/errors.d.ts +15 -2
- package/build/modules/errors.js +17 -1
- package/build/modules/storage.d.ts +1 -0
- package/build/modules/storage.js +2 -1
- package/build/package.json +8 -2
- package/build/services/activities/activity/context.d.ts +22 -0
- package/build/services/activities/activity/context.js +76 -0
- package/build/services/activities/activity/index.d.ts +116 -0
- package/build/services/activities/activity/index.js +299 -0
- package/build/services/activities/activity/mapping.d.ts +12 -0
- package/build/services/activities/activity/mapping.js +63 -0
- package/build/services/activities/activity/process.d.ts +28 -0
- package/build/services/activities/activity/process.js +100 -0
- package/build/services/activities/activity/protocol.d.ts +39 -0
- package/build/services/activities/activity/protocol.js +151 -0
- package/build/services/activities/activity/state.d.ts +40 -0
- package/build/services/activities/activity/state.js +143 -0
- package/build/services/activities/activity/transition.d.ts +23 -0
- package/build/services/activities/activity/transition.js +71 -0
- package/build/services/activities/activity/verify.d.ts +22 -0
- package/build/services/activities/activity/verify.js +85 -0
- package/build/services/activities/await.d.ts +1 -4
- package/build/services/activities/await.js +2 -36
- package/build/services/activities/cycle.d.ts +1 -11
- package/build/services/activities/cycle.js +3 -46
- package/build/services/activities/hook.d.ts +2 -11
- package/build/services/activities/hook.js +30 -50
- package/build/services/activities/interrupt.d.ts +2 -4
- package/build/services/activities/interrupt.js +4 -38
- package/build/services/activities/signal.d.ts +1 -11
- package/build/services/activities/signal.js +3 -48
- package/build/services/activities/trigger.d.ts +1 -3
- package/build/services/activities/trigger.js +0 -3
- package/build/services/activities/worker.d.ts +3 -6
- package/build/services/activities/worker.js +4 -40
- package/build/services/connector/factory.d.ts +6 -0
- package/build/services/connector/factory.js +24 -0
- package/build/services/dba/index.d.ts +14 -4
- package/build/services/dba/index.js +57 -18
- package/build/services/durable/activity.d.ts +30 -0
- package/build/services/durable/activity.js +46 -0
- package/build/services/durable/client.d.ts +26 -31
- package/build/services/durable/client.js +26 -31
- package/build/services/durable/connection.d.ts +13 -7
- package/build/services/durable/connection.js +13 -7
- package/build/services/durable/exporter.d.ts +2 -2
- package/build/services/durable/exporter.js +27 -12
- package/build/services/durable/handle.d.ts +59 -41
- package/build/services/durable/handle.js +61 -41
- package/build/services/durable/index.d.ts +152 -283
- package/build/services/durable/index.js +161 -289
- package/build/services/durable/interceptor.d.ts +43 -33
- package/build/services/durable/interceptor.js +59 -39
- package/build/services/durable/schemas/factory.d.ts +2 -3
- package/build/services/durable/schemas/factory.js +180 -30
- package/build/services/durable/telemetry.d.ts +80 -0
- package/build/services/durable/telemetry.js +137 -0
- package/build/services/durable/worker.d.ts +100 -21
- package/build/services/durable/worker.js +314 -60
- package/build/services/durable/workflow/all.d.ts +1 -1
- package/build/services/durable/workflow/all.js +1 -1
- package/build/services/durable/workflow/cancellationScope.d.ts +104 -0
- package/build/services/durable/workflow/cancellationScope.js +139 -0
- package/build/services/durable/workflow/common.d.ts +5 -4
- package/build/services/durable/workflow/common.js +6 -1
- package/build/services/durable/workflow/{waitFor.d.ts → condition.d.ts} +9 -8
- package/build/services/durable/workflow/{waitFor.js → condition.js} +44 -11
- package/build/services/durable/workflow/continueAsNew.d.ts +65 -0
- package/build/services/durable/workflow/continueAsNew.js +92 -0
- package/build/services/durable/workflow/didRun.d.ts +2 -2
- package/build/services/durable/workflow/didRun.js +4 -4
- package/build/services/durable/workflow/enrich.d.ts +5 -0
- package/build/services/durable/workflow/enrich.js +5 -0
- package/build/services/durable/workflow/entityMethods.d.ts +7 -0
- package/build/services/durable/workflow/entityMethods.js +7 -0
- package/build/services/durable/workflow/execHook.js +3 -3
- package/build/services/durable/workflow/execHookBatch.js +2 -2
- package/build/services/durable/workflow/{execChild.d.ts → executeChild.d.ts} +4 -40
- package/build/services/durable/workflow/{execChild.js → executeChild.js} +36 -45
- package/build/services/durable/workflow/hook.d.ts +1 -1
- package/build/services/durable/workflow/hook.js +4 -3
- package/build/services/durable/workflow/index.d.ts +45 -50
- package/build/services/durable/workflow/index.js +46 -51
- package/build/services/durable/workflow/interruption.d.ts +7 -6
- package/build/services/durable/workflow/interruption.js +11 -7
- package/build/services/durable/workflow/patched.d.ts +72 -0
- package/build/services/durable/workflow/patched.js +110 -0
- package/build/services/durable/workflow/proxyActivities.d.ts +7 -7
- package/build/services/durable/workflow/proxyActivities.js +51 -15
- package/build/services/durable/workflow/searchMethods.d.ts +7 -0
- package/build/services/durable/workflow/searchMethods.js +7 -0
- package/build/services/durable/workflow/signal.d.ts +4 -4
- package/build/services/durable/workflow/signal.js +4 -4
- package/build/services/durable/workflow/{sleepFor.d.ts → sleep.d.ts} +7 -7
- package/build/services/durable/workflow/{sleepFor.js → sleep.js} +39 -10
- package/build/services/durable/workflow/terminate.d.ts +55 -0
- package/build/services/durable/workflow/{interrupt.js → terminate.js} +21 -21
- package/build/services/durable/workflow/trace.js +2 -2
- package/build/services/durable/workflow/uuid4.d.ts +14 -0
- package/build/services/durable/workflow/uuid4.js +39 -0
- package/build/services/durable/workflow/{context.d.ts → workflowInfo.d.ts} +5 -5
- package/build/services/durable/workflow/{context.js → workflowInfo.js} +7 -7
- package/build/services/engine/compiler.d.ts +19 -0
- package/build/services/engine/compiler.js +20 -0
- package/build/services/engine/completion.d.ts +46 -0
- package/build/services/engine/completion.js +145 -0
- package/build/services/engine/dispatch.d.ts +24 -0
- package/build/services/engine/dispatch.js +98 -0
- package/build/services/engine/index.d.ts +49 -81
- package/build/services/engine/index.js +175 -573
- package/build/services/engine/init.d.ts +42 -0
- package/build/services/engine/init.js +74 -0
- package/build/services/engine/pubsub.d.ts +50 -0
- package/build/services/engine/pubsub.js +118 -0
- package/build/services/engine/reporting.d.ts +20 -0
- package/build/services/engine/reporting.js +38 -0
- package/build/services/engine/schema.d.ts +23 -0
- package/build/services/engine/schema.js +62 -0
- package/build/services/engine/signal.d.ts +57 -0
- package/build/services/engine/signal.js +117 -0
- package/build/services/engine/state.d.ts +35 -0
- package/build/services/engine/state.js +61 -0
- package/build/services/engine/version.d.ts +31 -0
- package/build/services/engine/version.js +73 -0
- package/build/services/hotmesh/deployment.d.ts +21 -0
- package/build/services/hotmesh/deployment.js +25 -0
- package/build/services/hotmesh/index.d.ts +142 -533
- package/build/services/hotmesh/index.js +223 -674
- package/build/services/hotmesh/init.d.ts +42 -0
- package/build/services/hotmesh/init.js +93 -0
- package/build/services/hotmesh/jobs.d.ts +67 -0
- package/build/services/hotmesh/jobs.js +99 -0
- package/build/services/hotmesh/pubsub.d.ts +38 -0
- package/build/services/hotmesh/pubsub.js +54 -0
- package/build/services/hotmesh/quorum.d.ts +30 -0
- package/build/services/hotmesh/quorum.js +62 -0
- package/build/services/hotmesh/validation.d.ts +6 -0
- package/build/services/hotmesh/validation.js +28 -0
- package/build/services/quorum/index.js +1 -0
- package/build/services/router/consumption/index.d.ts +11 -5
- package/build/services/router/consumption/index.js +24 -17
- package/build/services/router/error-handling/index.d.ts +2 -2
- package/build/services/router/error-handling/index.js +14 -14
- package/build/services/router/index.d.ts +1 -1
- package/build/services/router/index.js +2 -2
- package/build/services/serializer/index.d.ts +22 -0
- package/build/services/serializer/index.js +39 -1
- package/build/services/store/index.d.ts +1 -0
- package/build/services/store/providers/postgres/exporter-sql.d.ts +2 -2
- package/build/services/store/providers/postgres/exporter-sql.js +4 -4
- package/build/services/store/providers/postgres/kvtables.js +7 -6
- package/build/services/store/providers/postgres/kvtypes/hash/basic.js +67 -52
- package/build/services/store/providers/postgres/kvtypes/hash/jsonb.js +87 -72
- package/build/services/store/providers/postgres/kvtypes/hash/udata.js +106 -79
- package/build/services/store/providers/postgres/kvtypes/hash/utils.d.ts +16 -0
- package/build/services/store/providers/postgres/kvtypes/hash/utils.js +29 -16
- package/build/services/store/providers/postgres/postgres.d.ts +1 -0
- package/build/services/store/providers/postgres/postgres.js +14 -4
- package/build/services/stream/factory.d.ts +3 -1
- package/build/services/stream/factory.js +2 -2
- package/build/services/stream/index.d.ts +1 -0
- package/build/services/stream/providers/nats/nats.d.ts +1 -0
- package/build/services/stream/providers/nats/nats.js +1 -0
- package/build/services/stream/providers/postgres/credentials.d.ts +56 -0
- package/build/services/stream/providers/postgres/credentials.js +129 -0
- package/build/services/stream/providers/postgres/kvtables.js +18 -0
- package/build/services/stream/providers/postgres/messages.js +7 -7
- package/build/services/stream/providers/postgres/notifications.js +16 -2
- package/build/services/stream/providers/postgres/postgres.d.ts +7 -0
- package/build/services/stream/providers/postgres/postgres.js +35 -4
- package/build/services/stream/providers/postgres/procedures.d.ts +21 -0
- package/build/services/stream/providers/postgres/procedures.js +213 -0
- package/build/services/stream/providers/postgres/secured.d.ts +34 -0
- package/build/services/stream/providers/postgres/secured.js +146 -0
- package/build/services/stream/providers/postgres/stats.d.ts +1 -0
- package/build/services/stream/providers/postgres/stats.js +1 -0
- package/build/services/stream/registry.d.ts +1 -1
- package/build/services/stream/registry.js +5 -2
- package/build/services/telemetry/index.d.ts +10 -1
- package/build/services/telemetry/index.js +40 -7
- package/build/services/worker/credentials.d.ts +51 -0
- package/build/services/worker/credentials.js +87 -0
- package/build/services/worker/index.d.ts +2 -2
- package/build/services/worker/index.js +7 -6
- package/build/types/codec.d.ts +84 -0
- package/build/types/codec.js +2 -0
- package/build/types/dba.d.ts +39 -3
- package/build/types/durable.d.ts +123 -25
- package/build/types/error.d.ts +10 -0
- package/build/types/exporter.d.ts +1 -1
- package/build/types/hotmesh.d.ts +67 -4
- package/build/types/index.d.ts +2 -1
- package/build/types/provider.d.ts +2 -2
- package/build/types/quorum.d.ts +35 -1
- package/build/types/stream.d.ts +12 -6
- package/package.json +8 -2
- package/build/services/activities/activity.d.ts +0 -192
- package/build/services/activities/activity.js +0 -786
- package/build/services/durable/workflow/interrupt.d.ts +0 -55
|
@@ -1,35 +1,78 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
/**
|
|
3
|
+
* EngineService — the workflow execution engine.
|
|
4
|
+
*
|
|
5
|
+
* Consumes stream messages from the router and dispatches them
|
|
6
|
+
* to the appropriate activity handler (Trigger, Worker, Hook, …).
|
|
7
|
+
*
|
|
8
|
+
* Each section delegates to a purpose-specific module inside `engine/`.
|
|
9
|
+
* Open the module when you need implementation detail; read this file
|
|
10
|
+
* when you need the big picture.
|
|
11
|
+
*
|
|
12
|
+
* Lifecycle (maps to modules):
|
|
13
|
+
* 1. INIT → init.ts (channel setup, router, config)
|
|
14
|
+
* 2. VERSION → version.ts (app version resolution, caching)
|
|
15
|
+
* 3. SCHEMA → schema.ts (activity lookup, handler factory)
|
|
16
|
+
* 4. COMPILE → compiler.ts (YAML plan & deploy)
|
|
17
|
+
* 5. REPORT → reporting.ts (stats, IDs, query resolution)
|
|
18
|
+
* 6. DISPATCH → dispatch.ts (stream message → activity handler)
|
|
19
|
+
* 7. COMPLETION → completion.ts (parent notify, cleanup, expiry)
|
|
20
|
+
* 8. SIGNAL → signal.ts (webhook/timehook delivery, fan-out)
|
|
21
|
+
* 9. PUB/SUB → pubsub.ts (topic messaging, subscriptions)
|
|
22
|
+
* 10. STATE → state.ts (job state retrieval, export)
|
|
23
|
+
*/
|
|
24
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
27
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
28
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
29
|
+
}
|
|
30
|
+
Object.defineProperty(o, k2, desc);
|
|
31
|
+
}) : (function(o, m, k, k2) {
|
|
32
|
+
if (k2 === undefined) k2 = k;
|
|
33
|
+
o[k2] = m[k];
|
|
34
|
+
}));
|
|
35
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
36
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
37
|
+
}) : function(o, v) {
|
|
38
|
+
o["default"] = v;
|
|
39
|
+
});
|
|
40
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
41
|
+
if (mod && mod.__esModule) return mod;
|
|
42
|
+
var result = {};
|
|
43
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
44
|
+
__setModuleDefault(result, mod);
|
|
45
|
+
return result;
|
|
4
46
|
};
|
|
5
47
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
48
|
exports.EngineService = void 0;
|
|
7
49
|
const key_1 = require("../../modules/key");
|
|
8
|
-
const registry_1 = require("../stream/registry");
|
|
9
50
|
const enums_1 = require("../../modules/enums");
|
|
10
51
|
const utils_1 = require("../../modules/utils");
|
|
11
|
-
const activities_1 = __importDefault(require("../activities"));
|
|
12
|
-
const compiler_1 = require("../compiler");
|
|
13
|
-
const exporter_1 = require("../exporter");
|
|
14
|
-
const reporter_1 = require("../reporter");
|
|
15
|
-
const router_1 = require("../router");
|
|
16
|
-
const serializer_1 = require("../serializer");
|
|
17
|
-
const factory_1 = require("../search/factory");
|
|
18
|
-
const factory_2 = require("../store/factory");
|
|
19
|
-
const factory_3 = require("../stream/factory");
|
|
20
|
-
const factory_4 = require("../sub/factory");
|
|
21
|
-
const task_1 = require("../task");
|
|
22
52
|
const stream_1 = require("../../types/stream");
|
|
53
|
+
const Init = __importStar(require("./init"));
|
|
54
|
+
const Version = __importStar(require("./version"));
|
|
55
|
+
const Schema = __importStar(require("./schema"));
|
|
56
|
+
const Compiler = __importStar(require("./compiler"));
|
|
57
|
+
const Reporting = __importStar(require("./reporting"));
|
|
58
|
+
const Dispatch = __importStar(require("./dispatch"));
|
|
59
|
+
const Completion = __importStar(require("./completion"));
|
|
60
|
+
const Signal = __importStar(require("./signal"));
|
|
61
|
+
const PubSub = __importStar(require("./pubsub"));
|
|
62
|
+
const State = __importStar(require("./state"));
|
|
23
63
|
class EngineService {
|
|
64
|
+
// ═════════════════════════════════════════════════════════════════
|
|
65
|
+
// 1. INIT — bootstrap channels, router, and services
|
|
66
|
+
// → see init.ts
|
|
67
|
+
// ═════════════════════════════════════════════════════════════════
|
|
24
68
|
/**
|
|
25
69
|
* @private
|
|
26
70
|
*/
|
|
27
71
|
constructor() {
|
|
72
|
+
// ── execution state ───────────────────────────────────────────────
|
|
28
73
|
this.cacheMode = 'cache';
|
|
29
74
|
this.untilVersion = null;
|
|
30
75
|
this.jobCallbacks = {};
|
|
31
|
-
this.reporting = false;
|
|
32
|
-
this.jobId = 1;
|
|
33
76
|
}
|
|
34
77
|
/**
|
|
35
78
|
* @private
|
|
@@ -37,608 +80,238 @@ class EngineService {
|
|
|
37
80
|
static async init(namespace, appId, guid, config, logger) {
|
|
38
81
|
if (config.engine) {
|
|
39
82
|
const instance = new EngineService();
|
|
40
|
-
|
|
83
|
+
Init.verifyEngineFields(config);
|
|
41
84
|
instance.namespace = namespace;
|
|
42
85
|
instance.appId = appId;
|
|
43
86
|
instance.guid = guid;
|
|
44
87
|
instance.logger = logger;
|
|
45
|
-
await
|
|
46
|
-
await
|
|
47
|
-
|
|
48
|
-
await
|
|
49
|
-
await
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
await registry_1.StreamConsumerRegistry.registerEngine(namespace, appId, guid, instance.processStreamMessage.bind(instance), instance.stream, instance.store, logger, {
|
|
53
|
-
reclaimDelay: config.engine.reclaimDelay,
|
|
54
|
-
reclaimCount: config.engine.reclaimCount,
|
|
55
|
-
});
|
|
56
|
-
instance.taskService = new task_1.TaskService(instance.store, logger);
|
|
57
|
-
instance.exporter = new exporter_1.ExporterService(instance.appId, instance.store, logger);
|
|
58
|
-
instance.inited = (0, utils_1.formatISODate)(new Date());
|
|
88
|
+
await Init.initSearchChannel(instance, config.engine.store);
|
|
89
|
+
await Init.initStoreChannel(instance, config.engine.store);
|
|
90
|
+
await Init.initSubChannel(instance, config.engine.sub, config.engine.pub ?? config.engine.store);
|
|
91
|
+
await Init.initStreamChannel(instance, config.engine.stream, config.engine.store);
|
|
92
|
+
instance.router = await Init.initRouter(instance, config);
|
|
93
|
+
await Init.registerStreamConsumer(instance, config);
|
|
94
|
+
Init.initServices(instance);
|
|
59
95
|
return instance;
|
|
60
96
|
}
|
|
61
97
|
}
|
|
62
98
|
/**
|
|
63
99
|
* @private
|
|
64
100
|
*/
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
!(0, utils_1.identifyProvider)(config.engine.stream) ||
|
|
68
|
-
!(0, utils_1.identifyProvider)(config.engine.sub)) {
|
|
69
|
-
throw new Error('engine must include `store`, `stream`, and `sub` fields.');
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* @private
|
|
74
|
-
*/
|
|
75
|
-
async initSearchChannel(search, store) {
|
|
76
|
-
this.search = await factory_1.SearchServiceFactory.init(search, store, this.namespace, this.appId, this.logger);
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* @private
|
|
80
|
-
*/
|
|
81
|
-
async initStoreChannel(store) {
|
|
82
|
-
this.store = await factory_2.StoreServiceFactory.init(store, this.namespace, this.appId, this.logger);
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* @private
|
|
86
|
-
*/
|
|
87
|
-
async initSubChannel(sub, store) {
|
|
88
|
-
this.subscribe = await factory_4.SubServiceFactory.init(sub, store, this.namespace, this.appId, this.guid, this.logger);
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* @private
|
|
92
|
-
*/
|
|
93
|
-
async initStreamChannel(stream, store) {
|
|
94
|
-
this.stream = await factory_3.StreamServiceFactory.init(stream, store, this.namespace, this.appId, this.logger);
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* @private
|
|
98
|
-
*/
|
|
99
|
-
async initRouter(config) {
|
|
100
|
-
const throttle = await this.store.getThrottleRate(':');
|
|
101
|
-
return new router_1.Router({
|
|
102
|
-
namespace: this.namespace,
|
|
103
|
-
appId: this.appId,
|
|
104
|
-
guid: this.guid,
|
|
105
|
-
role: stream_1.StreamRole.ENGINE,
|
|
106
|
-
reclaimDelay: config.engine.reclaimDelay,
|
|
107
|
-
reclaimCount: config.engine.reclaimCount,
|
|
108
|
-
throttle,
|
|
109
|
-
readonly: config.engine.readonly,
|
|
110
|
-
}, this.stream, this.logger);
|
|
101
|
+
async getSettings() {
|
|
102
|
+
return Init.getSettings(this);
|
|
111
103
|
}
|
|
104
|
+
// ═════════════════════════════════════════════════════════════════
|
|
105
|
+
// 2. VERSION — app version resolution and cache management
|
|
106
|
+
// → see version.ts
|
|
107
|
+
// ═════════════════════════════════════════════════════════════════
|
|
112
108
|
/**
|
|
113
|
-
* resolves the distributed executable version using a delay
|
|
114
|
-
* to allow deployment race conditions to resolve
|
|
115
109
|
* @private
|
|
116
110
|
*/
|
|
117
|
-
async fetchAndVerifyVID(vid, count = 0) {
|
|
118
|
-
if (isNaN(Number(vid.version))) {
|
|
119
|
-
const app = await this.store.getApp(vid.id, true);
|
|
120
|
-
if (!isNaN(Number(app.version))) {
|
|
121
|
-
if (!this.apps)
|
|
122
|
-
this.apps = {};
|
|
123
|
-
this.apps[vid.id] = app;
|
|
124
|
-
return { id: vid.id, version: app.version };
|
|
125
|
-
}
|
|
126
|
-
else if (count < 10) {
|
|
127
|
-
await (0, utils_1.sleepFor)(enums_1.HMSH_QUORUM_DELAY_MS * 2);
|
|
128
|
-
return await this.fetchAndVerifyVID(vid, count + 1);
|
|
129
|
-
}
|
|
130
|
-
else {
|
|
131
|
-
this.logger.error('engine-vid-resolution-error', {
|
|
132
|
-
id: vid.id,
|
|
133
|
-
guid: this.guid,
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
return vid;
|
|
138
|
-
}
|
|
139
111
|
async getVID(vid) {
|
|
140
|
-
|
|
141
|
-
const app = await this.store.getApp(this.appId, true);
|
|
142
|
-
if (app.version.toString() === this.untilVersion.toString()) {
|
|
143
|
-
//new version is deployed; OK to cache again
|
|
144
|
-
if (!this.apps)
|
|
145
|
-
this.apps = {};
|
|
146
|
-
this.apps[this.appId] = app;
|
|
147
|
-
this.setCacheMode('cache', app.version.toString());
|
|
148
|
-
}
|
|
149
|
-
return { id: this.appId, version: app.version };
|
|
150
|
-
}
|
|
151
|
-
else if (!this.apps && vid) {
|
|
152
|
-
this.apps = {};
|
|
153
|
-
this.apps[this.appId] = vid;
|
|
154
|
-
return vid;
|
|
155
|
-
}
|
|
156
|
-
else {
|
|
157
|
-
return await this.fetchAndVerifyVID({
|
|
158
|
-
id: this.appId,
|
|
159
|
-
version: this.apps?.[this.appId].version,
|
|
160
|
-
});
|
|
161
|
-
}
|
|
112
|
+
return Version.getVID(this, vid);
|
|
162
113
|
}
|
|
163
114
|
/**
|
|
164
115
|
* @private
|
|
165
116
|
*/
|
|
166
117
|
setCacheMode(cacheMode, untilVersion) {
|
|
167
|
-
|
|
168
|
-
mode: cacheMode,
|
|
169
|
-
[cacheMode === 'cache' ? 'target' : 'until']: untilVersion,
|
|
170
|
-
});
|
|
171
|
-
this.cacheMode = cacheMode;
|
|
172
|
-
this.untilVersion = untilVersion;
|
|
118
|
+
Version.setCacheMode(this, cacheMode, untilVersion);
|
|
173
119
|
}
|
|
120
|
+
// ═════════════════════════════════════════════════════════════════
|
|
121
|
+
// 3. SCHEMA — activity schema lookup and handler instantiation
|
|
122
|
+
// → see schema.ts
|
|
123
|
+
// ═════════════════════════════════════════════════════════════════
|
|
174
124
|
/**
|
|
175
125
|
* @private
|
|
176
126
|
*/
|
|
177
|
-
async
|
|
178
|
-
|
|
179
|
-
if (jobCallback) {
|
|
180
|
-
this.delistJobCallback(message.metadata.jid);
|
|
181
|
-
jobCallback(topic, message);
|
|
182
|
-
}
|
|
127
|
+
async initActivity(topic, data = {}, context) {
|
|
128
|
+
return Schema.initActivity(this, topic, data, context);
|
|
183
129
|
}
|
|
184
130
|
/**
|
|
185
131
|
* @private
|
|
186
132
|
*/
|
|
187
|
-
async
|
|
188
|
-
|
|
133
|
+
async getSchema(topic) {
|
|
134
|
+
return Schema.getSchema(this, topic);
|
|
189
135
|
}
|
|
190
136
|
/**
|
|
191
137
|
* @private
|
|
192
138
|
*/
|
|
193
|
-
|
|
194
|
-
|
|
139
|
+
isPrivate(topic) {
|
|
140
|
+
return Schema.isPrivate(topic);
|
|
195
141
|
}
|
|
142
|
+
// ═════════════════════════════════════════════════════════════════
|
|
143
|
+
// 4. COMPILE — YAML app plan & deploy
|
|
144
|
+
// → see compiler.ts
|
|
145
|
+
// ═════════════════════════════════════════════════════════════════
|
|
196
146
|
/**
|
|
197
147
|
* @private
|
|
198
148
|
*/
|
|
199
|
-
async
|
|
200
|
-
|
|
201
|
-
this.router?.setThrottle(delayInMillis);
|
|
202
|
-
}
|
|
203
|
-
catch (e) {
|
|
204
|
-
this.logger.error('engine-throttle-error', { error: e });
|
|
205
|
-
}
|
|
149
|
+
async plan(pathOrYAML) {
|
|
150
|
+
return Compiler.plan(this, pathOrYAML);
|
|
206
151
|
}
|
|
207
|
-
// ************* METADATA/MODEL METHODS *************
|
|
208
152
|
/**
|
|
209
153
|
* @private
|
|
210
154
|
*/
|
|
211
|
-
async
|
|
212
|
-
|
|
213
|
-
if (!schema) {
|
|
214
|
-
throw new Error(`Activity schema not found for "${activityId}" (topic: ${topic}) in app ${this.appId}`);
|
|
215
|
-
}
|
|
216
|
-
const ActivityHandler = activities_1.default[schema.type];
|
|
217
|
-
if (ActivityHandler) {
|
|
218
|
-
const utc = (0, utils_1.formatISODate)(new Date());
|
|
219
|
-
const metadata = {
|
|
220
|
-
aid: activityId,
|
|
221
|
-
atp: schema.type,
|
|
222
|
-
stp: schema.subtype,
|
|
223
|
-
ac: utc,
|
|
224
|
-
au: utc,
|
|
225
|
-
};
|
|
226
|
-
const hook = null;
|
|
227
|
-
return new ActivityHandler(schema, data, metadata, hook, this, context);
|
|
228
|
-
}
|
|
229
|
-
else {
|
|
230
|
-
throw new Error(`activity type ${schema.type} not found`);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
async getSchema(topic) {
|
|
234
|
-
const app = (await this.store.getApp(this.appId));
|
|
235
|
-
if (!app) {
|
|
236
|
-
throw new Error(`no app found for id ${this.appId}`);
|
|
237
|
-
}
|
|
238
|
-
if (this.isPrivate(topic)) {
|
|
239
|
-
//private subscriptions use the schema id (.activityId)
|
|
240
|
-
const activityId = topic.substring(1);
|
|
241
|
-
const schema = await this.store.getSchema(activityId, await this.getVID(app));
|
|
242
|
-
return [activityId, schema];
|
|
243
|
-
}
|
|
244
|
-
else {
|
|
245
|
-
//public subscriptions use a topic (a.b.c) that is associated with a schema id
|
|
246
|
-
const activityId = await this.store.getSubscription(topic, await this.getVID(app));
|
|
247
|
-
if (activityId) {
|
|
248
|
-
const schema = await this.store.getSchema(activityId, await this.getVID(app));
|
|
249
|
-
return [activityId, schema];
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
throw new Error(`no subscription found for topic ${topic} in app ${this.appId} for app version ${app.version}`);
|
|
155
|
+
async deploy(pathOrYAML) {
|
|
156
|
+
return Compiler.deploy(this, pathOrYAML);
|
|
253
157
|
}
|
|
158
|
+
// ═════════════════════════════════════════════════════════════════
|
|
159
|
+
// 5. REPORT — stats queries and job-ID lookups
|
|
160
|
+
// → see reporting.ts
|
|
161
|
+
// ═════════════════════════════════════════════════════════════════
|
|
254
162
|
/**
|
|
255
163
|
* @private
|
|
256
164
|
*/
|
|
257
|
-
async
|
|
258
|
-
return
|
|
165
|
+
async getStats(topic, query) {
|
|
166
|
+
return Reporting.getStats(this, topic, query);
|
|
259
167
|
}
|
|
260
168
|
/**
|
|
261
169
|
* @private
|
|
262
170
|
*/
|
|
263
|
-
|
|
264
|
-
return
|
|
171
|
+
async getIds(topic, query, queryFacets = []) {
|
|
172
|
+
return Reporting.getIds(this, topic, query, queryFacets);
|
|
265
173
|
}
|
|
266
|
-
// ************* COMPILER METHODS *************
|
|
267
174
|
/**
|
|
268
175
|
* @private
|
|
269
176
|
*/
|
|
270
|
-
async
|
|
271
|
-
|
|
272
|
-
return await compiler.plan(pathOrYAML);
|
|
177
|
+
async resolveQuery(topic, query) {
|
|
178
|
+
return Reporting.resolveQuery(this, topic, query);
|
|
273
179
|
}
|
|
180
|
+
// ═════════════════════════════════════════════════════════════════
|
|
181
|
+
// 6. DISPATCH — stream message routing to activity handlers
|
|
182
|
+
// → see dispatch.ts
|
|
183
|
+
// ═════════════════════════════════════════════════════════════════
|
|
274
184
|
/**
|
|
275
185
|
* @private
|
|
276
186
|
*/
|
|
277
|
-
async
|
|
278
|
-
|
|
279
|
-
return await compiler.deploy(pathOrYAML);
|
|
187
|
+
async processStreamMessage(streamData) {
|
|
188
|
+
return Dispatch.processStreamMessage(this, streamData);
|
|
280
189
|
}
|
|
281
|
-
//
|
|
190
|
+
// ═════════════════════════════════════════════════════════════════
|
|
191
|
+
// 7. COMPLETION — parent notification, cleanup, and expiry
|
|
192
|
+
// → see completion.ts
|
|
193
|
+
// ═════════════════════════════════════════════════════════════════
|
|
282
194
|
/**
|
|
283
195
|
* @private
|
|
284
196
|
*/
|
|
285
|
-
async
|
|
286
|
-
|
|
287
|
-
const reporter = new reporter_1.ReporterService({ id, version }, this.store, this.logger);
|
|
288
|
-
const resolvedQuery = await this.resolveQuery(topic, query);
|
|
289
|
-
return await reporter.getStats(resolvedQuery);
|
|
197
|
+
async execAdjacentParent(context, jobOutput, emit = false, transaction) {
|
|
198
|
+
return Completion.execAdjacentParent(this, context, jobOutput, emit, transaction);
|
|
290
199
|
}
|
|
291
200
|
/**
|
|
292
201
|
* @private
|
|
293
202
|
*/
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
const reporter = new reporter_1.ReporterService({ id, version }, this.store, this.logger);
|
|
297
|
-
const resolvedQuery = await this.resolveQuery(topic, query);
|
|
298
|
-
return await reporter.getIds(resolvedQuery, queryFacets);
|
|
203
|
+
hasParentJob(context, checkSevered = false) {
|
|
204
|
+
return Completion.hasParentJob(context, checkSevered);
|
|
299
205
|
}
|
|
300
206
|
/**
|
|
301
207
|
* @private
|
|
302
208
|
*/
|
|
303
|
-
async
|
|
304
|
-
|
|
305
|
-
await trigger.getState();
|
|
306
|
-
return {
|
|
307
|
-
end: query.end,
|
|
308
|
-
start: query.start,
|
|
309
|
-
range: query.range,
|
|
310
|
-
granularity: trigger.resolveGranularity(),
|
|
311
|
-
key: trigger.resolveJobKey(trigger.createInputContext()),
|
|
312
|
-
sparse: query.sparse,
|
|
313
|
-
};
|
|
209
|
+
async interrupt(topic, jobId, options = {}) {
|
|
210
|
+
return Completion.interrupt(this, topic, jobId, options);
|
|
314
211
|
}
|
|
315
|
-
// ****************** STREAM RE-ENTRY POINT *****************
|
|
316
212
|
/**
|
|
317
213
|
* @private
|
|
318
214
|
*/
|
|
319
|
-
async
|
|
320
|
-
|
|
321
|
-
jid: streamData.metadata.jid,
|
|
322
|
-
gid: streamData.metadata.gid,
|
|
323
|
-
dad: streamData.metadata.dad,
|
|
324
|
-
aid: streamData.metadata.aid,
|
|
325
|
-
status: streamData.status || stream_1.StreamStatus.SUCCESS,
|
|
326
|
-
code: streamData.code || 200,
|
|
327
|
-
type: streamData.type,
|
|
328
|
-
});
|
|
329
|
-
const context = {
|
|
330
|
-
metadata: {
|
|
331
|
-
guid: streamData.metadata.guid,
|
|
332
|
-
jid: streamData.metadata.jid,
|
|
333
|
-
gid: streamData.metadata.gid,
|
|
334
|
-
dad: streamData.metadata.dad,
|
|
335
|
-
aid: streamData.metadata.aid,
|
|
336
|
-
},
|
|
337
|
-
data: streamData.data,
|
|
338
|
-
};
|
|
339
|
-
if (streamData.type === stream_1.StreamDataType.TIMEHOOK) {
|
|
340
|
-
//TIMEHOOK AWAKEN
|
|
341
|
-
const activityHandler = (await this.initActivity(`.${streamData.metadata.aid}`, context.data, context));
|
|
342
|
-
await activityHandler.processTimeHookEvent(streamData.metadata.jid);
|
|
343
|
-
}
|
|
344
|
-
else if (streamData.type === stream_1.StreamDataType.WEBHOOK) {
|
|
345
|
-
//WEBHOOK AWAKEN (SIGNAL IN)
|
|
346
|
-
const activityHandler = (await this.initActivity(`.${streamData.metadata.aid}`, context.data, context));
|
|
347
|
-
await activityHandler.processWebHookEvent(streamData.status, streamData.code);
|
|
348
|
-
}
|
|
349
|
-
else if (streamData.type === stream_1.StreamDataType.TRANSITION) {
|
|
350
|
-
//TRANSITION (ADJACENT ACTIVITY)
|
|
351
|
-
const activityHandler = (await this.initActivity(`.${streamData.metadata.aid}`, context.data, context)); //todo: `as Activity` (type is more generic)
|
|
352
|
-
await activityHandler.process();
|
|
353
|
-
}
|
|
354
|
-
else if (streamData.type === stream_1.StreamDataType.AWAIT) {
|
|
355
|
-
//TRIGGER JOB
|
|
356
|
-
context.metadata = {
|
|
357
|
-
...context.metadata,
|
|
358
|
-
pj: streamData.metadata.jid,
|
|
359
|
-
pg: streamData.metadata.gid,
|
|
360
|
-
pd: streamData.metadata.dad,
|
|
361
|
-
pa: streamData.metadata.aid,
|
|
362
|
-
px: streamData.metadata.await === false,
|
|
363
|
-
trc: streamData.metadata.trc,
|
|
364
|
-
spn: streamData.metadata.spn,
|
|
365
|
-
};
|
|
366
|
-
const activityHandler = (await this.initActivity(streamData.metadata.topic, streamData.data, context));
|
|
367
|
-
await activityHandler.process();
|
|
368
|
-
}
|
|
369
|
-
else if (streamData.type === stream_1.StreamDataType.RESULT) {
|
|
370
|
-
//AWAIT RESULT
|
|
371
|
-
const activityHandler = (await this.initActivity(`.${context.metadata.aid}`, streamData.data, context));
|
|
372
|
-
await activityHandler.processEvent(streamData.status, streamData.code);
|
|
373
|
-
}
|
|
374
|
-
else {
|
|
375
|
-
//WORKER RESULT
|
|
376
|
-
const activityHandler = (await this.initActivity(`.${streamData.metadata.aid}`, streamData.data, context));
|
|
377
|
-
await activityHandler.processEvent(streamData.status, streamData.code, 'output');
|
|
378
|
-
}
|
|
379
|
-
this.logger.debug('engine-process-end', {
|
|
380
|
-
jid: streamData.metadata.jid,
|
|
381
|
-
gid: streamData.metadata.gid,
|
|
382
|
-
aid: streamData.metadata.aid,
|
|
383
|
-
});
|
|
215
|
+
async scrub(jobId) {
|
|
216
|
+
return Completion.scrub(this, jobId);
|
|
384
217
|
}
|
|
385
|
-
// ***************** `AWAIT` ACTIVITY RETURN RESPONSE ****************
|
|
386
218
|
/**
|
|
387
219
|
* @private
|
|
388
220
|
*/
|
|
389
|
-
async
|
|
390
|
-
|
|
391
|
-
//errors are stringified `StreamError` objects
|
|
392
|
-
const error = this.resolveError(jobOutput.metadata);
|
|
393
|
-
const spn = context['$self']?.output?.metadata?.l2s ||
|
|
394
|
-
context['$self']?.output?.metadata?.l1s;
|
|
395
|
-
const streamData = {
|
|
396
|
-
metadata: {
|
|
397
|
-
guid: (0, utils_1.guid)(),
|
|
398
|
-
jid: context.metadata.pj,
|
|
399
|
-
gid: context.metadata.pg,
|
|
400
|
-
dad: context.metadata.pd,
|
|
401
|
-
aid: context.metadata.pa,
|
|
402
|
-
trc: context.metadata.trc,
|
|
403
|
-
spn,
|
|
404
|
-
},
|
|
405
|
-
type: stream_1.StreamDataType.RESULT,
|
|
406
|
-
data: jobOutput.data,
|
|
407
|
-
};
|
|
408
|
-
if (error && error.code) {
|
|
409
|
-
streamData.status = stream_1.StreamStatus.ERROR;
|
|
410
|
-
streamData.data = error;
|
|
411
|
-
streamData.code = error.code;
|
|
412
|
-
streamData.stack = error.stack;
|
|
413
|
-
}
|
|
414
|
-
else if (emit) {
|
|
415
|
-
streamData.status = stream_1.StreamStatus.PENDING;
|
|
416
|
-
streamData.code = enums_1.HMSH_CODE_PENDING;
|
|
417
|
-
}
|
|
418
|
-
else {
|
|
419
|
-
streamData.status = stream_1.StreamStatus.SUCCESS;
|
|
420
|
-
streamData.code = enums_1.HMSH_CODE_SUCCESS;
|
|
421
|
-
}
|
|
422
|
-
return (await this.router?.publishMessage(null, streamData, transaction));
|
|
423
|
-
}
|
|
221
|
+
async runJobCompletionTasks(context, options = {}, transaction) {
|
|
222
|
+
return Completion.runJobCompletionTasks(this, context, options, transaction);
|
|
424
223
|
}
|
|
224
|
+
// ═════════════════════════════════════════════════════════════════
|
|
225
|
+
// 8. SIGNAL — webhook/timehook delivery and fan-out
|
|
226
|
+
// → see signal.ts
|
|
227
|
+
// ═════════════════════════════════════════════════════════════════
|
|
425
228
|
/**
|
|
426
229
|
* @private
|
|
427
230
|
*/
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
return Boolean(context.metadata.pj && context.metadata.pa && !context.metadata.px);
|
|
431
|
-
}
|
|
432
|
-
return Boolean(context.metadata.pj && context.metadata.pa);
|
|
231
|
+
async signal(topic, data, status = stream_1.StreamStatus.SUCCESS, code = 200, transaction) {
|
|
232
|
+
return Signal.signal(this, topic, data, status, code, transaction);
|
|
433
233
|
}
|
|
434
234
|
/**
|
|
435
235
|
* @private
|
|
436
236
|
*/
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
return JSON.parse(metadata.err);
|
|
440
|
-
}
|
|
237
|
+
async hookTime(jobId, gId, topicOrActivity, type) {
|
|
238
|
+
return Signal.hookTime(this, jobId, gId, topicOrActivity, type);
|
|
441
239
|
}
|
|
442
|
-
// ****************** `INTERRUPT` ACTIVE JOBS *****************
|
|
443
240
|
/**
|
|
444
241
|
* @private
|
|
445
242
|
*/
|
|
446
|
-
async
|
|
447
|
-
|
|
448
|
-
await this.store.interrupt(topic, jobId, options);
|
|
449
|
-
//now that the job is interrupted, we can clean up
|
|
450
|
-
const context = (await this.getState(topic, jobId));
|
|
451
|
-
const completionOpts = {
|
|
452
|
-
interrupt: options.descend,
|
|
453
|
-
expire: options.expire,
|
|
454
|
-
};
|
|
455
|
-
return (await this.runJobCompletionTasks(context, completionOpts));
|
|
243
|
+
async signalAll(hookTopic, data, keyResolver, queryFacets = []) {
|
|
244
|
+
return Signal.signalAll(this, hookTopic, data, keyResolver, queryFacets);
|
|
456
245
|
}
|
|
457
|
-
// ****************** `SCRUB` CLEAN COMPLETED JOBS *****************
|
|
458
246
|
/**
|
|
459
247
|
* @private
|
|
460
248
|
*/
|
|
461
|
-
async
|
|
462
|
-
|
|
463
|
-
await this.store.scrub(jobId);
|
|
249
|
+
async routeToSubscribers(topic, message) {
|
|
250
|
+
return Signal.routeToSubscribers(this, topic, message);
|
|
464
251
|
}
|
|
465
|
-
// ****************** `SIGNAL` ACTIVITY RE-ENTRY POINT ****************
|
|
466
252
|
/**
|
|
467
|
-
* Delivers a signal (data payload) to a paused hook activity,
|
|
468
|
-
* resuming its Leg 2 execution. The `topic` must match a hook rule
|
|
469
|
-
* defined in the YAML graph's `hooks` section. The engine locates
|
|
470
|
-
* the target activity and dimension for reentry based on the hook
|
|
471
|
-
* rule's match conditions.
|
|
472
|
-
*
|
|
473
253
|
* @private
|
|
474
254
|
*/
|
|
475
|
-
async
|
|
476
|
-
|
|
477
|
-
const [aid] = await this.getSchema(`.${hookRule.to}`);
|
|
478
|
-
const streamData = {
|
|
479
|
-
type: stream_1.StreamDataType.WEBHOOK,
|
|
480
|
-
status,
|
|
481
|
-
code,
|
|
482
|
-
metadata: {
|
|
483
|
-
guid: (0, utils_1.guid)(),
|
|
484
|
-
aid,
|
|
485
|
-
topic,
|
|
486
|
-
},
|
|
487
|
-
data,
|
|
488
|
-
};
|
|
489
|
-
return (await this.router?.publishMessage(null, streamData, transaction));
|
|
255
|
+
async processWebHooks() {
|
|
256
|
+
return Signal.processWebHooks(this, this.signal.bind(this));
|
|
490
257
|
}
|
|
491
258
|
/**
|
|
492
259
|
* @private
|
|
493
260
|
*/
|
|
494
|
-
async
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
expire: 1,
|
|
499
|
-
});
|
|
500
|
-
}
|
|
501
|
-
const [aid, ...dimensions] = topicOrActivity.split(',');
|
|
502
|
-
const dad = `,${dimensions.join(',')}`;
|
|
503
|
-
const streamData = {
|
|
504
|
-
type: stream_1.StreamDataType.TIMEHOOK,
|
|
505
|
-
metadata: {
|
|
506
|
-
guid: (0, utils_1.guid)(),
|
|
507
|
-
jid: jobId,
|
|
508
|
-
gid: gId,
|
|
509
|
-
dad,
|
|
510
|
-
aid,
|
|
511
|
-
},
|
|
512
|
-
data: { timestamp: Date.now() },
|
|
513
|
-
};
|
|
514
|
-
await this.router?.publishMessage(null, streamData);
|
|
515
|
-
}
|
|
516
|
-
/**
|
|
517
|
-
* Fan-out variant of `signal()` that delivers data to **all**
|
|
518
|
-
* paused workflows matching a search query. Useful for resuming
|
|
519
|
-
* a batch of workflows waiting on the same external event.
|
|
520
|
-
*
|
|
261
|
+
async processTimeHooks() {
|
|
262
|
+
return Signal.processTimeHooks(this, this.hookTime.bind(this));
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
521
265
|
* @private
|
|
522
266
|
*/
|
|
523
|
-
async
|
|
524
|
-
|
|
525
|
-
const hookRule = await this.taskService.getHookRule(hookTopic);
|
|
526
|
-
if (hookRule) {
|
|
527
|
-
const subscriptionTopic = await (0, utils_1.getSubscriptionTopic)(hookRule.to, this.store, config);
|
|
528
|
-
const resolvedQuery = await this.resolveQuery(subscriptionTopic, keyResolver);
|
|
529
|
-
const reporter = new reporter_1.ReporterService(config, this.store, this.logger);
|
|
530
|
-
const workItems = await reporter.getWorkItems(resolvedQuery, queryFacets);
|
|
531
|
-
if (workItems.length) {
|
|
532
|
-
const taskService = new task_1.TaskService(this.store, this.logger);
|
|
533
|
-
await taskService.enqueueWorkItems(workItems.map((workItem) => [
|
|
534
|
-
hookTopic,
|
|
535
|
-
workItem,
|
|
536
|
-
keyResolver.scrub || false,
|
|
537
|
-
JSON.stringify(data),
|
|
538
|
-
].join(key_1.VALSEP)));
|
|
539
|
-
this.subscribe.publish(key_1.KeyType.QUORUM, { type: 'work', originator: this.guid }, this.appId);
|
|
540
|
-
}
|
|
541
|
-
return workItems;
|
|
542
|
-
}
|
|
543
|
-
else {
|
|
544
|
-
throw new Error(`unable to find hook rule for topic ${hookTopic}`);
|
|
545
|
-
}
|
|
267
|
+
async throttle(delayInMillis) {
|
|
268
|
+
return Signal.throttle(this, delayInMillis);
|
|
546
269
|
}
|
|
547
|
-
//
|
|
270
|
+
// ═════════════════════════════════════════════════════════════════
|
|
271
|
+
// 9. PUB/SUB — topic messaging, subscriptions, callbacks
|
|
272
|
+
// → see pubsub.ts
|
|
273
|
+
// ═════════════════════════════════════════════════════════════════
|
|
548
274
|
/**
|
|
549
275
|
* @private
|
|
550
276
|
*/
|
|
551
277
|
async pub(topic, data, context, extended) {
|
|
552
|
-
|
|
553
|
-
if (activityHandler) {
|
|
554
|
-
return await activityHandler.process(extended);
|
|
555
|
-
}
|
|
556
|
-
else {
|
|
557
|
-
throw new Error(`unable to process activity for topic ${topic}`);
|
|
558
|
-
}
|
|
278
|
+
return PubSub.pub(this, topic, data, context, extended);
|
|
559
279
|
}
|
|
560
280
|
/**
|
|
561
281
|
* @private
|
|
562
282
|
*/
|
|
563
283
|
async sub(topic, callback) {
|
|
564
|
-
|
|
565
|
-
let jobOutput = message.job;
|
|
566
|
-
// If _ref is true, payload was too large - fetch full job data via getState
|
|
567
|
-
if (message._ref && message.job?.metadata) {
|
|
568
|
-
jobOutput = await this.getState(message.job.metadata.tpc, message.job.metadata.jid);
|
|
569
|
-
}
|
|
570
|
-
callback(message.topic, jobOutput);
|
|
571
|
-
};
|
|
572
|
-
return await this.subscribe.subscribe(key_1.KeyType.QUORUM, subscriptionCallback, this.appId, topic);
|
|
284
|
+
return PubSub.sub(this, topic, callback);
|
|
573
285
|
}
|
|
574
286
|
/**
|
|
575
287
|
* @private
|
|
576
288
|
*/
|
|
577
289
|
async unsub(topic) {
|
|
578
|
-
return
|
|
290
|
+
return PubSub.unsub(this, topic);
|
|
579
291
|
}
|
|
580
292
|
/**
|
|
581
293
|
* @private
|
|
582
294
|
*/
|
|
583
295
|
async psub(wild, callback) {
|
|
584
|
-
|
|
585
|
-
let jobOutput = message.job;
|
|
586
|
-
// If _ref is true, payload was too large - fetch full job data via getState
|
|
587
|
-
if (message._ref && message.job?.metadata) {
|
|
588
|
-
jobOutput = await this.getState(message.job.metadata.tpc, message.job.metadata.jid);
|
|
589
|
-
}
|
|
590
|
-
callback(message.topic, jobOutput);
|
|
591
|
-
};
|
|
592
|
-
return await this.subscribe.psubscribe(key_1.KeyType.QUORUM, subscriptionCallback, this.appId, wild);
|
|
296
|
+
return PubSub.psub(this, wild, callback);
|
|
593
297
|
}
|
|
594
298
|
/**
|
|
595
299
|
* @private
|
|
596
300
|
*/
|
|
597
301
|
async punsub(wild) {
|
|
598
|
-
return
|
|
302
|
+
return PubSub.punsub(this, wild);
|
|
599
303
|
}
|
|
600
304
|
/**
|
|
601
305
|
* @private
|
|
602
306
|
*/
|
|
603
307
|
async pubsub(topic, data, context, timeout = enums_1.HMSH_OTT_WAIT_TIME) {
|
|
604
|
-
context
|
|
605
|
-
metadata: {
|
|
606
|
-
ngn: this.guid,
|
|
607
|
-
trc: context?.metadata?.trc,
|
|
608
|
-
spn: context?.metadata?.spn,
|
|
609
|
-
},
|
|
610
|
-
};
|
|
611
|
-
const jobId = await this.pub(topic, data, context);
|
|
612
|
-
return new Promise((resolve, reject) => {
|
|
613
|
-
this.registerJobCallback(jobId, (topic, output) => {
|
|
614
|
-
if (output.metadata.err) {
|
|
615
|
-
const error = JSON.parse(output.metadata.err);
|
|
616
|
-
reject({
|
|
617
|
-
error,
|
|
618
|
-
job_id: output.metadata.jid,
|
|
619
|
-
});
|
|
620
|
-
}
|
|
621
|
-
else {
|
|
622
|
-
resolve(output);
|
|
623
|
-
}
|
|
624
|
-
});
|
|
625
|
-
setTimeout(() => {
|
|
626
|
-
//note: job is still active (the subscriber timed out)
|
|
627
|
-
this.delistJobCallback(jobId);
|
|
628
|
-
reject({
|
|
629
|
-
code: enums_1.HMSH_CODE_TIMEOUT,
|
|
630
|
-
message: 'timeout',
|
|
631
|
-
job_id: jobId,
|
|
632
|
-
});
|
|
633
|
-
}, timeout);
|
|
634
|
-
});
|
|
308
|
+
return PubSub.pubsub(this, topic, data, context, timeout);
|
|
635
309
|
}
|
|
636
310
|
/**
|
|
637
311
|
* @private
|
|
638
312
|
*/
|
|
639
313
|
async pubOneTimeSubs(context, jobOutput, emit = false, transaction) {
|
|
640
|
-
|
|
641
|
-
if (this.hasOneTimeSubscription(context)) {
|
|
314
|
+
if (PubSub.hasOneTimeSubscription(context)) {
|
|
642
315
|
const message = {
|
|
643
316
|
type: 'job',
|
|
644
317
|
topic: context.metadata.jid,
|
|
@@ -647,20 +320,11 @@ class EngineService {
|
|
|
647
320
|
await this.subscribe.publish(key_1.KeyType.QUORUM, message, this.appId, context.metadata.ngn, transaction);
|
|
648
321
|
}
|
|
649
322
|
}
|
|
650
|
-
/**
|
|
651
|
-
* @private
|
|
652
|
-
*/
|
|
653
|
-
async getPublishesTopic(context) {
|
|
654
|
-
const config = await this.getVID();
|
|
655
|
-
const activityId = context.metadata.aid || context['$self']?.output?.metadata?.aid;
|
|
656
|
-
const schema = await this.store.getSchema(activityId, config);
|
|
657
|
-
return schema.publishes;
|
|
658
|
-
}
|
|
659
323
|
/**
|
|
660
324
|
* @private
|
|
661
325
|
*/
|
|
662
326
|
async pubPermSubs(context, jobOutput, emit = false, transaction) {
|
|
663
|
-
const topic = await
|
|
327
|
+
const topic = await PubSub.getPublishesTopic(this, context);
|
|
664
328
|
if (topic) {
|
|
665
329
|
const message = {
|
|
666
330
|
type: 'job',
|
|
@@ -673,135 +337,73 @@ class EngineService {
|
|
|
673
337
|
/**
|
|
674
338
|
* @private
|
|
675
339
|
*/
|
|
676
|
-
async
|
|
677
|
-
return (
|
|
678
|
-
}
|
|
679
|
-
/**
|
|
680
|
-
* @private
|
|
681
|
-
*/
|
|
682
|
-
registerJobCallback(jobId, jobCallback) {
|
|
683
|
-
this.jobCallbacks[jobId] = jobCallback;
|
|
340
|
+
async getPublishesTopic(context) {
|
|
341
|
+
return PubSub.getPublishesTopic(this, context);
|
|
684
342
|
}
|
|
685
343
|
/**
|
|
686
344
|
* @private
|
|
687
345
|
*/
|
|
688
|
-
|
|
689
|
-
|
|
346
|
+
async add(streamData) {
|
|
347
|
+
return PubSub.add(this, streamData);
|
|
690
348
|
}
|
|
691
349
|
/**
|
|
692
350
|
* @private
|
|
693
351
|
*/
|
|
694
|
-
|
|
695
|
-
|
|
352
|
+
registerJobCallback(jobId, jobCallback) {
|
|
353
|
+
PubSub.registerJobCallback(this, jobId, jobCallback);
|
|
696
354
|
}
|
|
697
|
-
// ********** JOB COMPLETION/CLEANUP (AND JOB EMIT) ***********
|
|
698
355
|
/**
|
|
699
356
|
* @private
|
|
700
357
|
*/
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
const isAwait = this.hasParentJob(context, true);
|
|
704
|
-
const isOneTimeSub = this.hasOneTimeSubscription(context);
|
|
705
|
-
const topic = await this.getPublishesTopic(context);
|
|
706
|
-
let msgId;
|
|
707
|
-
let jobOutput;
|
|
708
|
-
if (isAwait || isOneTimeSub || topic) {
|
|
709
|
-
jobOutput = await this.getState(context.metadata.tpc, context.metadata.jid);
|
|
710
|
-
//only send RESULT to parent for non-severed children (execChild).
|
|
711
|
-
//startChild (px=true) children already sent RESULT at spawn time
|
|
712
|
-
//via Trigger.execAdjacentParent; sending again here would cause
|
|
713
|
-
//a duplicate semaphore decrement in collation workflows.
|
|
714
|
-
if (isAwait) {
|
|
715
|
-
msgId = await this.execAdjacentParent(context, jobOutput, options.emit, transaction);
|
|
716
|
-
}
|
|
717
|
-
if (transaction) {
|
|
718
|
-
//transactional: await to queue NOTIFY in the transaction
|
|
719
|
-
await this.pubOneTimeSubs(context, jobOutput, options.emit, transaction);
|
|
720
|
-
await this.pubPermSubs(context, jobOutput, options.emit, transaction);
|
|
721
|
-
}
|
|
722
|
-
else {
|
|
723
|
-
//non-transactional: fire-and-forget to avoid race with inline
|
|
724
|
-
//trigger processing (callback registered after pub() returns)
|
|
725
|
-
this.pubOneTimeSubs(context, jobOutput, options.emit);
|
|
726
|
-
this.pubPermSubs(context, jobOutput, options.emit);
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
if (!options.emit) {
|
|
730
|
-
if (transaction) {
|
|
731
|
-
await this.taskService.registerJobForCleanup(context.metadata.jid, this.resolveExpires(context, options), options, transaction);
|
|
732
|
-
}
|
|
733
|
-
else {
|
|
734
|
-
this.taskService.registerJobForCleanup(context.metadata.jid, this.resolveExpires(context, options), options);
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
return msgId;
|
|
358
|
+
delistJobCallback(jobId) {
|
|
359
|
+
PubSub.removeJobCallback(this, jobId);
|
|
738
360
|
}
|
|
739
361
|
/**
|
|
740
|
-
* Job hash expiration is typically reliant on the metadata field
|
|
741
|
-
* if the activity concludes normally. However, if the job is `interrupted`,
|
|
742
|
-
* it will be expired immediately.
|
|
743
362
|
* @private
|
|
744
363
|
*/
|
|
745
|
-
|
|
746
|
-
return
|
|
364
|
+
hasOneTimeSubscription(context) {
|
|
365
|
+
return PubSub.hasOneTimeSubscription(context);
|
|
747
366
|
}
|
|
748
|
-
//
|
|
367
|
+
// ═════════════════════════════════════════════════════════════════
|
|
368
|
+
// 10. STATE — job state retrieval, export, and compression
|
|
369
|
+
// → see state.ts
|
|
370
|
+
// ═════════════════════════════════════════════════════════════════
|
|
749
371
|
/**
|
|
750
372
|
* @private
|
|
751
373
|
*/
|
|
752
374
|
async export(jobId, options = {}) {
|
|
753
|
-
return
|
|
375
|
+
return State.exportJob(this, jobId, options);
|
|
754
376
|
}
|
|
755
377
|
/**
|
|
756
378
|
* @private
|
|
757
379
|
*/
|
|
758
380
|
async getRaw(jobId) {
|
|
759
|
-
return
|
|
381
|
+
return State.getRaw(this, jobId);
|
|
760
382
|
}
|
|
761
383
|
/**
|
|
762
384
|
* @private
|
|
763
385
|
*/
|
|
764
386
|
async getStatus(jobId) {
|
|
765
|
-
|
|
766
|
-
return await this.store.getStatus(jobId, appId);
|
|
387
|
+
return State.getStatus(this, jobId);
|
|
767
388
|
}
|
|
768
389
|
/**
|
|
769
390
|
* @private
|
|
770
391
|
*/
|
|
771
392
|
async getState(topic, jobId) {
|
|
772
|
-
|
|
773
|
-
const consumes = {
|
|
774
|
-
[`$${topic}`]: Object.keys(jobSymbols),
|
|
775
|
-
};
|
|
776
|
-
//job data exists at the 'zero' dimension; pass an empty object
|
|
777
|
-
const dIds = {};
|
|
778
|
-
const output = await this.store.getState(jobId, consumes, dIds);
|
|
779
|
-
if (!output) {
|
|
780
|
-
throw new Error(`not found ${jobId}`);
|
|
781
|
-
}
|
|
782
|
-
const [state, status] = output;
|
|
783
|
-
const stateTree = (0, utils_1.restoreHierarchy)(state);
|
|
784
|
-
if (status != null && stateTree.metadata) {
|
|
785
|
-
stateTree.metadata.js = status;
|
|
786
|
-
}
|
|
787
|
-
return stateTree;
|
|
393
|
+
return State.getState(this, topic, jobId);
|
|
788
394
|
}
|
|
789
395
|
/**
|
|
790
396
|
* @private
|
|
791
397
|
*/
|
|
792
398
|
async getQueryState(jobId, fields) {
|
|
793
|
-
return
|
|
399
|
+
return State.getQueryState(this, jobId, fields);
|
|
794
400
|
}
|
|
795
401
|
/**
|
|
796
402
|
* @private
|
|
797
403
|
* @deprecated
|
|
798
404
|
*/
|
|
799
405
|
async compress(terms) {
|
|
800
|
-
|
|
801
|
-
const startIndex = Object.keys(existingSymbols).length;
|
|
802
|
-
const maxIndex = Math.pow(52, 2) - 1;
|
|
803
|
-
const newSymbols = serializer_1.SerializerService.filterSymVals(startIndex, maxIndex, existingSymbols, new Set(terms));
|
|
804
|
-
return await this.store.addSymbolValues(newSymbols);
|
|
406
|
+
return State.compress(this, terms);
|
|
805
407
|
}
|
|
806
408
|
}
|
|
807
409
|
exports.EngineService = EngineService;
|