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