@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.
Files changed (34) hide show
  1. package/dist/ipcMessageHandler.js +5 -3
  2. package/dist/ipcMessageHandler.js.map +1 -1
  3. package/dist/ipcMessageManager.js +14 -4
  4. package/dist/ipcMessageManager.js.map +1 -1
  5. package/dist/ipcMessageProcessorPrimary.js +3 -2
  6. package/dist/ipcMessageProcessorPrimary.js.map +1 -1
  7. package/dist/ipcMessageProcessorWorker.js +2 -1
  8. package/dist/ipcMessageProcessorWorker.js.map +1 -1
  9. package/dist/redisMessageHandler.js +73 -20
  10. package/dist/redisMessageHandler.js.map +1 -1
  11. package/dist/redisMessageHandler.test.js +4 -2
  12. package/dist/redisMessageHandler.test.js.map +1 -1
  13. package/dist/testing/app.js +215 -42
  14. package/dist/testing/app.js.map +1 -1
  15. package/dist/workerprocessbase.js +108 -1
  16. package/dist/workerprocessbase.js.map +1 -1
  17. package/package.json +1 -1
  18. package/src/ipcMessageHandler.ts +5 -3
  19. package/src/ipcMessageManager.ts +14 -4
  20. package/src/ipcMessageProcessorPrimary.ts +3 -2
  21. package/src/ipcMessageProcessorWorker.ts +2 -1
  22. package/src/redisMessageHandler.test.ts +4 -2
  23. package/src/redisMessageHandler.ts +78 -20
  24. package/src/testing/app.ts +219 -22
  25. package/src/workerprocessbase.ts +124 -3
  26. package/types/ipcMessageHandler.d.ts.map +1 -1
  27. package/types/ipcMessageManager.d.ts +1 -0
  28. package/types/ipcMessageManager.d.ts.map +1 -1
  29. package/types/ipcMessageProcessorPrimary.d.ts.map +1 -1
  30. package/types/ipcMessageProcessorWorker.d.ts.map +1 -1
  31. package/types/redisMessageHandler.d.ts +4 -1
  32. package/types/redisMessageHandler.d.ts.map +1 -1
  33. package/types/workerprocessbase.d.ts +15 -0
  34. 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
- this.emit('ping', this.#ipcMessageManager?.id, (response: any) => { });
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', (id: string, callback: any) => {
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: 2000,
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.keys(responses).forEach(r => {
161
- if (responses[r].senderRole.localeCompare('CLIENT') === 0) {
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
- Object.values(this.#clients).map(c => {
171
- if (!responses[c.id]) {
172
- found = false;
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
- if (found) {
177
- return true;
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
- return false;
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
- const retVal = await this.#ipcMessageManager?.SendMessage({
248
- __eventName: event,
249
- args: args.slice(0, args.length-1)
250
- } as IEventPayload);
251
- // Invoke the response callback
252
- args[args.length-1](retVal);
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
  }
@@ -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: 2000,
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: 2000,
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: 2000,
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 = 100;
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
- }, 1000);
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
- }, 1000);
495
+ */
496
+ }, 2000);
300
497
  }
@@ -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 = 2000; //@@ config
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
  }