@nsshunt/stsappframework 3.1.209 → 3.1.210
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.sh +5 -0
- package/dist/index.js +0 -5
- package/dist/index.js.map +1 -1
- package/dist/masterprocessbase.js +3 -53
- package/dist/masterprocessbase.js.map +1 -1
- package/dist/processbase.js +4 -17
- package/dist/processbase.js.map +1 -1
- package/dist/testing/app.js +0 -457
- package/dist/testing/app.js.map +1 -1
- package/dist/workerprocessbase.js +1 -36
- package/dist/workerprocessbase.js.map +1 -1
- package/package.json +14 -13
- package/src/commonTypes.ts +2 -2
- package/src/index.ts +0 -5
- package/src/masterprocessbase.ts +4 -18
- package/src/processbase.ts +7 -22
- package/src/testing/app.ts +1 -530
- package/src/workerprocessbase.ts +1 -40
- package/types/commonTypes.d.ts +0 -2
- package/types/commonTypes.d.ts.map +1 -1
- package/types/index.d.ts +0 -5
- package/types/index.d.ts.map +1 -1
- package/types/masterprocessbase.d.ts.map +1 -1
- package/types/processbase.d.ts +0 -2
- package/types/processbase.d.ts.map +1 -1
- package/types/workerprocessbase.d.ts.map +1 -1
- package/dist/ipcMessageHandler.js +0 -189
- package/dist/ipcMessageHandler.js.map +0 -1
- package/dist/ipcMessageManager.js +0 -146
- package/dist/ipcMessageManager.js.map +0 -1
- package/dist/ipcMessageProcessorPrimary.js +0 -65
- package/dist/ipcMessageProcessorPrimary.js.map +0 -1
- package/dist/ipcMessageProcessorWorker.js +0 -61
- package/dist/ipcMessageProcessorWorker.js.map +0 -1
- package/dist/messagehandling/webWorkerMessageHandler.js +0 -280
- package/dist/messagehandling/webWorkerMessageHandler.js.map +0 -1
- package/dist/messagehandling/webWorkerSupport.js +0 -62
- package/dist/messagehandling/webWorkerSupport.js.map +0 -1
- package/dist/redisMessageHandler.js +0 -305
- package/dist/redisMessageHandler.js.map +0 -1
- package/dist/redisMessageHandler.test.js +0 -129
- package/dist/redisMessageHandler.test.js.map +0 -1
- package/dist/testing/app_ipc_legacy.js +0 -84
- package/dist/testing/app_ipc_legacy.js.map +0 -1
- package/dist/testing/app_ipcex.js +0 -69
- package/dist/testing/app_ipcex.js.map +0 -1
- package/dist/testing/app_ww.js +0 -54
- package/dist/testing/app_ww.js.map +0 -1
- package/src/ipcMessageHandler.ts +0 -201
- package/src/ipcMessageManager.ts +0 -171
- package/src/ipcMessageProcessorPrimary.ts +0 -76
- package/src/ipcMessageProcessorWorker.ts +0 -70
- package/src/messagehandling/webWorkerMessageHandler.ts +0 -341
- package/src/messagehandling/webWorkerSupport.ts +0 -66
- package/src/redisMessageHandler.test.ts +0 -157
- package/src/redisMessageHandler.ts +0 -371
- package/src/testing/app_ipc_legacy.ts +0 -87
- package/src/testing/app_ipcex.ts +0 -68
- package/src/testing/app_ww.ts +0 -68
- package/types/ipcMessageHandler.d.ts +0 -30
- package/types/ipcMessageHandler.d.ts.map +0 -1
- package/types/ipcMessageManager.d.ts +0 -30
- package/types/ipcMessageManager.d.ts.map +0 -1
- package/types/ipcMessageProcessorPrimary.d.ts +0 -26
- package/types/ipcMessageProcessorPrimary.d.ts.map +0 -1
- package/types/ipcMessageProcessorWorker.d.ts +0 -25
- package/types/ipcMessageProcessorWorker.d.ts.map +0 -1
- package/types/messagehandling/webWorkerMessageHandler.d.ts +0 -52
- package/types/messagehandling/webWorkerMessageHandler.d.ts.map +0 -1
- package/types/messagehandling/webWorkerSupport.d.ts +0 -6
- package/types/messagehandling/webWorkerSupport.d.ts.map +0 -1
- package/types/redisMessageHandler.d.ts +0 -51
- package/types/redisMessageHandler.d.ts.map +0 -1
- package/types/redisMessageHandler.test.d.ts +0 -2
- package/types/redisMessageHandler.test.d.ts.map +0 -1
- package/types/testing/app_ipc_legacy.d.ts +0 -2
- package/types/testing/app_ipc_legacy.d.ts.map +0 -1
- package/types/testing/app_ipcex.d.ts +0 -2
- package/types/testing/app_ipcex.d.ts.map +0 -1
- package/types/testing/app_ww.d.ts +0 -2
- package/types/testing/app_ww.d.ts.map +0 -1
package/dist/testing/app_ww.js
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
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
|
-
/* eslint @typescript-eslint/no-explicit-any: 0, @typescript-eslint/no-unused-vars: 0 */ // --> OFF
|
|
7
|
-
const appConfig_1 = require("./appConfig");
|
|
8
|
-
const __1 = require("./..");
|
|
9
|
-
const appWorkerWSS_1 = require("./appWorkerWSS");
|
|
10
|
-
const node_cluster_1 = __importDefault(require("node:cluster"));
|
|
11
|
-
const stsutils_1 = require("@nsshunt/stsutils");
|
|
12
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
13
|
-
const webWorkerMessageHandler_1 = require("../messagehandling/webWorkerMessageHandler");
|
|
14
|
-
const worker_threads_1 = require("worker_threads");
|
|
15
|
-
const detect_node_1 = __importDefault(require("detect-node"));
|
|
16
|
-
if (node_cluster_1.default.isPrimary) {
|
|
17
|
-
new __1.MasterProcessBase((0, appConfig_1.ServiceConfigOptions)(true, node_cluster_1.default.isPrimary)).SetupServer();
|
|
18
|
-
}
|
|
19
|
-
else {
|
|
20
|
-
const worker = new appWorkerWSS_1.WorkerProcess((0, appConfig_1.ServiceConfigOptions)(true, node_cluster_1.default.isPrimary));
|
|
21
|
-
worker.SetupServer();
|
|
22
|
-
setTimeout(async () => {
|
|
23
|
-
const fileName = './dist/MessageHandling/webWorkerSupport.js';
|
|
24
|
-
const webWorker = new worker_threads_1.Worker(fileName);
|
|
25
|
-
if (detect_node_1.default) {
|
|
26
|
-
webWorker.unref();
|
|
27
|
-
}
|
|
28
|
-
const wwServer = new webWorkerMessageHandler_1.WebWorkerMessageHandler({
|
|
29
|
-
logger: stsutils_1.defaultLogger,
|
|
30
|
-
role: 'SERVER',
|
|
31
|
-
namespace: 'mytestapp',
|
|
32
|
-
groups: [],
|
|
33
|
-
messagePort: webWorker
|
|
34
|
-
});
|
|
35
|
-
wwServer.Start();
|
|
36
|
-
wwServer.on('test', (arg1, callback) => {
|
|
37
|
-
callback({
|
|
38
|
-
status: `PID: [${process.pid}]: response message from event = fromprimaryredis with args ${JSON.stringify(arg1)}`
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
wwServer.on('globalmessage', (arg1, callback) => {
|
|
42
|
-
callback({
|
|
43
|
-
status: `PID: [${process.pid}]: response message from event = globalmessage with args ${JSON.stringify(arg1)}`
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
setTimeout(async () => {
|
|
47
|
-
const sendObj = { from: 'parent' };
|
|
48
|
-
console.log(chalk_1.default.cyan(`calling test = [${JSON.stringify(sendObj)}]`));
|
|
49
|
-
const retVal = await wwServer.emitex('test', sendObj);
|
|
50
|
-
console.log(chalk_1.default.cyan(`caller response from test = [${JSON.stringify(retVal)}]`));
|
|
51
|
-
}, 2000);
|
|
52
|
-
}, 2000);
|
|
53
|
-
}
|
|
54
|
-
//# sourceMappingURL=app_ww.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"app_ww.js","sourceRoot":"","sources":["../../src/testing/app_ww.ts"],"names":[],"mappings":";;;;;AAAA,wFAAwF,CAAE,UAAU;AACpG,2CAAkD;AAClD,4BAAwC;AACxC,iDAA8C;AAE9C,gEAAmC;AAEnC,gDAA8D;AAE9D,kDAA0B;AAQ1B,wFAAoF;AAEpF,mDAAqD;AAErD,8DAAgC;AAEhC,IAAI,sBAAO,CAAC,SAAS,EAAE,CAAC;IAEpB,IAAI,qBAAiB,CAAC,IAAA,gCAAoB,EAAC,IAAI,EAAE,sBAAO,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;AAEvF,CAAC;KAAM,CAAC;IACJ,MAAM,MAAM,GAAG,IAAI,4BAAa,CAAC,IAAA,gCAAoB,EAAC,IAAI,EAAE,sBAAO,CAAC,SAAS,CAAC,CAAC,CAAC;IAChF,MAAM,CAAC,WAAW,EAAE,CAAC;IAErB,UAAU,CAAC,KAAK,IAAI,EAAE;QAClB,MAAM,QAAQ,GAAE,4CAA4C,CAAC;QAC7D,MAAM,SAAS,GAAG,IAAI,uBAAM,CAAC,QAAQ,CAAC,CAAC;QACvC,IAAI,qBAAM,EAAE,CAAC;YACT,SAAS,CAAC,KAAK,EAAE,CAAC;QACtB,CAAC;QAED,MAAM,QAAQ,GAA4B,IAAI,iDAAuB,CAAC;YAClE,MAAM,EAAE,wBAAa;YACrB,IAAI,EAAE,QAAQ;YACd,SAAS,EAAE,WAAW;YACtB,MAAM,EAAE,EAAG;YACX,WAAW,EAAE,SAAgB;SAChC,CAAC,CAAC;QACH,QAAQ,CAAC,KAAK,EAAE,CAAC;QAEjB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAgB,EAAE,QAAa,EAAE,EAAE;YACpD,QAAQ,CAAE;gBACN,MAAM,EAAE,SAAS,OAAO,CAAC,GAAG,+DAA+D,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE;aACpH,CAAC,CAAA;QACN,CAAC,CAAC,CAAC;QAEH,QAAQ,CAAC,EAAE,CAAC,eAAe,EAAE,CAAC,IAAgB,EAAE,QAAa,EAAE,EAAE;YAC7D,QAAQ,CAAE;gBACN,MAAM,EAAE,SAAS,OAAO,CAAC,GAAG,4DAA4D,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE;aACjH,CAAC,CAAA;QACN,CAAC,CAAC,CAAC;QAEH,UAAU,CAAC,KAAK,IAAI,EAAE;YAClB,MAAM,OAAO,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;YACnC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,mBAAmB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;YACvE,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YACtD,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,gCAAgC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QACvF,CAAC,EAAE,IAAI,CAAC,CAAC;IAEb,CAAC,EAAE,IAAI,CAAC,CAAC;AACb,CAAC"}
|
package/src/ipcMessageHandler.ts
DELETED
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
/* eslint @typescript-eslint/no-explicit-any: 0, @typescript-eslint/no-unused-vars: 0 */ // --> OFF */ // --> OFF
|
|
2
|
-
import { TinyEmitter } from "tiny-emitter";
|
|
3
|
-
import cluster, { Worker } from 'node:cluster'
|
|
4
|
-
import { ISTSLogger, JSONObject, defaultLogger } from '@nsshunt/stsutils'
|
|
5
|
-
|
|
6
|
-
import { IIPCMessageProcessorIPCPayload } from './commonTypes'
|
|
7
|
-
|
|
8
|
-
import { IPCMessageManager, IPCMessageManagerOptions } from './ipcMessageManager'
|
|
9
|
-
|
|
10
|
-
export interface IPCMessageHandlerOptions {
|
|
11
|
-
logger: ISTSLogger
|
|
12
|
-
requestResponseMessageTimeout: number
|
|
13
|
-
namespace: string
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* IPC Message Handling.
|
|
18
|
-
*
|
|
19
|
-
* This class can be used to support messages between cluster.primary and cluster.worker instances using IPC.
|
|
20
|
-
* This class can be used for both tghe cluster primary and the cluster worker.
|
|
21
|
-
* Note: Currently groups handling is not supported. Use the redis version for this capability.
|
|
22
|
-
*/
|
|
23
|
-
export class IPCMessageHandler extends TinyEmitter {
|
|
24
|
-
#ipcMessageManager: IPCMessageManager | null = null;
|
|
25
|
-
#options: IPCMessageHandlerOptions;
|
|
26
|
-
#worker: Worker | null = null;
|
|
27
|
-
#events: JSONObject = { };
|
|
28
|
-
#startWorkerOptions: any;
|
|
29
|
-
#startPrimaryWorker: Worker | null = null;
|
|
30
|
-
|
|
31
|
-
constructor(options: IPCMessageHandlerOptions) {
|
|
32
|
-
super();
|
|
33
|
-
this.#options = options;
|
|
34
|
-
if (cluster.isPrimary) {
|
|
35
|
-
this.SetupPrimary();
|
|
36
|
-
} else {
|
|
37
|
-
this.SetupWorker();
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
get __events() {
|
|
42
|
-
return this.#events;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
#ProcessPrimaryMessageRaw = (payload: any) => {
|
|
46
|
-
this.#ipcMessageManager?.ProcessMessage(payload, { worker: this.#startPrimaryWorker as Worker });
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
SetupPrimary = () => {
|
|
50
|
-
const ipcMessageManagerOptions: IPCMessageManagerOptions = {
|
|
51
|
-
logger: defaultLogger,
|
|
52
|
-
requestResponseMessageTimeout: 5000,
|
|
53
|
-
namespace: this.#options.namespace,
|
|
54
|
-
role: 'SERVER',
|
|
55
|
-
messageSender: (payload: IIPCMessageProcessorIPCPayload, options: any) => {
|
|
56
|
-
(options.worker as any).send(payload);
|
|
57
|
-
},
|
|
58
|
-
ProcessRequestMessage: async (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {
|
|
59
|
-
return this.#processPayload(payload, options);
|
|
60
|
-
},
|
|
61
|
-
messageReceiverStart: (options: any) => {
|
|
62
|
-
// Receive a message to process from a worker
|
|
63
|
-
const worker = (options.worker as Worker);
|
|
64
|
-
this.#startPrimaryWorker = worker;
|
|
65
|
-
worker.on('message', this.#ProcessPrimaryMessageRaw);
|
|
66
|
-
},
|
|
67
|
-
messageReceiverStop: (options: any) => {
|
|
68
|
-
const worker = (options.worker as Worker);
|
|
69
|
-
worker.off('message', this.#ProcessPrimaryMessageRaw);
|
|
70
|
-
},
|
|
71
|
-
groups: [ ]
|
|
72
|
-
}
|
|
73
|
-
this.#ipcMessageManager = new IPCMessageManager(ipcMessageManagerOptions);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
#ProcessWorkerMessageRaw = (payload: any) => {
|
|
77
|
-
this.#ipcMessageManager?.ProcessMessage(payload, this.#startWorkerOptions);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
SetupWorker = () => {
|
|
81
|
-
const ipcMessageManagerOptions: IPCMessageManagerOptions = {
|
|
82
|
-
logger: defaultLogger,
|
|
83
|
-
requestResponseMessageTimeout: this.#options.requestResponseMessageTimeout,
|
|
84
|
-
namespace: this.#options.namespace,
|
|
85
|
-
role: 'CLIENT',
|
|
86
|
-
|
|
87
|
-
messageSender: (payload: IIPCMessageProcessorIPCPayload, options: any) => {
|
|
88
|
-
// Options not required for sending payloads to the master process
|
|
89
|
-
(process as any).send(payload);
|
|
90
|
-
},
|
|
91
|
-
ProcessRequestMessage: async (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {
|
|
92
|
-
return this.#processPayload(payload, options);
|
|
93
|
-
},
|
|
94
|
-
messageReceiverStart: (options: any) => {
|
|
95
|
-
// Receive a message response back from the primary thread
|
|
96
|
-
this.#startWorkerOptions = { ...options };
|
|
97
|
-
process.on('message', this.#ProcessWorkerMessageRaw);
|
|
98
|
-
},
|
|
99
|
-
messageReceiverStop: (options: any) => {
|
|
100
|
-
process.off('message', this.#ProcessWorkerMessageRaw);
|
|
101
|
-
},
|
|
102
|
-
groups: [ ]
|
|
103
|
-
}
|
|
104
|
-
this.#ipcMessageManager = new IPCMessageManager(ipcMessageManagerOptions);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
SendMessage = async (payload: JSONObject): Promise<JSONObject> => {
|
|
108
|
-
if (this.#ipcMessageManager) {
|
|
109
|
-
if (this.#worker) {
|
|
110
|
-
return this.#ipcMessageManager?.SendMessage(payload, { worker: this.#worker });
|
|
111
|
-
} else {
|
|
112
|
-
return this.#ipcMessageManager?.SendMessage(payload, { });
|
|
113
|
-
}
|
|
114
|
-
} else {
|
|
115
|
-
// Error state - no #ipcMessageManager set
|
|
116
|
-
return { };
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
#processPayload = (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {
|
|
121
|
-
// check the event name from the collection and invoke that function
|
|
122
|
-
return new Promise<JSONObject>((resolve, reject) => {
|
|
123
|
-
if (payload.messageType.localeCompare('REQUEST') === 0) {
|
|
124
|
-
if (payload.requestPayload['__eventName']) {
|
|
125
|
-
const eventName = payload.requestPayload['__eventName'];
|
|
126
|
-
if (this.#events[eventName]) {
|
|
127
|
-
try {
|
|
128
|
-
//const retVal = this.#events[eventName].callback(payload.requestPayload.args, payload, options, this.#events[eventName].ctx);
|
|
129
|
-
this.#events[eventName].callback(...payload.requestPayload.args, (responseMessage: any) => {
|
|
130
|
-
resolve(responseMessage);
|
|
131
|
-
});
|
|
132
|
-
} catch (error) {
|
|
133
|
-
reject(error);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// p.on('fromworker', (arg1: number, arg2: string, callback: any) => {
|
|
142
|
-
override on(event: string, callback: any, ctx?: any): this {
|
|
143
|
-
if (this.#events[event]) {
|
|
144
|
-
// Update the event with the same name
|
|
145
|
-
delete this.#events[event];
|
|
146
|
-
}
|
|
147
|
-
const eventObject = {
|
|
148
|
-
event,
|
|
149
|
-
callback,
|
|
150
|
-
ctx
|
|
151
|
-
}
|
|
152
|
-
this.#events[eventObject.event] = eventObject;
|
|
153
|
-
return this;
|
|
154
|
-
//return super.on(event, callback, ctx);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
override off(event: string, callback?: any): this {
|
|
158
|
-
if (this.#events[event]) {
|
|
159
|
-
delete this.#events[event];
|
|
160
|
-
}
|
|
161
|
-
return this;
|
|
162
|
-
//return super.off(event, callback);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
Start = (worker?: Worker) => {
|
|
166
|
-
if (worker) {
|
|
167
|
-
this.#ipcMessageManager?.Start({ worker });
|
|
168
|
-
this.#worker = worker;
|
|
169
|
-
} else {
|
|
170
|
-
this.#ipcMessageManager?.Start({ });
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
Stop = () => {
|
|
175
|
-
if (this.#worker) {
|
|
176
|
-
this.#ipcMessageManager?.Stop({ worker: this.#worker });
|
|
177
|
-
this.#worker = null;
|
|
178
|
-
} else {
|
|
179
|
-
this.#ipcMessageManager?.Stop({ });
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
get worker(): Worker | null {
|
|
184
|
-
return this.#worker;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
override emit(event: string, ...args: any[]): this {
|
|
188
|
-
|
|
189
|
-
const sendMessage = async () => {
|
|
190
|
-
const retVal = await this.SendMessage({
|
|
191
|
-
__eventName: event,
|
|
192
|
-
args: args.slice(0, args.length-1)
|
|
193
|
-
});
|
|
194
|
-
// Invoke the response callback
|
|
195
|
-
args[args.length-1](retVal);
|
|
196
|
-
};
|
|
197
|
-
sendMessage();
|
|
198
|
-
return this;
|
|
199
|
-
//return super.emit(event, ...args);
|
|
200
|
-
}
|
|
201
|
-
}
|
package/src/ipcMessageManager.ts
DELETED
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
/* eslint @typescript-eslint/no-explicit-any: 0 */ // --> OFF
|
|
2
|
-
import { ISTSLogger, JSONObject } from '@nsshunt/stsutils'
|
|
3
|
-
|
|
4
|
-
import { v4 as uuidv4 } from 'uuid';
|
|
5
|
-
|
|
6
|
-
import { IIPCMessageProcessorIPCPayload, IIPCMessageProcessorWorkerRecord } from './commonTypes'
|
|
7
|
-
|
|
8
|
-
export interface IPCMessageManagerOptions {
|
|
9
|
-
logger: ISTSLogger
|
|
10
|
-
requestResponseMessageTimeout: number
|
|
11
|
-
namespace: string
|
|
12
|
-
role: 'SERVER' | 'CLIENT'
|
|
13
|
-
groups: string[]
|
|
14
|
-
messageSender: (payload: IIPCMessageProcessorIPCPayload, options: any) => void
|
|
15
|
-
ProcessRequestMessage: (payload: IIPCMessageProcessorIPCPayload, options: any) => Promise<JSONObject>
|
|
16
|
-
ProcessResponseMessage?: (reesponses: Record<string, IIPCMessageProcessorIPCPayload>, options: any) => Promise<boolean>
|
|
17
|
-
messageReceiverStart: (options: any) => void
|
|
18
|
-
messageReceiverStop: (options: any) => void
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* todo
|
|
22
|
-
* @typedef {Object} options - todo
|
|
23
|
-
* @property {boolean} [wssServer=false] - Create a web socket server on this worker instance
|
|
24
|
-
*/
|
|
25
|
-
export class IPCMessageManager
|
|
26
|
-
{
|
|
27
|
-
#id: string;
|
|
28
|
-
#options: IPCMessageManagerOptions;
|
|
29
|
-
#inflightMessages: Record<string, IIPCMessageProcessorWorkerRecord> = { };
|
|
30
|
-
#messageHeader: string;
|
|
31
|
-
|
|
32
|
-
constructor(options: IPCMessageManagerOptions) {
|
|
33
|
-
this.#id = uuidv4();
|
|
34
|
-
this.#options = options;
|
|
35
|
-
this.#messageHeader = `__STS__${this.#options.namespace}__${uuidv4()}`;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
get id() {
|
|
39
|
-
return this.#id;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
43
|
-
ReceivedMessageFromMaster(msg: any) {
|
|
44
|
-
// Override in subclass if required
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
SendMessage = (payload: JSONObject, options?: any): Promise<JSONObject> => {
|
|
48
|
-
return new Promise((resolve, reject) => {
|
|
49
|
-
this.#SendMessage(payload, options,
|
|
50
|
-
(payload: IIPCMessageProcessorIPCPayload) => {
|
|
51
|
-
resolve(payload.responsePayload);
|
|
52
|
-
},
|
|
53
|
-
(payload: IIPCMessageProcessorIPCPayload) => {
|
|
54
|
-
reject(payload.requestPayload);
|
|
55
|
-
})
|
|
56
|
-
})
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
#SendMessage = (payload: JSONObject, options: any,
|
|
60
|
-
callBack: (payload: IIPCMessageProcessorIPCPayload) => void,
|
|
61
|
-
errorCallBack: (payload: IIPCMessageProcessorIPCPayload) => void
|
|
62
|
-
): void => {
|
|
63
|
-
const messageId: string = uuidv4();
|
|
64
|
-
const requestPayload: IIPCMessageProcessorIPCPayload = {
|
|
65
|
-
header: this.#messageHeader,
|
|
66
|
-
messageId,
|
|
67
|
-
senderId: this.#id,
|
|
68
|
-
senderRole: this.#options.role,
|
|
69
|
-
requestPayload: payload,
|
|
70
|
-
responsePayload: { },
|
|
71
|
-
pid: process.pid.toString(),
|
|
72
|
-
messageType: 'REQUEST'
|
|
73
|
-
}
|
|
74
|
-
const messageRecord = {
|
|
75
|
-
messageId,
|
|
76
|
-
senderId: this.#id,
|
|
77
|
-
senderRole: this.#options.role,
|
|
78
|
-
requestPayload,
|
|
79
|
-
responses: { }, // record
|
|
80
|
-
startTime: performance.now(),
|
|
81
|
-
endTime: 0,
|
|
82
|
-
timeout: setTimeout(() => {
|
|
83
|
-
//this.#LogDebugMessage(chalk.red(`Timeout has occurred after: [${this.#options.requestResponseMessageTimeout}]ms with message id: [${messageRecord.messageId}]. Details: [${JSON.stringify(this.#inflightMessages[messageRecord.messageId].requestPayload)}]`));
|
|
84
|
-
setTimeout(() => {
|
|
85
|
-
delete this.#inflightMessages[messageRecord.messageId];
|
|
86
|
-
}, 0).unref();
|
|
87
|
-
errorCallBack(requestPayload);
|
|
88
|
-
}, this.#options.requestResponseMessageTimeout).unref(),// max message timeout allowed
|
|
89
|
-
callBack,
|
|
90
|
-
errorCallBack
|
|
91
|
-
}
|
|
92
|
-
this.#inflightMessages[messageRecord.messageId] = messageRecord;
|
|
93
|
-
//this.#LogDebugMessage(chalk.cyan(`sending: [${JSON.stringify(requestPayload)}]`));
|
|
94
|
-
this.#options.messageSender(requestPayload, options);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
#ProcessMessage = async (msg: any, options: any): Promise<void> => {
|
|
98
|
-
if (msg.header && msg.header.localeCompare(this.#messageHeader) === 0) {
|
|
99
|
-
const message = (msg as IIPCMessageProcessorIPCPayload);
|
|
100
|
-
if (this.#inflightMessages[message.messageId]) {
|
|
101
|
-
const inFlightMessageRecord: IIPCMessageProcessorWorkerRecord = this.#inflightMessages[message.messageId];
|
|
102
|
-
inFlightMessageRecord.responses[message.senderId ] = { ...message };
|
|
103
|
-
let completed = true; // Defaults to true
|
|
104
|
-
if (this.#options.ProcessResponseMessage) {
|
|
105
|
-
completed = await this.#options.ProcessResponseMessage(inFlightMessageRecord.responses, options);
|
|
106
|
-
if (completed) {
|
|
107
|
-
inFlightMessageRecord.endTime = performance.now();
|
|
108
|
-
clearTimeout(inFlightMessageRecord.timeout as NodeJS.Timeout);
|
|
109
|
-
inFlightMessageRecord.callBack({
|
|
110
|
-
responsePayload: Object.values(inFlightMessageRecord.responses).map(r => r.responsePayload)
|
|
111
|
-
} as any, options) //
|
|
112
|
-
delete this.#inflightMessages[message.messageId];
|
|
113
|
-
}
|
|
114
|
-
} else if (completed) {
|
|
115
|
-
inFlightMessageRecord.endTime = performance.now();
|
|
116
|
-
clearTimeout(inFlightMessageRecord.timeout as NodeJS.Timeout);
|
|
117
|
-
inFlightMessageRecord.callBack(message, options) // inFlightMessageRecord.responses
|
|
118
|
-
//@@inFlightMessageRecord.callBack(Object.values(inFlightMessageRecord.responses), options) //
|
|
119
|
-
delete this.#inflightMessages[message.messageId];
|
|
120
|
-
} else {
|
|
121
|
-
//console.log(chalk.grey(`#ProcessMessage:5`));
|
|
122
|
-
}
|
|
123
|
-
} else {
|
|
124
|
-
//throw new Error(`Could not find Request/Response message with id: [${message.messageId}]`); //@@
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
Start = (options?: any) => {
|
|
130
|
-
this.#messageHeader = `__STS__${this.#options.namespace}__${uuidv4()}`;
|
|
131
|
-
this.#options.messageReceiverStart(options);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
Stop = (options?: any) => {
|
|
135
|
-
// Kill in-flight messages
|
|
136
|
-
this.#options.messageReceiverStop(options);
|
|
137
|
-
|
|
138
|
-
for (const [, iPCMessageProcessorWorkerRecord] of Object.entries(this.#inflightMessages)) {
|
|
139
|
-
if (iPCMessageProcessorWorkerRecord.timeout) {
|
|
140
|
-
clearTimeout(iPCMessageProcessorWorkerRecord.timeout);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
this.#inflightMessages = { };
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// Process a message recieved from a worker
|
|
147
|
-
ProcessMessage = async (msg: any, options: any) => {
|
|
148
|
-
if (msg.header) {
|
|
149
|
-
const checkName = `__STS__${this.#options.namespace}__`; //@@ this is a broadcast becuase the unique uuid is not part of the header test
|
|
150
|
-
if ((msg.header as string).includes(checkName)) {
|
|
151
|
-
const message = (msg as IIPCMessageProcessorIPCPayload);
|
|
152
|
-
if (msg.messageType.localeCompare('REQUEST') === 0) {
|
|
153
|
-
let processMessage = true;
|
|
154
|
-
if (message.requestPayload.args && message.requestPayload.args.length > 0 && message.requestPayload.args[0].group) {
|
|
155
|
-
const group = message.requestPayload.args[0].group;
|
|
156
|
-
processMessage = (this.#options.groups.indexOf(group) === -1) ? false : true;
|
|
157
|
-
}
|
|
158
|
-
if (processMessage) {
|
|
159
|
-
message.responsePayload = await this.#options.ProcessRequestMessage(message, options);
|
|
160
|
-
message.senderId = this.#id;
|
|
161
|
-
message.messageType = 'RESPONSE';
|
|
162
|
-
this.#options.messageSender(message, options);
|
|
163
|
-
}
|
|
164
|
-
} else {
|
|
165
|
-
// Received a response (to my request)
|
|
166
|
-
this.#ProcessMessage(msg, options);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
/* eslint @typescript-eslint/no-explicit-any: 0 */ // --> OFF
|
|
2
|
-
import { ISTSLogger, JSONObject, defaultLogger } from '@nsshunt/stsutils'
|
|
3
|
-
|
|
4
|
-
import { Worker } from 'node:cluster';
|
|
5
|
-
|
|
6
|
-
import { IIPCMessageProcessorIPCPayload } from './commonTypes'
|
|
7
|
-
|
|
8
|
-
import { IPCMessageManager, IPCMessageManagerOptions } from './ipcMessageManager'
|
|
9
|
-
|
|
10
|
-
export interface IIPCMessageProcessorPrimary {
|
|
11
|
-
logger: ISTSLogger
|
|
12
|
-
namespace: string
|
|
13
|
-
processPayload?: (payload: IIPCMessageProcessorIPCPayload, options: any) => Promise<JSONObject>
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* IPC Message Handling.
|
|
18
|
-
*
|
|
19
|
-
* This class can be used to support messages between cluster.primary and cluster.worker instances using IPC.
|
|
20
|
-
* This class can be used for finer control for processing messages between the cluster primary and cluster workers.
|
|
21
|
-
* Use the ipcMessageHandler for a simpler implementation.
|
|
22
|
-
* This class is used for the cluster primary thread only.
|
|
23
|
-
* Note: Currently groups handling is not supported. Use the redis version for this capability.
|
|
24
|
-
*/
|
|
25
|
-
export class IPCMessageProcessorPrimary {
|
|
26
|
-
#ipcMessageManager: IPCMessageManager;
|
|
27
|
-
#worker: Worker | null = null;
|
|
28
|
-
|
|
29
|
-
constructor(classOptions: IIPCMessageProcessorPrimary) {
|
|
30
|
-
const ipcMessageManagerOptions: IPCMessageManagerOptions = {
|
|
31
|
-
logger: defaultLogger,
|
|
32
|
-
requestResponseMessageTimeout: 5000,
|
|
33
|
-
namespace: classOptions.namespace,
|
|
34
|
-
role: 'SERVER',
|
|
35
|
-
messageSender: (payload: IIPCMessageProcessorIPCPayload, options: any) => {
|
|
36
|
-
(options.worker as any).send(payload);
|
|
37
|
-
},
|
|
38
|
-
ProcessRequestMessage: async (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {
|
|
39
|
-
if (classOptions.processPayload) {
|
|
40
|
-
return classOptions.processPayload(payload, options);
|
|
41
|
-
} else {
|
|
42
|
-
return { };
|
|
43
|
-
}
|
|
44
|
-
},
|
|
45
|
-
messageReceiverStart: (options: any) => {
|
|
46
|
-
// Receive a message to process from a worker
|
|
47
|
-
const worker = (options.worker as Worker);
|
|
48
|
-
worker.on('message', (payload) => this.#ipcMessageManager.ProcessMessage(payload, { worker }));
|
|
49
|
-
},
|
|
50
|
-
messageReceiverStop: (options: any) => {
|
|
51
|
-
const worker = (options.worker as Worker);
|
|
52
|
-
worker.off('message', (payload) => this.#ipcMessageManager.ProcessMessage(payload, { worker }));
|
|
53
|
-
},
|
|
54
|
-
groups: [ ]
|
|
55
|
-
}
|
|
56
|
-
this.#ipcMessageManager = new IPCMessageManager(ipcMessageManagerOptions);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
SendMessage = async (payload: JSONObject): Promise<JSONObject> => {
|
|
60
|
-
return this.#ipcMessageManager.SendMessage(payload, { worker: this.#worker });
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
Start = (worker: Worker) => {
|
|
64
|
-
this.#ipcMessageManager.Start({ worker });
|
|
65
|
-
this.#worker = worker;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
Stop = () => {
|
|
69
|
-
this.#ipcMessageManager.Stop({ worker: this.#worker });
|
|
70
|
-
this.#worker = null;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
get worker(): Worker | null {
|
|
74
|
-
return this.#worker;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
/* eslint @typescript-eslint/no-explicit-any: 0 */ // --> OFF
|
|
2
|
-
import { ISTSLogger, JSONObject, defaultLogger } from '@nsshunt/stsutils'
|
|
3
|
-
|
|
4
|
-
import { IIPCMessageProcessorIPCPayload } from './commonTypes'
|
|
5
|
-
|
|
6
|
-
import { IPCMessageManager, IPCMessageManagerOptions } from './ipcMessageManager'
|
|
7
|
-
|
|
8
|
-
export interface IIPCMessageProcessorWorker {
|
|
9
|
-
logger: ISTSLogger
|
|
10
|
-
requestResponseMessageTimeout: number
|
|
11
|
-
namespace: string
|
|
12
|
-
processPayload?: (payload: IIPCMessageProcessorIPCPayload, options: any) => Promise<JSONObject>
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* IPC Message Handling.
|
|
17
|
-
*
|
|
18
|
-
* This class can be used to support messages between cluster.primary and cluster.worker instances using IPC.
|
|
19
|
-
* This class can be used for finer control for processing messages between the cluster primary and cluster workers.
|
|
20
|
-
* Use the ipcMessageHandler for a simpler implementation.
|
|
21
|
-
* This class is used for the cluster worker threads only.
|
|
22
|
-
* Note: Currently groups handling is not supported. Use the redis version for this capability.
|
|
23
|
-
*/
|
|
24
|
-
export class IPCMessageProcessorWorker {
|
|
25
|
-
#ipcMessageManager: IPCMessageManager;
|
|
26
|
-
|
|
27
|
-
constructor(classOptions: IIPCMessageProcessorWorker) {
|
|
28
|
-
const ipcMessageManagerOptions: IPCMessageManagerOptions = {
|
|
29
|
-
logger: defaultLogger,
|
|
30
|
-
requestResponseMessageTimeout: classOptions.requestResponseMessageTimeout,
|
|
31
|
-
namespace: classOptions.namespace,
|
|
32
|
-
role: 'CLIENT',
|
|
33
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
34
|
-
messageSender: (payload: IIPCMessageProcessorIPCPayload, options: any) => {
|
|
35
|
-
// Options not required for sending payloads to the master process
|
|
36
|
-
(process as any).send(payload);
|
|
37
|
-
},
|
|
38
|
-
ProcessRequestMessage: async (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {
|
|
39
|
-
if (classOptions.processPayload) {
|
|
40
|
-
return classOptions.processPayload(payload, options);
|
|
41
|
-
} else {
|
|
42
|
-
return { };
|
|
43
|
-
}
|
|
44
|
-
},
|
|
45
|
-
messageReceiverStart: (options: any) => {
|
|
46
|
-
// Receive a message response back from the primary thread
|
|
47
|
-
process.on('message', (payload) => {
|
|
48
|
-
this.#ipcMessageManager.ProcessMessage(payload, options);
|
|
49
|
-
});
|
|
50
|
-
},
|
|
51
|
-
messageReceiverStop: (options: any) => {
|
|
52
|
-
process.off('message', (payload) => this.#ipcMessageManager.ProcessMessage(payload, options));
|
|
53
|
-
},
|
|
54
|
-
groups: [ ]
|
|
55
|
-
}
|
|
56
|
-
this.#ipcMessageManager = new IPCMessageManager(ipcMessageManagerOptions);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
SendMessage = async (payload: JSONObject): Promise<JSONObject> => {
|
|
60
|
-
return this.#ipcMessageManager.SendMessage(payload, { });
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
Start = () => {
|
|
64
|
-
this.#ipcMessageManager.Start({ });
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
Stop = () => {
|
|
68
|
-
this.#ipcMessageManager.Stop({ });
|
|
69
|
-
}
|
|
70
|
-
}
|