@nsshunt/stsappframework 3.1.236 → 3.1.237

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 (61) hide show
  1. package/dist/stsappframework.mjs +1979 -0
  2. package/dist/stsappframework.mjs.map +1 -0
  3. package/dist/stsappframework.umd.js +1954 -0
  4. package/dist/stsappframework.umd.js.map +1 -0
  5. package/package.json +21 -7
  6. package/.github/dependabot.yml +0 -13
  7. package/.github/workflows/npm-publish.yml +0 -46
  8. package/.gitignore copy +0 -108
  9. package/build.sh +0 -36
  10. package/dist/index.js +0 -30
  11. package/eslint.config.mjs +0 -55
  12. package/jest/setEnvVars.js +0 -19
  13. package/keys/server.cert +0 -21
  14. package/keys/server.key +0 -28
  15. package/local-redis-stack.conf +0 -2
  16. package/run-grpc-client.sh +0 -2
  17. package/run-grpc-server.sh +0 -2
  18. package/run1.sh +0 -20
  19. package/run2.sh +0 -20
  20. package/run3.sh +0 -20
  21. package/runc1.sh +0 -19
  22. package/runc2.sh +0 -19
  23. package/runkafka.sh +0 -19
  24. package/runkafkaconsume01.sh +0 -21
  25. package/runkafkaconsume02.sh +0 -21
  26. package/runpromise.sh +0 -5
  27. package/runredis.sh +0 -5
  28. package/runredis1.sh +0 -4
  29. package/runredis2.sh +0 -24
  30. package/runredis3.sh +0 -4
  31. package/runtest1.sh +0 -19
  32. package/runtest2.sh +0 -19
  33. package/runtest_ipc_legacy.sh +0 -19
  34. package/runtest_ipcex.sh +0 -19
  35. package/runtest_redis.sh +0 -19
  36. package/runtest_ww.sh +0 -19
  37. package/src/commonTypes.ts +0 -374
  38. package/src/controller/stscontrollerbase.ts +0 -14
  39. package/src/controller/stslatencycontroller.ts +0 -26
  40. package/src/index.ts +0 -13
  41. package/src/logger/stsTransportLoggerWinston.ts +0 -24
  42. package/src/logger/stsTransportWinston.ts +0 -48
  43. package/src/middleware/serverNetworkMiddleware.ts +0 -243
  44. package/src/network.ts +0 -36
  45. package/src/process/masterprocessbase.ts +0 -674
  46. package/src/process/processbase.ts +0 -483
  47. package/src/process/serverprocessbase.ts +0 -455
  48. package/src/process/singleprocessbase.ts +0 -63
  49. package/src/process/workerprocessbase.ts +0 -224
  50. package/src/publishertransports/publishTransportUtils.ts +0 -53
  51. package/src/route/stslatencyroute.ts +0 -15
  52. package/src/route/stsrouterbase.ts +0 -21
  53. package/src/stsexpressserver.ts +0 -137
  54. package/src/validation/errors.ts +0 -6
  55. package/src/vitesttesting/appConfig.ts +0 -111
  56. package/src/vitesttesting/appSingleWSS.ts +0 -142
  57. package/src/vitesttesting/server.ts +0 -17
  58. package/src/vitesttesting/singleservertest.test.ts +0 -352
  59. package/src/vitesttesting/wsevents.ts +0 -44
  60. package/tsconfig.json +0 -42
  61. package/vite.config.ts +0 -19
