@nsshunt/stsappframework 2.19.172 → 2.19.174

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