@nsshunt/stsappframework 2.19.205 → 2.19.206

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 (56) hide show
  1. package/dist/masterprocessbase.js +18 -68
  2. package/dist/masterprocessbase.js.map +1 -1
  3. package/dist/processbase.js +59 -1
  4. package/dist/processbase.js.map +1 -1
  5. package/dist/processoptions.js +9 -0
  6. package/dist/processoptions.js.map +1 -1
  7. package/dist/serverprocessbase.js +342 -0
  8. package/dist/serverprocessbase.js.map +1 -0
  9. package/dist/singleprocessbase.js +13 -220
  10. package/dist/singleprocessbase.js.map +1 -1
  11. package/dist/tcpclient/app.js +21 -0
  12. package/dist/tcpclient/app.js.map +1 -0
  13. package/dist/tcpclient/app2.js +55 -0
  14. package/dist/tcpclient/app2.js.map +1 -0
  15. package/dist/tcpclientserver/app.js +15 -0
  16. package/dist/tcpclientserver/app.js.map +1 -0
  17. package/dist/tcpclientserver/appConfig.js +61 -0
  18. package/dist/tcpclientserver/appConfig.js.map +1 -0
  19. package/dist/workerprocessbase.js +15 -224
  20. package/dist/workerprocessbase.js.map +1 -1
  21. package/package.json +3 -2
  22. package/run.sh +24 -0
  23. package/runc1.sh +24 -0
  24. package/runc2.sh +24 -0
  25. package/src/commonTypes.ts +1 -1
  26. package/src/masterprocessbase.ts +11 -66
  27. package/src/processbase.ts +62 -2
  28. package/src/processoptions.ts +9 -9
  29. package/src/serverprocessbase.ts +390 -0
  30. package/src/singleprocessbase.ts +20 -254
  31. package/src/tcpclient/app.ts +19 -0
  32. package/src/tcpclient/app2.ts +55 -0
  33. package/src/tcpclientserver/app.ts +9 -0
  34. package/src/tcpclientserver/appConfig.ts +66 -0
  35. package/src/workerprocessbase.ts +24 -251
  36. package/types/commonTypes.d.ts +1 -1
  37. package/types/commonTypes.d.ts.map +1 -1
  38. package/types/masterprocessbase.d.ts.map +1 -1
  39. package/types/processbase.d.ts +4 -0
  40. package/types/processbase.d.ts.map +1 -1
  41. package/types/processoptions.d.ts +8 -8
  42. package/types/processoptions.d.ts.map +1 -1
  43. package/types/serverprocessbase.d.ts +21 -0
  44. package/types/serverprocessbase.d.ts.map +1 -0
  45. package/types/singleprocessbase.d.ts +3 -7
  46. package/types/singleprocessbase.d.ts.map +1 -1
  47. package/types/tcpclient/app.d.ts +2 -0
  48. package/types/tcpclient/app.d.ts.map +1 -0
  49. package/types/tcpclient/app2.d.ts +2 -0
  50. package/types/tcpclient/app2.d.ts.map +1 -0
  51. package/types/tcpclientserver/app.d.ts +2 -0
  52. package/types/tcpclientserver/app.d.ts.map +1 -0
  53. package/types/tcpclientserver/appConfig.d.ts +3 -0
  54. package/types/tcpclientserver/appConfig.d.ts.map +1 -0
  55. package/types/workerprocessbase.d.ts +2 -7
  56. package/types/workerprocessbase.d.ts.map +1 -1
@@ -18,7 +18,7 @@ const goptions = $Options()
18
18
 
19
19
  import { Gauge, GaugeTypes, InstrumentGaugeOptions, InstrumentGaugeTelemetry } from '@nsshunt/stsinstrumentation'
20
20
 
21
- import { ProcessOptions } from './processoptions'
21
+ import { ProcessOptions, STSServerType } from './processoptions'
22
22
  import { ProcessBase } from './processbase';
23
23
  import { ISingleProcessBase } from './commonTypes';
24
24
 
@@ -32,9 +32,11 @@ import { createAdapter } from "@socket.io/redis-streams-adapter";
32
32
 
33
33
  import { createClient, RedisClientType } from 'redis';
34
34
 
35
+ import { ServerProcessBase } from './serverprocessbase'
36
+
35
37
  export type EventCb = (socket: any, data: any) => void
36
38
 
37
- export class SingleProcessBase extends ProcessBase implements ISingleProcessBase
39
+ export class SingleProcessBase extends ServerProcessBase implements ISingleProcessBase
38
40
  {
39
41
  #masterProcessExitTime = goptions.masterProcessExitTime;
40
42
  #io: any = null;
@@ -90,18 +92,6 @@ export class SingleProcessBase extends ProcessBase implements ISingleProcessBase
90
92
  return null;
91
93
  }
