@hotmeshio/hotmesh 0.0.1
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/LICENSE +214 -0
- package/README.md +241 -0
- package/build/index.d.ts +4 -0
- package/build/index.js +7 -0
- package/build/modules/errors.d.ts +28 -0
- package/build/modules/errors.js +50 -0
- package/build/modules/key.d.ts +75 -0
- package/build/modules/key.js +116 -0
- package/build/modules/utils.d.ts +34 -0
- package/build/modules/utils.js +173 -0
- package/build/package.json +73 -0
- package/build/services/activities/activity.d.ts +59 -0
- package/build/services/activities/activity.js +396 -0
- package/build/services/activities/await.d.ts +16 -0
- package/build/services/activities/await.js +143 -0
- package/build/services/activities/emit.d.ts +9 -0
- package/build/services/activities/emit.js +13 -0
- package/build/services/activities/index.d.ts +15 -0
- package/build/services/activities/index.js +16 -0
- package/build/services/activities/iterate.d.ts +9 -0
- package/build/services/activities/iterate.js +13 -0
- package/build/services/activities/trigger.d.ts +22 -0
- package/build/services/activities/trigger.js +161 -0
- package/build/services/activities/worker.d.ts +17 -0
- package/build/services/activities/worker.js +164 -0
- package/build/services/collator/index.d.ts +54 -0
- package/build/services/collator/index.js +171 -0
- package/build/services/compiler/deployer.d.ts +35 -0
- package/build/services/compiler/deployer.js +412 -0
- package/build/services/compiler/index.d.ts +30 -0
- package/build/services/compiler/index.js +111 -0
- package/build/services/compiler/validator.d.ts +32 -0
- package/build/services/compiler/validator.js +134 -0
- package/build/services/connector/clients/ioredis.d.ts +13 -0
- package/build/services/connector/clients/ioredis.js +50 -0
- package/build/services/connector/clients/redis.d.ts +13 -0
- package/build/services/connector/clients/redis.js +62 -0
- package/build/services/connector/index.d.ts +5 -0
- package/build/services/connector/index.js +31 -0
- package/build/services/dimension/index.d.ts +29 -0
- package/build/services/dimension/index.js +35 -0
- package/build/services/durable/asyncLocalStorage.d.ts +3 -0
- package/build/services/durable/asyncLocalStorage.js +5 -0
- package/build/services/durable/client.d.ts +15 -0
- package/build/services/durable/client.js +108 -0
- package/build/services/durable/connection.d.ts +4 -0
- package/build/services/durable/connection.js +51 -0
- package/build/services/durable/factory.d.ts +3 -0
- package/build/services/durable/factory.js +123 -0
- package/build/services/durable/handle.d.ts +8 -0
- package/build/services/durable/handle.js +38 -0
- package/build/services/durable/index.d.ts +57 -0
- package/build/services/durable/index.js +58 -0
- package/build/services/durable/native.d.ts +4 -0
- package/build/services/durable/native.js +47 -0
- package/build/services/durable/worker.d.ts +36 -0
- package/build/services/durable/worker.js +266 -0
- package/build/services/durable/workflow.d.ts +6 -0
- package/build/services/durable/workflow.js +135 -0
- package/build/services/engine/index.d.ts +82 -0
- package/build/services/engine/index.js +511 -0
- package/build/services/hotmesh/index.d.ts +45 -0
- package/build/services/hotmesh/index.js +134 -0
- package/build/services/logger/index.d.ts +17 -0
- package/build/services/logger/index.js +73 -0
- package/build/services/mapper/index.d.ts +24 -0
- package/build/services/mapper/index.js +72 -0
- package/build/services/pipe/functions/array.d.ts +24 -0
- package/build/services/pipe/functions/array.js +69 -0
- package/build/services/pipe/functions/bitwise.d.ts +9 -0
- package/build/services/pipe/functions/bitwise.js +24 -0
- package/build/services/pipe/functions/conditional.d.ts +10 -0
- package/build/services/pipe/functions/conditional.js +27 -0
- package/build/services/pipe/functions/date.d.ts +57 -0
- package/build/services/pipe/functions/date.js +167 -0
- package/build/services/pipe/functions/index.d.ts +25 -0
- package/build/services/pipe/functions/index.js +26 -0
- package/build/services/pipe/functions/json.d.ts +5 -0
- package/build/services/pipe/functions/json.js +12 -0
- package/build/services/pipe/functions/math.d.ts +38 -0
- package/build/services/pipe/functions/math.js +111 -0
- package/build/services/pipe/functions/number.d.ts +25 -0
- package/build/services/pipe/functions/number.js +133 -0
- package/build/services/pipe/functions/object.d.ts +22 -0
- package/build/services/pipe/functions/object.js +63 -0
- package/build/services/pipe/functions/string.d.ts +23 -0
- package/build/services/pipe/functions/string.js +69 -0
- package/build/services/pipe/functions/symbol.d.ts +12 -0
- package/build/services/pipe/functions/symbol.js +33 -0
- package/build/services/pipe/functions/unary.d.ts +7 -0
- package/build/services/pipe/functions/unary.js +18 -0
- package/build/services/pipe/index.d.ts +30 -0
- package/build/services/pipe/index.js +128 -0
- package/build/services/quorum/index.d.ts +34 -0
- package/build/services/quorum/index.js +147 -0
- package/build/services/reporter/index.d.ts +47 -0
- package/build/services/reporter/index.js +330 -0
- package/build/services/serializer/index.d.ts +36 -0
- package/build/services/serializer/index.js +222 -0
- package/build/services/signaler/store.d.ts +15 -0
- package/build/services/signaler/store.js +53 -0
- package/build/services/signaler/stream.d.ts +43 -0
- package/build/services/signaler/stream.js +317 -0
- package/build/services/store/cache.d.ts +66 -0
- package/build/services/store/cache.js +127 -0
- package/build/services/store/clients/ioredis.d.ts +27 -0
- package/build/services/store/clients/ioredis.js +96 -0
- package/build/services/store/clients/redis.d.ts +29 -0
- package/build/services/store/clients/redis.js +143 -0
- package/build/services/store/index.d.ts +88 -0
- package/build/services/store/index.js +657 -0
- package/build/services/stream/clients/ioredis.d.ts +23 -0
- package/build/services/stream/clients/ioredis.js +115 -0
- package/build/services/stream/clients/redis.d.ts +23 -0
- package/build/services/stream/clients/redis.js +119 -0
- package/build/services/stream/index.d.ts +21 -0
- package/build/services/stream/index.js +9 -0
- package/build/services/sub/clients/ioredis.d.ts +20 -0
- package/build/services/sub/clients/ioredis.js +72 -0
- package/build/services/sub/clients/redis.d.ts +20 -0
- package/build/services/sub/clients/redis.js +63 -0
- package/build/services/sub/index.d.ts +18 -0
- package/build/services/sub/index.js +9 -0
- package/build/services/task/index.d.ts +18 -0
- package/build/services/task/index.js +73 -0
- package/build/services/telemetry/index.d.ts +49 -0
- package/build/services/telemetry/index.js +223 -0
- package/build/services/worker/index.d.ts +30 -0
- package/build/services/worker/index.js +105 -0
- package/build/types/activity.d.ts +86 -0
- package/build/types/activity.js +2 -0
- package/build/types/app.d.ts +16 -0
- package/build/types/app.js +2 -0
- package/build/types/async.d.ts +5 -0
- package/build/types/async.js +2 -0
- package/build/types/cache.d.ts +1 -0
- package/build/types/cache.js +2 -0
- package/build/types/collator.d.ts +8 -0
- package/build/types/collator.js +11 -0
- package/build/types/durable.d.ts +59 -0
- package/build/types/durable.js +2 -0
- package/build/types/hook.d.ts +31 -0
- package/build/types/hook.js +9 -0
- package/build/types/hotmesh.d.ts +82 -0
- package/build/types/hotmesh.js +2 -0
- package/build/types/index.d.ts +20 -0
- package/build/types/index.js +21 -0
- package/build/types/ioredisclient.d.ts +5 -0
- package/build/types/ioredisclient.js +5 -0
- package/build/types/job.d.ts +50 -0
- package/build/types/job.js +2 -0
- package/build/types/logger.d.ts +6 -0
- package/build/types/logger.js +2 -0
- package/build/types/map.d.ts +4 -0
- package/build/types/map.js +2 -0
- package/build/types/pipe.d.ts +4 -0
- package/build/types/pipe.js +2 -0
- package/build/types/quorum.d.ts +46 -0
- package/build/types/quorum.js +2 -0
- package/build/types/redis.d.ts +8 -0
- package/build/types/redis.js +2 -0
- package/build/types/redisclient.d.ts +25 -0
- package/build/types/redisclient.js +2 -0
- package/build/types/serializer.d.ts +33 -0
- package/build/types/serializer.js +2 -0
- package/build/types/stats.d.ts +83 -0
- package/build/types/stats.js +2 -0
- package/build/types/stream.d.ts +67 -0
- package/build/types/stream.js +25 -0
- package/build/types/telemetry.d.ts +1 -0
- package/build/types/telemetry.js +11 -0
- package/build/types/transition.d.ts +17 -0
- package/build/types/transition.js +2 -0
- package/index.ts +5 -0
- package/modules/errors.ts +55 -0
- package/modules/key.ts +129 -0
- package/modules/utils.ts +170 -0
- package/package.json +73 -0
- package/services/activities/activity.ts +473 -0
- package/services/activities/await.ts +172 -0
- package/services/activities/emit.ts +25 -0
- package/services/activities/index.ts +15 -0
- package/services/activities/iterate.ts +26 -0
- package/services/activities/trigger.ts +196 -0
- package/services/activities/worker.ts +190 -0
- package/services/collator/README.md +102 -0
- package/services/collator/index.ts +182 -0
- package/services/compiler/deployer.ts +432 -0
- package/services/compiler/index.ts +98 -0
- package/services/compiler/validator.ts +154 -0
- package/services/connector/clients/ioredis.ts +57 -0
- package/services/connector/clients/redis.ts +72 -0
- package/services/connector/index.ts +44 -0
- package/services/dimension/README.md +73 -0
- package/services/dimension/index.ts +39 -0
- package/services/durable/asyncLocalStorage.ts +3 -0
- package/services/durable/client.ts +116 -0
- package/services/durable/connection.ts +50 -0
- package/services/durable/factory.ts +124 -0
- package/services/durable/handle.ts +43 -0
- package/services/durable/index.ts +60 -0
- package/services/durable/native.ts +46 -0
- package/services/durable/worker.ts +254 -0
- package/services/durable/workflow.ts +136 -0
- package/services/engine/index.ts +615 -0
- package/services/hotmesh/index.ts +182 -0
- package/services/logger/index.ts +79 -0
- package/services/mapper/index.ts +84 -0
- package/services/pipe/functions/array.ts +87 -0
- package/services/pipe/functions/bitwise.ts +27 -0
- package/services/pipe/functions/conditional.ts +31 -0
- package/services/pipe/functions/date.ts +214 -0
- package/services/pipe/functions/index.ts +25 -0
- package/services/pipe/functions/json.ts +11 -0
- package/services/pipe/functions/math.ts +143 -0
- package/services/pipe/functions/number.ts +150 -0
- package/services/pipe/functions/object.ts +79 -0
- package/services/pipe/functions/string.ts +86 -0
- package/services/pipe/functions/symbol.ts +39 -0
- package/services/pipe/functions/unary.ts +19 -0
- package/services/pipe/index.ts +138 -0
- package/services/quorum/index.ts +200 -0
- package/services/reporter/index.ts +379 -0
- package/services/serializer/README.md +10 -0
- package/services/serializer/index.ts +243 -0
- package/services/signaler/store.ts +61 -0
- package/services/signaler/stream.ts +354 -0
- package/services/store/cache.ts +172 -0
- package/services/store/clients/ioredis.ts +123 -0
- package/services/store/clients/redis.ts +169 -0
- package/services/store/index.ts +757 -0
- package/services/stream/clients/ioredis.ts +148 -0
- package/services/stream/clients/redis.ts +144 -0
- package/services/stream/index.ts +57 -0
- package/services/sub/clients/ioredis.ts +83 -0
- package/services/sub/clients/redis.ts +74 -0
- package/services/sub/index.ts +25 -0
- package/services/task/index.ts +86 -0
- package/services/telemetry/index.ts +267 -0
- package/services/worker/index.ts +165 -0
- package/types/activity.ts +115 -0
- package/types/app.ts +20 -0
- package/types/async.ts +7 -0
- package/types/cache.ts +1 -0
- package/types/collator.ts +9 -0
- package/types/durable.ts +81 -0
- package/types/hook.ts +32 -0
- package/types/hotmesh.ts +102 -0
- package/types/index.ts +138 -0
- package/types/ioredisclient.ts +10 -0
- package/types/job.ts +59 -0
- package/types/logger.ts +6 -0
- package/types/map.ts +5 -0
- package/types/ms.d.ts +7 -0
- package/types/pipe.ts +7 -0
- package/types/quorum.ts +59 -0
- package/types/redis.ts +27 -0
- package/types/redisclient.ts +29 -0
- package/types/serializer.ts +38 -0
- package/types/stats.ts +100 -0
- package/types/stream.ts +75 -0
- package/types/telemetry.ts +15 -0
- package/types/transition.ts +20 -0
|
@@ -0,0 +1,511 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.EngineService = void 0;
|
|
7
|
+
const key_1 = require("../../modules/key");
|
|
8
|
+
const utils_1 = require("../../modules/utils");
|
|
9
|
+
const activities_1 = __importDefault(require("../activities"));
|
|
10
|
+
const compiler_1 = require("../compiler");
|
|
11
|
+
const reporter_1 = require("../reporter");
|
|
12
|
+
const serializer_1 = require("../serializer");
|
|
13
|
+
const store_1 = require("../signaler/store");
|
|
14
|
+
const stream_1 = require("../signaler/stream");
|
|
15
|
+
const redis_1 = require("../store/clients/redis");
|
|
16
|
+
const ioredis_1 = require("../store/clients/ioredis");
|
|
17
|
+
const redis_2 = require("../stream/clients/redis");
|
|
18
|
+
const ioredis_2 = require("../stream/clients/ioredis");
|
|
19
|
+
const ioredis_3 = require("../sub/clients/ioredis");
|
|
20
|
+
const redis_3 = require("../sub/clients/redis");
|
|
21
|
+
const task_1 = require("../task");
|
|
22
|
+
const stream_2 = require("../../types/stream");
|
|
23
|
+
//wait time to see if a job is complete
|
|
24
|
+
const OTT_WAIT_TIME = 1000;
|
|
25
|
+
const STATUS_CODE_SUCCESS = 200;
|
|
26
|
+
const STATUS_CODE_TIMEOUT = 504;
|
|
27
|
+
class EngineService {
|
|
28
|
+
constructor() {
|
|
29
|
+
this.cacheMode = 'cache';
|
|
30
|
+
this.untilVersion = null;
|
|
31
|
+
this.jobCallbacks = {};
|
|
32
|
+
this.reporting = false;
|
|
33
|
+
this.jobId = 1;
|
|
34
|
+
}
|
|
35
|
+
static async init(namespace, appId, guid, config, logger) {
|
|
36
|
+
if (config.engine) {
|
|
37
|
+
const instance = new EngineService();
|
|
38
|
+
instance.verifyEngineFields(config);
|
|
39
|
+
instance.namespace = namespace;
|
|
40
|
+
instance.appId = appId;
|
|
41
|
+
instance.guid = guid;
|
|
42
|
+
instance.logger = logger;
|
|
43
|
+
await instance.initStoreChannel(config.engine.store);
|
|
44
|
+
await instance.initSubChannel(config.engine.sub);
|
|
45
|
+
await instance.initStreamChannel(config.engine.stream);
|
|
46
|
+
instance.streamSignaler = instance.initStreamSignaler(config);
|
|
47
|
+
instance.streamSignaler.consumeMessages(instance.stream.mintKey(key_1.KeyType.STREAMS, { appId: instance.appId }), 'ENGINE', instance.guid, instance.processStreamMessage.bind(instance));
|
|
48
|
+
//the storeSignaler service is used by the engine to create `webhooks`
|
|
49
|
+
//todo: unify/move to the task service (it manages all `signal` types)
|
|
50
|
+
instance.storeSignaler = new store_1.StoreSignaler(instance.store, logger);
|
|
51
|
+
//the task service is used by the engine to process `webhooks` and `timehooks`
|
|
52
|
+
instance.task = new task_1.TaskService(instance.store, logger);
|
|
53
|
+
return instance;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
verifyEngineFields(config) {
|
|
57
|
+
if (!(0, utils_1.identifyRedisType)(config.engine.store) ||
|
|
58
|
+
!(0, utils_1.identifyRedisType)(config.engine.stream) ||
|
|
59
|
+
!(0, utils_1.identifyRedisType)(config.engine.sub)) {
|
|
60
|
+
throw new Error('engine config must reference 3 redis client instances');
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async initStoreChannel(store) {
|
|
64
|
+
if ((0, utils_1.identifyRedisType)(store) === 'redis') {
|
|
65
|
+
this.store = new redis_1.RedisStoreService(store);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
this.store = new ioredis_1.IORedisStoreService(store);
|
|
69
|
+
}
|
|
70
|
+
await this.store.init(this.namespace, this.appId, this.logger);
|
|
71
|
+
}
|
|
72
|
+
async initSubChannel(sub) {
|
|
73
|
+
if ((0, utils_1.identifyRedisType)(sub) === 'redis') {
|
|
74
|
+
this.subscribe = new redis_3.RedisSubService(sub);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
this.subscribe = new ioredis_3.IORedisSubService(sub);
|
|
78
|
+
}
|
|
79
|
+
await this.subscribe.init(this.namespace, this.appId, this.guid, this.logger);
|
|
80
|
+
}
|
|
81
|
+
async initStreamChannel(stream) {
|
|
82
|
+
if ((0, utils_1.identifyRedisType)(stream) === 'redis') {
|
|
83
|
+
this.stream = new redis_2.RedisStreamService(stream);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
this.stream = new ioredis_2.IORedisStreamService(stream);
|
|
87
|
+
}
|
|
88
|
+
await this.stream.init(this.namespace, this.appId, this.logger);
|
|
89
|
+
}
|
|
90
|
+
initStreamSignaler(config) {
|
|
91
|
+
return new stream_1.StreamSignaler({
|
|
92
|
+
namespace: this.namespace,
|
|
93
|
+
appId: this.appId,
|
|
94
|
+
guid: this.guid,
|
|
95
|
+
role: stream_2.StreamRole.ENGINE,
|
|
96
|
+
reclaimDelay: config.engine.reclaimDelay,
|
|
97
|
+
reclaimCount: config.engine.reclaimCount,
|
|
98
|
+
}, this.stream, this.store, this.logger);
|
|
99
|
+
}
|
|
100
|
+
async getVID(vid) {
|
|
101
|
+
if (this.cacheMode === 'nocache') {
|
|
102
|
+
const app = await this.store.getApp(this.appId, true);
|
|
103
|
+
if (app.version.toString() === this.untilVersion.toString()) {
|
|
104
|
+
//new version is deployed; OK to cache again
|
|
105
|
+
if (!this.apps)
|
|
106
|
+
this.apps = {};
|
|
107
|
+
this.apps[this.appId] = app;
|
|
108
|
+
this.setCacheMode('cache', app.version.toString());
|
|
109
|
+
}
|
|
110
|
+
return { id: this.appId, version: app.version };
|
|
111
|
+
}
|
|
112
|
+
else if (!this.apps && vid) {
|
|
113
|
+
this.apps = {};
|
|
114
|
+
this.apps[this.appId] = vid;
|
|
115
|
+
return vid;
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
return { id: this.appId, version: this.apps?.[this.appId].version };
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
setCacheMode(cacheMode, untilVersion) {
|
|
122
|
+
this.logger.info(`engine-rule-cache-updated`, { mode: cacheMode, until: untilVersion });
|
|
123
|
+
this.cacheMode = cacheMode;
|
|
124
|
+
this.untilVersion = untilVersion;
|
|
125
|
+
}
|
|
126
|
+
async routeToSubscribers(topic, message) {
|
|
127
|
+
const jobCallback = this.jobCallbacks[message.metadata.jid];
|
|
128
|
+
if (jobCallback) {
|
|
129
|
+
this.delistJobCallback(message.metadata.jid);
|
|
130
|
+
jobCallback(topic, message);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
async processWebHooks() {
|
|
134
|
+
this.task.processWebHooks((this.hook).bind(this));
|
|
135
|
+
}
|
|
136
|
+
async processTimeHooks() {
|
|
137
|
+
this.task.processTimeHooks((this.hookTime).bind(this));
|
|
138
|
+
}
|
|
139
|
+
async throttle(delayInMillis) {
|
|
140
|
+
this.streamSignaler.setThrottle(delayInMillis);
|
|
141
|
+
}
|
|
142
|
+
// ************* METADATA/MODEL METHODS *************
|
|
143
|
+
async initActivity(topic, data = {}, context) {
|
|
144
|
+
const [activityId, schema] = await this.getSchema(topic);
|
|
145
|
+
const ActivityHandler = activities_1.default[schema.type];
|
|
146
|
+
if (ActivityHandler) {
|
|
147
|
+
const utc = (0, utils_1.formatISODate)(new Date());
|
|
148
|
+
const metadata = {
|
|
149
|
+
aid: activityId,
|
|
150
|
+
atp: schema.type,
|
|
151
|
+
stp: schema.subtype,
|
|
152
|
+
ac: utc,
|
|
153
|
+
au: utc
|
|
154
|
+
};
|
|
155
|
+
const hook = null;
|
|
156
|
+
return new ActivityHandler(schema, data, metadata, hook, this, context);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
throw new Error(`activity type ${schema.type} not found`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
async getSchema(topic) {
|
|
163
|
+
const app = await this.store.getApp(this.appId);
|
|
164
|
+
if (!app) {
|
|
165
|
+
throw new Error(`no app found for id ${this.appId}`);
|
|
166
|
+
}
|
|
167
|
+
if (this.isPrivate(topic)) {
|
|
168
|
+
//private subscriptions use the schema id (.activityId)
|
|
169
|
+
const activityId = topic.substring(1);
|
|
170
|
+
const schema = await this.store.getSchema(activityId, await this.getVID(app));
|
|
171
|
+
return [activityId, schema];
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
//public subscriptions use a topic (a.b.c) that is associated with a schema id
|
|
175
|
+
const activityId = await this.store.getSubscription(topic, await this.getVID(app));
|
|
176
|
+
if (activityId) {
|
|
177
|
+
const schema = await this.store.getSchema(activityId, await this.getVID(app));
|
|
178
|
+
return [activityId, schema];
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
throw new Error(`no subscription found for topic ${topic} in app ${this.appId} for app version ${app.version}`);
|
|
182
|
+
}
|
|
183
|
+
async getSettings() {
|
|
184
|
+
return await this.store.getSettings();
|
|
185
|
+
}
|
|
186
|
+
isPrivate(topic) {
|
|
187
|
+
return topic.startsWith('.');
|
|
188
|
+
}
|
|
189
|
+
// ************* COMPILER METHODS *************
|
|
190
|
+
async plan(pathOrYAML) {
|
|
191
|
+
const compiler = new compiler_1.CompilerService(this.store, this.logger);
|
|
192
|
+
return await compiler.plan(pathOrYAML);
|
|
193
|
+
}
|
|
194
|
+
async deploy(pathOrYAML) {
|
|
195
|
+
const compiler = new compiler_1.CompilerService(this.store, this.logger);
|
|
196
|
+
return await compiler.deploy(pathOrYAML);
|
|
197
|
+
}
|
|
198
|
+
// ************* REPORTER METHODS *************
|
|
199
|
+
async getStats(topic, query) {
|
|
200
|
+
const { id, version } = await this.getVID();
|
|
201
|
+
const reporter = new reporter_1.ReporterService({ id, version }, this.store, this.logger);
|
|
202
|
+
const resolvedQuery = await this.resolveQuery(topic, query);
|
|
203
|
+
return await reporter.getStats(resolvedQuery);
|
|
204
|
+
}
|
|
205
|
+
async getIds(topic, query, queryFacets = []) {
|
|
206
|
+
const { id, version } = await this.getVID();
|
|
207
|
+
const reporter = new reporter_1.ReporterService({ id, version }, this.store, this.logger);
|
|
208
|
+
const resolvedQuery = await this.resolveQuery(topic, query);
|
|
209
|
+
return await reporter.getIds(resolvedQuery, queryFacets);
|
|
210
|
+
}
|
|
211
|
+
async resolveQuery(topic, query) {
|
|
212
|
+
const trigger = await this.initActivity(topic, query.data);
|
|
213
|
+
await trigger.getState();
|
|
214
|
+
return {
|
|
215
|
+
end: query.end,
|
|
216
|
+
start: query.start,
|
|
217
|
+
range: query.range,
|
|
218
|
+
granularity: trigger.resolveGranularity(),
|
|
219
|
+
key: trigger.resolveJobKey(trigger.createInputContext()),
|
|
220
|
+
sparse: query.sparse,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
// ****************** STREAM RE-ENTRY POINT *****************
|
|
224
|
+
async processStreamMessage(streamData) {
|
|
225
|
+
this.logger.debug('engine-process-stream-message', {
|
|
226
|
+
jid: streamData.metadata.jid,
|
|
227
|
+
dad: streamData.metadata.dad,
|
|
228
|
+
aid: streamData.metadata.aid,
|
|
229
|
+
status: streamData.status || stream_2.StreamStatus.SUCCESS,
|
|
230
|
+
code: streamData.code || 200,
|
|
231
|
+
});
|
|
232
|
+
const context = {
|
|
233
|
+
metadata: {
|
|
234
|
+
jid: streamData.metadata.jid,
|
|
235
|
+
dad: streamData.metadata.dad,
|
|
236
|
+
aid: streamData.metadata.aid,
|
|
237
|
+
},
|
|
238
|
+
data: streamData.data,
|
|
239
|
+
};
|
|
240
|
+
if (streamData.type === stream_2.StreamDataType.TIMEHOOK || streamData.type === stream_2.StreamDataType.WEBHOOK || streamData.type === stream_2.StreamDataType.TRANSITION) {
|
|
241
|
+
const activityHandler = await this.initActivity(`.${streamData.metadata.aid}`, context.data, context);
|
|
242
|
+
if (streamData.type === stream_2.StreamDataType.TIMEHOOK) {
|
|
243
|
+
await activityHandler.processTimeHookEvent(streamData.metadata.jid);
|
|
244
|
+
}
|
|
245
|
+
else if (streamData.type === stream_2.StreamDataType.TRANSITION) {
|
|
246
|
+
await activityHandler.process();
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
await activityHandler.processWebHookEvent();
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
else if (streamData.type === stream_2.StreamDataType.AWAIT) {
|
|
253
|
+
context.metadata = {
|
|
254
|
+
...context.metadata,
|
|
255
|
+
pj: streamData.metadata.jid,
|
|
256
|
+
pd: streamData.metadata.dad,
|
|
257
|
+
pa: streamData.metadata.aid,
|
|
258
|
+
trc: streamData.metadata.trc,
|
|
259
|
+
spn: streamData.metadata.spn,
|
|
260
|
+
};
|
|
261
|
+
const activityHandler = await this.initActivity(streamData.metadata.topic, streamData.data, context);
|
|
262
|
+
await activityHandler.process();
|
|
263
|
+
}
|
|
264
|
+
else if (streamData.type === stream_2.StreamDataType.RESULT) {
|
|
265
|
+
const activityHandler = await this.initActivity(`.${context.metadata.aid}`, streamData.data, context);
|
|
266
|
+
await activityHandler.processEvent(streamData.status, streamData.code);
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
const activityHandler = await this.initActivity(`.${streamData.metadata.aid}`, streamData.data, context);
|
|
270
|
+
await activityHandler.processEvent(streamData.status, streamData.code);
|
|
271
|
+
}
|
|
272
|
+
this.logger.debug('engine-process-stream-message-end', {
|
|
273
|
+
jid: streamData.metadata.jid,
|
|
274
|
+
aid: streamData.metadata.aid
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
// ***************** `AWAIT` ACTIVITY RETURN RESPONSE ****************
|
|
278
|
+
async execAdjacentParent(context, jobOutput) {
|
|
279
|
+
if (this.hasParentJob(context)) {
|
|
280
|
+
//errors are stringified `StreamError` objects
|
|
281
|
+
const error = this.resolveError(jobOutput.metadata);
|
|
282
|
+
const spn = context['$self']?.output?.metadata?.l2s || context['$self']?.output?.metadata?.l1s;
|
|
283
|
+
const streamData = {
|
|
284
|
+
metadata: {
|
|
285
|
+
jid: context.metadata.pj,
|
|
286
|
+
dad: context.metadata.pd,
|
|
287
|
+
aid: context.metadata.pa,
|
|
288
|
+
trc: context.metadata.trc,
|
|
289
|
+
spn,
|
|
290
|
+
},
|
|
291
|
+
type: stream_2.StreamDataType.RESULT,
|
|
292
|
+
data: jobOutput.data,
|
|
293
|
+
};
|
|
294
|
+
if (error && error.code) {
|
|
295
|
+
streamData.status = stream_2.StreamStatus.ERROR;
|
|
296
|
+
streamData.data = error;
|
|
297
|
+
streamData.code = error.code;
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
streamData.status = stream_2.StreamStatus.SUCCESS;
|
|
301
|
+
streamData.code = STATUS_CODE_SUCCESS;
|
|
302
|
+
}
|
|
303
|
+
return (await this.streamSignaler?.publishMessage(null, streamData));
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
hasParentJob(context) {
|
|
307
|
+
//todo: include the dimensional address (pd)
|
|
308
|
+
return Boolean(context.metadata.pj && context.metadata.pa);
|
|
309
|
+
}
|
|
310
|
+
resolveError(metadata) {
|
|
311
|
+
if (metadata && metadata.err) {
|
|
312
|
+
return JSON.parse(metadata.err);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
// ****************** `SCRUB` CLEAN COMPLETED JOBS *****************
|
|
316
|
+
async scrub(jobId) {
|
|
317
|
+
await this.store.scrub(jobId);
|
|
318
|
+
}
|
|
319
|
+
// ****************** `HOOK` ACTIVITY RE-ENTRY POINT *****************
|
|
320
|
+
async hook(topic, data) {
|
|
321
|
+
const hookRule = await this.storeSignaler.getHookRule(topic);
|
|
322
|
+
const streamData = {
|
|
323
|
+
type: stream_2.StreamDataType.WEBHOOK,
|
|
324
|
+
metadata: { aid: `${hookRule.to}`, topic },
|
|
325
|
+
data,
|
|
326
|
+
};
|
|
327
|
+
await this.streamSignaler.publishMessage(null, streamData);
|
|
328
|
+
}
|
|
329
|
+
async hookTime(jobId, activityId) {
|
|
330
|
+
const streamData = {
|
|
331
|
+
type: stream_2.StreamDataType.TIMEHOOK,
|
|
332
|
+
metadata: {
|
|
333
|
+
jid: jobId,
|
|
334
|
+
aid: activityId,
|
|
335
|
+
},
|
|
336
|
+
data: { timestamp: Date.now() },
|
|
337
|
+
};
|
|
338
|
+
await this.streamSignaler.publishMessage(null, streamData);
|
|
339
|
+
}
|
|
340
|
+
async hookAll(hookTopic, data, query, queryFacets = []) {
|
|
341
|
+
const config = await this.getVID();
|
|
342
|
+
const hookRule = await this.storeSignaler.getHookRule(hookTopic);
|
|
343
|
+
if (hookRule) {
|
|
344
|
+
const subscriptionTopic = await (0, utils_1.getSubscriptionTopic)(hookRule.to, this.store, config);
|
|
345
|
+
const resolvedQuery = await this.resolveQuery(subscriptionTopic, query);
|
|
346
|
+
const reporter = new reporter_1.ReporterService(config, this.store, this.logger);
|
|
347
|
+
const workItems = await reporter.getWorkItems(resolvedQuery, queryFacets);
|
|
348
|
+
const taskService = new task_1.TaskService(this.store, this.logger);
|
|
349
|
+
await taskService.enqueueWorkItems(workItems.map(workItem => `${hookTopic}::${workItem}::${JSON.stringify(data)}`));
|
|
350
|
+
this.store.publish(key_1.KeyType.QUORUM, { type: 'work', originator: this.guid }, this.appId);
|
|
351
|
+
return workItems;
|
|
352
|
+
}
|
|
353
|
+
else {
|
|
354
|
+
throw new Error(`unable to find hook rule for topic ${hookTopic}`);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
// ********************** PUB/SUB ENTRY POINT **********************
|
|
358
|
+
//publish (returns just the job id)
|
|
359
|
+
async pub(topic, data, context) {
|
|
360
|
+
const activityHandler = await this.initActivity(topic, data, context);
|
|
361
|
+
if (activityHandler) {
|
|
362
|
+
return await activityHandler.process();
|
|
363
|
+
}
|
|
364
|
+
else {
|
|
365
|
+
throw new Error(`unable to process activity for topic ${topic}`);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
//subscribe to all jobs for a topic
|
|
369
|
+
async sub(topic, callback) {
|
|
370
|
+
const subscriptionCallback = async (topic, message) => {
|
|
371
|
+
callback(message.topic, message.job);
|
|
372
|
+
};
|
|
373
|
+
return await this.subscribe.subscribe(key_1.KeyType.QUORUM, subscriptionCallback, this.appId, topic);
|
|
374
|
+
}
|
|
375
|
+
//unsubscribe to all jobs for a topic
|
|
376
|
+
async unsub(topic) {
|
|
377
|
+
return await this.subscribe.unsubscribe(key_1.KeyType.QUORUM, this.appId, topic);
|
|
378
|
+
}
|
|
379
|
+
//subscribe to all jobs for a wildcard topic
|
|
380
|
+
async psub(wild, callback) {
|
|
381
|
+
const subscriptionCallback = async (topic, message) => {
|
|
382
|
+
callback(message.topic, message.job);
|
|
383
|
+
};
|
|
384
|
+
return await this.subscribe.psubscribe(key_1.KeyType.QUORUM, subscriptionCallback, this.appId, wild);
|
|
385
|
+
}
|
|
386
|
+
//unsubscribe to all jobs for a wildcard topic
|
|
387
|
+
async punsub(wild) {
|
|
388
|
+
return await this.subscribe.punsubscribe(key_1.KeyType.QUORUM, this.appId, wild);
|
|
389
|
+
}
|
|
390
|
+
//publish and await (returns the job and data (if ready)); throws error with jobid if not
|
|
391
|
+
async pubsub(topic, data, context, timeout = OTT_WAIT_TIME) {
|
|
392
|
+
context = {
|
|
393
|
+
metadata: {
|
|
394
|
+
ngn: this.guid,
|
|
395
|
+
trc: context?.metadata?.trc,
|
|
396
|
+
spn: context?.metadata?.spn
|
|
397
|
+
}
|
|
398
|
+
};
|
|
399
|
+
const jobId = await this.pub(topic, data, context);
|
|
400
|
+
return new Promise((resolve, reject) => {
|
|
401
|
+
this.registerJobCallback(jobId, (topic, output) => {
|
|
402
|
+
if (output.metadata.err) {
|
|
403
|
+
const error = JSON.parse(output.metadata.err);
|
|
404
|
+
reject({
|
|
405
|
+
...error,
|
|
406
|
+
job_id: output.metadata.jid,
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
else {
|
|
410
|
+
resolve(output);
|
|
411
|
+
}
|
|
412
|
+
});
|
|
413
|
+
setTimeout(() => {
|
|
414
|
+
this.delistJobCallback(jobId);
|
|
415
|
+
reject({
|
|
416
|
+
code: STATUS_CODE_TIMEOUT,
|
|
417
|
+
message: 'timeout',
|
|
418
|
+
job_id: jobId
|
|
419
|
+
});
|
|
420
|
+
}, timeout);
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
async resolveOneTimeSubscription(context, jobOutput) {
|
|
424
|
+
//todo: subscriber should query for the job...only publish minimum context needed
|
|
425
|
+
if (this.hasOneTimeSubscription(context)) {
|
|
426
|
+
const message = {
|
|
427
|
+
type: 'job',
|
|
428
|
+
topic: context.metadata.jid,
|
|
429
|
+
job: (0, utils_1.restoreHierarchy)(jobOutput),
|
|
430
|
+
};
|
|
431
|
+
this.store.publish(key_1.KeyType.QUORUM, message, this.appId, context.metadata.ngn);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
async getPublishesTopic(context) {
|
|
435
|
+
const config = await this.getVID();
|
|
436
|
+
const activityId = context.metadata.aid || context['$self']?.output?.metadata?.aid;
|
|
437
|
+
const schema = await this.store.getSchema(activityId, config);
|
|
438
|
+
return schema.publishes;
|
|
439
|
+
}
|
|
440
|
+
async resolvePersistentSubscriptions(context, jobOutput) {
|
|
441
|
+
const topic = await this.getPublishesTopic(context);
|
|
442
|
+
if (topic) {
|
|
443
|
+
const message = {
|
|
444
|
+
type: 'job',
|
|
445
|
+
topic,
|
|
446
|
+
job: (0, utils_1.restoreHierarchy)(jobOutput),
|
|
447
|
+
};
|
|
448
|
+
this.store.publish(key_1.KeyType.QUORUM, message, this.appId, `${topic}.${context.metadata.jid}`);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
async add(streamData) {
|
|
452
|
+
return await this.streamSignaler.publishMessage(null, streamData);
|
|
453
|
+
}
|
|
454
|
+
registerJobCallback(jobId, jobCallback) {
|
|
455
|
+
this.jobCallbacks[jobId] = jobCallback;
|
|
456
|
+
}
|
|
457
|
+
delistJobCallback(jobId) {
|
|
458
|
+
delete this.jobCallbacks[jobId];
|
|
459
|
+
}
|
|
460
|
+
hasOneTimeSubscription(context) {
|
|
461
|
+
return Boolean(context.metadata.ngn);
|
|
462
|
+
}
|
|
463
|
+
// ***************** JOB COMPLETION/CLEANUP *****************
|
|
464
|
+
async runJobCompletionTasks(context) {
|
|
465
|
+
const isAwait = this.hasParentJob(context);
|
|
466
|
+
const isOneTimeSubscription = this.hasOneTimeSubscription(context);
|
|
467
|
+
const topic = await this.getPublishesTopic(context);
|
|
468
|
+
if (isAwait || isOneTimeSubscription || topic) {
|
|
469
|
+
const jobOutput = await this.getState(context.metadata.tpc, context.metadata.jid);
|
|
470
|
+
//always wait for stream pub/sub
|
|
471
|
+
await this.execAdjacentParent(context, jobOutput);
|
|
472
|
+
//no need to wait for standard pub/sub
|
|
473
|
+
this.resolveOneTimeSubscription(context, jobOutput);
|
|
474
|
+
this.resolvePersistentSubscriptions(context, jobOutput);
|
|
475
|
+
}
|
|
476
|
+
this.task.registerJobForCleanup(context.metadata.jid, context.metadata.expire);
|
|
477
|
+
}
|
|
478
|
+
// ****** GET JOB STATE/COLLATION STATUS BY ID *********
|
|
479
|
+
async getStatus(jobId) {
|
|
480
|
+
const { id: appId } = await this.getVID();
|
|
481
|
+
return this.store.getStatus(jobId, appId);
|
|
482
|
+
}
|
|
483
|
+
//todo: add 'options' parameter;
|
|
484
|
+
// (e.g, if {dimensions:true}, use hscan to deliver
|
|
485
|
+
// the full set of dimensional job data)
|
|
486
|
+
async getState(topic, jobId) {
|
|
487
|
+
const { id: appId } = await this.getVID();
|
|
488
|
+
const jobSymbols = await this.store.getSymbols(`$${topic}`);
|
|
489
|
+
const consumes = {
|
|
490
|
+
[`$${topic}`]: Object.keys(jobSymbols)
|
|
491
|
+
};
|
|
492
|
+
const output = await this.store.getState(jobId, consumes);
|
|
493
|
+
if (!output) {
|
|
494
|
+
throw new Error(`not found ${jobId}`);
|
|
495
|
+
}
|
|
496
|
+
const [state, status] = output;
|
|
497
|
+
const stateTree = (0, utils_1.restoreHierarchy)(state);
|
|
498
|
+
if (status && stateTree.metadata) {
|
|
499
|
+
stateTree.metadata.js = status;
|
|
500
|
+
}
|
|
501
|
+
return stateTree;
|
|
502
|
+
}
|
|
503
|
+
async compress(terms) {
|
|
504
|
+
const existingSymbols = await this.store.getSymbolValues();
|
|
505
|
+
const startIndex = Object.keys(existingSymbols).length;
|
|
506
|
+
const maxIndex = Math.pow(52, 2) - 1;
|
|
507
|
+
const newSymbols = serializer_1.SerializerService.filterSymVals(startIndex, maxIndex, existingSymbols, new Set(terms));
|
|
508
|
+
return await this.store.addSymbolValues(newSymbols);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
exports.EngineService = EngineService;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { EngineService } from '../engine';
|
|
2
|
+
import { ILogger } from '../logger';
|
|
3
|
+
import { QuorumService } from '../quorum';
|
|
4
|
+
import { WorkerService } from '../worker';
|
|
5
|
+
import { JobState, JobData, JobOutput, JobStatus } from '../../types/job';
|
|
6
|
+
import { HotMeshConfig, HotMeshManifest } from '../../types/hotmesh';
|
|
7
|
+
import { JobMessageCallback } from '../../types/quorum';
|
|
8
|
+
import { JobStatsInput, GetStatsOptions, IdsResponse, StatsResponse } from '../../types/stats';
|
|
9
|
+
import { StreamData, StreamDataResponse } from '../../types/stream';
|
|
10
|
+
declare class HotMeshService {
|
|
11
|
+
namespace: string;
|
|
12
|
+
appId: string;
|
|
13
|
+
guid: string;
|
|
14
|
+
engine: EngineService | null;
|
|
15
|
+
quorum: QuorumService | null;
|
|
16
|
+
workers: WorkerService[];
|
|
17
|
+
logger: ILogger;
|
|
18
|
+
verifyAndSetNamespace(namespace?: string): void;
|
|
19
|
+
verifyAndSetAppId(appId: string): void;
|
|
20
|
+
static init(config: HotMeshConfig): Promise<HotMeshService>;
|
|
21
|
+
initEngine(config: HotMeshConfig, logger: ILogger): Promise<void>;
|
|
22
|
+
initQuorum(config: HotMeshConfig, engine: EngineService, logger: ILogger): Promise<void>;
|
|
23
|
+
initWorkers(config: HotMeshConfig, logger: ILogger): Promise<void>;
|
|
24
|
+
pub(topic: string, data?: JobData, context?: JobState): Promise<string>;
|
|
25
|
+
sub(topic: string, callback: JobMessageCallback): Promise<void>;
|
|
26
|
+
unsub(topic: string): Promise<void>;
|
|
27
|
+
psub(wild: string, callback: JobMessageCallback): Promise<void>;
|
|
28
|
+
punsub(wild: string): Promise<void>;
|
|
29
|
+
pubsub(topic: string, data?: JobData, context?: JobState | null, timeout?: number): Promise<JobOutput>;
|
|
30
|
+
add(streamData: StreamData | StreamDataResponse): Promise<string>;
|
|
31
|
+
plan(path: string): Promise<HotMeshManifest>;
|
|
32
|
+
deploy(pathOrYAML: string): Promise<HotMeshManifest>;
|
|
33
|
+
activate(version: string, delay?: number): Promise<boolean>;
|
|
34
|
+
getStats(topic: string, query: JobStatsInput): Promise<StatsResponse>;
|
|
35
|
+
getStatus(jobId: string): Promise<JobStatus>;
|
|
36
|
+
getState(topic: string, jobId: string): Promise<JobOutput>;
|
|
37
|
+
getIds(topic: string, query: JobStatsInput, queryFacets?: any[]): Promise<IdsResponse>;
|
|
38
|
+
resolveQuery(topic: string, query: JobStatsInput): Promise<GetStatsOptions>;
|
|
39
|
+
scrub(jobId: string): Promise<void>;
|
|
40
|
+
hook(topic: string, data: JobData): Promise<JobStatus | void>;
|
|
41
|
+
hookAll(hookTopic: string, data: JobData, query: JobStatsInput, queryFacets?: string[]): Promise<string[]>;
|
|
42
|
+
stop(): Promise<void>;
|
|
43
|
+
compress(terms: string[]): Promise<boolean>;
|
|
44
|
+
}
|
|
45
|
+
export { HotMeshService };
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HotMeshService = void 0;
|
|
4
|
+
const nanoid_1 = require("nanoid");
|
|
5
|
+
const key_1 = require("../../modules/key");
|
|
6
|
+
const engine_1 = require("../engine");
|
|
7
|
+
const logger_1 = require("../logger");
|
|
8
|
+
const stream_1 = require("../signaler/stream");
|
|
9
|
+
const quorum_1 = require("../quorum");
|
|
10
|
+
const worker_1 = require("../worker");
|
|
11
|
+
const connector_1 = require("../connector");
|
|
12
|
+
class HotMeshService {
|
|
13
|
+
constructor() {
|
|
14
|
+
this.engine = null;
|
|
15
|
+
this.quorum = null;
|
|
16
|
+
this.workers = [];
|
|
17
|
+
}
|
|
18
|
+
verifyAndSetNamespace(namespace) {
|
|
19
|
+
if (!namespace) {
|
|
20
|
+
this.namespace = key_1.PSNS;
|
|
21
|
+
}
|
|
22
|
+
else if (!namespace.match(/^[A-Za-z0-9-]+$/)) {
|
|
23
|
+
throw new Error(`config.namespace [${namespace}] is invalid`);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
this.namespace = namespace;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
verifyAndSetAppId(appId) {
|
|
30
|
+
if (!appId?.match(/^[A-Za-z0-9-]+$/)) {
|
|
31
|
+
throw new Error(`config.appId [${appId}] is invalid`);
|
|
32
|
+
}
|
|
33
|
+
else if (appId === 'a') {
|
|
34
|
+
throw new Error(`config.appId [${appId}] is reserved`);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
this.appId = appId;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
static async init(config) {
|
|
41
|
+
const instance = new HotMeshService();
|
|
42
|
+
instance.guid = (0, nanoid_1.nanoid)();
|
|
43
|
+
instance.verifyAndSetNamespace(config.namespace);
|
|
44
|
+
instance.verifyAndSetAppId(config.appId);
|
|
45
|
+
instance.logger = new logger_1.LoggerService(config.appId, instance.guid, config.name || '', config.logLevel);
|
|
46
|
+
await instance.initEngine(config, instance.logger);
|
|
47
|
+
await instance.initQuorum(config, instance.engine, instance.logger);
|
|
48
|
+
await instance.initWorkers(config, instance.logger);
|
|
49
|
+
return instance;
|
|
50
|
+
}
|
|
51
|
+
async initEngine(config, logger) {
|
|
52
|
+
if (config.engine) {
|
|
53
|
+
await connector_1.ConnectorService.initRedisClients(config.engine.redis?.class, config.engine.redis?.options, config.engine);
|
|
54
|
+
this.engine = await engine_1.EngineService.init(this.namespace, this.appId, this.guid, config, logger);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async initQuorum(config, engine, logger) {
|
|
58
|
+
if (engine) {
|
|
59
|
+
this.quorum = await quorum_1.QuorumService.init(this.namespace, this.appId, this.guid, config, engine, logger);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async initWorkers(config, logger) {
|
|
63
|
+
this.workers = await worker_1.WorkerService.init(this.namespace, this.appId, this.guid, config, logger);
|
|
64
|
+
}
|
|
65
|
+
// ************* PUB/SUB METHODS *************
|
|
66
|
+
async pub(topic, data = {}, context) {
|
|
67
|
+
return await this.engine?.pub(topic, data, context);
|
|
68
|
+
}
|
|
69
|
+
async sub(topic, callback) {
|
|
70
|
+
return await this.engine?.sub(topic, callback);
|
|
71
|
+
}
|
|
72
|
+
async unsub(topic) {
|
|
73
|
+
return await this.engine?.unsub(topic);
|
|
74
|
+
}
|
|
75
|
+
async psub(wild, callback) {
|
|
76
|
+
return await this.engine?.psub(wild, callback);
|
|
77
|
+
}
|
|
78
|
+
async punsub(wild) {
|
|
79
|
+
return await this.engine?.punsub(wild);
|
|
80
|
+
}
|
|
81
|
+
async pubsub(topic, data = {}, context, timeout) {
|
|
82
|
+
return await this.engine?.pubsub(topic, data, context, timeout);
|
|
83
|
+
}
|
|
84
|
+
async add(streamData) {
|
|
85
|
+
return await this.engine.add(streamData);
|
|
86
|
+
}
|
|
87
|
+
// ************* COMPILER METHODS *************
|
|
88
|
+
async plan(path) {
|
|
89
|
+
return await this.engine?.plan(path);
|
|
90
|
+
}
|
|
91
|
+
async deploy(pathOrYAML) {
|
|
92
|
+
return await this.engine?.deploy(pathOrYAML);
|
|
93
|
+
}
|
|
94
|
+
async activate(version, delay) {
|
|
95
|
+
//activation is a quorum operation
|
|
96
|
+
return await this.quorum?.activate(version, delay);
|
|
97
|
+
}
|
|
98
|
+
// ************* REPORTER METHODS *************
|
|
99
|
+
async getStats(topic, query) {
|
|
100
|
+
return await this.engine?.getStats(topic, query);
|
|
101
|
+
}
|
|
102
|
+
async getStatus(jobId) {
|
|
103
|
+
return this.engine?.getStatus(jobId);
|
|
104
|
+
}
|
|
105
|
+
async getState(topic, jobId) {
|
|
106
|
+
return this.engine?.getState(topic, jobId);
|
|
107
|
+
}
|
|
108
|
+
async getIds(topic, query, queryFacets = []) {
|
|
109
|
+
return await this.engine?.getIds(topic, query, queryFacets);
|
|
110
|
+
}
|
|
111
|
+
async resolveQuery(topic, query) {
|
|
112
|
+
return await this.engine?.resolveQuery(topic, query);
|
|
113
|
+
}
|
|
114
|
+
// ****************** `SCRUB` CLEAN COMPLETED JOBS *****************
|
|
115
|
+
async scrub(jobId) {
|
|
116
|
+
await this.engine?.scrub(jobId);
|
|
117
|
+
}
|
|
118
|
+
// ****** `HOOK` ACTIVITY RE-ENTRY POINT ******
|
|
119
|
+
async hook(topic, data) {
|
|
120
|
+
//return collation int
|
|
121
|
+
return await this.engine?.hook(topic, data);
|
|
122
|
+
}
|
|
123
|
+
async hookAll(hookTopic, data, query, queryFacets = []) {
|
|
124
|
+
return await this.engine?.hookAll(hookTopic, data, query, queryFacets);
|
|
125
|
+
}
|
|
126
|
+
async stop() {
|
|
127
|
+
await stream_1.StreamSignaler.stopConsuming();
|
|
128
|
+
this.engine?.task.cancelCleanup();
|
|
129
|
+
}
|
|
130
|
+
async compress(terms) {
|
|
131
|
+
return await this.engine?.compress(terms);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
exports.HotMeshService = HotMeshService;
|