@hotmeshio/hotmesh 0.2.3 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/package.json +1 -1
- package/build/services/engine/index.js +1 -0
- package/build/services/meshcall/index.d.ts +5 -5
- package/build/services/meshcall/index.js +44 -25
- package/build/services/meshcall/schemas/factory.js +2 -2
- package/build/services/router/index.js +3 -1
- package/build/types/meshcall.d.ts +6 -2
- package/package.json +1 -1
- package/types/meshcall.ts +19 -2
package/build/package.json
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import { HotMesh } from '../hotmesh';
|
|
2
|
-
import { MeshCallConnectParams, MeshCallCronParams, MeshCallExecParams, MeshCallFlushParams, MeshCallInterruptParams } from '../../types/meshcall';
|
|
2
|
+
import { MeshCallConnectParams, MeshCallCronParams, MeshCallExecParams, MeshCallFlushParams, MeshCallInstanceOptions, MeshCallInterruptParams } from '../../types/meshcall';
|
|
3
3
|
import { RedisConfig } from '../../types';
|
|
4
4
|
declare class MeshCall {
|
|
5
5
|
static workers: Map<string, HotMesh | Promise<HotMesh>>;
|
|
6
6
|
static engines: Map<string, HotMesh | Promise<HotMesh>>;
|
|
7
7
|
static connections: Map<string, any>;
|
|
8
8
|
constructor();
|
|
9
|
-
static findFirstMatching(
|
|
10
|
-
static getHotMeshClient: (namespace: string, connection: RedisConfig) => Promise<HotMesh>;
|
|
9
|
+
static findFirstMatching(targets: Map<string, HotMesh | Promise<HotMesh>>, namespace: string, config: RedisConfig, options?: MeshCallInstanceOptions): Promise<HotMesh | void>;
|
|
10
|
+
static getHotMeshClient: (namespace: string, connection: RedisConfig, options?: MeshCallInstanceOptions) => Promise<HotMesh>;
|
|
11
11
|
static verifyWorkflowActive(hotMesh: HotMesh, appId?: string, count?: number): Promise<boolean>;
|
|
12
12
|
static activateWorkflow(hotMesh: HotMesh, appId?: string, version?: string): Promise<void>;
|
|
13
|
-
static getInstance(namespace: string, redis: RedisConfig): Promise<HotMesh>;
|
|
13
|
+
static getInstance(namespace: string, redis: RedisConfig, options?: MeshCallInstanceOptions): Promise<HotMesh>;
|
|
14
14
|
static connect(params: MeshCallConnectParams): Promise<HotMesh>;
|
|
15
15
|
static exec<U>(params: MeshCallExecParams): Promise<U>;
|
|
16
16
|
static flush(params: MeshCallFlushParams): Promise<void>;
|
|
17
17
|
static cron(params: MeshCallCronParams): Promise<boolean>;
|
|
18
|
-
static interrupt(params: MeshCallInterruptParams): Promise<
|
|
18
|
+
static interrupt(params: MeshCallInterruptParams): Promise<boolean>;
|
|
19
19
|
static shutdown(): Promise<void>;
|
|
20
20
|
}
|
|
21
21
|
export { MeshCall };
|
|
@@ -14,11 +14,15 @@ const cron_1 = require("../pipe/functions/cron");
|
|
|
14
14
|
const factory_1 = require("./schemas/factory");
|
|
15
15
|
class MeshCall {
|
|
16
16
|
constructor() { }
|
|
17
|
-
static async findFirstMatching(
|
|
18
|
-
for (const [id, hotMeshInstance] of
|
|
19
|
-
|
|
17
|
+
static async findFirstMatching(targets, namespace = key_1.HMNS, config, options = {}) {
|
|
18
|
+
for (const [id, hotMeshInstance] of targets) {
|
|
19
|
+
const hotMesh = await hotMeshInstance;
|
|
20
|
+
const appId = hotMesh.engine.appId;
|
|
21
|
+
if (appId === namespace) {
|
|
20
22
|
if (id.startsWith((0, utils_1.hashOptions)(config.options))) {
|
|
21
|
-
|
|
23
|
+
if (Boolean(options.readonly) == Boolean(hotMesh.engine.router.readonly)) {
|
|
24
|
+
return hotMeshInstance;
|
|
25
|
+
}
|
|
22
26
|
}
|
|
23
27
|
}
|
|
24
28
|
}
|
|
@@ -60,12 +64,15 @@ class MeshCall {
|
|
|
60
64
|
}
|
|
61
65
|
}
|
|
62
66
|
}
|
|
63
|
-
static async getInstance(namespace, redis) {
|
|
64
|
-
let hotMeshInstance
|
|
67
|
+
static async getInstance(namespace, redis, options = {}) {
|
|
68
|
+
let hotMeshInstance;
|
|
69
|
+
if (!options.readonly) {
|
|
70
|
+
hotMeshInstance = await MeshCall.findFirstMatching(MeshCall.workers, namespace, redis, options);
|
|
71
|
+
}
|
|
65
72
|
if (!hotMeshInstance) {
|
|
66
|
-
hotMeshInstance = await MeshCall.findFirstMatching(MeshCall.engines, namespace, redis);
|
|
73
|
+
hotMeshInstance = await MeshCall.findFirstMatching(MeshCall.engines, namespace, redis, options);
|
|
67
74
|
if (!hotMeshInstance) {
|
|
68
|
-
hotMeshInstance = (await MeshCall.getHotMeshClient(namespace, redis));
|
|
75
|
+
hotMeshInstance = (await MeshCall.getHotMeshClient(namespace, redis, options));
|
|
69
76
|
}
|
|
70
77
|
}
|
|
71
78
|
return hotMeshInstance;
|
|
@@ -131,7 +138,7 @@ class MeshCall {
|
|
|
131
138
|
await hotMeshInstance.scrub(params.id ?? params?.options?.id);
|
|
132
139
|
}
|
|
133
140
|
static async cron(params) {
|
|
134
|
-
|
|
141
|
+
if (params.callback) {
|
|
135
142
|
await MeshCall.connect({
|
|
136
143
|
logLevel: params.logLevel,
|
|
137
144
|
guid: params.guid,
|
|
@@ -140,22 +147,26 @@ class MeshCall {
|
|
|
140
147
|
callback: params.callback,
|
|
141
148
|
namespace: params.namespace,
|
|
142
149
|
});
|
|
143
|
-
|
|
144
|
-
|
|
150
|
+
}
|
|
151
|
+
const TOPIC = `${params.namespace ?? key_1.HMNS}.cron`;
|
|
152
|
+
const maxCycles = params.options.maxCycles ?? 100000;
|
|
153
|
+
let interval = enums_1.HMSH_FIDELITY_SECONDS;
|
|
154
|
+
let delay;
|
|
155
|
+
let cron;
|
|
156
|
+
if ((0, utils_1.isValidCron)(params.options.interval)) {
|
|
157
|
+
cron = params.options.interval;
|
|
158
|
+
const nextDelay = new cron_1.CronHandler().nextDelay(cron);
|
|
159
|
+
delay = nextDelay > 0 ? nextDelay : undefined;
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
const seconds = (0, ms_1.default)(params.options.interval) / 1000;
|
|
163
|
+
interval = Math.max(seconds, enums_1.HMSH_FIDELITY_SECONDS);
|
|
164
|
+
delay = params.options.delay
|
|
145
165
|
? (0, ms_1.default)(params.options.delay) / 1000
|
|
146
166
|
: undefined;
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
cron = params.options.interval;
|
|
151
|
-
delay = Math.max(new cron_1.CronHandler().nextDelay(cron), 0);
|
|
152
|
-
}
|
|
153
|
-
else {
|
|
154
|
-
const seconds = (0, ms_1.default)(params.options.interval) / 1000;
|
|
155
|
-
interval = Math.max(seconds, enums_1.HMSH_FIDELITY_SECONDS);
|
|
156
|
-
}
|
|
157
|
-
const maxCycles = params.options.maxCycles ?? 1000000;
|
|
158
|
-
const hotMeshInstance = await MeshCall.getInstance(params.namespace, params.redis);
|
|
167
|
+
}
|
|
168
|
+
try {
|
|
169
|
+
const hotMeshInstance = await MeshCall.getInstance(params.namespace, params.redis, { readonly: params.callback ? false : true, guid: params.guid });
|
|
159
170
|
await hotMeshInstance.pub(TOPIC, {
|
|
160
171
|
id: params.options.id,
|
|
161
172
|
topic: params.topic,
|
|
@@ -176,7 +187,13 @@ class MeshCall {
|
|
|
176
187
|
}
|
|
177
188
|
static async interrupt(params) {
|
|
178
189
|
const hotMeshInstance = await MeshCall.getInstance(params.namespace, params.redis);
|
|
179
|
-
|
|
190
|
+
try {
|
|
191
|
+
await hotMeshInstance.interrupt(`${params.namespace ?? key_1.HMNS}.cron`, params.options.id, { throw: false, expire: 1 });
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
return true;
|
|
180
197
|
}
|
|
181
198
|
static async shutdown() {
|
|
182
199
|
for (const [_, hotMeshInstance] of MeshCall.workers) {
|
|
@@ -193,7 +210,7 @@ _a = MeshCall;
|
|
|
193
210
|
MeshCall.workers = new Map();
|
|
194
211
|
MeshCall.engines = new Map();
|
|
195
212
|
MeshCall.connections = new Map();
|
|
196
|
-
MeshCall.getHotMeshClient = async (namespace, connection) => {
|
|
213
|
+
MeshCall.getHotMeshClient = async (namespace, connection, options = {}) => {
|
|
197
214
|
const optionsHash = (0, utils_1.hashOptions)(connection.options);
|
|
198
215
|
const targetNS = namespace ?? key_1.HMNS;
|
|
199
216
|
const connectionNS = `${optionsHash}.${targetNS}`;
|
|
@@ -203,6 +220,7 @@ MeshCall.getHotMeshClient = async (namespace, connection) => {
|
|
|
203
220
|
return hotMeshClient;
|
|
204
221
|
}
|
|
205
222
|
const hotMeshClient = hotmesh_1.HotMesh.init({
|
|
223
|
+
guid: options.guid,
|
|
206
224
|
appId: targetNS,
|
|
207
225
|
logLevel: enums_1.HMSH_LOGLEVEL,
|
|
208
226
|
engine: {
|
|
@@ -210,6 +228,7 @@ MeshCall.getHotMeshClient = async (namespace, connection) => {
|
|
|
210
228
|
class: connection.class,
|
|
211
229
|
options: connection.options,
|
|
212
230
|
},
|
|
231
|
+
readonly: options.readonly,
|
|
213
232
|
},
|
|
214
233
|
});
|
|
215
234
|
MeshCall.engines.set(connectionNS, hotMeshClient);
|
|
@@ -72,8 +72,6 @@ const getWorkflowYAML = (appId = key_1.HMNS, version = exports.VERSION) => {
|
|
|
72
72
|
|
|
73
73
|
- subscribes: ${appId}.cron
|
|
74
74
|
|
|
75
|
-
expire: 120
|
|
76
|
-
|
|
77
75
|
input:
|
|
78
76
|
schema:
|
|
79
77
|
type: object
|
|
@@ -123,6 +121,8 @@ const getWorkflowYAML = (appId = key_1.HMNS, version = exports.VERSION) => {
|
|
|
123
121
|
properties:
|
|
124
122
|
sleepSeconds:
|
|
125
123
|
type: number
|
|
124
|
+
iterationCount:
|
|
125
|
+
type: number
|
|
126
126
|
maps:
|
|
127
127
|
sleepSeconds:
|
|
128
128
|
'@pipe':
|
|
@@ -74,8 +74,10 @@ class Router {
|
|
|
74
74
|
});
|
|
75
75
|
}
|
|
76
76
|
async consumeMessages(stream, group, consumer, callback) {
|
|
77
|
-
if (this.readonly)
|
|
77
|
+
if (this.readonly) {
|
|
78
|
+
this.logger.info(`router-stream-readonly`, { group, consumer, stream });
|
|
78
79
|
return;
|
|
80
|
+
}
|
|
79
81
|
this.logger.info(`router-stream-starting`, { group, consumer, stream });
|
|
80
82
|
Router.instances.add(this);
|
|
81
83
|
this.shouldConsume = true;
|
|
@@ -46,13 +46,17 @@ interface MeshCallCronParams {
|
|
|
46
46
|
topic: string;
|
|
47
47
|
redis: RedisConfig;
|
|
48
48
|
args: any[];
|
|
49
|
-
callback
|
|
49
|
+
callback?: (...args: any[]) => any;
|
|
50
50
|
options: MeshCallCronOptions;
|
|
51
51
|
}
|
|
52
|
+
interface MeshCallInstanceOptions {
|
|
53
|
+
readonly?: boolean;
|
|
54
|
+
guid?: string;
|
|
55
|
+
}
|
|
52
56
|
interface MeshCallInterruptParams {
|
|
53
57
|
namespace?: string;
|
|
54
58
|
topic: string;
|
|
55
59
|
redis: RedisConfig;
|
|
56
60
|
options: MeshCallInterruptOptions;
|
|
57
61
|
}
|
|
58
|
-
export { MeshCallConnectParams, MeshCallExecParams, MeshCallCronParams, MeshCallExecOptions, MeshCallCronOptions, MeshCallInterruptOptions, MeshCallInterruptParams, MeshCallFlushOptions, MeshCallFlushParams, };
|
|
62
|
+
export { MeshCallConnectParams, MeshCallExecParams, MeshCallCronParams, MeshCallExecOptions, MeshCallCronOptions, MeshCallInterruptOptions, MeshCallInterruptParams, MeshCallFlushOptions, MeshCallFlushParams, MeshCallInstanceOptions, };
|
package/package.json
CHANGED
package/types/meshcall.ts
CHANGED
|
@@ -153,15 +153,31 @@ interface MeshCallCronParams {
|
|
|
153
153
|
*/
|
|
154
154
|
args: any[];
|
|
155
155
|
/**
|
|
156
|
-
* linked worker function to run
|
|
156
|
+
* linked worker function to run; if not provided, the system will
|
|
157
|
+
* attempt to start the cron job using the topic, but a new
|
|
158
|
+
* worker will not be created. This is useful for spawning a cron job
|
|
159
|
+
* from an ephemeral node process.
|
|
157
160
|
*/
|
|
158
|
-
callback
|
|
161
|
+
callback?: (...args: any[]) => any;
|
|
159
162
|
/**
|
|
160
163
|
* Options for the cron job
|
|
161
164
|
*/
|
|
162
165
|
options: MeshCallCronOptions;
|
|
163
166
|
}
|
|
164
167
|
|
|
168
|
+
interface MeshCallInstanceOptions {
|
|
169
|
+
/**
|
|
170
|
+
* if true, the connection to HotMesh will be in readonly mode
|
|
171
|
+
* and the instantiated client will not route messages
|
|
172
|
+
* @default false
|
|
173
|
+
*/
|
|
174
|
+
readonly?: boolean;
|
|
175
|
+
/**
|
|
176
|
+
* Idempotent GUID for the worker and engine
|
|
177
|
+
*/
|
|
178
|
+
guid?: string;
|
|
179
|
+
}
|
|
180
|
+
|
|
165
181
|
interface MeshCallInterruptParams {
|
|
166
182
|
/**
|
|
167
183
|
* namespace for grouping common functions
|
|
@@ -191,4 +207,5 @@ export {
|
|
|
191
207
|
MeshCallInterruptParams,
|
|
192
208
|
MeshCallFlushOptions,
|
|
193
209
|
MeshCallFlushParams,
|
|
210
|
+
MeshCallInstanceOptions,
|
|
194
211
|
};
|