@nsshunt/stsappframework 3.0.103 → 3.0.105

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 (140) hide show
  1. package/dist/authutilsnode.js +6 -7
  2. package/dist/authutilsnode.js.map +1 -1
  3. package/dist/influxdb/influxDBManager.js +16 -17
  4. package/dist/influxdb/influxDBManager.js.map +1 -1
  5. package/dist/influxdb/influxDBManagerAgent.js +9 -13
  6. package/dist/influxdb/influxDBManagerAgent.js.map +1 -1
  7. package/dist/influxdb/influxDBManagerBase.js +2 -6
  8. package/dist/influxdb/influxDBManagerBase.js.map +1 -1
  9. package/dist/influxdb/influxDBManagerService.js +10 -14
  10. package/dist/influxdb/influxDBManagerService.js.map +1 -1
  11. package/dist/instrumentationsubscriber.js +11 -15
  12. package/dist/instrumentationsubscriber.js.map +1 -1
  13. package/dist/kafka/IMKafkaManager.js +2 -6
  14. package/dist/kafka/IMKafkaManager.js.map +1 -1
  15. package/dist/kafkatesting/produce.js +1 -5
  16. package/dist/kafkatesting/produce.js.map +1 -1
  17. package/dist/masterprocessbase.js +19 -20
  18. package/dist/masterprocessbase.js.map +1 -1
  19. package/dist/processbase.js +8 -10
  20. package/dist/processbase.js.map +1 -1
  21. package/dist/server.js +1 -1
  22. package/dist/server.js.map +1 -1
  23. package/dist/singleprocessbase.js +3 -4
  24. package/dist/singleprocessbase.js.map +1 -1
  25. package/dist/tcpclient/app2.js +2 -2
  26. package/dist/tcpserver/appmaster.js +39 -16
  27. package/dist/tcpserver/appmaster.js.map +1 -1
  28. package/dist/workerprocessbase.js +3 -4
  29. package/dist/workerprocessbase.js.map +1 -1
  30. package/package.json +7 -7
  31. package/src/authutilsnode.ts +8 -10
  32. package/src/influxdb/influxDBManager.ts +16 -18
  33. package/src/influxdb/influxDBManagerAgent.ts +9 -11
  34. package/src/influxdb/influxDBManagerBase.ts +2 -4
  35. package/src/influxdb/influxDBManagerService.ts +10 -12
  36. package/src/instrumentationsubscriber.ts +11 -14
  37. package/src/kafka/IMKafkaManager.ts +2 -4
  38. package/src/kafkatesting/produce.ts +1 -3
  39. package/src/masterprocessbase.ts +32 -24
  40. package/src/processbase.ts +7 -11
  41. package/src/server.ts +1 -1
  42. package/src/singleprocessbase.ts +3 -5
  43. package/src/tcpclient/app2.ts +2 -2
  44. package/src/tcpserver/appmaster.ts +39 -17
  45. package/src/workerprocessbase.ts +3 -5
  46. package/types/authutilsnode.d.ts.map +1 -1
  47. package/types/influxdb/influxDBManager.d.ts.map +1 -1
  48. package/types/influxdb/influxDBManagerAgent.d.ts.map +1 -1
  49. package/types/influxdb/influxDBManagerBase.d.ts.map +1 -1
  50. package/types/influxdb/influxDBManagerService.d.ts.map +1 -1
  51. package/types/instrumentationsubscriber.d.ts.map +1 -1
  52. package/types/kafka/IMKafkaManager.d.ts.map +1 -1
  53. package/types/masterprocessbase.d.ts.map +1 -1
  54. package/types/processbase.d.ts +2 -2
  55. package/types/processbase.d.ts.map +1 -1
  56. package/types/singleprocessbase.d.ts.map +1 -1
  57. package/types/tcpserver/appmaster.d.ts.map +1 -1
  58. package/types/workerprocessbase.d.ts.map +1 -1
  59. package/src_new/authDefs.ts +0 -37
  60. package/src_new/authutilsnode.ts +0 -375
  61. package/src_new/commonTypes.ts +0 -239
  62. package/src_new/index.ts +0 -22
  63. package/src_new/influxdb/influxDBManager.ts +0 -972
  64. package/src_new/influxdb/influxDBManagerAgent.ts +0 -316
  65. package/src_new/influxdb/influxDBManagerBase.ts +0 -111
  66. package/src_new/influxdb/influxDBManagerService.ts +0 -375
  67. package/src_new/instrumentationsubscriber.ts +0 -286
  68. package/src_new/kafka/IMKafkaManager.ts +0 -154
  69. package/src_new/kafka/kafkaconsumer.ts +0 -82
  70. package/src_new/kafka/kafkamanager.ts +0 -186
  71. package/src_new/kafka/kafkaproducer.ts +0 -58
  72. package/src_new/kafkatesting/config.ts +0 -10
  73. package/src_new/kafkatesting/consume.ts +0 -116
  74. package/src_new/kafkatesting/produce.ts +0 -155
  75. package/src_new/masterprocessbase.ts +0 -590
  76. package/src_new/middleware/serverNetworkMiddleware.ts +0 -240
  77. package/src_new/network.ts +0 -36
  78. package/src_new/processbase.ts +0 -413
  79. package/src_new/processoptions.ts +0 -164
  80. package/src_new/publishertransports/publishTransportDirect.ts +0 -45
  81. package/src_new/publishertransports/publishTransportUtils.ts +0 -53
  82. package/src_new/server.ts +0 -141
  83. package/src_new/serverprocessbase.ts +0 -393
  84. package/src_new/singleprocessbase.ts +0 -123
  85. package/src_new/socketIoServerHelper.ts +0 -177
  86. package/src_new/stscontrollerbase.ts +0 -15
  87. package/src_new/stslatencycontroller.ts +0 -27
  88. package/src_new/stslatencyroute.ts +0 -16
  89. package/src_new/stsrouterbase.ts +0 -22
  90. package/src_new/tcpclient/app.ts +0 -19
  91. package/src_new/tcpclient/app2.ts +0 -56
  92. package/src_new/tcpserver/app.ts +0 -11
  93. package/src_new/tcpserver/appConfig.ts +0 -65
  94. package/src_new/tcpserver/appmaster.ts +0 -522
  95. package/src_new/validation/errors.ts +0 -6
  96. package/src_new/webworkertesting/app.ts +0 -49
  97. package/src_new/webworkertesting/worker.ts +0 -24
  98. package/src_new/workerprocessbase.test.ts +0 -47
  99. package/src_new/workerprocessbase.ts +0 -187
  100. package/src_working/authDefs.ts +0 -37
  101. package/src_working/authutilsnode.ts +0 -373
  102. package/src_working/commonTypes.ts +0 -239
  103. package/src_working/index.ts +0 -22
  104. package/src_working/influxdb/influxDBManager.ts +0 -970
  105. package/src_working/influxdb/influxDBManagerAgent.ts +0 -314
  106. package/src_working/influxdb/influxDBManagerBase.ts +0 -109
  107. package/src_working/influxdb/influxDBManagerService.ts +0 -373
  108. package/src_working/instrumentationsubscriber.ts +0 -283
  109. package/src_working/kafka/IMKafkaManager.ts +0 -152
  110. package/src_working/kafka/kafkaconsumer.ts +0 -82
  111. package/src_working/kafka/kafkamanager.ts +0 -186
  112. package/src_working/kafka/kafkaproducer.ts +0 -58
  113. package/src_working/kafkatesting/config.ts +0 -10
  114. package/src_working/kafkatesting/consume.ts +0 -116
  115. package/src_working/kafkatesting/produce.ts +0 -153
  116. package/src_working/masterprocessbase.ts +0 -598
  117. package/src_working/middleware/serverNetworkMiddleware.ts +0 -240
  118. package/src_working/network.ts +0 -36
  119. package/src_working/processbase.ts +0 -411
  120. package/src_working/processoptions.ts +0 -164
  121. package/src_working/publishertransports/publishTransportDirect.ts +0 -45
  122. package/src_working/publishertransports/publishTransportUtils.ts +0 -53
  123. package/src_working/server.ts +0 -141
  124. package/src_working/serverprocessbase.ts +0 -393
  125. package/src_working/singleprocessbase.ts +0 -121
  126. package/src_working/socketIoServerHelper.ts +0 -177
  127. package/src_working/stscontrollerbase.ts +0 -15
  128. package/src_working/stslatencycontroller.ts +0 -27
  129. package/src_working/stslatencyroute.ts +0 -16
  130. package/src_working/stsrouterbase.ts +0 -22
  131. package/src_working/tcpclient/app.ts +0 -19
  132. package/src_working/tcpclient/app2.ts +0 -56
  133. package/src_working/tcpserver/app.ts +0 -11
  134. package/src_working/tcpserver/appConfig.ts +0 -65
  135. package/src_working/tcpserver/appmaster.ts +0 -544
  136. package/src_working/validation/errors.ts +0 -6
  137. package/src_working/webworkertesting/app.ts +0 -49
  138. package/src_working/webworkertesting/worker.ts +0 -24
  139. package/src_working/workerprocessbase.test.ts +0 -47
  140. package/src_working/workerprocessbase.ts +0 -185
