@nsshunt/stsappframework 3.1.130 → 3.1.132
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/dist/ipcMessageHandler.js +5 -3
- package/dist/ipcMessageHandler.js.map +1 -1
- package/dist/ipcMessageManager.js +14 -4
- package/dist/ipcMessageManager.js.map +1 -1
- package/dist/ipcMessageProcessorPrimary.js +3 -2
- package/dist/ipcMessageProcessorPrimary.js.map +1 -1
- package/dist/ipcMessageProcessorWorker.js +2 -1
- package/dist/ipcMessageProcessorWorker.js.map +1 -1
- package/dist/redisMessageHandler.js +73 -20
- package/dist/redisMessageHandler.js.map +1 -1
- package/dist/redisMessageHandler.test.js +4 -2
- package/dist/redisMessageHandler.test.js.map +1 -1
- package/dist/testing/app.js +215 -42
- package/dist/testing/app.js.map +1 -1
- package/dist/workerprocessbase.js +108 -1
- package/dist/workerprocessbase.js.map +1 -1
- package/package.json +1 -1
- package/src/ipcMessageHandler.ts +5 -3
- package/src/ipcMessageManager.ts +14 -4
- package/src/ipcMessageProcessorPrimary.ts +3 -2
- package/src/ipcMessageProcessorWorker.ts +2 -1
- package/src/redisMessageHandler.test.ts +4 -2
- package/src/redisMessageHandler.ts +78 -20
- package/src/testing/app.ts +219 -22
- package/src/workerprocessbase.ts +124 -3
- package/types/ipcMessageHandler.d.ts.map +1 -1
- package/types/ipcMessageManager.d.ts +1 -0
- package/types/ipcMessageManager.d.ts.map +1 -1
- package/types/ipcMessageProcessorPrimary.d.ts.map +1 -1
- package/types/ipcMessageProcessorWorker.d.ts.map +1 -1
- package/types/redisMessageHandler.d.ts +4 -1
- package/types/redisMessageHandler.d.ts.map +1 -1
- package/types/workerprocessbase.d.ts +15 -0
- package/types/workerprocessbase.d.ts.map +1 -1
|
@@ -39,7 +39,8 @@ export class IPCMessageProcessorWorker {
|
|
|
39
39
|
},
|
|
40
40
|
messageReceiverStop: (options: any) => {
|
|
41
41
|
process.off('message', (payload) => this.#ipcMessageManager.ProcessMessage(payload, options));
|
|
42
|
-
}
|
|
42
|
+
},
|
|
43
|
+
groups: [ ]
|
|
43
44
|
}
|
|
44
45
|
this.#ipcMessageManager = new IPCMessageManager(ipcMessageManagerOptions);
|
|
45
46
|
}
|
|
@@ -39,7 +39,8 @@ describe.skip("Redis Message Handler Test", () =>
|
|
|
39
39
|
logger: defaultLogger,
|
|
40
40
|
role: 'SERVER',
|
|
41
41
|
redisUrl: ioRedisMessageProcessorUrl, // goptions.imRedisMessageProcessorUrl,
|
|
42
|
-
namespace: 'redistestingstsframework'
|
|
42
|
+
namespace: 'redistestingstsframework',
|
|
43
|
+
groups: [ ]
|
|
43
44
|
});
|
|
44
45
|
this.#r1.Start();
|
|
45
46
|
|
|
@@ -87,7 +88,8 @@ describe.skip("Redis Message Handler Test", () =>
|
|
|
87
88
|
logger: defaultLogger,
|
|
88
89
|
role: 'CLIENT',
|
|
89
90
|
redisUrl: ioRedisMessageProcessorUrl, // goptions.imRedisMessageProcessorUrl,
|
|
90
|
-
namespace: 'redistestingstsframework'
|
|
91
|
+
namespace: 'redistestingstsframework',
|
|
92
|
+
groups: [ ]
|
|
91
93
|
});
|
|
92
94
|
this.#r1.Start();
|
|
93
95
|
|
|
@@ -8,6 +8,7 @@ import { IPCMessageManager, IPCMessageManagerOptions } from './ipcMessageManager
|
|
|
8
8
|
import { Redis, RedisOptions } from "ioredis";
|
|
9
9
|
|
|
10
10
|
import chalk from 'chalk';
|
|
11
|
+
import { AggregateSteps } from "redis";
|
|
11
12
|
|
|
12
13
|
const REQUEST_CHANNEL = '__STS__SVC_stsappframework_request'
|
|
13
14
|
const RESPONSE_CHANNEL = '__STS__SVC_stsappframework_response'
|
|
@@ -17,6 +18,7 @@ export interface IRedisAdminManagerOptions {
|
|
|
17
18
|
logger: ISTSLogger
|
|
18
19
|
role: 'SERVER' | 'CLIENT'
|
|
19
20
|
namespace: string
|
|
21
|
+
groups: string[]
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
export interface IClientRecord {
|
|
@@ -24,6 +26,7 @@ export interface IClientRecord {
|
|
|
24
26
|
clientConnected: Date
|
|
25
27
|
pingCount: number
|
|
26
28
|
timeout: NodeJS.Timeout
|
|
29
|
+
groups: string[]
|
|
27
30
|
}
|
|
28
31
|
|
|
29
32
|
export interface IEventPayload {
|
|
@@ -78,19 +81,32 @@ export class RedisMessageHandler extends TinyEmitter {
|
|
|
78
81
|
if (this.#options.role.localeCompare('CLIENT') === 0) {
|
|
79
82
|
const ping = () => {
|
|
80
83
|
this.#pingTimeout = setTimeout(() => {
|
|
81
|
-
|
|
84
|
+
let group = '';
|
|
85
|
+
if (process.pid % 2 === 0) {
|
|
86
|
+
group = 'even';
|
|
87
|
+
} else {
|
|
88
|
+
group = 'odd';
|
|
89
|
+
}
|
|
90
|
+
this.emit('ping', {
|
|
91
|
+
id: this.#ipcMessageManager?.id,
|
|
92
|
+
groups: [
|
|
93
|
+
group
|
|
94
|
+
]
|
|
95
|
+
}, (response: any) => { });
|
|
82
96
|
ping();
|
|
83
97
|
}, 1000).unref();
|
|
84
98
|
}
|
|
85
99
|
ping();
|
|
86
100
|
} else {
|
|
87
|
-
this.on('ping', (
|
|
101
|
+
this.on('ping', (pingData: JSONObject, callback: any) => {
|
|
102
|
+
const { id, groups } = pingData;
|
|
88
103
|
if (this.#clients[id]) {
|
|
89
104
|
clearTimeout(this.#clients[id].timeout);
|
|
90
105
|
this.#clients[id].pingCount++;
|
|
91
106
|
this.#clients[id].timeout = setTimeout(() => {
|
|
92
107
|
delete this.#clients[id];
|
|
93
108
|
}, 2000);
|
|
109
|
+
this.#clients[id].groups = groups;
|
|
94
110
|
} else {
|
|
95
111
|
this.#clients[id] = {
|
|
96
112
|
id,
|
|
@@ -98,7 +114,8 @@ export class RedisMessageHandler extends TinyEmitter {
|
|
|
98
114
|
pingCount: 0,
|
|
99
115
|
timeout: setTimeout(() => {
|
|
100
116
|
delete this.#clients[id];
|
|
101
|
-
}, 2000)
|
|
117
|
+
}, 2000),
|
|
118
|
+
groups
|
|
102
119
|
}
|
|
103
120
|
}
|
|
104
121
|
callback('ok');
|
|
@@ -122,10 +139,11 @@ export class RedisMessageHandler extends TinyEmitter {
|
|
|
122
139
|
SetupPrimary = () => {
|
|
123
140
|
const ipcMessageManagerOptions: IPCMessageManagerOptions = {
|
|
124
141
|
logger: this.#options.logger,
|
|
125
|
-
requestResponseMessageTimeout:
|
|
142
|
+
requestResponseMessageTimeout: 5000,
|
|
126
143
|
namespace: this.#options.namespace,
|
|
127
144
|
role: this.#options.role,
|
|
128
145
|
messageSender: this.#messageSender,
|
|
146
|
+
groups: this.#options.groups,
|
|
129
147
|
// This method is used to calculate if all responses have been received from multiple clients (broadcast)
|
|
130
148
|
// returns true/false.
|
|
131
149
|
ProcessResponseMessage: this.#ProcessResponseMessage,
|
|
@@ -157,26 +175,55 @@ export class RedisMessageHandler extends TinyEmitter {
|
|
|
157
175
|
// Now check if we have all responses ...
|
|
158
176
|
let allFound = false;
|
|
159
177
|
|
|
160
|
-
Object.
|
|
161
|
-
if (
|
|
178
|
+
for (const [responseId, response] of Object.entries(responses)) {
|
|
179
|
+
if (response.senderRole.localeCompare('CLIENT') === 0) {
|
|
162
180
|
allFound = true;
|
|
181
|
+
break;
|
|
163
182
|
}
|
|
164
|
-
}
|
|
183
|
+
}
|
|
165
184
|
if (allFound) {
|
|
166
185
|
return allFound;
|
|
167
186
|
}
|
|
168
187
|
|
|
169
188
|
let found = true;
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
189
|
+
|
|
190
|
+
// Sender role here is SERVER
|
|
191
|
+
let requestGroup = null;
|
|
192
|
+
for (const [responseId, response] of Object.entries(responses)) {
|
|
193
|
+
if (response.requestPayload.args.length > 0 && response.requestPayload.args[0].group) {
|
|
194
|
+
requestGroup = response.requestPayload.args[0].group;
|
|
195
|
+
break;
|
|
173
196
|
}
|
|
174
|
-
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (requestGroup) {
|
|
200
|
+
const clientsInGroup = Object.values(this.#clients).filter(c => {
|
|
201
|
+
if (c.groups.indexOf(requestGroup) === -1) {
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
return true;
|
|
205
|
+
});
|
|
175
206
|
|
|
176
|
-
|
|
177
|
-
|
|
207
|
+
// Now make sure that all clients are in the responses
|
|
208
|
+
found = true;
|
|
209
|
+
clientsInGroup.forEach(c => {
|
|
210
|
+
if (!responses[c.id]) {
|
|
211
|
+
found = false;
|
|
212
|
+
}
|
|
213
|
+
})
|
|
214
|
+
} else {
|
|
215
|
+
const clientsInGroup = Object.values(this.#clients)
|
|
216
|
+
|
|
217
|
+
// Now make sure that all clients are in the responses
|
|
218
|
+
found = true;
|
|
219
|
+
clientsInGroup.forEach(c => {
|
|
220
|
+
if (!responses[c.id]) {
|
|
221
|
+
found = false;
|
|
222
|
+
}
|
|
223
|
+
})
|
|
178
224
|
}
|
|
179
|
-
|
|
225
|
+
|
|
226
|
+
return found;
|
|
180
227
|
}
|
|
181
228
|
|
|
182
229
|
#processPayload = (payload: IIPCMessageProcessorIPCPayload, options: any): Promise<JSONObject> => {
|
|
@@ -244,13 +291,24 @@ export class RedisMessageHandler extends TinyEmitter {
|
|
|
244
291
|
|
|
245
292
|
override emit(event: string, ...args: any[]): this {
|
|
246
293
|
(async () => {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
294
|
+
try {
|
|
295
|
+
const retVal = await this.#ipcMessageManager?.SendMessage({
|
|
296
|
+
__eventName: event,
|
|
297
|
+
args: args.slice(0, args.length-1)
|
|
298
|
+
} as IEventPayload);
|
|
299
|
+
// Invoke the response callback
|
|
300
|
+
args[args.length-1](retVal);
|
|
301
|
+
} catch (error) {
|
|
302
|
+
this.#options.logger.error(chalk.red(`emit(): Error: [${JSON.stringify(error)}]`));
|
|
303
|
+
}
|
|
253
304
|
})();
|
|
254
305
|
return this;
|
|
255
306
|
}
|
|
307
|
+
|
|
308
|
+
emitex = async(event: string, ...args: any[]): Promise<JSONObject> => {
|
|
309
|
+
return (this.#ipcMessageManager as IPCMessageManager).SendMessage({
|
|
310
|
+
__eventName: event,
|
|
311
|
+
args
|
|
312
|
+
} as IEventPayload);
|
|
313
|
+
}
|
|
256
314
|
}
|
package/src/testing/app.ts
CHANGED
|
@@ -20,6 +20,9 @@ import { v4 as uuidv4 } from 'uuid';
|
|
|
20
20
|
import { RedisMessageHandler } from './../redisMessageHandler'
|
|
21
21
|
import { goptions } from '@nsshunt/stsconfig'
|
|
22
22
|
|
|
23
|
+
import si from 'systeminformation' // https://systeminformation.io/
|
|
24
|
+
import { GetFirstNetworkInterface } from './../network'
|
|
25
|
+
|
|
23
26
|
const sleepVal = 0;
|
|
24
27
|
const maxLoop = 100;
|
|
25
28
|
|
|
@@ -105,7 +108,7 @@ const StartTestWorker = () => {
|
|
|
105
108
|
const w1 = new IPCMessageProcessorWorker({
|
|
106
109
|
logger: defaultLogger,
|
|
107
110
|
namespace: 'test1',
|
|
108
|
-
requestResponseMessageTimeout:
|
|
111
|
+
requestResponseMessageTimeout: 5000,
|
|
109
112
|
processPayload: async (payload) => {
|
|
110
113
|
return {
|
|
111
114
|
msg1: `From WORKER: [${process.pid}]`,
|
|
@@ -118,7 +121,7 @@ const StartTestWorker = () => {
|
|
|
118
121
|
const w2 = new IPCMessageProcessorWorker({
|
|
119
122
|
logger: defaultLogger,
|
|
120
123
|
namespace: 'test2',
|
|
121
|
-
requestResponseMessageTimeout:
|
|
124
|
+
requestResponseMessageTimeout: 5000,
|
|
122
125
|
processPayload: async (payload) => {
|
|
123
126
|
return {
|
|
124
127
|
msg2: `From WORKER: [${process.pid}]`,
|
|
@@ -131,7 +134,7 @@ const StartTestWorker = () => {
|
|
|
131
134
|
const w3 = new IPCMessageProcessorWorker({
|
|
132
135
|
logger: defaultLogger,
|
|
133
136
|
namespace: 'zzz',
|
|
134
|
-
requestResponseMessageTimeout:
|
|
137
|
+
requestResponseMessageTimeout: 5000,
|
|
135
138
|
processPayload: async (payload) => {
|
|
136
139
|
switch (payload.requestPayload.cmd) {
|
|
137
140
|
case 'cmd1' : return {
|
|
@@ -177,13 +180,97 @@ const StartTestWorker = () => {
|
|
|
177
180
|
}, 1000);
|
|
178
181
|
}
|
|
179
182
|
|
|
180
|
-
const iterations =
|
|
183
|
+
const iterations = 0;
|
|
181
184
|
const delay = 100;
|
|
182
185
|
|
|
186
|
+
const GetNumCPUs = async (): Promise<number> => {
|
|
187
|
+
// https://systeminformation.io/
|
|
188
|
+
const valueObject = {
|
|
189
|
+
cpu: '*'
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const sysinfo = await si.get(valueObject);
|
|
193
|
+
let numCPUs = 2;
|
|
194
|
+
if (goptions.useCPUs > 0) {
|
|
195
|
+
if (goptions.useCPUs >= 1) {
|
|
196
|
+
numCPUs = goptions.useCPUs;
|
|
197
|
+
} else {
|
|
198
|
+
numCPUs = Math.round(sysinfo.cpu.cores * goptions.useCPUs);
|
|
199
|
+
}
|
|
200
|
+
} else {
|
|
201
|
+
numCPUs = sysinfo.cpu.physicalCores;
|
|
202
|
+
}
|
|
203
|
+
return numCPUs;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const LogInfoMessage = (message: string) => {
|
|
207
|
+
console.log(message);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const LogSystemTelemetry = async () => {
|
|
211
|
+
// https://systeminformation.io/
|
|
212
|
+
const valueObject = {
|
|
213
|
+
system: '*',
|
|
214
|
+
osInfo: '*',
|
|
215
|
+
cpu: '*',
|
|
216
|
+
mem: '*',
|
|
217
|
+
dockerInfo: '*',
|
|
218
|
+
//dockerImages: '*',
|
|
219
|
+
dockerContainers: '*',
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const sysinfo = await si.get(valueObject);
|
|
223
|
+
const numCPUs = await GetNumCPUs();
|
|
224
|
+
const hostname = sysinfo.osInfo.hostname;
|
|
225
|
+
|
|
226
|
+
const hostaddr = GetFirstNetworkInterface();
|
|
227
|
+
if (hostaddr !== null) {
|
|
228
|
+
LogInfoMessage(`Host Address: ${hostaddr}`);
|
|
229
|
+
} else {
|
|
230
|
+
LogInfoMessage(`Unknown Host Address.`);
|
|
231
|
+
}
|
|
232
|
+
LogInfoMessage(`Server starting with ${numCPUs} Cores/Threads`);
|
|
233
|
+
|
|
234
|
+
LogInfoMessage(`Hostname: ${hostname}`);
|
|
235
|
+
LogInfoMessage(`System: ${JSON.stringify(sysinfo.system)}`);
|
|
236
|
+
LogInfoMessage(`OS Info: ${JSON.stringify(sysinfo.osInfo)}`);
|
|
237
|
+
LogInfoMessage(`CPU: ${JSON.stringify(sysinfo.cpu)}`);
|
|
238
|
+
LogInfoMessage(`Memory: ${JSON.stringify(sysinfo.mem)}`);
|
|
239
|
+
|
|
240
|
+
const promArray: Promise<any>[] = [ ];
|
|
241
|
+
|
|
242
|
+
sysinfo.dockerContainers.forEach((dc: { id: string; }) => {
|
|
243
|
+
LogInfoMessage(dc.id);
|
|
244
|
+
const dcs = promArray.push(si.dockerContainerStats(dc.id));
|
|
245
|
+
console.log(dcs);
|
|
246
|
+
});
|
|
247
|
+
const dockerContainerStats = await Promise.all(promArray);
|
|
248
|
+
|
|
249
|
+
const sysInfo = {
|
|
250
|
+
hostname,
|
|
251
|
+
numCPUs,
|
|
252
|
+
hostaddr,
|
|
253
|
+
system: sysinfo.system,
|
|
254
|
+
osInfo: sysinfo.osInfo,
|
|
255
|
+
cpu: sysinfo.cpu,
|
|
256
|
+
mem: sysinfo.mem,
|
|
257
|
+
dockerInfo: sysinfo.dockerInfo,
|
|
258
|
+
//dockerImages: sysinfo.dockerImages,
|
|
259
|
+
dockerContainers: sysinfo.dockerContainers,
|
|
260
|
+
dockerContainerStats
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
console.log(sysInfo);
|
|
264
|
+
|
|
265
|
+
console.log(JSON.stringify(sysInfo));
|
|
266
|
+
}
|
|
267
|
+
|
|
183
268
|
if (cluster.isPrimary) {
|
|
184
269
|
new MasterProcessBase(ServiceConfigOptions(true, cluster.isPrimary)).SetupServer();
|
|
185
270
|
//StartTestPrimary();
|
|
186
271
|
|
|
272
|
+
LogSystemTelemetry();
|
|
273
|
+
|
|
187
274
|
setTimeout(() => {
|
|
188
275
|
const p: Record<string, IPCMessageHandler> = { };
|
|
189
276
|
/*
|
|
@@ -206,7 +293,94 @@ if (cluster.isPrimary) {
|
|
|
206
293
|
}
|
|
207
294
|
*/
|
|
208
295
|
|
|
296
|
+
/*
|
|
297
|
+
const stsServiceControl: RedisMessageHandler = new RedisMessageHandler({
|
|
298
|
+
logger: defaultLogger,
|
|
299
|
+
role: 'SERVER',
|
|
300
|
+
redisUrl: goptions.imRedisMessageProcessorUrl,
|
|
301
|
+
namespace: 'stsServiceControl',
|
|
302
|
+
groups: [ ]
|
|
303
|
+
});
|
|
304
|
+
stsServiceControl.Start();
|
|
305
|
+
|
|
306
|
+
stsServiceControl.on('ping_ex', (pingData: JSONObject, callback: any) => {
|
|
307
|
+
console.log(chalk.yellow(`${process.pid}: stsServiceControl.on(ping): [${JSON.stringify(pingData)}]`));
|
|
308
|
+
callback({pingData, dateTime: new Date().getTime()})
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
setInterval(() => {
|
|
312
|
+
stsServiceControl.emit('GET_SYSTEM_TELEMETRY', { }, (response: any) => {
|
|
313
|
+
console.log(chalk.green(` ==>> ${process.pid}: Response(GET_SYSTEM_TELEMETRY): [${JSON.stringify(response)}]`));
|
|
314
|
+
});
|
|
315
|
+
}, 5000);
|
|
316
|
+
*/
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
const r1: RedisMessageHandler = new RedisMessageHandler({
|
|
321
|
+
logger: defaultLogger,
|
|
322
|
+
role: 'SERVER',
|
|
323
|
+
redisUrl: goptions.imRedisMessageProcessorUrl,
|
|
324
|
+
namespace: 'mytestapp',
|
|
325
|
+
groups: [ ]
|
|
326
|
+
});
|
|
327
|
+
r1.Start();
|
|
328
|
+
|
|
329
|
+
const RunTest = async (eventName: string, emitobj: JSONObject) => {
|
|
330
|
+
const start = performance.now();
|
|
331
|
+
try {
|
|
332
|
+
const response = await r1.emitex(eventName, emitobj);
|
|
333
|
+
const duration = performance.now() - start;
|
|
334
|
+
console.log(chalk.cyan(`${process.pid}: Duration: ${duration} Test: [test1] Response(${chalk.bold(eventName)}): [${JSON.stringify(response)}]`));
|
|
335
|
+
} catch (error) {
|
|
336
|
+
const duration = performance.now() - start;
|
|
337
|
+
console.log(chalk.cyan(`${process.pid}: Duration: ${duration} Test: [test1] Response(${chalk.bold(eventName)}): Error: [${JSON.stringify(error)}]`));
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
let i = 0;
|
|
342
|
+
let group = '';
|
|
343
|
+
const maxIterations = 20;
|
|
344
|
+
const xxx = () => {
|
|
345
|
+
setTimeout(() => {
|
|
346
|
+
i++;
|
|
347
|
+
|
|
348
|
+
if (i > maxIterations) {
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
console.log(chalk.yellow(`Iteration: [${i}]`));
|
|
353
|
+
|
|
354
|
+
if (i % 2 === 0) {
|
|
355
|
+
group = 'even'
|
|
356
|
+
} else {
|
|
357
|
+
group = 'odd'
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const promArray: Promise<void>[] = [ ];
|
|
361
|
+
const start = performance.now();
|
|
362
|
+
promArray.push(
|
|
363
|
+
RunTest('fromprimaryredis', { group, i: i, a: 'a', b: 'b' }),
|
|
364
|
+
RunTest('fromprimaryredis', { group: '2', i: i, a: 'a', b: 'b' }),
|
|
365
|
+
RunTest('fromprimaryredis', { group: '4', i: i, a: 'a', b: 'b' }),
|
|
366
|
+
RunTest('globalmessage', { i: i, a: 'a', b: 'b' })
|
|
367
|
+
);
|
|
368
|
+
(async () => {
|
|
369
|
+
await Promise.all(promArray);
|
|
370
|
+
const duration = performance.now() - start;
|
|
371
|
+
console.log(chalk.green(`${process.pid}: Duration: ${duration} Test: [All Tests Run]`));
|
|
372
|
+
console.log();
|
|
373
|
+
xxx();
|
|
374
|
+
})();
|
|
375
|
+
}, 250);
|
|
376
|
+
}
|
|
377
|
+
setTimeout(() => xxx(), 1000);
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
|
|
209
382
|
|
|
383
|
+
/*
|
|
210
384
|
const r1: RedisMessageHandler = new RedisMessageHandler({
|
|
211
385
|
logger: defaultLogger,
|
|
212
386
|
role: 'SERVER',
|
|
@@ -224,16 +398,6 @@ if (cluster.isPrimary) {
|
|
|
224
398
|
|
|
225
399
|
setTimeout(async () => {
|
|
226
400
|
for (let i=0; i < iterations; i++) {
|
|
227
|
-
/*
|
|
228
|
-
Object.keys(p).forEach(async (pKey) => {
|
|
229
|
-
const emitobj = { i: i, a: 'a', b: 'b', worker: pKey };
|
|
230
|
-
console.log(chalk.green(`${process.pid}: emit event to worker: [${pKey}] fromprimary: [${JSON.stringify(emitobj)}`));
|
|
231
|
-
p[pKey].emit('fromprimary', emitobj, (response: any) => {
|
|
232
|
-
console.log(chalk.green(`${process.pid}: ${JSON.stringify(response)}`));
|
|
233
|
-
});
|
|
234
|
-
});
|
|
235
|
-
*/
|
|
236
|
-
|
|
237
401
|
|
|
238
402
|
const emitobj = { i: i, a: 'a', b: 'b' };
|
|
239
403
|
console.log(chalk.cyan(`${process.pid}: emit event fromprimaryredis fromprimary: [${JSON.stringify(emitobj)}`));
|
|
@@ -245,12 +409,49 @@ if (cluster.isPrimary) {
|
|
|
245
409
|
}
|
|
246
410
|
|
|
247
411
|
}, 1000);
|
|
248
|
-
|
|
412
|
+
*/
|
|
413
|
+
}, 2000);
|
|
249
414
|
} else {
|
|
250
415
|
new WorkerProcess(ServiceConfigOptions(true, cluster.isPrimary)).SetupServer();
|
|
251
416
|
//StartTestWorker();
|
|
252
417
|
|
|
253
418
|
setTimeout(async () => {
|
|
419
|
+
|
|
420
|
+
let group = '';
|
|
421
|
+
if (process.pid % 2 === 0) {
|
|
422
|
+
group = 'even'
|
|
423
|
+
} else {
|
|
424
|
+
group = 'odd'
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
let workerId = '0';
|
|
428
|
+
if (cluster.worker) {
|
|
429
|
+
console.log(chalk.blue(`Worker: [${cluster.worker?.id}]`));
|
|
430
|
+
workerId = cluster.worker?.id.toString();
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
const r1: RedisMessageHandler = new RedisMessageHandler({
|
|
434
|
+
logger: defaultLogger,
|
|
435
|
+
role: 'CLIENT',
|
|
436
|
+
redisUrl: goptions.imRedisMessageProcessorUrl,
|
|
437
|
+
namespace: 'mytestapp',
|
|
438
|
+
groups: [ group, workerId ]
|
|
439
|
+
});
|
|
440
|
+
r1.Start();
|
|
441
|
+
|
|
442
|
+
r1.on('fromprimaryredis', (arg1: JSONObject, callback: any) => {
|
|
443
|
+
callback( {
|
|
444
|
+
status: `PID: [${process.pid}]: response message from event = fromprimaryredis with args ${JSON.stringify(arg1)}`
|
|
445
|
+
})
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
r1.on('globalmessage', (arg1: JSONObject, callback: any) => {
|
|
449
|
+
callback( {
|
|
450
|
+
status: `PID: [${process.pid}]: response message from event = globalmessage with args ${JSON.stringify(arg1)}`
|
|
451
|
+
})
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
|
|
254
455
|
/*
|
|
255
456
|
const w1: IPCMessageHandler = new IPCMessageHandler({
|
|
256
457
|
logger: defaultLogger,
|
|
@@ -265,6 +466,7 @@ if (cluster.isPrimary) {
|
|
|
265
466
|
});
|
|
266
467
|
*/
|
|
267
468
|
|
|
469
|
+
/*
|
|
268
470
|
const r1: RedisMessageHandler = new RedisMessageHandler({
|
|
269
471
|
logger: defaultLogger,
|
|
270
472
|
role: 'CLIENT',
|
|
@@ -282,12 +484,6 @@ if (cluster.isPrimary) {
|
|
|
282
484
|
setTimeout(async () => {
|
|
283
485
|
for (let i=0; i < iterations; i++) {
|
|
284
486
|
const id = uuidv4();
|
|
285
|
-
/*
|
|
286
|
-
console.log(chalk.yellow(`${process.pid}: emit event fromworker: [${id} ${i} Hello]`));
|
|
287
|
-
w1.emit('fromworker', id, i, 'Hello', (response: any) => {
|
|
288
|
-
console.log(chalk.yellow(`${process.pid}: ${JSON.stringify(response)}`));
|
|
289
|
-
});
|
|
290
|
-
*/
|
|
291
487
|
|
|
292
488
|
console.log(chalk.green(`${process.pid}: emit event fromworkerredis: [${id} ${i} Hello]`));
|
|
293
489
|
r1.emit('fromworkerredis', id, i, 'Hello', (response: any) => {
|
|
@@ -296,5 +492,6 @@ if (cluster.isPrimary) {
|
|
|
296
492
|
await Sleep(delay);
|
|
297
493
|
}
|
|
298
494
|
}, 1000);
|
|
299
|
-
|
|
495
|
+
*/
|
|
496
|
+
}, 2000);
|
|
300
497
|
}
|
package/src/workerprocessbase.ts
CHANGED
|
@@ -12,6 +12,13 @@ import { v4 as uuidv4 } from 'uuid';
|
|
|
12
12
|
|
|
13
13
|
import { STSTransportLoggerWinston } from './stsTransportLoggerWinston'
|
|
14
14
|
|
|
15
|
+
import { RedisMessageHandler } from './redisMessageHandler';
|
|
16
|
+
|
|
17
|
+
import { goptions } from '@nsshunt/stsconfig'
|
|
18
|
+
|
|
19
|
+
import si from 'systeminformation' // https://systeminformation.io/
|
|
20
|
+
import { GetFirstNetworkInterface } from './network'
|
|
21
|
+
|
|
15
22
|
/**
|
|
16
23
|
* todo
|
|
17
24
|
* @typedef {Object} options - todo
|
|
@@ -20,7 +27,11 @@ import { STSTransportLoggerWinston } from './stsTransportLoggerWinston'
|
|
|
20
27
|
export class WorkerProcessBase extends ServerProcessBase implements IWorkerProcessBase
|
|
21
28
|
{
|
|
22
29
|
#inFlightMessage: IPCMessages = { }
|
|
23
|
-
#requestResponseMessageTimeout =
|
|
30
|
+
#requestResponseMessageTimeout = 5000; //@@ config
|
|
31
|
+
#redisMessageHandler: RedisMessageHandler | null = null;
|
|
32
|
+
#redisMessageHandlerPing: number = 1000;
|
|
33
|
+
#pingTimeout: NodeJS.Timeout | null = null;
|
|
34
|
+
#instanceId: string = uuidv4();
|
|
24
35
|
|
|
25
36
|
constructor(options: ProcessOptions) {
|
|
26
37
|
super(options);
|
|
@@ -120,14 +131,77 @@ export class WorkerProcessBase extends ServerProcessBase implements IWorkerProce
|
|
|
120
131
|
return parentResponse;
|
|
121
132
|
}
|
|
122
133
|
|
|
123
|
-
SetupServer = async () =>
|
|
124
|
-
{
|
|
134
|
+
SetupServer = async () => {
|
|
125
135
|
this.SetupInstrumentation();
|
|
126
136
|
setTimeout(() => {
|
|
127
137
|
this.SetupServerEx();
|
|
128
138
|
}, 100);
|
|
129
139
|
}
|
|
130
140
|
|
|
141
|
+
GetNumCPUs = async (): Promise<number> => {
|
|
142
|
+
// https://systeminformation.io/
|
|
143
|
+
const valueObject = {
|
|
144
|
+
cpu: '*'
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const sysinfo = await si.get(valueObject);
|
|
148
|
+
let numCPUs = 2;
|
|
149
|
+
if (goptions.useCPUs > 0) {
|
|
150
|
+
if (goptions.useCPUs >= 1) {
|
|
151
|
+
numCPUs = goptions.useCPUs;
|
|
152
|
+
} else {
|
|
153
|
+
numCPUs = Math.round(sysinfo.cpu.cores * goptions.useCPUs);
|
|
154
|
+
}
|
|
155
|
+
} else {
|
|
156
|
+
numCPUs = sysinfo.cpu.physicalCores;
|
|
157
|
+
}
|
|
158
|
+
return numCPUs;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
GetSystemTelemetry = async () => {
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
// https://systeminformation.io/
|
|
165
|
+
const valueObject = {
|
|
166
|
+
system: '*',
|
|
167
|
+
osInfo: '*',
|
|
168
|
+
cpu: '*',
|
|
169
|
+
mem: '*',
|
|
170
|
+
dockerInfo: '*',
|
|
171
|
+
//dockerImages: '*',
|
|
172
|
+
dockerContainers: '*',
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const sysinfo = await si.get(valueObject);
|
|
176
|
+
const numCPUs = await this.GetNumCPUs();
|
|
177
|
+
const hostname = sysinfo.osInfo.hostname;
|
|
178
|
+
const hostaddr = GetFirstNetworkInterface();
|
|
179
|
+
|
|
180
|
+
const promArray: Promise<any>[] = [ ];
|
|
181
|
+
|
|
182
|
+
sysinfo.dockerContainers.forEach((dc: { id: string; }) => {
|
|
183
|
+
const dcs = promArray.push(si.dockerContainerStats(dc.id));
|
|
184
|
+
console.log(dcs);
|
|
185
|
+
});
|
|
186
|
+
const dockerContainerStats = await Promise.all(promArray);
|
|
187
|
+
|
|
188
|
+
const sysInfo = {
|
|
189
|
+
instanceId: this.#instanceId,
|
|
190
|
+
hostname,
|
|
191
|
+
numCPUs,
|
|
192
|
+
hostaddr,
|
|
193
|
+
system: sysinfo.system,
|
|
194
|
+
osInfo: sysinfo.osInfo,
|
|
195
|
+
cpu: sysinfo.cpu,
|
|
196
|
+
mem: sysinfo.mem,
|
|
197
|
+
dockerInfo: sysinfo.dockerInfo,
|
|
198
|
+
dockerContainers: sysinfo.dockerContainers,
|
|
199
|
+
dockerContainerStats
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return sysInfo;
|
|
203
|
+
}
|
|
204
|
+
|
|
131
205
|
SetupServerEx = async () => {
|
|
132
206
|
this.ProcessStartup();
|
|
133
207
|
|
|
@@ -192,8 +266,55 @@ export class WorkerProcessBase extends ServerProcessBase implements IWorkerProce
|
|
|
192
266
|
|
|
193
267
|
await this.SetupSTSServer();
|
|
194
268
|
|
|
269
|
+
/*
|
|
270
|
+
this.#redisMessageHandler = new RedisMessageHandler({
|
|
271
|
+
logger: this.options.logger,
|
|
272
|
+
role: 'CLIENT',
|
|
273
|
+
redisUrl: goptions.imRedisMessageProcessorUrl,
|
|
274
|
+
namespace: 'stsServiceControl',
|
|
275
|
+
groups: [ ]
|
|
276
|
+
});
|
|
277
|
+
this.#redisMessageHandler.Start();
|
|
278
|
+
|
|
279
|
+
const ping = () => {
|
|
280
|
+
this.#pingTimeout = setTimeout(() => {
|
|
281
|
+
const pingData = {
|
|
282
|
+
instanceId: this.#instanceId
|
|
283
|
+
}
|
|
284
|
+
if (this.#redisMessageHandler) {
|
|
285
|
+
this.#redisMessageHandler.emit('ping_ex', pingData, (response: any) => {
|
|
286
|
+
console.log(chalk.cyan(` ==>> ${process.pid}: Response(ping): [${JSON.stringify(response)}]`));
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
ping();
|
|
290
|
+
}, this.#redisMessageHandlerPing).unref();
|
|
291
|
+
}
|
|
292
|
+
ping();
|
|
293
|
+
*/
|
|
294
|
+
|
|
295
|
+
// this.#redisMessageHandler.on('GET_SYSTEM_TELEMETRY', async (getSystemTelemetryCommand: JSONObject, callback: any) => {
|
|
296
|
+
// callback({ instanceId: this.#instanceId, process: process.pid, systemTelemetry: getSystemTelemetryCommand });
|
|
297
|
+
/*
|
|
298
|
+
if (getSystemTelemetryCommand.instanceId.localeCompare(this.#instanceId) === 0) {
|
|
299
|
+
const systemTelemetry = await this.GetSystemTelemetry();
|
|
300
|
+
callback({ systemTelemetry });
|
|
301
|
+
} else {
|
|
302
|
+
callback({ systemTelemetry: null });
|
|
303
|
+
}
|
|
304
|
+
*/
|
|
305
|
+
// });
|
|
306
|
+
|
|
195
307
|
this.WorkerStarted();
|
|
196
308
|
|
|
197
309
|
this.LogInfoMessage(chalk.green(`Worker process:${process.pid} started`));
|
|
198
310
|
};
|
|
311
|
+
|
|
312
|
+
override ProcessTerminate(): Promise<void> {
|
|
313
|
+
//this.#redisMessageHandler?.off()
|
|
314
|
+
if (this.#pingTimeout) {
|
|
315
|
+
clearTimeout(this.#pingTimeout);
|
|
316
|
+
}
|
|
317
|
+
this.#redisMessageHandler?.Stop();
|
|
318
|
+
return super.ProcessTerminate();
|
|
319
|
+
}
|
|
199
320
|
}
|