92
94
 
93
- get io() {
94
- return this.#io;
95
- }
96
-
97
- ProcessTerminating() {
98
- return null;
99
- }
100
-
101
- get expressServer() {
102
- return this.#expressServer;
103
- }
104
-
105
95
  SetupServer(): Promise<boolean>
106
96
  {
107
97
  return new Promise((resolve, reject) => {
@@ -121,16 +111,6 @@ export class SingleProcessBase extends ProcessBase implements ISingleProcessBase
121
111
  })
122
112
  }
123
113
 
124
- /*
125
- SetupServer = async () =>
126
- {
127
- this.SetupInstrumentation();
128
- setTimeout(() => {
129
- this.SetupServerEx();
130
- }, 100);
131
- }
132
- */
133
-
134
114
  SetupServerEx = async () => {
135
115
  this.ProcessStartup();
136
116
 
@@ -138,251 +118,37 @@ export class SingleProcessBase extends ProcessBase implements ISingleProcessBase
138
118
  this.#expressServer = new STSExpressServer(this.options, this);
139
119
  }
140
120
 
141
- const LogEx = this.LogEx;
142
-
143
- /*
144
- if (this.instruments !== null) {
145
- this.instruments[Gauge.LOGGER].consoleLogging = this.options.consoleLogging;
146
- this.instruments[Gauge.LOGGER].instrumentLogging = this.options.instrumentLogging;
147
- }
148
- */
149
-
150
- LogEx(`Service instance starting. Instance Id: [${this.options.serviceInstanceId}]`);
151
- LogEx(`Master process:${process.pid} started`);
152
-
153
- const hostaddr = GetFirstNetworkInterface();
154
- if (hostaddr !== null)
155
- {
156
- LogEx(`Host Address: ${hostaddr}`);
157
- } else {
158
- LogEx(`Unknown Host Address.`);
159
- }
160
-
161
- LogEx(`Server starting with ${numCPUs} Cores/Threads`);
162
-
163
- // https://systeminformation.io/
164
- const valueObject = {
165
- system: '*',
166
- osInfo: '*',
167
- cpu: '*',
168
- mem: '*'
169
- }
170
-
171
- const sysinfo = await si.get(valueObject);
172
- const hostname = sysinfo.osInfo.hostname;
173
-
174
- LogEx(`Hostname: ${hostname}`);
175
- LogEx(`System: ${JSON.stringify(sysinfo.system)}`);
176
- LogEx(`OS Info: ${JSON.stringify(sysinfo.osInfo)}`);
177
- LogEx(`CPU: ${JSON.stringify(sysinfo.cpu)}`);
178
- LogEx(`Memory: ${JSON.stringify(sysinfo.mem)}`);
179
-
180
- const GetSignalColour = (signal: any) =>
181
- {
182
- let msgcolor = null;
183
- if (signal === 'SIGINT')
184
- {
185
- msgcolor = colors.yellow;
186
- } else {
187
- msgcolor = colors.red;
188
- }
189
- return msgcolor;
190
- };
191
-
192
- this.#httpServer = null;
193
-
194
- // Terminate in order;
195
- // forked worker threads (send signal)
196
- // De-Register service
197
- // systeminformation observers
198
- // instrument timers (gauge etc.)
199
- // publisher
200
- // terminate UI (if loaded)
201
- const Terminate = async (signal: any) =>
202
- {
203
- if (this.#shuttingDown === false)
204
- {
205
- this.#shuttingDown = true;
206
-
207
- await this.ProcessTerminate();
208
-
209
- this.ProcessTerminating();
210
-
211
- if (this.GetUIController() !== null)
212
- {
213
- LogEx('Destroy the user interface controller.');
214
- this.GetUIController().DestroyUI();
215
- }
216
-
217
- if (signal) {
218
- LogEx(GetSignalColour(signal)(`Main Process (singleprocess): ${process.pid} received signal: ${signal}`));
219
- } else {
220
- LogEx(GetSignalColour(null)(`Main Process (singleprocess): ${process.pid} received Terminate without signal.`));
221
- }
222
-
223
- LogEx(`De-Registering service.`);
224
- //@@ De-register here ...
225
-
226
- LogEx(`Stopping instruments.`);
227
- //@@StopInstruments(this.instruments);
228
-
229
- if (this.options.wssServer === true && this.#io !== null)
230
- {
231
- LogEx(`Disconnect Sockets.`);
232
- if (this.socketIoHelper !== null) {
233
- this.socketIoHelper.DisconnectSockets();
234
- } else {
235
- this.#io.disconnectSockets();
236
- }
237
- this.socketIoHelper = null;
238
- this.#io = null;
239
- // Note that this.#redisClient.disconnect() is not required becuase DisconnectSockets performs this action.
240
- }
241
-
242
- if (this.options.httpServer === true) {
243
- LogEx(`Closing httpServer.`);
244
- await this.#httpServer.close();
245
- }
246
-
247
- if (this.options.useDatabase) {
248
- LogEx(`Ending database connections and pools.`);
249
- await this.TerminateDatabase();
250
- //await this.accessLayer.enddatabase();
251
- }
252
-
253
- // Now allow some time for the workers to die and send any remaining messages ...
254
- if (this.InstrumentController && this.InstrumentController.Workers.length > 0) {
255
- LogEx(`Ending publisher.`);
256
- setTimeout(() => {
257
- if (this.InstrumentController) {
258
- this.InstrumentController.InstrumentTerminate();
259
- }
260
- }, 100);
261
- }
262
-
263
- await Sleep(1000); // Allow socket.io time to clean-up
264
-
265
- if (this.options.processExitOnTerminate && this.options.processExitOnTerminate === true) {
266
- setTimeout(() => {
267
- LogEx(`Performing process.exit(0).`);
268
- process.exit(0);
269
- }, this.#masterProcessExitTime); // Give the workers time to terminate gracefully
270
- } else {
271
- LogEx(`Performing process.exit(0) - Immediate.`);
272
- }
273
- }
274
- LogEx(`Service instance stopped.`);
275
- }
121
+ this.LogEx(`Service instance starting. Instance Id: [${this.options.serviceInstanceId}]`);
122
+ this.LogEx(`Master process:${process.pid} started`);
276
123
 
277
- this.#Terminate = Terminate;
124
+ this.LogSystemTelemetry();
278
125
 
279
- process.on('SIGINT', async () =>
280
- {
281
- await Terminate('SIGINT');
126
+ process.on('SIGINT', async () => {
127
+ await this.Terminate(false, false, 'SIGINT');
282
128
  });
283
129
 
284
- process.on('SIGTERM', async () =>
285
- {
286
- await Terminate('SIGTERM');
130
+ process.on('SIGTERM', async () => {
131
+ await this.Terminate(false, false, 'SIGTERM');
287
132
  });
288
133
 
289
- process.on('exit', (code) =>
290
- {
291
- if (code === 0)
292
- {
293
- LogEx(`Main Process: ${process.pid} terminated gracefully with code: ${code}`.green);
134
+ process.on('exit', (code) => {
135
+ if (code === 0) {
136
+ this.LogEx(`Main Process: ${process.pid} terminated gracefully with code: ${code}`.green);
294
137
  } else {
295
- LogEx(`Main Process: ${process.pid} terminated with code: ${code}`.red);
138
+ this.LogEx(`Main Process: ${process.pid} terminated with code: ${code}`.red);
296
139
  }
297
140
  });
298
141
 
299
- if (this.options.httpServer === true) {
300
- if (this.options.httpsServer === true) {
301
- const options = {
302
- key: fs.readFileSync(this.options.httpsServerKeyPath),
303
- cert: fs.readFileSync(this.options.httpsServerCertificatePath)
304
- };
305
- this.#httpServer = createServerHttps(options, (this.#expressServer as STSExpressServer).App);
306
- } else {
307
- this.#httpServer = createServer((this.#expressServer as STSExpressServer).App);
308
- }
309
-
310
- //this.#httpServer.maxConnections = 50;
311
-
312
- // Setup the web socket server (using socket.io) if enabled.
313
- if (this.options.wssServer === true) {
314
- // socket.io
315
- // WebSocket
316
- const options: Partial<ServerOptions> = {
317
- transports: [ "websocket" ] // or [ "websocket", "polling" ] (to use long-poolling. Note that the order matters)
318
- // The default path is /socket.io
319
- // This can be changed with the path option as shown below
320
- //,path: '/zzz'
321
- };
322
-
323
- this.#io = new Server(this.#httpServer, options);
324
-
325
- if (this.options.useRedisAdaptor) {
326
- LogEx(`Using Redis for socket.io cluster management (worker)`);
327
- if (this.options.redisAdaptorUrl) {
328
- LogEx(`Redis url: [${this.options.redisAdaptorUrl}]`);
329
- this.#redisClient = createClient({url: this.options.redisAdaptorUrl});
330
- } else {
331
- LogEx(`Redis url: [localhost]`);
332
- this.#redisClient = createClient();
333
- }
334
- await this.#redisClient.connect();
335
- this.#io.adapter(createAdapter(this.#redisClient) as any);
336
- LogEx(`Redis successfully connected.`);
337
- } else {
338
- LogEx(`Not using any adaptors for socket.io cluster management.}`);
339
- }
340
-
341
- // To use a seperate socket server, the code below can be applied.
342
- // this.#io = require("socket.io")(options);
343
- // this.#io.listen(3006);
344
- // LogEx(`socket.io init`);
345
-
346
- this.#io.engine.on("connection_error", (err: any) => {
347
- LogEx(err.req); // the request object
348
- LogEx(err.code); // the error code, for example 1
349
- LogEx(err.message); // the error message, for example "Session ID unknown"
350
- LogEx(err.context); // some additional error context
351
- });
352
- }
353
-
354
- try {
355
- // https://stackoverflow.com/questions/21342828/node-express-unix-domain-socket-permissions
356
- //@@httpServer.listen('/tmp/stsrest01.sock').on('listening', () =>
357
- //@@httpServer.listen('/var/run/sts/stsrest01.sock').on('listening', () =>
358
- this.#httpServer.listen(this.options.listenPort, () => {
359
- //@@chmodSync(listenPort, 511);
360
- }).on('listening', () =>
361
- {
362
- LogEx(`live on ${this.options.endpoint}:${this.options.listenPort}${this.options.apiRoot}`);
363
- });
364
- } catch (error)
365
- {
366
- console.error(error);
367
- throw error;
368
- }
369
-
370
- }
371
-
372
- /*
373
- if (this.publishBroker !== null) {
374
- setTimeout(() => {
375
- this.publishBroker.StartPublish();
376
- }, 0);
377
- }
378
- */
142
+ await this.SetupSTSServer();
379
143
 
380
144
  this.ProcessStarted();
145
+
146
+ this.LogEx(`Main process:${process.pid} started`.green);
381
147
  }
382
148
 
383
- async Terminate()
149
+ async TerminateApplication()
384
150
  {
385
- await this.#Terminate('SIGINT');
151
+ await this.Terminate(false, false, 'SIGINT');
386
152
  this.#Terminate = null;
387
153
  }
388
154
  }
@@ -0,0 +1,19 @@
1
+ import jayson from 'jayson'
2
+ import { JsonWebTokenError } from 'jsonwebtoken';
3
+
4
+ // Read node's tls documentation for more information about these options:
5
+ // https://nodejs.org/api/tls.html#tls_tls_connect_options_callback
6
+ const options: jayson.TcpClientOptions = {
7
+ port: 3003,
8
+ host: 'stscore.stsmda.org'
9
+ };
10
+
11
+ const client = jayson.client.tls(options);
12
+
13
+ // create a client
14
+
15
+ // invoke "add"
16
+ client.request('add', [1, 1], function(err: any, response: any) {
17
+ if(err) throw err;
18
+ console.log(response.result); // 2
19
+ });
@@ -0,0 +1,55 @@
1
+ import tls from 'tls';
2
+ import { Sleep } from '@nsshunt/stsutils'
3
+
4
+ import 'colors'
5
+
6
+ const options = {
7
+ port: 3003,
8
+ host: 'stscore.stsmda.org'
9
+ };
10
+
11
+ const done: boolean[] = [];
12
+
13
+ const dosomework = (socket: any, index: number) => {
14
+ console.log('Connected');
15
+ socket.write("Hello From Client " + JSON.stringify(socket.address()));
16
+ (async () => {
17
+ for (;;) {
18
+ const msg = `${new Date()}: Hello`;
19
+ console.log(`sending: [${msg}]`);
20
+ socket.write(msg);
21
+ await Sleep(1000);
22
+ if (done[index]) {
23
+ break;
24
+ }
25
+ }
26
+ })();
27
+ }
28
+
29
+ for (let i=0; i < 6; i++) {
30
+ const socket1 = tls.connect(options);
31
+ done[i] = false;
32
+ socket1.on('secureConnect', () => {
33
+ dosomework(socket1, i);
34
+ });
35
+ socket1.on('close', function(data: any) {
36
+ console.log(`CLOSED: ${socket1.remoteAddress} ${socket1.remotePort}`.yellow);
37
+ done[i]=true;
38
+ });
39
+ socket1.on('data', function(data: any) {
40
+ console.log(`DATA ${socket1.remoteAddress} ${socket1.remotePort} ${data}`.yellow);
41
+ });
42
+ }
43
+
44
+ /*
45
+ const socket2 = tls.connect(options);
46
+ socket2.on('secureConnect', () => {
47
+ dosomework(socket2);
48
+ });
49
+ socket2.on('close', function(data: any) {
50
+ console.log(`CLOSED: ${socket2.remoteAddress} ${socket2.remotePort}`.green);
51
+ });
52
+ socket2.on('data', function(data: any) {
53
+ console.log(`DATA ${socket2.remoteAddress} ${socket2.remotePort} ${data}`.green);
54
+ });
55
+ */
@@ -0,0 +1,9 @@
1
+ import { ServiceConfigOptions } from './appConfig.js'
2
+ import { MasterProcessBase, WorkerProcessBase } from './../index'
3
+ import cluster from 'cluster';
4
+
5
+ if (cluster.isPrimary) {
6
+ new MasterProcessBase(ServiceConfigOptions(cluster.isPrimary)).SetupServer();
7
+ } else {
8
+ new WorkerProcessBase(ServiceConfigOptions(cluster.isPrimary)).SetupServer();
9
+ }
@@ -0,0 +1,66 @@
1
+ import { v4 as uuidv4 } from 'uuid';
2
+ import express from 'express';
3
+
4
+ import { $Options } from '@nsshunt/stsconfig'
5
+ const goptions = $Options()
6
+
7
+ import { ProcessOptions, IProcessBase, STSServerType } from './../index'
8
+
9
+ /*
10
+ // nid: `${goptions.rest01servicename} @ ${goptions.rest01serviceversion} | ${this.options.globalServiceData.serviceInstanceId} @ ${os.hostname()} ^ ${process.pid} @ ${(cluster.isMaster ? process.pid : process.ppid)}`,
11
+ // <serviceId> <serviceInstanceId> <serviceInstanceProcessId>
12
+ // <serviceName> <serviceVersion> <sid> <hostName> <pid> <ppid>
13
+ // << ............... Static Nid ............... >> << ............... Dynamic Nid ............... >>
14
+ // Note: The final nid will NOT contain the NID_SEPERATOR character. This will be replaced with the SEPERATOR character.
15
+ const Context = (isMaster, serviceInstanceId) => {
16
+ return {
17
+ nid: `\
18
+ ${goptions.rest01servicename}${ModelDelimeter.COMPONENT_SEPERATOR}${goptions.rest01serviceversion}\
19
+ ${ModelDelimeter.SEPERATOR}\
20
+ ${serviceInstanceId}${ModelDelimeter.COMPONENT_SEPERATOR}${os.hostname()}\
21
+ ${ModelDelimeter.NID_SEPERATOR}\
22
+ ${process.pid}${ModelDelimeter.COMPONENT_SEPERATOR}${(isMaster ? process.pid : process.ppid)}`
23
+ }
24
+ }
25
+ */
26
+
27
+ export function ServiceConfigOptions(isMaster: boolean): ProcessOptions {
28
+ if (isMaster === true) {
29
+ const serviceInstanceId = uuidv4();
30
+ const data: ProcessOptions = {
31
+ serverType: STSServerType.TCPRAW_TLS,
32
+
33
+ wssServer: false,
34
+ useLatency: false,
35
+ httpsServerKeyPath: goptions.httpsserverkeypath,
36
+ httpsServerCertificatePath: goptions.httpsservercertpath,
37
+ processExitOnTerminate: true,
38
+ serviceInstanceId: serviceInstanceId,
39
+ useDatabase: true,
40
+ useInstrumentationWorkers: true,
41
+
42
+ isMaster: isMaster,
43
+ endpoint: goptions.rest01endpoint,
44
+ apiRoot: goptions.rest01apiroot,
45
+ listenPort: goptions.rest01hostport,
46
+ port: goptions.rest01port,
47
+
48
+ prometheusSupport: false,
49
+ prometheusClusterPort: goptions.rest01prometheusclusterport,
50
+
51
+ serviceName: goptions.rest01servicename,
52
+ serviceVersion: goptions.rest01serviceversion,
53
+ consoleLogging: true,
54
+ instrumentLogging: true,
55
+
56
+ instrumentationObservationInterval: goptions.instrumentationObservationInterval,
57
+ instrumentationTimeWindow: goptions.instrumentationTimeWindow,
58
+
59
+ useRedisAdaptor: false
60
+ }
61
+ return data;
62
+ } else {
63
+ const data: ProcessOptions = JSON.parse(process.env['STS_GSD_SII'] as string) as ProcessOptions;
64
+ return data;
65
+ }
66
+ }