@@ -0,0 +1,1979 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __typeError = (msg) => {
3
+ throw TypeError(msg);
4
+ };
5
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
7
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
8
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
9
+ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
10
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
11
+ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
12
+ var __privateWrapper = (obj, member, setter, getter) => ({
13
+ set _(value) {
14
+ __privateSet(obj, member, value, setter);
15
+ },
16
+ get _() {
17
+ return __privateGet(obj, member, getter);
18
+ }
19
+ });
20
+ var _options, _instrumentController, _systemInformationInterval, _socketIoServerHelper, _accessLayer, _ProcessBase_instances, GetFormattedLogMessage_fn, _UpdatePGPoolManagerInstrument, _options2, _masterProcessExitTime, _childProcessExitTime, _siValueObject, _httpServer, _metricsServer, _aggregatorRegistry, _checkLatency, _killWorkers, _workers, _shuttingDown, _agentManager, _MasterProcessBase_instances, LogErrorMessage_fn, LogDebugMessage_fn, WorkerMessageEvent_fn, _InitCluster, _SetupPrometheusForMaster, _CheckLatency, _GetLatency, _LatencyRequestCompleted, __KillWorker, _UpdateWorkersInstrument, _processIPCCommand, _SpawnWorker, _tinyEmitter, _socketCollection, _id, _ServerNetworkMiddleware_instances, LogSillyMessage_fn, LogErrorMessage_fn2, _GetRequestContentSize, _app, _masterProcessExitTime2, _io, _redisClient, _httpServer2, _expressServer, _sockets, _shuttingDown2, _SetupPrometheusEndPoints, _SetupTLSServer, _SetupRPCServer, _SetupWSSServer, _GetTLSOptions, _SetupExpressServer, _SetupTCPRawServer, _SetupJSONRPCServer, _inFlightMessage, _requestResponseMessageTimeout, _pingTimeout, _SendMessageToParentProcess, _stsApp, _router, _stsApp2, _options3;
21
+ import { CheckValidChar, ModelDelimeter, Sleep, STSOptionsBase } from "@nsshunt/stsutils";
22
+ import fs from "node:fs";
23
+ import si from "/home/runner/work/stsappframework/stsappframework/node_modules/systeminformation/lib/index.js";
24
+ import axios from "axios";
25
+ import cluster from "node:cluster";
26
+ import chalk from "/home/runner/work/stsappframework/stsappframework/node_modules/chalk/source/index.js";
27
+ import express, { Router } from "/home/runner/work/stsappframework/stsappframework/node_modules/express/index.js";
28
+ import { setupPrimary, createAdapter as createAdapter$1 } from "/home/runner/work/stsappframework/stsappframework/node_modules/@socket.io/cluster-adapter/dist/index.js";
29
+ import { createServer as createServer$1 } from "node:https";
30
+ import { createServer } from "node:http";
31
+ import { AggregatorRegistry, collectDefaultMetrics, Counter, register } from "/home/runner/work/stsappframework/stsappframework/node_modules/prom-client/index.js";
32
+ import { goptions, AgentManager, STSAxiosConfig } from "/home/runner/work/stsappframework/stsappframework/node_modules/@nsshunt/stsconfig/dist/stsconfig.mjs";
33
+ import { Gauge, TransportType, GetInstruments, PublishInstrumentController, GaugeTypes, RequestLoggerMiddleware, RequestLoggerMiddlewareEventName } from "/home/runner/work/stsappframework/stsappframework/node_modules/@nsshunt/stsobservability/dist/stsobservability.mjs";
34
+ import pidusage from "/home/runner/work/stsappframework/stsappframework/node_modules/pidusage/index.js";
35
+ import { memoryUsage } from "/home/runner/work/stsappframework/stsappframework/node_modules/process/browser.js";
36
+ import os from "os";
37
+ import { IDBAccessLayerEvents, DBAccessLayerManager, accessLayerType } from "/home/runner/work/stsappframework/stsappframework/node_modules/@nsshunt/stsdatamanagement/dist/dbaccess.js";
38
+ import { StatusCodes } from "/home/runner/work/stsappframework/stsappframework/node_modules/http-status-codes/build/es/index.js";
39
+ import { TinyEmitter } from "/home/runner/work/stsappframework/stsappframework/node_modules/tiny-emitter/index.js";
40
+ import Transport from "/home/runner/work/stsappframework/stsappframework/node_modules/winston-transport/dist/index.js";
41
+ import tls from "node:tls";
42
+ import { Server } from "/home/runner/work/stsappframework/stsappframework/node_modules/socket.io/wrapper.mjs";
43
+ import cors from "/home/runner/work/stsappframework/stsappframework/node_modules/cors/lib/index.js";
44
+ import cookieParser from "/home/runner/work/stsappframework/stsappframework/node_modules/cookie-parser/index.js";
45
+ import { v4 } from "/home/runner/work/stsappframework/stsappframework/node_modules/uuid/dist/esm-browser/index.js";
46
+ import onHeaders from "/home/runner/work/stsappframework/stsappframework/node_modules/on-headers/index.js";
47
+ import { createAdapter } from "/home/runner/work/stsappframework/stsappframework/node_modules/@socket.io/redis-streams-adapter/dist/index.js";
48
+ import { createClient } from "/home/runner/work/stsappframework/stsappframework/node_modules/redis/dist/index.js";
49
+ import jayson from "/home/runner/work/stsappframework/stsappframework/node_modules/jayson/index.js";
50
+ function CreateServiceProcessContext(serviceName, serviceVersion, serviceInstanceId, hostName, processId, parentProcessId) {
51
+ const checkParams = [
52
+ ["servicename", serviceName],
53
+ ["serviceversion", serviceVersion],
54
+ ["hostname", hostName],
55
+ ["serviceInstanceId", serviceInstanceId]
56
+ ];
57
+ CheckValidChar(checkParams);
58
+ return {
59
+ nid: `${serviceName}${ModelDelimeter.COMPONENT_SEPERATOR}${serviceVersion}${ModelDelimeter.SEPERATOR}${serviceInstanceId}${ModelDelimeter.COMPONENT_SEPERATOR}${hostName}${ModelDelimeter.NID_SEPERATOR}${processId.toString()}${ModelDelimeter.COMPONENT_SEPERATOR}${parentProcessId.toString()}`,
60
+ serviceName,
61
+ serviceVersion,
62
+ serviceInstanceId,
63
+ hostName,
64
+ processId: processId.toString(),
65
+ parentProcessId: parentProcessId.toString()
66
+ };
67
+ }
68
+ var IPCMessageCommand = /* @__PURE__ */ ((IPCMessageCommand2) => {
69
+ IPCMessageCommand2["AddWorker"] = "AddWorker";
70
+ IPCMessageCommand2["DeleteWorker"] = "DeleteWorker";
71
+ IPCMessageCommand2["GetConfig"] = "GetConfig";
72
+ return IPCMessageCommand2;
73
+ })(IPCMessageCommand || {});
74
+ const iss = `https://stscore.stsmda.org/oauth2/v2.0`;
75
+ function GetNetworkInterfaces() {
76
+ const nets = os.networkInterfaces();
77
+ const results = {};
78
+ for (const name of Object.keys(nets)) {
79
+ for (const net of nets[name]) {
80
+ if (net.family === "IPv4" && !net.internal) {
81
+ if (!results[name]) {
82
+ results[name] = [];
83
+ }
84
+ results[name].push(net.address);
85
+ }
86
+ }
87
+ }
88
+ return results;
89
+ }
90
+ function GetFirstNetworkInterface() {
91
+ const nics = GetNetworkInterfaces();
92
+ let hostaddr = null;
93
+ for (const nic in nics) {
94
+ const val = nics[nic];
95
+ if (val.length > 0) {
96
+ hostaddr = val[0];
97
+ break;
98
+ }
99
+ }
100
+ return hostaddr;
101
+ }
102
+ class ProcessBase extends TinyEmitter {
103
+ //#redisMessageHandler: RedisMessageHandler | null = null;
104
+ constructor(options) {
105
+ super();
106
+ __privateAdd(this, _ProcessBase_instances);
107
+ __privateAdd(this, _options);
108
+ __privateAdd(this, _instrumentController, null);
109
+ __privateAdd(this, _systemInformationInterval, null);
110
+ __privateAdd(this, _socketIoServerHelper, null);
111
+ __privateAdd(this, _accessLayer, null);
112
+ __publicField(this, "ProcessStartup", () => {
113
+ const ExecuteGetStats = async () => {
114
+ const startTime = performance.now();
115
+ if (__privateGet(this, _instrumentController)) {
116
+ const stats = await pidusage(process.pid);
117
+ let useStatsCpu = stats.cpu;
118
+ if (useStatsCpu < 0.01) {
119
+ useStatsCpu = 0.01;
120
+ }
121
+ __privateGet(this, _instrumentController).UpdateInstrument(Gauge.CPU_LOAD_GAUGE, {
122
+ val: useStatsCpu
123
+ });
124
+ }
125
+ const usage = memoryUsage();
126
+ const telemetry = {
127
+ r: usage.rss,
128
+ t: usage.heapTotal,
129
+ u: usage.heapUsed,
130
+ x: usage.external,
131
+ a: usage.arrayBuffers
132
+ };
133
+ this.UpdateInstrument(Gauge.OBJECT_GAUGE, {
134
+ val: telemetry
135
+ });
136
+ this.CollectAdditionalTelemetry();
137
+ const totalTime = performance.now() - startTime;
138
+ const nextLoopTime = goptions.systemInformationInterval - totalTime;
139
+ __privateSet(this, _systemInformationInterval, setTimeout(ExecuteGetStats, nextLoopTime).unref());
140
+ };
141
+ __privateSet(this, _systemInformationInterval, setTimeout(ExecuteGetStats, goptions.systemInformationInterval).unref());
142
+ if (this.options.useDatabase) {
143
+ this.accessLayer;
144
+ }
145
+ });
146
+ __publicField(this, "UpdateInstrument", (instrumentName, telemetry) => {
147
+ if (__privateGet(this, _instrumentController)) {
148
+ __privateGet(this, _instrumentController).UpdateInstrument(instrumentName, telemetry);
149
+ }
150
+ });
151
+ __publicField(this, "ProcessExit", (processExitDelay) => {
152
+ if (this.options.processExitOnTerminate && this.options.processExitOnTerminate === true) {
153
+ setTimeout(() => {
154
+ this.LogInfoMessage(`Performing process.exit(0).`);
155
+ process.exit(0);
156
+ }, processExitDelay);
157
+ } else {
158
+ this.LogInfoMessage(`Performing process.exit(0) - Immediate.`);
159
+ }
160
+ });
161
+ __publicField(this, "TerminateInstrumentController", () => {
162
+ if (this.InstrumentController) {
163
+ this.LogInfoMessage(`ProcessBase:TerminateInstrumentController()`);
164
+ setTimeout(() => {
165
+ if (this.InstrumentController) {
166
+ this.InstrumentController.EndPublish();
167
+ }
168
+ }, 100);
169
+ }
170
+ });
171
+ __publicField(this, "TerminateUIController", () => {
172
+ if (this.GetUIController() !== null) {
173
+ this.LogInfoMessage("ProcessBase:TerminateUIController(): Destroy the user interface controller.");
174
+ this.GetUIController().DestroyUI();
175
+ }
176
+ });
177
+ __privateAdd(this, _UpdatePGPoolManagerInstrument, (data) => {
178
+ this.UpdateInstrument(Gauge.CONNECTION_POOL_TOTAL_GAUGE, {
179
+ val: data.totalCount
180
+ });
181
+ this.UpdateInstrument(Gauge.CONNECTION_POOL_IDLE_GAUGE, {
182
+ val: data.idleCount
183
+ });
184
+ this.UpdateInstrument(Gauge.CONNECTION_POOL_WAITING_GAUGE, {
185
+ val: data.waitingCount
186
+ });
187
+ });
188
+ __publicField(this, "GetNumCPUs", async () => {
189
+ const valueObject = {
190
+ cpu: "*"
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
+ __publicField(this, "LogSystemTelemetry", async () => {
206
+ const valueObject = {
207
+ system: "*",
208
+ osInfo: "*",
209
+ cpu: "*",
210
+ mem: "*"
211
+ };
212
+ const sysinfo = await si.get(valueObject);
213
+ const numCPUs = await this.GetNumCPUs();
214
+ const hostname = sysinfo.osInfo.hostname;
215
+ const hostaddr = GetFirstNetworkInterface();
216
+ if (hostaddr !== null) {
217
+ this.LogInfoMessage(`Host Address: ${hostaddr}`);
218
+ } else {
219
+ this.LogInfoMessage(`Unknown Host Address.`);
220
+ }
221
+ this.LogInfoMessage(`Server starting with ${numCPUs} Cores/Threads`);
222
+ this.LogInfoMessage(`Hostname: ${hostname}`);
223
+ this.LogInfoMessage(`System: ${JSON.stringify(sysinfo.system)}`);
224
+ this.LogInfoMessage(`OS Info: ${JSON.stringify(sysinfo.osInfo)}`);
225
+ this.LogInfoMessage(`CPU: ${JSON.stringify(sysinfo.cpu)}`);
226
+ this.LogInfoMessage(`Memory: ${JSON.stringify(sysinfo.mem)}`);
227
+ });
228
+ __publicField(this, "GetSignalColour", (signal) => {
229
+ let msgcolor = null;
230
+ if (signal === "SIGINT") {
231
+ msgcolor = chalk.yellow;
232
+ } else {
233
+ msgcolor = chalk.red;
234
+ }
235
+ return msgcolor;
236
+ });
237
+ __privateSet(this, _options, options);
238
+ if (options.serviceName) {
239
+ this.options.serviceProcessContext = CreateServiceProcessContext(
240
+ options.serviceName,
241
+ options.serviceVersion,
242
+ options.serviceInstanceId,
243
+ os.hostname(),
244
+ process.pid,
245
+ options.isMaster ? process.pid : process.ppid
246
+ );
247
+ }
248
+ }
249
+ LogErrorMessage(message) {
250
+ this.options.logger.error(__privateMethod(this, _ProcessBase_instances, GetFormattedLogMessage_fn).call(this, message));
251
+ }
252
+ LogInfoMessage(message) {
253
+ this.options.logger.info(__privateMethod(this, _ProcessBase_instances, GetFormattedLogMessage_fn).call(this, message));
254
+ }
255
+ LogMessageToLoggerInstrument(message) {
256
+ this.UpdateInstrument(Gauge.LOGGER, {
257
+ LogMessage: __privateMethod(this, _ProcessBase_instances, GetFormattedLogMessage_fn).call(this, message)
258
+ });
259
+ }
260
+ get options() {
261
+ return __privateGet(this, _options);
262
+ }
263
+ get shuttingDown() {
264
+ return false;
265
+ }
266
+ SetupInstrumentation() {
267
+ if (!this.options.serviceProcessContext) {
268
+ return;
269
+ }
270
+ let publishTransportOptions = null;
271
+ if (goptions.observabilityPublishMode.localeCompare("PROXY") === 0) {
272
+ publishTransportOptions = {
273
+ transportType: TransportType.RESTAPI,
274
+ url: `${goptions.imendpoint}:${goptions.import}${goptions.imapiroot}/publishmessage`,
275
+ // socketPath: '/var/run/sts/stsrest01.sock'
276
+ agentOptions: {
277
+ keepAlive: goptions.keepAlive,
278
+ maxSockets: goptions.maxSockets,
279
+ maxTotalSockets: goptions.maxTotalSockets,
280
+ maxFreeSockets: goptions.maxFreeSockets,
281
+ timeout: goptions.timeout,
282
+ rejectUnauthorized: goptions.isProduction
283
+ // Allows self signed certs in non production mode(s)
284
+ },
285
+ logger: this.options.publisherLogger
286
+ };
287
+ } else {
288
+ return;
289
+ }
290
+ const httpServer = goptions.STSServerType.localeCompare("EXPRESS") === 0 || goptions.STSServerType.localeCompare("EXPRESS_TLS") === 0;
291
+ const instrumentControllerOptions = {
292
+ processContext: this.options.serviceProcessContext,
293
+ //payloadType: InstrumentPayloadType.service,
294
+ consoleLogging: this.options.consoleLogging,
295
+ instrumentLogging: this.options.instrumentLogging,
296
+ httpServer,
297
+ instrumentationObservationInterval: this.options.instrumentationObservationInterval,
298
+ instrumentationTimeWindow: this.options.instrumentationTimeWindow,
299
+ logger: this.options.publisherLogger,
300
+ publishInterval: this.options.publishInterval,
301
+ publishPostFailInterval: 5e3,
302
+ //@@
303
+ instrumentDefinitions: GetInstruments("service"),
304
+ publishTransportBaseOptions: publishTransportOptions,
305
+ autoStart: true
306
+ /*
307
+ [
308
+ ...this.#GetDefaultServiceInstruments(httpServer),
309
+ ...this.GetAdditionalInstruments()
310
+ ]
311
+ */
312
+ };
313
+ __privateSet(this, _instrumentController, new PublishInstrumentController(instrumentControllerOptions));
314
+ }
315
+ /*
316
+ #GetDefaultServiceInstruments(httpServer: boolean): InstrumentDefinitions {
317
+ const standardInstruments: InstrumentDefinitions = [
318
+ [ Gauge.TIMER_GAUGE, GaugeTypes.INSTRUMENT_TIMER ],
319
+ [ Gauge.LOGGER, GaugeTypes.INSTRUMENT_LOG, {
320
+ consoleLogging: this.options.consoleLogging,
321
+ instrumentLogging: this.options.instrumentLogging } as InstrumentLogOptions],
322
+ [ Gauge.NETWORK_RX_GAUGE , GaugeTypes.INSTRUMENT_VELOCITY ],
323
+ [ Gauge.NETWORK_TX_GAUGE, GaugeTypes.INSTRUMENT_VELOCITY ],
324
+ [ Gauge.CPU_LOAD_GAUGE, GaugeTypes.INSTRUMENT_GAUGE, {
325
+ interval: this.options.instrumentationObservationInterval,
326
+ sampleSize: this.options.instrumentationTimeWindow } as InstrumentGaugeOptions],
327
+ [ Gauge.OBJECT_GAUGE, GaugeTypes.INSTRUMENT_OBJECT, {
328
+ label:'InstrumentObjectMaster' } as InstrumentObjectOptions]
329
+ ];
330
+
331
+ let httpServerInstruments: InstrumentDefinitions = [ ];
332
+ if (httpServer) {
333
+ httpServerInstruments = [
334
+ [ Gauge.REQUEST_COUNT_GAUGE, GaugeTypes.INSTRUMENT_GAUGE ], // Total number of requests serviced
335
+ [ Gauge.AUTHENTICATION_COUNT_GAUGE, GaugeTypes.INSTRUMENT_GAUGE ], // Total number of new token requests
336
+ [ Gauge.AUTHENTICATION_ERROR_COUNT_GAUGE, GaugeTypes.INSTRUMENT_GAUGE ], // Total number of new token requests errors
337
+ [ Gauge.AUTHENTICATION_RETRY_COUNT_GAUGE, GaugeTypes.INSTRUMENT_GAUGE ], // Total number of new token requests retries
338
+
339
+ [ Gauge.ACTIVE_REQUEST_GAUGE, GaugeTypes.INSTRUMENT_GAUGE, {
340
+ interval: this.options.instrumentationObservationInterval,
341
+ sampleSize: this.options.instrumentationTimeWindow } as InstrumentGaugeOptions],
342
+ [ Gauge.DURATION_GAUGE, GaugeTypes.INSTRUMENT_GAUGE, {
343
+ interval: this.options.instrumentationObservationInterval,
344
+ sampleSize: this.options.instrumentationTimeWindow } as InstrumentGaugeOptions],
345
+ [ Gauge.DURATION_HISTOGRAM_GAUGE, GaugeTypes.INSTRUMENT_HISTOGRAM ],
346
+ [ Gauge.CONNECTION_COUNT_GAUGE, GaugeTypes.INSTRUMENT_GAUGE, {
347
+ interval: this.options.instrumentationObservationInterval,
348
+ sampleSize: this.options.instrumentationTimeWindow } as InstrumentGaugeOptions],
349
+
350
+ [ Gauge.CONNECTION_POOL_TOTAL_GAUGE, GaugeTypes.INSTRUMENT_GAUGE ],
351
+ [ Gauge.CONNECTION_POOL_IDLE_GAUGE, GaugeTypes.INSTRUMENT_GAUGE ],
352
+ [ Gauge.CONNECTION_POOL_WAITING_GAUGE, GaugeTypes.INSTRUMENT_GAUGE ],
353
+ [ Gauge.VELOCITY_GAUGE, GaugeTypes.INSTRUMENT_VELOCITY ], // Requests per second
354
+ [ Gauge.ERROR_COUNT_GAUGE, GaugeTypes.INSTRUMENT_GAUGE ],
355
+ [ Gauge.RETRY_COUNT_GAUGE, GaugeTypes.INSTRUMENT_GAUGE ],
356
+ [ Gauge.LATENCY_GAUGE, GaugeTypes.INSTRUMENT_GAUGE, {
357
+ interval: this.options.instrumentationObservationInterval,
358
+ sampleSize: this.options.instrumentationTimeWindow } as InstrumentGaugeOptions],
359
+ [ Gauge.LATENCY_HISTOGRAM_GAUGE, GaugeTypes.INSTRUMENT_HISTOGRAM ],
360
+ [ Gauge.CORE_COUNT_GAUGE, GaugeTypes.INSTRUMENT_GAUGE ]
361
+ ]
362
+ }
363
+ return [
364
+ ...standardInstruments,
365
+ ...httpServerInstruments
366
+ ]
367
+ }
368
+ */
369
+ GetAdditionalInstruments() {
370
+ return [];
371
+ }
372
+ CollectAdditionalTelemetry() {
373
+ }
374
+ get InstrumentController() {
375
+ return __privateGet(this, _instrumentController);
376
+ }
377
+ InstrumentExists(instrumentName) {
378
+ if (__privateGet(this, _instrumentController)) {
379
+ return __privateGet(this, _instrumentController).InstrumentExists(instrumentName);
380
+ }
381
+ return false;
382
+ }
383
+ async ProcessTerminate() {
384
+ this.emit("ProcessTerminate");
385
+ if (__privateGet(this, _systemInformationInterval)) {
386
+ clearTimeout(__privateGet(this, _systemInformationInterval));
387
+ }
388
+ __privateSet(this, _systemInformationInterval, null);
389
+ }
390
+ /**
391
+ * UIController (instance of UIController) to manage a console based user interface associated for this node application.
392
+ * @returns UIController instance to manage a console based user interface associated for this node application.
393
+ */
394
+ GetUIController() {
395
+ return null;
396
+ }
397
+ get socketIoServerHelper() {
398
+ return __privateGet(this, _socketIoServerHelper);
399
+ }
400
+ set socketIoServerHelper(value) {
401
+ __privateSet(this, _socketIoServerHelper, value);
402
+ }
403
+ async TerminateDatabase() {
404
+ if (__privateGet(this, _accessLayer)) {
405
+ const logPrefix = `ProcessBase:TerminateDatabase():${process.pid}:`;
406
+ this.LogInfoMessage(`${logPrefix} Ending database connections and pools.`);
407
+ __privateGet(this, _accessLayer).off(IDBAccessLayerEvents.UpdateInstruments, __privateGet(this, _UpdatePGPoolManagerInstrument));
408
+ await __privateGet(this, _accessLayer).EndDatabase();
409
+ }
410
+ }
411
+ get accessLayer() {
412
+ if (this.options.useDatabase) {
413
+ if (__privateGet(this, _accessLayer) === null) {
414
+ __privateSet(this, _accessLayer, new DBAccessLayerManager().CreateAccessLayer({
415
+ accessLayerType: accessLayerType.postgresql,
416
+ accessLayerOptions: {
417
+ logger: this.options.logger,
418
+ usedefaultdb: false
419
+ }
420
+ }));
421
+ __privateGet(this, _accessLayer).on(IDBAccessLayerEvents.UpdateInstruments, __privateGet(this, _UpdatePGPoolManagerInstrument));
422
+ (async () => {
423
+ try {
424
+ const retVal = await this.accessLayer.GetResourceCount();
425
+ if (retVal.status !== StatusCodes.OK) {
426
+ this.LogInfoMessage(chalk.red(`Unable to get resources from the database. Is the database running? [${JSON.stringify(retVal)}]`));
427
+ } else {
428
+ this.LogInfoMessage(chalk.green(`Database connection successful. Resources: [${retVal.detail}]`));
429
+ }
430
+ } catch (error) {
431
+ this.LogInfoMessage(chalk.red(`Unable to get resources from the database. Is the database running? Error: [${error}]`));
432
+ }
433
+ })();
434
+ }
435
+ return __privateGet(this, _accessLayer);
436
+ }
437
+ return null;
438
+ }
439
+ emit(event, ...arg) {
440
+ super.emit(event, arg);
441
+ return this;
442
+ }
443
+ on(event, callback) {
444
+ super.on(event, callback);
445
+ return this;
446
+ }
447
+ off(event, callback) {
448
+ super.off(event, callback);
449
+ return this;
450
+ }
451
+ /*@@
452
+ get redisMessageHandler(): RedisMessageHandler {
453
+ return this.#redisMessageHandler as RedisMessageHandler;
454
+ }
455
+ */
456
+ }
457
+ _options = new WeakMap();
458
+ _instrumentController = new WeakMap();
459
+ _systemInformationInterval = new WeakMap();
460
+ _socketIoServerHelper = new WeakMap();
461
+ _accessLayer = new WeakMap();
462
+ _ProcessBase_instances = new WeakSet();
463
+ GetFormattedLogMessage_fn = function(message) {
464
+ let prefix = "";
465
+ let col = null;
466
+ const appName = this.options.serviceName;
467
+ if (cluster.isPrimary) {
468
+ prefix = "M";
469
+ col = chalk.bold.cyan;
470
+ } else {
471
+ prefix = "W";
472
+ col = chalk.green;
473
+ }
474
+ return col(`${prefix}(${process.pid}) [${appName}]: ${message}`);
475
+ };
476
+ _UpdatePGPoolManagerInstrument = new WeakMap();
477
+ class STSTransportLoggerWinston extends Transport {
478
+ constructor(opts) {
479
+ super(opts);
480
+ __privateAdd(this, _options2);
481
+ __privateSet(this, _options2, opts);
482
+ }
483
+ log(info, callback) {
484
+ __privateGet(this, _options2).stsApp.LogMessageToLoggerInstrument(info.message);
485
+ this.emit("logged", info);
486
+ callback();
487
+ }
488
+ }
489
+ _options2 = new WeakMap();
490
+ class MasterProcessBase extends ProcessBase {
491
+ constructor(options) {
492
+ super(options);
493
+ __privateAdd(this, _MasterProcessBase_instances);
494
+ //static WORKER_MESSAGE_EVENT = 'sts_worker_message_event';
495
+ __privateAdd(this, _masterProcessExitTime, goptions.masterProcessExitTime);
496
+ __privateAdd(this, _childProcessExitTime, goptions.childProcessExitTime);
497
+ __privateAdd(this, _siValueObject, {
498
+ currentLoad: "currentLoad"
499
+ });
500
+ __privateAdd(this, _httpServer, null);
501
+ // Prometheus cluster server. See https://github.com/siimon/prom-client/blob/master/example/cluster.js
502
+ __privateAdd(this, _metricsServer, null);
503
+ __privateAdd(this, _aggregatorRegistry, null);
504
+ __privateAdd(this, _checkLatency, null);
505
+ __privateAdd(this, _killWorkers, {});
506
+ __privateAdd(this, _workers, 1);
507
+ // Start at 1 becuase of main thread
508
+ __privateAdd(this, _shuttingDown, false);
509
+ __privateAdd(this, _agentManager);
510
+ __privateAdd(this, _InitCluster, () => {
511
+ cluster.on("listening", (worker, address) => {
512
+ this.emit("clusterListening", worker, address);
513
+ let allListening = true;
514
+ for (const worker2 of Object.values(cluster.workers)) {
515
+ if (worker2 == null ? void 0 : worker2.isConnected) {
516
+ allListening = false;
517
+ break;
518
+ }
519
+ }
520
+ if (allListening) {
521
+ this.LogInfoMessage(`Service instance started.`);
522
+ this.emit("allListening");
523
+ }
524
+ });
525
+ });
526
+ // https://github.com/siimon/prom-client/blob/master/example/cluster.js
527
+ __privateAdd(this, _SetupPrometheusForMaster, () => {
528
+ __privateSet(this, _metricsServer, express());
529
+ __privateSet(this, _aggregatorRegistry, new AggregatorRegistry());
530
+ switch (goptions.STSServerType) {
531
+ case "EXPRESS_TLS":
532
+ {
533
+ const options = {
534
+ key: fs.readFileSync(this.options.httpsServerKeyPath),
535
+ cert: fs.readFileSync(this.options.httpsServerCertificatePath)
536
+ };
537
+ __privateSet(this, _httpServer, createServer$1(options, __privateGet(this, _metricsServer)));
538
+ }
539
+ break;
540
+ case "EXPRESS": {
541
+ __privateSet(this, _httpServer, createServer(__privateGet(this, _metricsServer)));
542
+ }
543
+ }
544
+ __privateGet(this, _metricsServer).get("/cluster_metrics", async (req, res) => {
545
+ try {
546
+ const metrics = await __privateGet(this, _aggregatorRegistry).clusterMetrics();
547
+ res.set("Content-Type", __privateGet(this, _aggregatorRegistry).contentType);
548
+ res.send(metrics);
549
+ } catch (ex) {
550
+ res.statusCode = 500;
551
+ res.send(ex.message);
552
+ }
553
+ });
554
+ try {
555
+ __privateGet(this, _httpServer).listen(this.options.prometheusClusterPort, () => {
556
+ }).on("listening", () => {
557
+ this.emit(
558
+ "prometheusScrapesListening",
559
+ `${this.options.endpoint}:${this.options.prometheusClusterPort}/metrics`,
560
+ this.options.endpoint,
561
+ this.options.prometheusClusterPort
562
+ );
563
+ this.LogInfoMessage(`Prometheus scrapes ready and live on ${this.options.endpoint}:${this.options.prometheusClusterPort}/metrics`);
564
+ });
565
+ } catch (error) {
566
+ __privateMethod(this, _MasterProcessBase_instances, LogErrorMessage_fn).call(this, error);
567
+ throw error;
568
+ }
569
+ });
570
+ __privateAdd(this, _CheckLatency, async () => {
571
+ const start = process.hrtime();
572
+ await __privateGet(this, _GetLatency).call(this);
573
+ __privateGet(this, _LatencyRequestCompleted).call(this, start);
574
+ });
575
+ __privateAdd(this, _GetLatency, async () => {
576
+ let retVal = null;
577
+ const url = `${this.options.endpoint}:${this.options.port}${this.options.apiRoot}/latency`;
578
+ try {
579
+ retVal = await axios(new STSAxiosConfig(url, "get").withDefaultHeaders().withAgentManager(__privateGet(this, _agentManager)).config);
580
+ if (retVal.status !== 200) {
581
+ __privateMethod(this, _MasterProcessBase_instances, LogDebugMessage_fn).call(this, chalk.magenta(`Error (MasterProcessBase:#GetLatency): Invalid response from server: [${retVal.status}]`));
582
+ return null;
583
+ }
584
+ return retVal.data.detail;
585
+ } catch (error) {
586
+ __privateMethod(this, _MasterProcessBase_instances, LogDebugMessage_fn).call(this, chalk.red(`Error (MasterProcessBase:#GetLatency:catch): [${error}]`));
587
+ __privateMethod(this, _MasterProcessBase_instances, LogDebugMessage_fn).call(this, chalk.red(` url: [${url}]`));
588
+ if (error.response && error.response.data) {
589
+ __privateMethod(this, _MasterProcessBase_instances, LogDebugMessage_fn).call(this, chalk.red(` Details: [${JSON.stringify(error.response.data)}]`));
590
+ }
591
+ }
592
+ });
593
+ __privateAdd(this, _LatencyRequestCompleted, (start) => {
594
+ let timeInMs = 0;
595
+ const end = process.hrtime(start);
596
+ timeInMs = (end[0] * 1e9 + end[1]) / 1e6;
597
+ timeInMs = parseFloat(timeInMs.toFixed(4));
598
+ this.UpdateInstrument(Gauge.LATENCY_HISTOGRAM_GAUGE, {
599
+ val: timeInMs
600
+ });
601
+ this.UpdateInstrument(Gauge.LATENCY_GAUGE, {
602
+ val: timeInMs
603
+ });
604
+ });
605
+ __publicField(this, "SetupServer", async () => {
606
+ this.SetupInstrumentation();
607
+ setTimeout(() => {
608
+ this.SetupServerEx();
609
+ }, 100);
610
+ });
611
+ __privateAdd(this, __KillWorker, (id, signal, killProcess) => {
612
+ try {
613
+ if (cluster.workers && cluster.workers[id]) {
614
+ const worker = cluster.workers[id];
615
+ if (worker.process) {
616
+ this.LogInfoMessage(chalk.grey(`Sending terminate message `) + chalk.yellow(`(initiated by ${signal})`) + chalk.grey(` for worker PID: ${worker.process.pid}`));
617
+ const command = killProcess ? "TerminateAndKill" : "Terminate";
618
+ try {
619
+ worker.send({ command });
620
+ } catch (error) {
621
+ this.LogInfoMessage(chalk.red(`MasterProcessBase:#_KillWorker() (1): id: [${id}], signal: [${signal}], killProcess: [${killProcess}], error: [${error}]`));
622
+ return false;
623
+ }
624
+ return true;
625
+ } else {
626
+ this.LogInfoMessage(chalk.red(`MasterProcessBase:#_KillWorker(): Could not kill worker with id: [${id}]. The process does not exists`));
627
+ return false;
628
+ }
629
+ } else {
630
+ this.LogInfoMessage(chalk.red(`MasterProcessBase:#_KillWorker(): Could not kill worker with id: [${id}]. Worker does not exist within workers collection`));
631
+ return false;
632
+ }
633
+ } catch (error) {
634
+ this.LogInfoMessage(chalk.red(`MasterProcessBase:#_KillWorker() (2): id: [${id}], signal: [${signal}], killProcess: [${killProcess}], error: [${error}]`));
635
+ return false;
636
+ }
637
+ });
638
+ __publicField(this, "KillWorker", (id, signal = "SIGTERM", options, killProcess, allowKillAll) => {
639
+ try {
640
+ if (allowKillAll || Object.keys(cluster.workers).length > 1) {
641
+ if (id.localeCompare("0") === 0) {
642
+ const keys = Object.keys(cluster.workers);
643
+ for (let i = keys.length - 1; i > 0; i--) {
644
+ id = keys[i];
645
+ if (!__privateGet(this, _killWorkers)[id]) {
646
+ __privateGet(this, _killWorkers)[id] = id;
647
+ setTimeout(() => {
648
+ delete __privateGet(this, _killWorkers)[id];
649
+ }, 2e3).unref();
650
+ return __privateGet(this, __KillWorker).call(this, id, signal, killProcess);
651
+ }
652
+ }
653
+ return false;
654
+ } else {
655
+ return __privateGet(this, __KillWorker).call(this, id, signal, killProcess);
656
+ }
657
+ } else {
658
+ this.LogInfoMessage(chalk.yellow(`MasterProcessBase:KillWorker(): Not allowed to kill the last worker process.`));
659
+ return false;
660
+ }
661
+ } catch (error) {
662
+ this.LogInfoMessage(chalk.red(`MasterProcessBase:KillWorker(): id: [${id}], signal: [${signal}], killProcess: [${killProcess}], error: [${error}]`));
663
+ return false;
664
+ }
665
+ });
666
+ __publicField(this, "KillWorkers", (signal, keepOne) => {
667
+ const logPrefix = `MasterProcessBase:KillWorkers():${process.pid}:`;
668
+ try {
669
+ this.LogInfoMessage(`${logPrefix} Killing Workers.`);
670
+ const keepOneAlive = keepOne ? keepOne : false;
671
+ let skippedFirst = false;
672
+ const sortedIdList = [];
673
+ for (const id in cluster.workers) {
674
+ sortedIdList.push(parseInt(id));
675
+ }
676
+ sortedIdList.sort().forEach((id) => {
677
+ if (keepOneAlive && !skippedFirst) {
678
+ skippedFirst = true;
679
+ } else {
680
+ this.KillWorker(id.toString(), signal, null, false, true);
681
+ }
682
+ });
683
+ } catch (error) {
684
+ this.LogInfoMessage(chalk.red(`${logPrefix} signal: [${signal}], keepOne: [${keepOne}], error: [${error}]`));
685
+ }
686
+ });
687
+ __privateAdd(this, _UpdateWorkersInstrument, () => {
688
+ setTimeout(() => {
689
+ this.UpdateInstrument(Gauge.CORE_COUNT_GAUGE, {
690
+ val: __privateGet(this, _workers)
691
+ });
692
+ }, 2e3);
693
+ });
694
+ __publicField(this, "IncWorkers", () => {
695
+ __privateWrapper(this, _workers)._++;
696
+ __privateMethod(this, _MasterProcessBase_instances, LogDebugMessage_fn).call(this, ` Inc Workers. Total thread count: [${__privateGet(this, _workers)}]`);
697
+ __privateGet(this, _UpdateWorkersInstrument).call(this);
698
+ });
699
+ __publicField(this, "DecWorkers", () => {
700
+ __privateWrapper(this, _workers)._--;
701
+ __privateMethod(this, _MasterProcessBase_instances, LogDebugMessage_fn).call(this, ` Dec Workers. Total thread count: [${__privateGet(this, _workers)}]`);
702
+ __privateGet(this, _UpdateWorkersInstrument).call(this);
703
+ });
704
+ __publicField(this, "AddWorker", (options) => {
705
+ const workerId = __privateGet(this, _SpawnWorker).call(this, options);
706
+ __privateMethod(this, _MasterProcessBase_instances, LogDebugMessage_fn).call(this, chalk.yellow(` Spawned worker with id: [${workerId}]`));
707
+ if (options) {
708
+ __privateMethod(this, _MasterProcessBase_instances, LogDebugMessage_fn).call(this, chalk.yellow(` Options: [${JSON.stringify(options)}]`));
709
+ }
710
+ return workerId;
711
+ });
712
+ __privateAdd(this, _processIPCCommand, async (iPCMessagePayload) => {
713
+ var _a, _b, _c;
714
+ __privateMethod(this, _MasterProcessBase_instances, LogDebugMessage_fn).call(this, chalk.yellow(` Processing message command: [${iPCMessagePayload.command}]`));
715
+ switch (iPCMessagePayload.command) {
716
+ case IPCMessageCommand.AddWorker: {
717
+ const workerId = this.AddWorker((_a = iPCMessagePayload.requestDetail) == null ? void 0 : _a.options);
718
+ iPCMessagePayload.responseDetail = {
719
+ workerId
720
+ };
721
+ return iPCMessagePayload;
722
+ }
723
+ case IPCMessageCommand.DeleteWorker: {
724
+ const workerId = (_b = iPCMessagePayload.requestDetail) == null ? void 0 : _b.workerId;
725
+ const workerKilled = this.KillWorker(workerId, "SIGTERM", (_c = iPCMessagePayload.requestDetail) == null ? void 0 : _c.options, true, false);
726
+ __privateMethod(this, _MasterProcessBase_instances, LogDebugMessage_fn).call(this, chalk.yellow(` Killed worker with id: [${workerId}]`));
727
+ iPCMessagePayload.responseDetail = {
728
+ workerId,
729
+ workerKilled
730
+ };
731
+ return iPCMessagePayload;
732
+ }
733
+ case IPCMessageCommand.GetConfig: {
734
+ const safeOptions = { ...this.options };
735
+ delete safeOptions.logger;
736
+ delete safeOptions.publisherLogger;
737
+ delete safeOptions.expressServerRouteFactory;
738
+ iPCMessagePayload.responseDetail = {
739
+ safeOptions
740
+ };
741
+ return iPCMessagePayload;
742
+ }
743
+ default: {
744
+ const errorMessage = `Could not process command: [${iPCMessagePayload.command}].`;
745
+ __privateMethod(this, _MasterProcessBase_instances, LogDebugMessage_fn).call(this, chalk.red(` ${errorMessage}`));
746
+ throw new Error(errorMessage);
747
+ }
748
+ }
749
+ });
750
+ __privateAdd(this, _SpawnWorker, (spawnWorkerOptions) => {
751
+ const workerEnv = {};
752
+ const tempOptions = { ...this.options };
753
+ delete tempOptions.logger;
754
+ delete tempOptions.publisherLogger;
755
+ workerEnv["STS_GSD_SII"] = JSON.stringify(tempOptions);
756
+ if (spawnWorkerOptions) {
757
+ workerEnv["STS_GSD_OPTIONS"] = JSON.stringify(spawnWorkerOptions);
758
+ }
759
+ if (this.options.workerExec) {
760
+ cluster.setupPrimary({
761
+ exec: this.options.workerExec,
762
+ silent: true
763
+ });
764
+ }
765
+ const worker = cluster.fork(workerEnv);
766
+ this.IncWorkers();
767
+ worker.on("exit", (code, signal) => {
768
+ this.emit("workerExit", code, signal);
769
+ if (signal) {
770
+ this.LogInfoMessage(`Worker: ${worker.process.pid} was killed by signal: ${signal}`);
771
+ } else if (code !== 0) {
772
+ this.LogInfoMessage(`Worker: ${worker.process.pid} exited with error code: ${code}`);
773
+ } else {
774
+ this.LogInfoMessage(`Worker: ${worker.process.pid} exited successfully, code: ${code}, signal: ${signal}`);
775
+ }
776
+ });
777
+ worker.on("message", async (payload) => {
778
+ this.emit("workerMessage", worker.id, payload);
779
+ if (payload.requestResponse) {
780
+ const iPCMessagePayload = payload;
781
+ const response = await this.ProcessIPCCommand(iPCMessagePayload);
782
+ worker.send(response);
783
+ } else {
784
+ __privateMethod(this, _MasterProcessBase_instances, WorkerMessageEvent_fn).call(this, worker.id, payload);
785
+ }
786
+ });
787
+ worker.on("error", (error) => {
788
+ this.emit("workerError", error);
789
+ const message = chalk.red(`#SpawnWorker():worker.on('error'): Error: [${error}]`);
790
+ this.LogErrorMessage(message);
791
+ });
792
+ this.emit("workerAdded", worker.id);
793
+ return worker.id;
794
+ });
795
+ __publicField(this, "SetupServerEx", async () => {
796
+ this.ProcessStartup();
797
+ this.LogInfoMessage(`Service instance starting. Instance Id: [${this.options.serviceInstanceId}]`);
798
+ this.LogSystemTelemetry();
799
+ if (this.options.wssServer === true) {
800
+ if (this.options.useSocketIoRedisAdaptor) {
801
+ this.LogInfoMessage(`Using Redis for socket.io cluster management (master)`);
802
+ } else {
803
+ this.LogInfoMessage(`Using nodejs cluster mode for socket.io cluster management`);
804
+ setupPrimary();
805
+ }
806
+ }
807
+ if (this.options.prometheusSupport === true) {
808
+ __privateGet(this, _SetupPrometheusForMaster).call(this);
809
+ }
810
+ const numCPUs = await this.GetNumCPUs();
811
+ for (let i = 0; i < numCPUs; i++) {
812
+ __privateGet(this, _SpawnWorker).call(this);
813
+ }
814
+ __privateGet(this, _InitCluster).call(this);
815
+ cluster.on("listening", (worker, address) => {
816
+ this.emit("clusterListening", worker, address);
817
+ this.LogInfoMessage(`Worker process ${worker.process.pid} is listening at address: ${JSON.stringify(address)}`);
818
+ });
819
+ cluster.on("online", (worker) => {
820
+ this.emit("clusterOnline", worker);
821
+ this.LogInfoMessage(`Worker process ${worker.process.pid} is online`);
822
+ });
823
+ cluster.on("exit", (worker, code, signal) => {
824
+ this.emit("clusterExit", worker, code, signal);
825
+ if (code !== null && code === 0 || signal === "SIGINT") {
826
+ this.LogInfoMessage(chalk.green(`Process ${worker.process.pid} terminated gracefully with code: ${code}, signal: ${signal}`));
827
+ this.DecWorkers();
828
+ } else if (code !== null && code === 15 || signal === "SIGTERM") {
829
+ this.DecWorkers();
830
+ this.LogInfoMessage(chalk.red(`Process ${worker.process.pid} terminated with code: ${code}, signal: ${signal}`));
831
+ } else {
832
+ this.DecWorkers();
833
+ this.LogInfoMessage(chalk.red(`worker ${worker.process.pid} died`));
834
+ this.LogInfoMessage(chalk.red(`code: ${code}`));
835
+ this.LogInfoMessage(chalk.red(`signal: ${signal}`));
836
+ this.LogInfoMessage(chalk.red("process terminated in an error state"));
837
+ if (goptions.respawnOnFail === true) {
838
+ this.LogInfoMessage(chalk.magenta(`Attemping to respawn worker`));
839
+ __privateGet(this, _SpawnWorker).call(this);
840
+ }
841
+ }
842
+ });
843
+ const TerminateLatency = () => {
844
+ if (__privateGet(this, _checkLatency)) {
845
+ clearInterval(__privateGet(this, _checkLatency));
846
+ __privateSet(this, _checkLatency, null);
847
+ }
848
+ };
849
+ const TerminateHTTPServer = async () => {
850
+ if (__privateGet(this, _httpServer) !== null) {
851
+ const logPrefix = `ServerProcessBase:TerminateHTTPServer():${process.pid}:`;
852
+ this.LogInfoMessage(`${logPrefix} Closing httpServer.`);
853
+ await __privateGet(this, _httpServer).close();
854
+ __privateSet(this, _httpServer, null);
855
+ }
856
+ };
857
+ const Terminate = async (signal) => {
858
+ const logPrefix = `MasterProcessBase:Terminate():${process.pid}:`;
859
+ if (__privateGet(this, _shuttingDown) === false) {
860
+ __privateSet(this, _shuttingDown, true);
861
+ if (signal) {
862
+ this.LogInfoMessage(this.GetSignalColour(signal)(`${logPrefix} Received signal: ${signal}`));
863
+ } else {
864
+ this.LogInfoMessage(this.GetSignalColour(null)(`${logPrefix} Received Terminate without signal.`));
865
+ }
866
+ TerminateLatency();
867
+ await this.ProcessTerminate();
868
+ this.TerminateUIController();
869
+ this.LogInfoMessage(`${logPrefix} De-Registering service.`);
870
+ await TerminateHTTPServer();
871
+ this.KillWorkers(signal);
872
+ await this.TerminateDatabase();
873
+ this.TerminateInstrumentController();
874
+ await Sleep(1e3);
875
+ this.ProcessExit(__privateGet(this, _childProcessExitTime) + __privateGet(this, _masterProcessExitTime));
876
+ } else {
877
+ this.LogInfoMessage(`${logPrefix} Process already terminating.`);
878
+ }
879
+ };
880
+ process.on("SIGINT", async () => {
881
+ this.emit("processSigint");
882
+ await Terminate("SIGINT");
883
+ });
884
+ process.on("SIGTERM", async () => {
885
+ this.emit("processSigterm");
886
+ await Terminate("SIGTERM");
887
+ });
888
+ process.on("exit", (code) => {
889
+ this.emit("processExit", code);
890
+ if (code === 0) {
891
+ this.LogInfoMessage(chalk.green(`Main Process: ${process.pid} terminated gracefully with code: ${code}`));
892
+ } else {
893
+ this.LogInfoMessage(chalk.red(`Main Process: ${process.pid} terminated with code: ${code}`));
894
+ }
895
+ });
896
+ if (this.options.useLatency) {
897
+ __privateSet(this, _checkLatency, setInterval(() => {
898
+ __privateGet(this, _CheckLatency).call(this);
899
+ }, 1e3).unref());
900
+ }
901
+ this.MasterStarted();
902
+ this.LogInfoMessage(chalk.green(`Master process:${process.pid} started`));
903
+ });
904
+ __publicField(this, "BroadcastDataToWorkers", (command, data) => {
905
+ try {
906
+ for (const id in cluster.workers) {
907
+ try {
908
+ cluster.workers[id].process.send({ command, data });
909
+ } catch (error) {
910
+ }
911
+ }
912
+ } catch (error) {
913
+ }
914
+ });
915
+ __privateSet(this, _agentManager, new AgentManager({
916
+ agentOptions: {
917
+ keepAlive: false,
918
+ // Use basic defaults. This agent will not use keep-alive.
919
+ maxFreeSockets: goptions.maxFreeSockets,
920
+ maxSockets: goptions.maxSockets,
921
+ maxTotalSockets: goptions.maxTotalSockets,
922
+ timeout: goptions.timeout,
923
+ rejectUnauthorized: goptions.isProduction
924
+ // Allows self-signed certificates if non-production
925
+ }
926
+ }));
927
+ }
928
+ CollectAdditionalTelemetry() {
929
+ si.get(__privateGet(this, _siValueObject)).then((data) => {
930
+ this.UpdateInstrument(Gauge.CPU_SYSTEM_LOAD_GAUGE, {
931
+ val: data.currentLoad.currentLoad
932
+ });
933
+ });
934
+ }
935
+ GetAdditionalInstruments() {
936
+ return [
937
+ [Gauge.CPU_SYSTEM_LOAD_GAUGE, GaugeTypes.INSTRUMENT_GAUGE, {
938
+ interval: goptions.instrumentationObservationInterval,
939
+ sampleSize: goptions.instrumentationTimeWindow
940
+ }]
941
+ ];
942
+ }
943
+ /**
944
+ * Note: msg removed from signature but will be passed at run-time.
945
+ * @param {*} msg
946
+ */
947
+ WorkerMessageEvent(workerId, msg) {
948
+ return null;
949
+ }
950
+ async ProcessIPCCommand(iPCMessagePayload) {
951
+ return __privateGet(this, _processIPCCommand).call(this, iPCMessagePayload);
952
+ }
953
+ MasterStarted() {
954
+ const transport = new STSTransportLoggerWinston({
955
+ stsApp: this
956
+ });
957
+ setTimeout(() => {
958
+ this.options.logger.add(transport);
959
+ }, 0);
960
+ }
961
+ get shuttingDown() {
962
+ return __privateGet(this, _shuttingDown);
963
+ }
964
+ /*
965
+ #GetSystemInformation = async (): Promise<JSONObject> => {
966
+ // https://systeminformation.io/
967
+ const valueObject = {
968
+ system: '*',
969
+ osInfo: '*',
970
+ cpu: '*',
971
+ mem: '*',
972
+ dockerInfo: '*',
973
+ //dockerImages: '*',
974
+ dockerContainers: '*',
975
+ }
976
+
977
+ const sysinfo = await si.get(valueObject);
978
+ const numCPUs = await this.GetNumCPUs();
979
+ const hostname = sysinfo.osInfo.hostname;
980
+
981
+ const hostaddr = GetFirstNetworkInterface();
982
+
983
+ const promArray: Promise<any>[] = [ ];
984
+
985
+ sysinfo.dockerContainers.forEach((dc: { id: string; }) => {
986
+ const dcs = promArray.push(si.dockerContainerStats(dc.id));
987
+ console.log(dcs);
988
+ });
989
+ const dockerContainerStats = await Promise.all(promArray);
990
+
991
+ const sysInfo = {
992
+ serviceProcessContext: this.options.serviceProcessContext,
993
+ hostname,
994
+ numCPUs,
995
+ hostaddr,
996
+ system: sysinfo.system,
997
+ osInfo: sysinfo.osInfo,
998
+ cpu: sysinfo.cpu,
999
+ mem: sysinfo.mem,
1000
+ dockerInfo: sysinfo.dockerInfo,
1001
+ //dockerImages: sysinfo.dockerImages,
1002
+ dockerContainers: sysinfo.dockerContainers,
1003
+ dockerContainerStats
1004
+ }
1005
+
1006
+ return sysInfo;
1007
+ }
1008
+ */
1009
+ }
1010
+ _masterProcessExitTime = new WeakMap();
1011
+ _childProcessExitTime = new WeakMap();
1012
+ _siValueObject = new WeakMap();
1013
+ _httpServer = new WeakMap();
1014
+ _metricsServer = new WeakMap();
1015
+ _aggregatorRegistry = new WeakMap();
1016
+ _checkLatency = new WeakMap();
1017
+ _killWorkers = new WeakMap();
1018
+ _workers = new WeakMap();
1019
+ _shuttingDown = new WeakMap();
1020
+ _agentManager = new WeakMap();
1021
+ _MasterProcessBase_instances = new WeakSet();
1022
+ LogErrorMessage_fn = function(message) {
1023
+ this.options.logger.error(message);
1024
+ };
1025
+ LogDebugMessage_fn = function(message) {
1026
+ this.options.logger.debug(message);
1027
+ };
1028
+ WorkerMessageEvent_fn = function(workerId, msg) {
1029
+ if (msg.command) {
1030
+ this.WorkerMessageEvent(workerId, msg);
1031
+ }
1032
+ };
1033
+ _InitCluster = new WeakMap();
1034
+ _SetupPrometheusForMaster = new WeakMap();
1035
+ _CheckLatency = new WeakMap();
1036
+ _GetLatency = new WeakMap();
1037
+ _LatencyRequestCompleted = new WeakMap();
1038
+ __KillWorker = new WeakMap();
1039
+ _UpdateWorkersInstrument = new WeakMap();
1040
+ _processIPCCommand = new WeakMap();
1041
+ _SpawnWorker = new WeakMap();
1042
+ var ServerNetworkMiddlewareEventName = /* @__PURE__ */ ((ServerNetworkMiddlewareEventName2) => {
1043
+ ServerNetworkMiddlewareEventName2["UpdateInstrument_SERVER_NET_VAL"] = "UpdateInstrument_SERVER_NET_VAL";
1044
+ return ServerNetworkMiddlewareEventName2;
1045
+ })(ServerNetworkMiddlewareEventName || {});
1046
+ class ServerNetworkMiddleware extends STSOptionsBase {
1047
+ constructor(options) {
1048
+ super(options);
1049
+ __privateAdd(this, _ServerNetworkMiddleware_instances);
1050
+ __privateAdd(this, _tinyEmitter, new TinyEmitter());
1051
+ __privateAdd(this, _socketCollection, {});
1052
+ __privateAdd(this, _id, "");
1053
+ __publicField(this, "GetSocketRecord", (socket) => {
1054
+ for (const [, socketRecord] of Object.entries(__privateGet(this, _socketCollection))) {
1055
+ if (socketRecord.socket === socket) {
1056
+ return socketRecord;
1057
+ }
1058
+ }
1059
+ return null;
1060
+ });
1061
+ __publicField(this, "UpdateNetworkStats", (workingSocketRecord, eventName, req) => {
1062
+ workingSocketRecord.originalUrl = req.originalUrl;
1063
+ workingSocketRecord.eventName = eventName;
1064
+ workingSocketRecord.currentBytesRead = req.socket.bytesRead;
1065
+ workingSocketRecord.currentBytesWritten = req.socket.bytesWritten;
1066
+ workingSocketRecord.requestBytesRead = workingSocketRecord.currentBytesRead - workingSocketRecord.lastBytesRead;
1067
+ workingSocketRecord.requestBytesWritten = workingSocketRecord.currentBytesWritten - workingSocketRecord.lastBytesWritten;
1068
+ const workingSocketEventRecord = { ...workingSocketRecord };
1069
+ delete workingSocketEventRecord.socket;
1070
+ __privateMethod(this, _ServerNetworkMiddleware_instances, LogSillyMessage_fn).call(this, chalk.gray(`Sending event: [${JSON.stringify(workingSocketEventRecord)}]`));
1071
+ __privateGet(this, _tinyEmitter).emit("UpdateInstrument_SERVER_NET_VAL", workingSocketEventRecord);
1072
+ workingSocketRecord.lastBytesRead = workingSocketRecord.currentBytesRead;
1073
+ workingSocketRecord.lastBytesWritten = workingSocketRecord.currentBytesWritten;
1074
+ });
1075
+ __privateAdd(this, _GetRequestContentSize, (req) => {
1076
+ try {
1077
+ let contentLength = 0;
1078
+ if (req["_contentLength"]) {
1079
+ contentLength = req["_contentLength"];
1080
+ } else {
1081
+ if (req.headers["content-length"]) {
1082
+ contentLength = parseInt(req.headers["content-length"]);
1083
+ }
1084
+ }
1085
+ return contentLength;
1086
+ } catch (error) {
1087
+ __privateMethod(this, _ServerNetworkMiddleware_instances, LogErrorMessage_fn2).call(this, chalk.red(`ServerNetworkMiddleware:#GetRequestContentSize(): Error: [${error}]`));
1088
+ return 0;
1089
+ }
1090
+ });
1091
+ __publicField(this, "Middleware", (req, res, next) => {
1092
+ let workingSocketRecord = null;
1093
+ workingSocketRecord = this.GetSocketRecord(req.socket);
1094
+ if (!workingSocketRecord) {
1095
+ __privateSet(this, _id, v4());
1096
+ workingSocketRecord = {
1097
+ id: `${this.options.name}_${__privateGet(this, _id).toString()}`,
1098
+ socket: req.socket,
1099
+ currentBytesRead: 0,
1100
+ currentBytesWritten: 0,
1101
+ lastBytesRead: 0,
1102
+ lastBytesWritten: 0,
1103
+ requestBytesRead: 0,
1104
+ requestBytesWritten: 0,
1105
+ originalUrl: req.originalUrl,
1106
+ eventName: ""
1107
+ };
1108
+ __privateGet(this, _socketCollection)[workingSocketRecord.id] = workingSocketRecord;
1109
+ __privateMethod(this, _ServerNetworkMiddleware_instances, LogSillyMessage_fn).call(this, chalk.gray(`Adding new socket to recordset: ID: [${workingSocketRecord.id}], originalUrl: [${workingSocketRecord.originalUrl}]`));
1110
+ workingSocketRecord.socket.on("data", () => {
1111
+ const socketRecord = this.GetSocketRecord(workingSocketRecord.socket);
1112
+ if (socketRecord) {
1113
+ __privateMethod(this, _ServerNetworkMiddleware_instances, LogSillyMessage_fn).call(this, chalk.gray(`Socket data event: ID: [${socketRecord.id}], originalUrl: [${socketRecord.originalUrl}]`));
1114
+ this.UpdateNetworkStats(socketRecord, "socket_data", req);
1115
+ } else {
1116
+ __privateMethod(this, _ServerNetworkMiddleware_instances, LogSillyMessage_fn).call(this, chalk.magenta(`Socket data event: Could not find socket within recordset`));
1117
+ }
1118
+ });
1119
+ workingSocketRecord.socket.on("close", () => {
1120
+ const socketRecord = this.GetSocketRecord(workingSocketRecord.socket);
1121
+ if (socketRecord) {
1122
+ __privateMethod(this, _ServerNetworkMiddleware_instances, LogSillyMessage_fn).call(this, chalk.gray(`Socket close event: ID: [${socketRecord.id}], originalUrl: [${socketRecord.originalUrl}]`));
1123
+ this.UpdateNetworkStats(socketRecord, "socket_close", req);
1124
+ delete __privateGet(this, _socketCollection)[socketRecord.id];
1125
+ __privateMethod(this, _ServerNetworkMiddleware_instances, LogSillyMessage_fn).call(this, chalk.gray(`Socket removed from recordset: ID: [${socketRecord.id}], originalUrl: [${socketRecord.originalUrl}]`));
1126
+ } else {
1127
+ __privateMethod(this, _ServerNetworkMiddleware_instances, LogSillyMessage_fn).call(this, chalk.magenta(`Socket close event: Could not find socket within recordset`));
1128
+ }
1129
+ });
1130
+ workingSocketRecord.socket.on("end", () => {
1131
+ const socketRecord = this.GetSocketRecord(workingSocketRecord.socket);
1132
+ if (socketRecord) {
1133
+ __privateMethod(this, _ServerNetworkMiddleware_instances, LogSillyMessage_fn).call(this, chalk.gray(`Socket end event: ID: [${socketRecord.id}], originalUrl: [${socketRecord.originalUrl}]`));
1134
+ this.UpdateNetworkStats(socketRecord, "socket_end", req);
1135
+ } else {
1136
+ __privateMethod(this, _ServerNetworkMiddleware_instances, LogSillyMessage_fn).call(this, chalk.magenta(`Socket end event: Could not find socket within recordset`));
1137
+ }
1138
+ });
1139
+ }
1140
+ onHeaders(res, () => {
1141
+ let contentLength = 0;
1142
+ if (res["_contentLength"]) {
1143
+ contentLength = res["_contentLength"];
1144
+ } else {
1145
+ if (res.hasHeader("content-length")) {
1146
+ contentLength = parseInt(res.getHeader("content-length"));
1147
+ }
1148
+ }
1149
+ res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
1150
+ res.setHeader("Pragma", "no-cache");
1151
+ res.setHeader("Expires", "0");
1152
+ const headerLength = JSON.stringify(res.getHeaders()).length;
1153
+ const totalSize = contentLength + headerLength;
1154
+ __privateMethod(this, _ServerNetworkMiddleware_instances, LogSillyMessage_fn).call(this, chalk.white.bgBlue(`contentLength: [${contentLength}], headerLength: [${headerLength}], total Size: [${totalSize}]`));
1155
+ });
1156
+ req.on("end", () => {
1157
+ const socketRecord = this.GetSocketRecord(req.socket);
1158
+ if (socketRecord) {
1159
+ __privateMethod(this, _ServerNetworkMiddleware_instances, LogSillyMessage_fn).call(this, chalk.gray(`Request end event: ID: [${socketRecord.id}], originalUrl: [${socketRecord.originalUrl}]`));
1160
+ this.UpdateNetworkStats(socketRecord, "req_end", req);
1161
+ } else {
1162
+ __privateMethod(this, _ServerNetworkMiddleware_instances, LogSillyMessage_fn).call(this, chalk.magenta(`Request end event: Could not find socket within recordset`));
1163
+ }
1164
+ });
1165
+ req.on("close", () => {
1166
+ const socketRecord = this.GetSocketRecord(req.socket);
1167
+ if (socketRecord) {
1168
+ __privateMethod(this, _ServerNetworkMiddleware_instances, LogSillyMessage_fn).call(this, chalk.gray(`Request close event: ID: [${socketRecord.id}], originalUrl: [${socketRecord.originalUrl}]`));
1169
+ this.UpdateNetworkStats(socketRecord, "req_close", req);
1170
+ } else {
1171
+ __privateMethod(this, _ServerNetworkMiddleware_instances, LogSillyMessage_fn).call(this, chalk.magenta(`Request close event: Could not find socket within recordset`));
1172
+ }
1173
+ });
1174
+ const inHeadersLength = JSON.stringify(req.headers).length;
1175
+ const inContentLength = __privateGet(this, _GetRequestContentSize).call(this, req);
1176
+ const inTotal = inHeadersLength + inContentLength;
1177
+ __privateMethod(this, _ServerNetworkMiddleware_instances, LogSillyMessage_fn).call(this, chalk.white.bgGray(`inHeadersLength: [${inHeadersLength}], inContentLength: [${inContentLength}], inTotal: [${inTotal}]`));
1178
+ this.UpdateNetworkStats(workingSocketRecord, "middleware", req);
1179
+ next();
1180
+ });
1181
+ }
1182
+ on(eventName, callBackFn) {
1183
+ __privateGet(this, _tinyEmitter).on(eventName, callBackFn);
1184
+ }
1185
+ }
1186
+ _tinyEmitter = new WeakMap();
1187
+ _socketCollection = new WeakMap();
1188
+ _id = new WeakMap();
1189
+ _ServerNetworkMiddleware_instances = new WeakSet();
1190
+ LogSillyMessage_fn = function(message) {
1191
+ var _a;
1192
+ (_a = this.options) == null ? void 0 : _a.logger.silly(message);
1193
+ };
1194
+ LogErrorMessage_fn2 = function(message) {
1195
+ var _a;
1196
+ (_a = this.options) == null ? void 0 : _a.logger.error(message);
1197
+ };
1198
+ _GetRequestContentSize = new WeakMap();
1199
+ class STSExpressServer {
1200
+ constructor(options, stsApp) {
1201
+ __privateAdd(this, _app);
1202
+ var _a;
1203
+ const requestLoggerMiddleware = new RequestLoggerMiddleware({
1204
+ ignoresocketio: goptions.ignoresocketio
1205
+ });
1206
+ const serverNetworkMiddleware = new ServerNetworkMiddleware({
1207
+ name: stsApp.options.serviceName,
1208
+ outputDebug: false,
1209
+ logger: (_a = stsApp.options) == null ? void 0 : _a.logger
1210
+ });
1211
+ serverNetworkMiddleware.on(ServerNetworkMiddlewareEventName.UpdateInstrument_SERVER_NET_VAL, (data) => {
1212
+ stsApp.UpdateInstrument(Gauge.NETWORK_RX_GAUGE, {
1213
+ Inc: data.requestBytesRead
1214
+ });
1215
+ stsApp.UpdateInstrument(Gauge.NETWORK_TX_GAUGE, {
1216
+ Inc: data.requestBytesWritten
1217
+ });
1218
+ });
1219
+ requestLoggerMiddleware.on(RequestLoggerMiddlewareEventName.UpdateInstrument_AR_INC, () => {
1220
+ stsApp.UpdateInstrument(Gauge.ACTIVE_REQUEST_GAUGE, {
1221
+ Inc: 1
1222
+ });
1223
+ });
1224
+ requestLoggerMiddleware.on(RequestLoggerMiddlewareEventName.UpdateInstrument_AR_DEC, () => {
1225
+ stsApp.UpdateInstrument(Gauge.ACTIVE_REQUEST_GAUGE, {
1226
+ Dec: 1
1227
+ });
1228
+ });
1229
+ requestLoggerMiddleware.on(RequestLoggerMiddlewareEventName.UpdateInstrument_DH_VAL, (timeInMs) => {
1230
+ stsApp.UpdateInstrument(Gauge.DURATION_HISTOGRAM_GAUGE, {
1231
+ val: timeInMs
1232
+ });
1233
+ });
1234
+ requestLoggerMiddleware.on(RequestLoggerMiddlewareEventName.UpdateInstrument_D_VAL, (timeInMs) => {
1235
+ stsApp.UpdateInstrument(Gauge.DURATION_GAUGE, {
1236
+ val: timeInMs
1237
+ });
1238
+ });
1239
+ requestLoggerMiddleware.on(RequestLoggerMiddlewareEventName.UpdateInstrument_RC_INC, () => {
1240
+ stsApp.UpdateInstrument(Gauge.REQUEST_COUNT_GAUGE, {
1241
+ Inc: 1
1242
+ });
1243
+ });
1244
+ requestLoggerMiddleware.on(RequestLoggerMiddlewareEventName.UpdateInstrument_V_INC, () => {
1245
+ if (stsApp.InstrumentExists(Gauge.VELOCITY_GAUGE)) {
1246
+ stsApp.UpdateInstrument(Gauge.VELOCITY_GAUGE, {
1247
+ Inc: 1
1248
+ });
1249
+ }
1250
+ });
1251
+ const app = express();
1252
+ __privateSet(this, _app, app);
1253
+ const corsConfig = {
1254
+ credentials: true,
1255
+ origin: true
1256
+ };
1257
+ app.use(cors(corsConfig));
1258
+ app.use(cookieParser());
1259
+ app.use(express.urlencoded({ extended: false, limit: goptions.maxPayloadSize }));
1260
+ app.use(express.json({ limit: goptions.maxPayloadSize }));
1261
+ if (options.expressServerRouteStaticFactory) {
1262
+ options.expressServerRouteStaticFactory(app, stsApp);
1263
+ }
1264
+ app.use(requestLoggerMiddleware.Middleware.bind(requestLoggerMiddleware));
1265
+ app.use(serverNetworkMiddleware.Middleware.bind(serverNetworkMiddleware));
1266
+ if (options.expressServerRouteFactory) {
1267
+ options.expressServerRouteFactory(app, stsApp);
1268
+ }
1269
+ app.use(function(err, req, res, next) {
1270
+ if (err) {
1271
+ res.status(err.status).send(err);
1272
+ } else {
1273
+ next();
1274
+ }
1275
+ });
1276
+ }
1277
+ get App() {
1278
+ return __privateGet(this, _app);
1279
+ }
1280
+ }
1281
+ _app = new WeakMap();
1282
+ class ServerProcessBase extends ProcessBase {
1283
+ constructor(options) {
1284
+ super(options);
1285
+ __privateAdd(this, _masterProcessExitTime2, goptions.masterProcessExitTime);
1286
+ __privateAdd(this, _io, null);
1287
+ __privateAdd(this, _redisClient, null);
1288
+ __privateAdd(this, _httpServer2, null);
1289
+ __privateAdd(this, _expressServer, null);
1290
+ __privateAdd(this, _sockets, []);
1291
+ __privateAdd(this, _shuttingDown2, false);
1292
+ // Setup server to Prometheus scrapes:
1293
+ __privateAdd(this, _SetupPrometheusEndPoints, (expressServer) => {
1294
+ new AggregatorRegistry();
1295
+ const prefix = "sts_";
1296
+ collectDefaultMetrics({
1297
+ labels: { NODE_APP_INSTANCE: process.pid },
1298
+ prefix
1299
+ });
1300
+ const c = new Counter({
1301
+ name: "sts_test_counter",
1302
+ help: "Example of a counter",
1303
+ labelNames: ["code"]
1304
+ });
1305
+ setInterval(() => {
1306
+ c.inc({ code: 200 });
1307
+ }, 1e3).unref();
1308
+ setInterval(() => {
1309
+ c.inc({ code: 400 });
1310
+ c.inc({ code: "worker_" + process.pid });
1311
+ }, 500).unref();
1312
+ expressServer.get("/metrics", async (req, res) => {
1313
+ try {
1314
+ res.set("Content-Type", register.contentType);
1315
+ res.end(await register.metrics());
1316
+ } catch (ex) {
1317
+ res.status(500).end(ex);
1318
+ }
1319
+ });
1320
+ expressServer.get("/metrics/counter", async (req, res) => {
1321
+ try {
1322
+ res.set("Content-Type", register.contentType);
1323
+ res.end(await register.getSingleMetricAsString("test_counter"));
1324
+ } catch (ex) {
1325
+ res.status(500).end(ex);
1326
+ }
1327
+ });
1328
+ });
1329
+ __privateAdd(this, _SetupTLSServer, async (socket) => {
1330
+ this.LogInfoMessage("CONNECTED: " + socket.remoteAddress + ":" + socket.remotePort + " " + process.pid);
1331
+ __privateGet(this, _sockets).push(socket);
1332
+ socket.on("close", (data) => {
1333
+ const index = __privateGet(this, _sockets).findIndex(function(o) {
1334
+ return o.remoteAddress === socket.remoteAddress && o.remotePort === socket.remotePort;
1335
+ });
1336
+ if (index !== -1) __privateGet(this, _sockets).splice(index, 1);
1337
+ this.LogInfoMessage("CLOSED: " + socket.remoteAddress + " " + socket.remotePort + " " + process.pid);
1338
+ });
1339
+ socket.on("data", (data) => {
1340
+ this.LogInfoMessage("DATA " + socket.remoteAddress + ": " + socket.remotePort + ": " + data);
1341
+ socket.write(socket.remoteAddress + ":" + socket.remotePort + " said " + data + "\n");
1342
+ });
1343
+ });
1344
+ __privateAdd(this, _SetupRPCServer, async (socket) => {
1345
+ this.LogInfoMessage("CONNECTED: " + socket.remoteAddress + ":" + socket.remotePort + " " + process.pid);
1346
+ socket.on("close", (data) => {
1347
+ this.LogInfoMessage("CLOSED: " + socket.remoteAddress + " " + socket.remotePort + " " + process.pid);
1348
+ });
1349
+ socket.on("data", (data) => {
1350
+ this.LogInfoMessage("DATA " + socket.remoteAddress + ": " + data);
1351
+ });
1352
+ });
1353
+ __privateAdd(this, _SetupWSSServer, async () => {
1354
+ const options = {
1355
+ transports: ["websocket"]
1356
+ // or [ "websocket", "polling" ] (to use long-poolling. Note that the order matters)
1357
+ // The default path is /socket.io
1358
+ // This can be changed with the path option as shown below
1359
+ //,path: '/zzz'
1360
+ };
1361
+ __privateSet(this, _io, new Server(__privateGet(this, _httpServer2), options));
1362
+ if (this.options.useSocketIoRedisAdaptor) {
1363
+ this.LogInfoMessage(`Using Redis for socket.io cluster management (worker)`);
1364
+ if (this.options.socketIoRedisAdaptorUrl) {
1365
+ this.LogInfoMessage(`Redis url: [${this.options.socketIoRedisAdaptorUrl}]`);
1366
+ __privateSet(this, _redisClient, createClient({ url: this.options.socketIoRedisAdaptorUrl }));
1367
+ } else {
1368
+ this.LogInfoMessage(`Redis url: [localhost]`);
1369
+ __privateSet(this, _redisClient, createClient());
1370
+ }
1371
+ await __privateGet(this, _redisClient).connect();
1372
+ __privateGet(this, _io).adapter(createAdapter(__privateGet(this, _redisClient)));
1373
+ this.LogInfoMessage(`Redis successfully connected.`);
1374
+ } else {
1375
+ if (this.options.clusterMode) {
1376
+ __privateGet(this, _io).adapter(createAdapter$1());
1377
+ this.LogInfoMessage(`Using nodejs cluster mode for socket.io cluster management`);
1378
+ } else {
1379
+ this.LogInfoMessage(`Not using any adaptors for socket.io cluster management.}`);
1380
+ }
1381
+ }
1382
+ __privateGet(this, _io).engine.on("connection_error", (err) => {
1383
+ this.LogInfoMessage(err.req);
1384
+ this.LogInfoMessage(err.code);
1385
+ this.LogInfoMessage(err.message);
1386
+ this.LogInfoMessage(err.context);
1387
+ });
1388
+ });
1389
+ __privateAdd(this, _GetTLSOptions, () => {
1390
+ return {
1391
+ key: fs.readFileSync(this.options.httpsServerKeyPath),
1392
+ cert: fs.readFileSync(this.options.httpsServerCertificatePath)
1393
+ };
1394
+ });
1395
+ __privateAdd(this, _SetupExpressServer, async (useTls) => {
1396
+ if (useTls) {
1397
+ __privateSet(this, _httpServer2, createServer$1(__privateGet(this, _GetTLSOptions).call(this), __privateGet(this, _expressServer).App));
1398
+ } else {
1399
+ __privateSet(this, _httpServer2, createServer(__privateGet(this, _expressServer).App));
1400
+ }
1401
+ if (this.options.prometheusSupport === true) {
1402
+ __privateGet(this, _SetupPrometheusEndPoints).call(this, __privateGet(this, _expressServer).App);
1403
+ }
1404
+ if (this.options.wssServer === true) {
1405
+ await __privateGet(this, _SetupWSSServer).call(this);
1406
+ }
1407
+ __privateGet(this, _httpServer2).listen(this.options.listenPort, () => {
1408
+ }).on("listening", () => {
1409
+ this.LogInfoMessage(`live on ${this.options.endpoint}:${this.options.listenPort}${this.options.apiRoot}`);
1410
+ });
1411
+ });
1412
+ __privateAdd(this, _SetupTCPRawServer, async () => {
1413
+ __privateSet(this, _httpServer2, tls.createServer(__privateGet(this, _GetTLSOptions).call(this), __privateGet(this, _SetupTLSServer)));
1414
+ __privateGet(this, _httpServer2).listen(this.options.listenPort, "stscore.stsmda.org", () => {
1415
+ this.LogInfoMessage("TCP Server is running on port " + this.options.listenPort + ".");
1416
+ }).on("listening", () => {
1417
+ this.LogInfoMessage(`TCP live on ${this.options.endpoint}:${this.options.listenPort}${this.options.apiRoot}`);
1418
+ });
1419
+ });
1420
+ __privateAdd(this, _SetupJSONRPCServer, async () => {
1421
+ const jaysonServer = new jayson.server();
1422
+ jaysonServer.method("add", function(args, callback) {
1423
+ callback(null, args[0] + args[1]);
1424
+ });
1425
+ __privateSet(this, _httpServer2, jaysonServer.tls(__privateGet(this, _GetTLSOptions).call(this)));
1426
+ __privateGet(this, _httpServer2).on("secureConnection", __privateGet(this, _SetupRPCServer));
1427
+ __privateGet(this, _httpServer2).listen(this.options.listenPort, "stscore.stsmda.org", () => {
1428
+ this.LogInfoMessage("JSON RPC 2.0 Server is running on port " + this.options.listenPort + ".");
1429
+ }).on("listening", () => {
1430
+ this.LogInfoMessage(`JSON RPC 2.0 live on ${this.options.endpoint}:${this.options.listenPort}${this.options.apiRoot}`);
1431
+ });
1432
+ });
1433
+ __publicField(this, "TerminateSocketIO", async () => {
1434
+ var _a;
1435
+ if (this.options.wssServer === true && __privateGet(this, _io) !== null) {
1436
+ const logPrefix = `ServerProcessBase:TerminateSockets():${process.pid}:`;
1437
+ this.LogInfoMessage(`${logPrefix} Disconnect SocketIO Sockets.`);
1438
+ await Sleep(250);
1439
+ await ((_a = __privateGet(this, _io)) == null ? void 0 : _a.of("/").adapter.close());
1440
+ if (this.socketIoServerHelper !== null) {
1441
+ await this.socketIoServerHelper.CloseAdaptors();
1442
+ await Sleep(50);
1443
+ if (__privateGet(this, _redisClient)) {
1444
+ __privateGet(this, _redisClient).disconnect();
1445
+ await Sleep(50);
1446
+ }
1447
+ this.LogInfoMessage(`${logPrefix} this.socketIoServerHelper.DisconnectSockets()`);
1448
+ await this.socketIoServerHelper.DisconnectSockets();
1449
+ } else {
1450
+ this.LogInfoMessage(`${logPrefix} this.#io.disconnectSockets()`);
1451
+ if (__privateGet(this, _redisClient)) {
1452
+ __privateGet(this, _redisClient).disconnect();
1453
+ await Sleep(50);
1454
+ }
1455
+ __privateGet(this, _io).disconnectSockets();
1456
+ }
1457
+ this.socketIoServerHelper = null;
1458
+ __privateSet(this, _io, null);
1459
+ }
1460
+ });
1461
+ __publicField(this, "TerminateHTTPServer", async () => {
1462
+ const logPrefix = `ServerProcessBase:TerminateHTTPServer():${process.pid}:`;
1463
+ if (__privateGet(this, _httpServer2) !== null) {
1464
+ if (goptions.STSServerType.localeCompare("TCPRAW_TLS") === 0) {
1465
+ __privateGet(this, _sockets).forEach((socket, index, array) => {
1466
+ this.LogInfoMessage(chalk.yellow(`${logPrefix} TCP Socket destroy, remote address: [${socket.remoteAddress}], remote port: [${socket.remotePort}]`));
1467
+ socket.destroy();
1468
+ });
1469
+ }
1470
+ this.LogInfoMessage(`${logPrefix} Closing httpServer.`);
1471
+ await __privateGet(this, _httpServer2).close();
1472
+ __privateSet(this, _httpServer2, null);
1473
+ }
1474
+ });
1475
+ // Terminate in order;
1476
+ // forked worker threads (send signal)
1477
+ // De-Register service
1478
+ // systeminformation observers
1479
+ // instrument timers (gauge etc.)
1480
+ // publisher
1481
+ // terminate UI (if loaded)
1482
+ __publicField(this, "Terminate", async (clusterPerformExit, signal) => {
1483
+ const logPrefix = `ServerProcessBase:Terminate():${process.pid}:`;
1484
+ if (__privateGet(this, _shuttingDown2) === false) {
1485
+ __privateSet(this, _shuttingDown2, true);
1486
+ if (signal) {
1487
+ this.LogInfoMessage(this.GetSignalColour(signal)(`${logPrefix} Received signal: ${signal}`));
1488
+ } else {
1489
+ this.LogInfoMessage(this.GetSignalColour(null)(`${logPrefix} Received Terminate without signal.`));
1490
+ }
1491
+ await this.ProcessTerminate();
1492
+ this.TerminateUIController();
1493
+ await this.TerminateSocketIO();
1494
+ await this.TerminateHTTPServer();
1495
+ await this.TerminateDatabase();
1496
+ if (this.options.clusterMode) {
1497
+ this.LogInfoMessage(`${logPrefix} clusterPerformExit value: [${clusterPerformExit}]`);
1498
+ if (clusterPerformExit) {
1499
+ this.LogInfoMessage(`${logPrefix} Process will self terminate with process.exit(0).`);
1500
+ } else {
1501
+ this.LogInfoMessage(`${logPrefix} Child process will not self terminate. Terminate will be handled by master process.`);
1502
+ }
1503
+ }
1504
+ this.TerminateInstrumentController();
1505
+ await Sleep(1e3);
1506
+ if (this.options.clusterMode === true) {
1507
+ if (clusterPerformExit === true) {
1508
+ setTimeout(() => {
1509
+ process.exit(0);
1510
+ }, 0);
1511
+ }
1512
+ } else {
1513
+ this.ProcessExit(__privateGet(this, _masterProcessExitTime2));
1514
+ }
1515
+ } else {
1516
+ this.LogInfoMessage(`${logPrefix} Process already terminating.`);
1517
+ }
1518
+ });
1519
+ __publicField(this, "SetupSTSServer", async () => {
1520
+ switch (goptions.STSServerType) {
1521
+ case "EXPRESS":
1522
+ await __privateGet(this, _SetupExpressServer).call(this, false);
1523
+ break;
1524
+ case "EXPRESS_TLS":
1525
+ await __privateGet(this, _SetupExpressServer).call(this, true);
1526
+ break;
1527
+ case "TCPRAW_TLS":
1528
+ await __privateGet(this, _SetupTCPRawServer).call(this);
1529
+ break;
1530
+ case "JSONRPC2_TLS":
1531
+ await __privateGet(this, _SetupJSONRPCServer).call(this);
1532
+ break;
1533
+ }
1534
+ });
1535
+ }
1536
+ get httpServer() {
1537
+ return __privateGet(this, _httpServer2);
1538
+ }
1539
+ get io() {
1540
+ return __privateGet(this, _io);
1541
+ }
1542
+ get expressServer() {
1543
+ return __privateGet(this, _expressServer);
1544
+ }
1545
+ set expressServer(val) {
1546
+ __privateSet(this, _expressServer, val);
1547
+ }
1548
+ get shuttingDown() {
1549
+ return __privateGet(this, _shuttingDown2);
1550
+ }
1551
+ async SetupServer() {
1552
+ return new Promise((resolve, reject) => {
1553
+ try {
1554
+ this.SetupInstrumentation();
1555
+ setTimeout(async () => {
1556
+ try {
1557
+ await this.SetupServerEx();
1558
+ resolve(true);
1559
+ } catch (error) {
1560
+ reject(error);
1561
+ }
1562
+ }, 100);
1563
+ } catch (error) {
1564
+ reject(error);
1565
+ }
1566
+ });
1567
+ }
1568
+ ProcessStarted() {
1569
+ const transport = new STSTransportLoggerWinston({
1570
+ stsApp: this
1571
+ });
1572
+ setTimeout(() => {
1573
+ this.options.logger.add(transport);
1574
+ }, 0);
1575
+ }
1576
+ async SetupServerEx() {
1577
+ this.LogInfoMessage(chalk.green(`ServerProcessBase:SetupServerEx(): Main Process:${process.pid} Starting ...`));
1578
+ this.ProcessStartup();
1579
+ if (this.options.expressServerRouteFactory || this.options.expressServerRouteStaticFactory) {
1580
+ this.expressServer = new STSExpressServer(this.options, this);
1581
+ }
1582
+ this.LogInfoMessage(`ServerProcessBase:SetupServerEx(): Worker instance starting. Service instance Id: [${this.options.serviceInstanceId}]`);
1583
+ process.on("SIGTERM", async () => {
1584
+ this.LogInfoMessage(`ServerProcessBase:SetupServerEx(): SIGTERM signal received for worker: ${process.pid}`);
1585
+ await this.Terminate(true, true);
1586
+ });
1587
+ process.on("SIGINT", async () => {
1588
+ this.LogInfoMessage(`ServerProcessBase:SetupServerEx(): SIGINT signal received for worker: ${process.pid}`);
1589
+ await this.Terminate(true, true);
1590
+ });
1591
+ process.on("exit", (code) => {
1592
+ if (code === 0) {
1593
+ this.LogInfoMessage(chalk.green(`ServerProcessBase:SetupServerEx(): Process: ${process.pid} terminated gracefully with code: ${code}`));
1594
+ } else {
1595
+ this.LogInfoMessage(chalk.red(`ServerProcessBase:SetupServerEx(): Process: ${process.pid} terminated with code: ${code}`));
1596
+ }
1597
+ });
1598
+ await this.SetupSTSServer();
1599
+ this.ProcessStarted();
1600
+ this.LogInfoMessage(chalk.green(`ServerProcessBase:SetupServerEx(): Main Process:${process.pid} Started`));
1601
+ return true;
1602
+ }
1603
+ }
1604
+ _masterProcessExitTime2 = new WeakMap();
1605
+ _io = new WeakMap();
1606
+ _redisClient = new WeakMap();
1607
+ _httpServer2 = new WeakMap();
1608
+ _expressServer = new WeakMap();
1609
+ _sockets = new WeakMap();
1610
+ _shuttingDown2 = new WeakMap();
1611
+ _SetupPrometheusEndPoints = new WeakMap();
1612
+ _SetupTLSServer = new WeakMap();
1613
+ _SetupRPCServer = new WeakMap();
1614
+ _SetupWSSServer = new WeakMap();
1615
+ _GetTLSOptions = new WeakMap();
1616
+ _SetupExpressServer = new WeakMap();
1617
+ _SetupTCPRawServer = new WeakMap();
1618
+ _SetupJSONRPCServer = new WeakMap();
1619
+ class SingleProcessBase extends ServerProcessBase {
1620
+ /**
1621
+ *
1622
+ * @param {SingleProcessBaseOptions} options
1623
+ */
1624
+ constructor(options) {
1625
+ super(options);
1626
+ __publicField(this, "SetupServerEx", async () => {
1627
+ await super.SetupServerEx();
1628
+ this.LogSystemTelemetry();
1629
+ return true;
1630
+ });
1631
+ }
1632
+ CollectAdditionalTelemetry() {
1633
+ const siValueObject = {
1634
+ currentLoad: "currentLoad"
1635
+ };
1636
+ si.get(siValueObject).then((data) => {
1637
+ this.UpdateInstrument(Gauge.CPU_SYSTEM_LOAD_GAUGE, {
1638
+ val: data.currentLoad.currentLoad
1639
+ });
1640
+ });
1641
+ }
1642
+ GetAdditionalInstruments() {
1643
+ return [
1644
+ [Gauge.CPU_SYSTEM_LOAD_GAUGE, GaugeTypes.INSTRUMENT_GAUGE, {
1645
+ interval: goptions.instrumentationObservationInterval,
1646
+ sampleSize: goptions.instrumentationTimeWindow
1647
+ }]
1648
+ ];
1649
+ }
1650
+ /**
1651
+ * UIController (instance of UIController) to manage a console based user interface associated for this node application.
1652
+ * @returns UIController instance to manage a console based user interface associated for this node application. Null for no capability.
1653
+ */
1654
+ GetUIController() {
1655
+ return null;
1656
+ }
1657
+ async TerminateApplication() {
1658
+ await this.Terminate(false, "SIGINT");
1659
+ }
1660
+ }
1661
+ class WorkerProcessBase extends ServerProcessBase {
1662
+ constructor(options) {
1663
+ super(options);
1664
+ __privateAdd(this, _inFlightMessage, {});
1665
+ __privateAdd(this, _requestResponseMessageTimeout, 5e3);
1666
+ //@@ config
1667
+ __privateAdd(this, _pingTimeout, null);
1668
+ __privateAdd(this, _SendMessageToParentProcess, (message) => {
1669
+ return new Promise((resolve, reject) => {
1670
+ if (__privateGet(this, _inFlightMessage)[message.id]) {
1671
+ reject(`Message with id: [${message.id}] already exists within the Request/Response record structure`);
1672
+ } else {
1673
+ __privateGet(this, _inFlightMessage)[message.id] = {
1674
+ iPCMessagePayload: { ...message },
1675
+ cb: () => {
1676
+ const detail = __privateGet(this, _inFlightMessage)[message.id].iPCMessagePayload.responseDetail;
1677
+ clearTimeout(__privateGet(this, _inFlightMessage)[message.id].timeout);
1678
+ setTimeout(() => {
1679
+ delete __privateGet(this, _inFlightMessage)[message.id];
1680
+ }, 0).unref();
1681
+ resolve(detail);
1682
+ },
1683
+ timeout: setTimeout(() => {
1684
+ setTimeout(() => {
1685
+ delete __privateGet(this, _inFlightMessage)[message.id];
1686
+ }, 0).unref();
1687
+ reject("Did not receive response form parent process.");
1688
+ }, __privateGet(this, _requestResponseMessageTimeout))
1689
+ // max message timeout allowed
1690
+ };
1691
+ process.send(message);
1692
+ }
1693
+ });
1694
+ });
1695
+ __publicField(this, "AddWorker", async (options) => {
1696
+ const workerResponse = await __privateGet(this, _SendMessageToParentProcess).call(this, {
1697
+ requestResponse: true,
1698
+ id: v4(),
1699
+ command: IPCMessageCommand.AddWorker,
1700
+ requestDetail: {
1701
+ options
1702
+ }
1703
+ });
1704
+ return workerResponse.workerId;
1705
+ });
1706
+ __publicField(this, "DeleteWorker", async (workerId, options) => {
1707
+ const workerResponse = await __privateGet(this, _SendMessageToParentProcess).call(this, {
1708
+ requestResponse: true,
1709
+ id: v4(),
1710
+ command: IPCMessageCommand.DeleteWorker,
1711
+ requestDetail: {
1712
+ options,
1713
+ workerId
1714
+ }
1715
+ });
1716
+ return workerResponse;
1717
+ });
1718
+ __publicField(this, "GetMasterProcessOptions", async () => {
1719
+ const parentResponse = await __privateGet(this, _SendMessageToParentProcess).call(this, {
1720
+ requestResponse: true,
1721
+ id: v4(),
1722
+ command: IPCMessageCommand.GetConfig,
1723
+ requestDetail: {}
1724
+ });
1725
+ return parentResponse;
1726
+ });
1727
+ __publicField(this, "GetNumCPUs", async () => {
1728
+ const valueObject = {
1729
+ cpu: "*"
1730
+ };
1731
+ const sysinfo = await si.get(valueObject);
1732
+ let numCPUs = 2;
1733
+ if (goptions.useCPUs > 0) {
1734
+ if (goptions.useCPUs >= 1) {
1735
+ numCPUs = goptions.useCPUs;
1736
+ } else {
1737
+ numCPUs = Math.round(sysinfo.cpu.cores * goptions.useCPUs);
1738
+ }
1739
+ } else {
1740
+ numCPUs = sysinfo.cpu.physicalCores;
1741
+ }
1742
+ return numCPUs;
1743
+ });
1744
+ __publicField(this, "GetSystemTelemetry", async () => {
1745
+ const valueObject = {
1746
+ system: "*",
1747
+ osInfo: "*",
1748
+ cpu: "*",
1749
+ mem: "*",
1750
+ dockerInfo: "*",
1751
+ //dockerImages: '*',
1752
+ dockerContainers: "*"
1753
+ };
1754
+ const sysinfo = await si.get(valueObject);
1755
+ const numCPUs = await this.GetNumCPUs();
1756
+ const hostname = sysinfo.osInfo.hostname;
1757
+ const hostaddr = GetFirstNetworkInterface();
1758
+ const promArray = [];
1759
+ sysinfo.dockerContainers.forEach((dc) => {
1760
+ const dcs = promArray.push(si.dockerContainerStats(dc.id));
1761
+ console.log(dcs);
1762
+ });
1763
+ const dockerContainerStats = await Promise.all(promArray);
1764
+ const sysInfo = {
1765
+ serviceInstanceId: this.options.serviceInstanceId,
1766
+ serviceProcessContext: this.options.serviceProcessContext,
1767
+ hostname,
1768
+ numCPUs,
1769
+ hostaddr,
1770
+ system: sysinfo.system,
1771
+ osInfo: sysinfo.osInfo,
1772
+ cpu: sysinfo.cpu,
1773
+ mem: sysinfo.mem,
1774
+ dockerInfo: sysinfo.dockerInfo,
1775
+ dockerContainers: sysinfo.dockerContainers,
1776
+ dockerContainerStats
1777
+ };
1778
+ return sysInfo;
1779
+ });
1780
+ __publicField(this, "SetupServerEx", async () => {
1781
+ await super.SetupServerEx();
1782
+ process.on("message", async (msg) => {
1783
+ if (msg.requestResponse) {
1784
+ const iPCMessagePayload = msg;
1785
+ if (iPCMessagePayload.id) {
1786
+ if (__privateGet(this, _inFlightMessage)[iPCMessagePayload.id]) {
1787
+ const responseMessage = __privateGet(this, _inFlightMessage)[iPCMessagePayload.id];
1788
+ responseMessage.iPCMessagePayload.responseDetail = { ...iPCMessagePayload.responseDetail };
1789
+ responseMessage.cb();
1790
+ } else {
1791
+ throw new Error(`Could not find Request/Response message with id: [${iPCMessagePayload.id}]`);
1792
+ }
1793
+ } else {
1794
+ throw new Error(`Message does not have id attribute. [${JSON.stringify(iPCMessagePayload)}]`);
1795
+ }
1796
+ return;
1797
+ }
1798
+ if (msg.command) {
1799
+ switch (msg.command) {
1800
+ case "Terminate":
1801
+ this.LogInfoMessage(chalk.grey(`Received ` + chalk.bold.italic(`Terminate`) + ` message from master thread`));
1802
+ await this.Terminate(true, false);
1803
+ break;
1804
+ case "TerminateAndKill":
1805
+ this.LogInfoMessage(chalk.grey(`Received ` + chalk.bold.italic(`Terminate`) + ` message from master thread`));
1806
+ await this.Terminate(true, true);
1807
+ break;
1808
+ case "Message":
1809
+ this.ReceivedMessageFromMaster(msg.data);
1810
+ break;
1811
+ }
1812
+ }
1813
+ });
1814
+ return true;
1815
+ });
1816
+ }
1817
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1818
+ ReceivedMessageFromMaster(msg) {
1819
+ }
1820
+ CollectAdditionalTelemetry() {
1821
+ this.httpServer.getConnections((error, count) => {
1822
+ this.UpdateInstrument(Gauge.CONNECTION_COUNT_GAUGE, {
1823
+ val: count
1824
+ });
1825
+ });
1826
+ }
1827
+ ProcessTerminate() {
1828
+ if (__privateGet(this, _pingTimeout)) {
1829
+ clearTimeout(__privateGet(this, _pingTimeout));
1830
+ }
1831
+ return super.ProcessTerminate();
1832
+ }
1833
+ }
1834
+ _inFlightMessage = new WeakMap();
1835
+ _requestResponseMessageTimeout = new WeakMap();
1836
+ _pingTimeout = new WeakMap();
1837
+ _SendMessageToParentProcess = new WeakMap();
1838
+ class STSControllerBase {
1839
+ constructor(stsApp) {
1840
+ __privateAdd(this, _stsApp);
1841
+ __privateSet(this, _stsApp, stsApp);
1842
+ }
1843
+ get stsApp() {
1844
+ return __privateGet(this, _stsApp);
1845
+ }
1846
+ }
1847
+ _stsApp = new WeakMap();
1848
+ class STSLatencyController extends STSControllerBase {
1849
+ constructor(stsApp) {
1850
+ super(stsApp);
1851
+ }
1852
+ // curl http://localhost:3000/api/v1/latency/latency
1853
+ async stslatency(req, res) {
1854
+ try {
1855
+ const retVal = {
1856
+ data: `Ping Completed At: ${Date.now()}`,
1857
+ pid: process.pid,
1858
+ ppid: process.ppid
1859
+ };
1860
+ return res.status(StatusCodes.OK).send(retVal);
1861
+ } catch (error) {
1862
+ this.stsApp.LogErrorMessage(error);
1863
+ return res.status(StatusCodes.INTERNAL_SERVER_ERROR).send({ status: StatusCodes.INTERNAL_SERVER_ERROR, error: "Operation was not successful", detail: error });
1864
+ }
1865
+ }
1866
+ }
1867
+ class STSRouterBase {
1868
+ constructor(stsApp) {
1869
+ __privateAdd(this, _router);
1870
+ __privateAdd(this, _stsApp2);
1871
+ __privateSet(this, _stsApp2, stsApp);
1872
+ __privateSet(this, _router, Router());
1873
+ }
1874
+ get router() {
1875
+ return __privateGet(this, _router);
1876
+ }
1877
+ get stsApp() {
1878
+ return __privateGet(this, _stsApp2);
1879
+ }
1880
+ }
1881
+ _router = new WeakMap();
1882
+ _stsApp2 = new WeakMap();
1883
+ class STSLatencyRoute extends STSRouterBase {
1884
+ constructor(stsApp) {
1885
+ super(stsApp);
1886
+ const latencyController = new STSLatencyController(stsApp);
1887
+ const { stslatency } = latencyController;
1888
+ this.router.get("/latency", stslatency.bind(latencyController));
1889
+ }
1890
+ }
1891
+ class PublishTransportUtils {
1892
+ static GetServiceContext(nid) {
1893
+ if (nid === ModelDelimeter.ROOT) {
1894
+ return { root: ModelDelimeter.ROOT };
1895
+ }
1896
+ const context = { nid };
1897
+ const idsplit = nid.split(ModelDelimeter.SEPERATOR);
1898
+ const serviceId = idsplit[0];
1899
+ const serviceInstanceId = idsplit[1].split(ModelDelimeter.NID_SEPERATOR)[0];
1900
+ const serviceInstanceProcessId = idsplit[1].split(ModelDelimeter.NID_SEPERATOR)[1];
1901
+ const serviceIdSplit = serviceId.split(ModelDelimeter.COMPONENT_SEPERATOR);
1902
+ const serviceName = serviceIdSplit[0];
1903
+ const serviceVersion = serviceIdSplit[1];
1904
+ context.serviceId = serviceId;
1905
+ if (typeof serviceInstanceId != "undefined") {
1906
+ const serviceInstanceIdSplit = serviceInstanceId.split(ModelDelimeter.COMPONENT_SEPERATOR);
1907
+ const sid = serviceInstanceIdSplit[0];
1908
+ const hostName = serviceInstanceIdSplit[1];
1909
+ context.serviceInstanceId = serviceInstanceId;
1910
+ context.sid = sid;
1911
+ context.hostName = hostName;
1912
+ if (typeof serviceInstanceProcessId != "undefined") {
1913
+ const serviceInstanceProcessIdSplit = serviceInstanceProcessId.split(ModelDelimeter.COMPONENT_SEPERATOR);
1914
+ const pid = parseInt(serviceInstanceProcessIdSplit[0]);
1915
+ const ppid = parseInt(serviceInstanceProcessIdSplit[1]);
1916
+ const isMaster = pid === ppid ? true : false;
1917
+ context.serviceInstanceProcessId = serviceInstanceProcessId;
1918
+ context.pid = pid;
1919
+ context.ppid = ppid;
1920
+ context.isMaster = isMaster;
1921
+ context.isWorker = !isMaster;
1922
+ context.serviceName = serviceName;
1923
+ context.serviceVersion = serviceVersion;
1924
+ context.serviceInstanceId = serviceInstanceId;
1925
+ }
1926
+ }
1927
+ return context;
1928
+ }
1929
+ }
1930
+ function UpdateSTSTransportWithDebugger(logger, newDebugger) {
1931
+ const stsTransport = logger.transports.find((transport) => {
1932
+ return transport instanceof STSTransportWinston;
1933
+ });
1934
+ if (stsTransport) {
1935
+ stsTransport.debugger = newDebugger;
1936
+ }
1937
+ }
1938
+ class STSTransportWinston extends Transport {
1939
+ constructor(opts) {
1940
+ super(opts);
1941
+ __privateAdd(this, _options3);
1942
+ __privateSet(this, _options3, opts);
1943
+ }
1944
+ get debugger() {
1945
+ return __privateGet(this, _options3).debugger;
1946
+ }
1947
+ set debugger(newDebugger) {
1948
+ __privateGet(this, _options3).debugger = newDebugger;
1949
+ }
1950
+ log(info, callback) {
1951
+ if (info[Symbol.for("level")] == "debug") {
1952
+ if (__privateGet(this, _options3).debugger) {
1953
+ __privateGet(this, _options3).debugger(info.message);
1954
+ }
1955
+ }
1956
+ this.emit("logged", info);
1957
+ callback();
1958
+ }
1959
+ }
1960
+ _options3 = new WeakMap();
1961
+ export {
1962
+ CreateServiceProcessContext,
1963
+ IPCMessageCommand,
1964
+ MasterProcessBase,
1965
+ ProcessBase,
1966
+ PublishTransportUtils,
1967
+ STSControllerBase,
1968
+ STSLatencyController,
1969
+ STSLatencyRoute,
1970
+ STSRouterBase,
1971
+ STSTransportLoggerWinston,
1972
+ STSTransportWinston,
1973
+ ServerProcessBase,
1974
+ SingleProcessBase,
1975
+ UpdateSTSTransportWithDebugger,
1976
+ WorkerProcessBase,
1977
+ iss
1978
+ };
1979
+ //# sourceMappingURL=stsappframework.mjs.map