@@ -1,590 +0,0 @@
1
- /* eslint @typescript-eslint/no-explicit-any: 0, @typescript-eslint/no-unused-vars: 0 */ // --> OFF
2
- import fs from "fs"
3
- import si from 'systeminformation' // https://systeminformation.io/
4
- import https from 'https'
5
-
6
- import axios from 'axios';
7
-
8
- import cluster, { Worker } from 'node:cluster'
9
-
10
- import chalk from 'chalk';
11
-
12
- import express from 'express'
13
-
14
- import { setupPrimary } from '@socket.io/cluster-adapter'
15
- import { createServer as createServerHttps } from 'https'
16
- import { createServer } from 'http'
17
- import { AggregatorRegistry } from 'prom-client'
18
-
19
- import { $Options } from '@nsshunt/stsconfig'
20
- const goptions = $Options()
21
-
22
- import debugModule from 'debug'
23
-
24
- import { Gauge, GaugeTypes, InstrumentGaugeTelemetry, InstrumentGaugeOptions, InstrumentHistogramTelemetry } from '@nsshunt/stsinstrumentation'
25
-
26
- import { ProcessOptions, STSServerType } from './processoptions'
27
- import { ProcessBase } from './processbase';
28
- import { IMasterProcessBase } from './commonTypes';
29
-
30
- import { InstrumentDefinitions } from '@nsshunt/stspublisherserver'
31
- import { IPCMessagePayload, IPCMessageCommand } from './commonTypes'
32
-
33
-
34
- export class MasterProcessBase extends ProcessBase implements IMasterProcessBase
35
- {
36
- //static WORKER_MESSAGE_EVENT = 'sts_worker_message_event';
37
- #masterProcessExitTime = goptions.masterProcessExitTime;
38
- #childProcessExitTime = goptions.childProcessExitTime;
39
- #siValueObject = {
40
- currentLoad: 'currentLoad'
41
- }
42
- #httpServer: any = null; // Prometheus cluster server. See https://github.com/siimon/prom-client/blob/master/example/cluster.js
43
- #metricsServer: any= null;
44
- #aggregatorRegistry: any = null;
45
- #httpsAgent: any;
46
- #debug = debugModule(`proc:${process.pid}`);
47
- #checkLatency: NodeJS.Timeout | null = null;
48
- #killWorkers: Record<string, string> = { };
49
- #workers = 1; // Start at 1 becuase of main thread
50
- #shuttingDown = false;
51
-
52
- constructor(options: ProcessOptions)
53
- {
54
- super(options);
55
-
56
- this.#httpsAgent = new https.Agent({
57
- // Use basic defaults. This agent will not use keep-alive.
58
- timeout: goptions.timeout,
59
- rejectUnauthorized: goptions.isProduction // Allows self-signed certificates if non-production
60
- });
61
- }
62
-
63
- override CollectAdditionalTelemetry(): void {
64
- si.get(this.#siValueObject).then(data => {
65
- this.UpdateInstrument(Gauge.CPU_SYSTEM_LOAD_GAUGE, {
66
- val: data.currentLoad.currentLoad
67
- } as InstrumentGaugeTelemetry);
68
- });
69
- }
70
-
71
- override GetAdditionalInstruments(): InstrumentDefinitions {
72
- return [
73
- [ Gauge.CPU_SYSTEM_LOAD_GAUGE, GaugeTypes.INSTRUMENT_GAUGE, {
74
- interval: goptions.instrumentationObservationInterval,
75
- sampleSize: goptions.instrumentationTimeWindow
76
- } as InstrumentGaugeOptions]
77
- ]
78
- }
79
-
80
- /**
81
- * Note: msg removed from signature but will be passed at run-time.
82
- * @param {*} msg
83
- */
84
- // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
85
- WorkerMessageEvent(msg: any)
86
- {
87
- return null;
88
- }
89
-
90
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
91
- #WorkerMessageEvent(msg: any)
92
- {
93
- if (msg.command) {
94
- this.WorkerMessageEvent(msg);
95
- }
96
- }
97
-
98
- #InitCluster = (LogEx: any) =>
99
- {
100
- cluster.on('listening', () => {
101
- let allListening = true;
102
- for (const worker of Object.values(cluster.workers as NodeJS.Dict<Worker>)) {
103
- if (worker?.isConnected) {
104
- allListening = false;
105
- break;
106
- }
107
- }
108
-
109
- if (allListening) {
110
- LogEx(`Service instance started.`);
111
- }
112
- });
113
- };
114
-
115
- // https://github.com/siimon/prom-client/blob/master/example/cluster.js
116
- #SetupPrometheusForMaster = (LogEx: any) => {
117
- this.#metricsServer = express();
118
- this.#aggregatorRegistry = new AggregatorRegistry();
119
-
120
- switch (this.options.serverType) {
121
- case STSServerType.EXPRESS_TLS : {
122
- const options = {
123
- key: fs.readFileSync(this.options.httpsServerKeyPath),
124
- cert: fs.readFileSync(this.options.httpsServerCertificatePath)
125
- };
126
- this.#httpServer = createServerHttps(options, this.#metricsServer);
127
- }
128
- break;
129
- case STSServerType.EXPRESS : {
130
- this.#httpServer = createServer(this.#metricsServer);
131
- }
132
- }
133
- //this.#httpServer.maxConnections = 50;
134
-
135
- this.#metricsServer.get('/cluster_metrics', async (req: any, res: any) => {
136
- try {
137
- const metrics = await this.#aggregatorRegistry.clusterMetrics();
138
- res.set('Content-Type', this.#aggregatorRegistry.contentType);
139
- res.send(metrics);
140
- } catch (ex: any) {
141
- res.statusCode = 500;
142
- res.send(ex.message);
143
- }
144
- });
145
-
146
- //@@@ options wrong
147
-
148
- try {
149
- // https://stackoverflow.com/questions/21342828/node-express-unix-domain-socket-permissions
150
- //@@httpServer.listen('/tmp/stsrest01.sock').on('listening', () =>
151
- //@@httpServer.listen('/var/run/sts/stsrest01.sock').on('listening', () =>
152
- //@@httpServer.listen('/var/lib/sts/stsrest01.sock').on('listening', () =>
153
- this.#httpServer.listen(this.options.prometheusClusterPort, () => {
154
- //@@chmodSync(this.options.port, 511);
155
- }).on('listening', () =>
156
- {
157
- LogEx(`Prometheus scrapes ready and live on ${this.options.endpoint}:${this.options.prometheusClusterPort}/metrics`);
158
- });
159
- } catch (error)
160
- {
161
- console.error(error);
162
- throw error;
163
- }
164
- }
165
-
166
- #CheckLatency = async () => {
167
- const start = process.hrtime();
168
- await this.#GetLatency();
169
- this.#LatencyRequestCompleted(start);
170
- }
171
-
172
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
173
- #GetLatency = async (): Promise<any> => {
174
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
175
- let retVal: any = null;
176
- // We use port rather than hostport becuase this test going outside the service and comes back in as a regular client
177
- const url = `${this.options.endpoint}:${this.options.port}${this.options.apiRoot}/latency`;
178
- const headers = {
179
- 'Content-Type': 'application/json'
180
- };
181
- try {
182
- retVal = await axios({
183
- url: url
184
- ,method: 'get'
185
- ,headers: headers
186
- ,httpsAgent: this.#httpsAgent
187
- });
188
- if (retVal.status !== 200) {
189
- this.#debug(chalk.magenta(`Error (MasterProcessBase:#GetLatency): Invalid response from server: [${retVal.status}]`));
190
- return null;
191
- }
192
- return retVal.data.detail;
193
- } catch (error: any) {
194
- this.#debug(chalk.red(`Error (MasterProcessBase:#GetLatency:catch): [${error}]`));
195
- this.#debug(chalk.red(` url: [${url}]`));
196
- if (error.response && error.response.data) {
197
- this.#debug(chalk.red(` Details: [${JSON.stringify(error.response.data)}]`));
198
- }
199
- }
200
- }
201
-
202
- #LatencyRequestCompleted = (start: any) => {
203
- // Update request duration histo data
204
- let timeInMs = 0;
205
- const end = process.hrtime(start);
206
- timeInMs = (end[0]* 1000000000 + end[1]) / 1000000;
207
- timeInMs = parseFloat(timeInMs.toFixed(4));
208
-
209
- this.UpdateInstrument(Gauge.LATENCY_HISTOGRAM_GAUGE, {
210
- val: timeInMs
211
- } as InstrumentHistogramTelemetry);
212
-
213
- this.UpdateInstrument(Gauge.LATENCY_GAUGE, {
214
- val: timeInMs
215
- } as InstrumentGaugeTelemetry);
216
- };
217
-
218
- SetupServer = async () =>
219
- {
220
- this.SetupInstrumentation();
221
- setTimeout(() => {
222
- this.SetupServerEx();
223
- }, 100);
224
- }
225
-
226
- #_KillWorker = (id: string, signal: NodeJS.Signals, killProcess: boolean): boolean => {
227
- if (cluster.workers && cluster.workers[id]) {
228
- const worker = cluster.workers[id] as Worker;
229
- if (worker.process) {
230
- this.LogEx(`Sending terminate message `.grey + `(initiated by ${signal})`.yellow + ` for worker PID: ${worker.process.pid}`.grey);
231
- const command: string = (killProcess ? 'TerminateAndKill' : 'Terminate');
232
- worker.process.send( { command } );
233
- return true;
234
- } else {
235
- this.LogEx(chalk.red(`Could not kill worker with id: [${id}]. The process does not exists`));
236
- return false;
237
- }
238
- } else {
239
- this.LogEx(chalk.red(`Could not kill worker with id: [${id}]. Worker does not exist within workers collection`));
240
- return false;
241
- }
242
- }
243
-
244
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
245
- KillWorker = (id: string, signal: NodeJS.Signals = "SIGTERM", options: any, killProcess: boolean, allowKillAll: boolean): boolean => {
246
- if (allowKillAll || Object.keys(cluster.workers as NodeJS.Dict<Worker>).length > 1) {
247
- if (id.localeCompare('0') === 0) {
248
- const keys = Object.keys(cluster.workers as NodeJS.Dict<Worker>);
249
- for (let i=keys.length-1; i > 0; i--) {
250
- // Kill the last one added (assumed node keeps them in order)
251
- id = keys[i];
252
- if (!this.#killWorkers[id]) {
253
- this.#killWorkers[id] = id;
254
- // Allow some time for the worker to be terminated before clean-up of the killWorkers array
255
- setTimeout(() => {
256
- delete this.#killWorkers[id];
257
- }, 2000).unref(); //@@
258
- return this.#_KillWorker(id, signal, killProcess);
259
- }
260
- }
261
- return false;
262
- } else {
263
- return this.#_KillWorker(id, signal, killProcess);
264
- }
265
- } else {
266
- this.LogEx(`Not allowed to kill the last worker process.`.yellow);
267
- return false;
268
- }
269
- }
270
-
271
- KillWorkers = (signal: NodeJS.Signals): void => {
272
- try {
273
- for (const id in cluster.workers) {
274
- try {
275
- this.KillWorker(id, signal, null, false, true);
276
- //cluster.workers[id].process.kill(signal);
277
-
278
- // Using kill (below) does not fire the events in the worker processes.
279
- //cluster.workers[id].kill('SIGINT');
280
- } catch (error) {
281
- this.LogEx(error);
282
- }
283
- }
284
- } catch (error) {
285
- this.LogEx(error);
286
- }
287
- }
288
-
289
- #UpdateWorkersInstrument = (): void => {
290
- setTimeout(() => {
291
- this.UpdateInstrument(Gauge.CORE_COUNT_GAUGE, {
292
- val: this.#workers
293
- } as InstrumentGaugeTelemetry);
294
- }, 2000);
295
- }
296
-
297
- IncWorkers = (): void => {
298
- this.#workers++;
299
- this.#debug(` Inc Workers. Total thread count: [${this.#workers}]`);
300
- this.#UpdateWorkersInstrument();
301
- }
302
-
303
- DecWorkers = (): void => {
304
- this.#workers--;
305
- this.#debug(` Dec Workers. Total thread count: [${this.#workers}]`);
306
- this.#UpdateWorkersInstrument();
307
- }
308
-
309
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
310
- AddWorker = (options: any): number => {
311
- const workerId: number = this.#SpawnWorker(options);
312
- this.#debug(` Spawned worker with id: [${workerId}]`.yellow);
313
- if (options) {
314
- this.#debug(` Options: [${JSON.stringify(options)}]`.yellow);
315
- }
316
- return workerId;
317
- }
318
-
319
- #processIPCCommand = async (iPCMessagePayload: IPCMessagePayload): Promise<IPCMessagePayload> => {
320
- this.#debug(` Processing message command: [${iPCMessagePayload.command}]`.yellow);
321
- switch (iPCMessagePayload.command) {
322
- case IPCMessageCommand.AddWorker : {
323
- const workerId = this.AddWorker(iPCMessagePayload.requestDetail?.options);
324
- iPCMessagePayload.responseDetail = {
325
- workerId
326
- }
327
- return iPCMessagePayload;
328
- }
329
- case IPCMessageCommand.DeleteWorker : {
330
- const workerId = iPCMessagePayload.requestDetail?.workerId;
331
- const workerKilled = this.KillWorker(workerId, "SIGTERM", iPCMessagePayload.requestDetail?.options, true, false);
332
- this.#debug(` Killed worker with id: [${workerId}]`.yellow);
333
- iPCMessagePayload.responseDetail = {
334
- workerId,
335
- workerKilled
336
- }
337
- return iPCMessagePayload;
338
- }
339
- default : {
340
- const errorMessage = `Could not process command: [${iPCMessagePayload.command}].`;
341
- this.#debug(chalk.red(` ${errorMessage}`));
342
- throw new Error(errorMessage);
343
- }
344
- }
345
- }
346
-
347
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
348
- #SpawnWorker = (spawnWorkerOptions?: any): number => {
349
- const workerEnv: any = { };
350
- workerEnv['STS_GSD_SII'] = JSON.stringify(this.options);
351
- if (spawnWorkerOptions) {
352
- workerEnv['STS_GSD_OPTIONS'] = JSON.stringify(spawnWorkerOptions);
353
- }
354
-
355
- // https://nodejs.org/api/cluster.html#clustersetupprimarysettings
356
- if (this.options.workerExec) {
357
- cluster.setupPrimary({
358
- exec: this.options.workerExec,
359
- silent: true,
360
- });
361
- }
362
-
363
- const worker = cluster.fork(workerEnv);
364
- this.IncWorkers();
365
-
366
- worker.on('exit', (code, signal) => {
367
- if (signal) {
368
- this.LogEx(`Worker: ${worker.process.pid} was killed by signal: ${signal}`);
369
- } else if (code !== 0) {
370
- this.LogEx(`Worker: ${worker.process.pid} exited with error code: ${code}`);
371
- } else {
372
- this.LogEx(`Worker: ${worker.process.pid} exited successfully, code: ${code}, signal: ${signal}`);
373
- }
374
- });
375
-
376
- worker.on('message', async (payload) => {
377
- // Only handle request/response message types here ...
378
- if (payload.requestResponse) {
379
- const iPCMessagePayload: IPCMessagePayload = payload as IPCMessagePayload;
380
- this.#debug(chalk.yellow(`Received message with id: [${iPCMessagePayload.id}] from worker: [${worker.process.pid}]. Details: [${JSON.stringify(iPCMessagePayload)}]`));
381
- const response: IPCMessagePayload = await this.#processIPCCommand(iPCMessagePayload);
382
- this.#debug(chalk.green(`Sending response message with id: [${iPCMessagePayload.id}] to worker: [${worker.process.pid}]. Details: [${JSON.stringify(response)}]`));
383
- worker.send(response);
384
- } else {
385
- this.#WorkerMessageEvent(payload);
386
- }
387
- });
388
-
389
- return worker.id;
390
- };
391
-
392
- MasterStarted(): void { // eslint-disable @typescript-eslint/no-empty-function
393
-
394
- }
395
-
396
- override get shuttingDown(): boolean {
397
- return this.#shuttingDown;
398
- }
399
-
400
- ProcessTerminating = async (): Promise<void> => {
401
- return;
402
- }
403
-
404
- SetupServerEx = async () =>
405
- {
406
- this.ProcessStartup();
407
- const LogEx = this.LogEx;
408
-
409
- LogEx(`Service instance starting. Instance Id: [${this.options.serviceInstanceId}]`);
410
-
411
- this.LogSystemTelemetry();
412
-
413
- // socket.io
414
- // setup connections between the workers
415
- if (this.options.wssServer === true) {
416
- if (this.options.useRedisAdaptor) {
417
- LogEx(`Using Redis for socket.io cluster management (master)`);
418
- } else {
419
- LogEx(`Using nodejs cluster mode for socket.io cluster management`);
420
- setupPrimary();
421
- }
422
- }
423
-
424
- if (this.options.prometheusSupport === true) {
425
- this.#SetupPrometheusForMaster(LogEx);
426
- }
427
-
428
- const numCPUs = await this.GetNumCPUs();
429
- for (let i=0; i < numCPUs; i++) {
430
- this.#SpawnWorker();
431
- }
432
-
433
- this.#InitCluster(LogEx);
434
-
435
- cluster.on('listening', (worker, address) =>
436
- {
437
- LogEx(`Worker process ${worker.process.pid} is listening at address: ${JSON.stringify(address)}`);
438
- });
439
-
440
- //Setting up lifecycle event listeners for worker processes
441
- cluster.on('online', worker =>
442
- {
443
- LogEx(`Worker process ${worker.process.pid} is online`);
444
- });
445
-
446
- cluster.on('exit', (worker, code, signal) => {
447
- if ((code !== null && code === 0) || (signal === 'SIGINT')) {
448
- LogEx(chalk.green(`Process ${worker.process.pid} terminated gracefully with code: ${code}, signal: ${signal}`));
449
- this.DecWorkers();
450
- } else if ((code !== null && code === 15) || (signal === 'SIGTERM')) {
451
- this.DecWorkers();
452
- LogEx(chalk.red(`Process ${worker.process.pid} terminated with code: ${code}, signal: ${signal}`));
453
- } else {
454
- this.DecWorkers();
455
- LogEx(chalk.red(`worker ${worker.process.pid} died`));
456
- LogEx(chalk.red(`code: ${code}`));
457
- LogEx(chalk.red(`signal: ${signal}`));
458
- LogEx(chalk.red('process terminated in an error state'));
459
- if (goptions.respawnOnFail === true) {
460
- LogEx(chalk.magenta(`Attemping to respawn worker`));
461
- this.#SpawnWorker();
462
- }
463
- }
464
- });
465
-
466
- // Terminate in order;
467
- // forked worker threads (send signal)
468
- // De-Register service
469
- // systeminformation observers
470
- // instrument timers (gauge etc.)
471
- // publisher
472
- // terminate UI (if loaded)
473
- const Terminate = async (signal: any) =>
474
- {
475
- if (this.#shuttingDown === false)
476
- {
477
- this.#shuttingDown = true;
478
-
479
- if (this.#checkLatency) {
480
- clearInterval(this.#checkLatency);
481
- this.#checkLatency = null;
482
- }
483
-
484
- await this.ProcessTerminate();
485
-
486
- await this.ProcessTerminating();
487
-
488
- if (this.GetUIController() !== null)
489
- {
490
- LogEx('Destroy the user interface controller.');
491
- this.GetUIController().DestroyUI();
492
- }
493
-
494
- if (signal) {
495
- LogEx(this.GetSignalColour(signal)(`Main Process (masterprocess): ${process.pid} received signal: ${signal}`));
496
- } else {
497
- LogEx(this.GetSignalColour(null)(`Main Process (masterprocess): ${process.pid} received Terminate without signal.`));
498
- }
499
-
500
- LogEx(`De-Registering service.`);
501
- //@@ De-register here ...
502
-
503
- if (this.#httpServer !== null) {
504
- LogEx(`Closing httpServer.`);
505
- await this.#httpServer.close();
506
- this.#httpServer = null;
507
- }
508
-
509
- LogEx(`Stopping instruments.`);
510
- //@@StopInstruments(this.instruments);
511
-
512
- //@@endpublish was here (and working ...)
513
-
514
- LogEx('Killing Workers.');
515
- this.KillWorkers(signal);
516
-
517
- if (this.options.useDatabase) {
518
- LogEx(`Ending database connections and pools.`);
519
- await this.TerminateDatabase();
520
- //await this.accessLayer.enddatabase();
521
- }
522
-
523
- // Now allow some time for the workers to die and send any remaining messages ...
524
- //if (this.InstrumentController && this.InstrumentController.Workers.length > 0) {
525
- if (this.InstrumentController) {
526
- LogEx(`Ending publisher.`);
527
- setTimeout(() => {
528
- if (this.InstrumentController) {
529
- this.InstrumentController.InstrumentTerminate();
530
- }
531
- }, 100);
532
- }
533
-
534
- if (this.options.processExitOnTerminate && this.options.processExitOnTerminate === true) {
535
- setTimeout(() => {
536
- LogEx(`Performing process.exit(0).`);
537
- process.exit(0);
538
- }, this.#childProcessExitTime + this.#masterProcessExitTime); // Give the workers time to terminate gracefully
539
- } else {
540
- LogEx(`Performing process.exit(0) - Immediate.`);
541
- }
542
- }
543
- }
544
-
545
- process.on('SIGINT', async () =>
546
- {
547
- await Terminate('SIGINT');
548
- });
549
-
550
- process.on('SIGTERM', async () =>
551
- {
552
- await Terminate('SIGTERM');
553
- });
554
-
555
- process.on('exit', (code) =>
556
- {
557
- if (code === 0)
558
- {
559
- LogEx(chalk.green(`Main Process: ${process.pid} terminated gracefully with code: ${code}`));
560
- } else {
561
- LogEx(chalk.red(`Main Process: ${process.pid} terminated with code: ${code}`));
562
- }
563
- });
564
-
565
- if (this.options.useLatency) {
566
- this.#checkLatency = setInterval(() => {
567
- this.#CheckLatency();
568
- }, 1000).unref();
569
- }
570
-
571
- this.MasterStarted();
572
-
573
- LogEx(chalk.green(`Master process:${process.pid} started`));
574
- }
575
-
576
- BroadcastDataToWorkers = (command: any, data: any) => {
577
- try {
578
- for (const id in cluster.workers) {
579
- try {
580
- //@@LogEx(`Sending message to worker PID: ${cluster.workers[id].process.pid}`.grey);
581
- (cluster.workers[id] as Worker).process.send( { command: command, data: data } );
582
- } catch (error) {
583
- //@@LogEx(error);
584
- }
585
- }
586
- } catch (error) {
587
- //@@LogEx(error);
588
- }
589
- }
590
- }