@nsshunt/stsappframework 3.1.211 → 3.1.213
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.
- package/dist/commonTypes.js.map +1 -1
- package/dist/masterprocessbase.js +14 -9
- package/dist/masterprocessbase.js.map +1 -1
- package/dist/processbase.js +12 -0
- package/dist/processbase.js.map +1 -1
- package/dist/serverprocessbase.js +60 -0
- package/dist/serverprocessbase.js.map +1 -1
- package/dist/singleprocessbase.js +2 -53
- package/dist/singleprocessbase.js.map +1 -1
- package/dist/workerprocessbase.js +2 -35
- package/dist/workerprocessbase.js.map +1 -1
- package/package.json +1 -1
- package/src/commonTypes.ts +38 -18
- package/src/masterprocessbase.ts +23 -26
- package/src/processbase.ts +16 -1
- package/src/serverprocessbase.ts +71 -2
- package/src/singleprocessbase.ts +3 -63
- package/src/workerprocessbase.ts +3 -50
- package/types/commonTypes.d.ts +30 -13
- package/types/commonTypes.d.ts.map +1 -1
- package/types/masterprocessbase.d.ts.map +1 -1
- package/types/processbase.d.ts +4 -1
- package/types/processbase.d.ts.map +1 -1
- package/types/serverprocessbase.d.ts +5 -2
- package/types/serverprocessbase.d.ts.map +1 -1
- package/types/singleprocessbase.d.ts +1 -3
- package/types/singleprocessbase.d.ts.map +1 -1
- package/types/workerprocessbase.d.ts +1 -3
- package/types/workerprocessbase.d.ts.map +1 -1
package/src/commonTypes.ts
CHANGED
|
@@ -10,6 +10,8 @@ import { Consumer, KafkaMessage } from 'kafkajs'
|
|
|
10
10
|
//@@import { RedisMessageHandler } from '@nsshunt/stsmessaging'
|
|
11
11
|
import { TinyEmitter } from "tiny-emitter";
|
|
12
12
|
|
|
13
|
+
import { Worker, Address } from 'node:cluster'
|
|
14
|
+
|
|
13
15
|
export interface IServiceProcessContext extends IContextBase {
|
|
14
16
|
serviceId?: string // Service name and the service version
|
|
15
17
|
|
|
@@ -80,6 +82,26 @@ export type IPCMessages = Record<string, IPCMessage>
|
|
|
80
82
|
|
|
81
83
|
//------------------------------------
|
|
82
84
|
|
|
85
|
+
export interface IProcessBaseEvents {
|
|
86
|
+
'processSigint': []
|
|
87
|
+
'processSigterm': []
|
|
88
|
+
'processExit': [ workerid: number ]
|
|
89
|
+
|
|
90
|
+
'ProcessTerminate': []
|
|
91
|
+
|
|
92
|
+
'clusterListening': [ worker: Worker, address: Address ];
|
|
93
|
+
'clusterOnline': [ worker: Worker ]
|
|
94
|
+
'clusterExit': [ worker: Worker, code: number, signal: string ]
|
|
95
|
+
'allListening': []
|
|
96
|
+
|
|
97
|
+
'workerMessage': [ id: number, payload: any ]
|
|
98
|
+
'workerError': [ error: Error ]
|
|
99
|
+
'workerAdded': [ id: number ]
|
|
100
|
+
'workerExit': [ code: number, signal: string ]
|
|
101
|
+
|
|
102
|
+
'prometheusScrapesListening': [ url: string, endpoint: string, prometheusClusterPort: string ]
|
|
103
|
+
}
|
|
104
|
+
|
|
83
105
|
export interface IProcessBase extends TinyEmitter {
|
|
84
106
|
SetupInstrumentation(): void
|
|
85
107
|
GetAdditionalInstruments(): InstrumentDefinitions
|
|
@@ -102,10 +124,13 @@ export interface IProcessBase extends TinyEmitter {
|
|
|
102
124
|
get accessLayer(): IDBAccessLayer | null
|
|
103
125
|
get shuttingDown(): boolean
|
|
104
126
|
//@@get redisMessageHandler(): RedisMessageHandler
|
|
127
|
+
|
|
128
|
+
emit<K extends keyof IProcessBaseEvents>(event: K, ...arg: IProcessBaseEvents[K]): this
|
|
129
|
+
on<K extends keyof IProcessBaseEvents>(event: K, callback: (...arg: IProcessBaseEvents[K]) => void): this
|
|
130
|
+
off<K extends keyof IProcessBaseEvents>(event: K, callback: (...arg: IProcessBaseEvents[K]) => void): this
|
|
105
131
|
}
|
|
106
132
|
|
|
107
133
|
export interface IMasterProcessBase extends IProcessBase {
|
|
108
|
-
|
|
109
134
|
WorkerMessageEvent(messageId: number, msg: any): any
|
|
110
135
|
SetupServer: () => Promise<void>
|
|
111
136
|
SetupServerEx: () => Promise<void>
|
|
@@ -122,32 +147,27 @@ export interface IMasterProcessBase extends IProcessBase {
|
|
|
122
147
|
ProcessIPCCommand(iPCMessagePayload: IPCMessagePayload): Promise<IPCMessagePayload>
|
|
123
148
|
}
|
|
124
149
|
|
|
125
|
-
export interface
|
|
126
|
-
|
|
150
|
+
export interface IServerProcessBase extends IProcessBase {
|
|
127
151
|
get httpServer(): any
|
|
128
|
-
CollectAdditionalTelemetry(): void
|
|
129
|
-
ProcessStarted(): void
|
|
130
152
|
get io(): any
|
|
131
|
-
get expressServer():
|
|
153
|
+
get expressServer(): STSExpressServer | null
|
|
154
|
+
set expressServer(server: STSExpressServer | null)
|
|
155
|
+
Terminate: (clusterPerformExit: boolean, signal?: any) => Promise<void>
|
|
156
|
+
SetupSTSServer: () => Promise<void>
|
|
157
|
+
CollectAdditionalTelemetry(): void
|
|
132
158
|
SetupServer(): Promise<boolean>
|
|
133
|
-
SetupServerEx: () => Promise<
|
|
159
|
+
SetupServerEx: () => Promise<boolean>
|
|
160
|
+
ProcessStarted(): void
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export interface ISingleProcessBase extends IServerProcessBase {
|
|
134
164
|
TerminateApplication(): Promise<void>
|
|
135
165
|
}
|
|
136
166
|
|
|
137
|
-
export interface IWorkerProcessBase extends
|
|
138
|
-
get httpServer(): any
|
|
139
|
-
WorkerStarted(): void
|
|
140
|
-
|
|
167
|
+
export interface IWorkerProcessBase extends IServerProcessBase {
|
|
141
168
|
ReceivedMessageFromMaster(msg: any): void
|
|
142
|
-
CollectAdditionalTelemetry(): void
|
|
143
|
-
get io(): any
|
|
144
|
-
|
|
145
169
|
AddWorker: (options: any) => Promise<string>
|
|
146
|
-
|
|
147
170
|
DeleteWorker: (workerId: string, options: any) => Promise<JSONObject>
|
|
148
|
-
get expressServer(): any
|
|
149
|
-
SetupServer: () => Promise<void>
|
|
150
|
-
SetupServerEx: () => Promise<void>
|
|
151
171
|
GetMasterProcessOptions: () => Promise<JSONObject>
|
|
152
172
|
}
|
|
153
173
|
|
package/src/masterprocessbase.ts
CHANGED
|
@@ -5,7 +5,7 @@ import https from 'https'
|
|
|
5
5
|
|
|
6
6
|
import axios from 'axios';
|
|
7
7
|
|
|
8
|
-
import cluster, { Worker } from 'node:cluster'
|
|
8
|
+
import cluster, { Worker, Address } from 'node:cluster'
|
|
9
9
|
|
|
10
10
|
import chalk from 'chalk';
|
|
11
11
|
|
|
@@ -27,9 +27,8 @@ import { InstrumentDefinitions } from '@nsshunt/stsobservability'
|
|
|
27
27
|
import { IPCMessagePayload, IPCMessageCommand } from './commonTypes'
|
|
28
28
|
|
|
29
29
|
import { STSTransportLoggerWinston } from './stsTransportLoggerWinston'
|
|
30
|
-
import { JSONObject } from "@nsshunt/stsutils";
|
|
31
30
|
|
|
32
|
-
import { GetFirstNetworkInterface } from './network';
|
|
31
|
+
//import { GetFirstNetworkInterface } from './network';
|
|
33
32
|
|
|
34
33
|
export class MasterProcessBase extends ProcessBase implements IMasterProcessBase
|
|
35
34
|
{
|
|
@@ -101,7 +100,8 @@ export class MasterProcessBase extends ProcessBase implements IMasterProcessBase
|
|
|
101
100
|
}
|
|
102
101
|
|
|
103
102
|
#InitCluster = () => {
|
|
104
|
-
cluster.on('listening', () => {
|
|
103
|
+
cluster.on('listening', (worker: Worker, address: Address) => {
|
|
104
|
+
this.emit('clusterListening', worker, address);
|
|
105
105
|
let allListening = true;
|
|
106
106
|
for (const worker of Object.values(cluster.workers as NodeJS.Dict<Worker>)) {
|
|
107
107
|
if (worker?.isConnected) {
|
|
@@ -109,9 +109,9 @@ export class MasterProcessBase extends ProcessBase implements IMasterProcessBase
|
|
|
109
109
|
break;
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
|
-
|
|
113
112
|
if (allListening) {
|
|
114
113
|
this.LogInfoMessage(`Service instance started.`);
|
|
114
|
+
this.emit('allListening');
|
|
115
115
|
}
|
|
116
116
|
});
|
|
117
117
|
};
|
|
@@ -158,6 +158,9 @@ export class MasterProcessBase extends ProcessBase implements IMasterProcessBase
|
|
|
158
158
|
//@@chmodSync(this.options.port, 511);
|
|
159
159
|
}).on('listening', () =>
|
|
160
160
|
{
|
|
161
|
+
this.emit('prometheusScrapesListening', `${this.options.endpoint}:${this.options.prometheusClusterPort}/metrics`,
|
|
162
|
+
this.options.endpoint,
|
|
163
|
+
this.options.prometheusClusterPort);
|
|
161
164
|
this.LogInfoMessage(`Prometheus scrapes ready and live on ${this.options.endpoint}:${this.options.prometheusClusterPort}/metrics`);
|
|
162
165
|
});
|
|
163
166
|
} catch (error)
|
|
@@ -407,6 +410,7 @@ export class MasterProcessBase extends ProcessBase implements IMasterProcessBase
|
|
|
407
410
|
this.IncWorkers();
|
|
408
411
|
|
|
409
412
|
worker.on('exit', (code, signal) => {
|
|
413
|
+
this.emit('workerExit', code, signal);
|
|
410
414
|
if (signal) {
|
|
411
415
|
this.LogInfoMessage(`Worker: ${worker.process.pid} was killed by signal: ${signal}`);
|
|
412
416
|
} else if (code !== 0) {
|
|
@@ -417,6 +421,7 @@ export class MasterProcessBase extends ProcessBase implements IMasterProcessBase
|
|
|
417
421
|
});
|
|
418
422
|
|
|
419
423
|
worker.on('message', async (payload) => {
|
|
424
|
+
this.emit('workerMessage', worker.id, payload);
|
|
420
425
|
// Only handle request/response message types here ...
|
|
421
426
|
if (payload.requestResponse) {
|
|
422
427
|
const iPCMessagePayload: IPCMessagePayload = payload as IPCMessagePayload;
|
|
@@ -430,6 +435,7 @@ export class MasterProcessBase extends ProcessBase implements IMasterProcessBase
|
|
|
430
435
|
});
|
|
431
436
|
|
|
432
437
|
worker.on('error', (error) => {
|
|
438
|
+
this.emit('workerError', error);
|
|
433
439
|
const message = chalk.red(`#SpawnWorker():worker.on('error'): Error: [${error}]`);
|
|
434
440
|
this.LogErrorMessage(message);
|
|
435
441
|
});
|
|
@@ -482,18 +488,19 @@ export class MasterProcessBase extends ProcessBase implements IMasterProcessBase
|
|
|
482
488
|
|
|
483
489
|
this.#InitCluster();
|
|
484
490
|
|
|
485
|
-
cluster.on('listening', (worker, address) =>
|
|
486
|
-
|
|
491
|
+
cluster.on('listening', (worker, address) => {
|
|
492
|
+
this.emit('clusterListening', worker, address);
|
|
487
493
|
this.LogInfoMessage(`Worker process ${worker.process.pid} is listening at address: ${JSON.stringify(address)}`);
|
|
488
494
|
});
|
|
489
495
|
|
|
490
496
|
//Setting up lifecycle event listeners for worker processes
|
|
491
|
-
cluster.on('online', worker =>
|
|
492
|
-
|
|
497
|
+
cluster.on('online', worker => {
|
|
498
|
+
this.emit('clusterOnline', worker);
|
|
493
499
|
this.LogInfoMessage(`Worker process ${worker.process.pid} is online`);
|
|
494
500
|
});
|
|
495
501
|
|
|
496
502
|
cluster.on('exit', (worker, code, signal) => {
|
|
503
|
+
this.emit('clusterExit', worker, code, signal);
|
|
497
504
|
if ((code !== null && code === 0) || (signal === 'SIGINT')) {
|
|
498
505
|
this.LogInfoMessage(chalk.green(`Process ${worker.process.pid} terminated gracefully with code: ${code}, signal: ${signal}`));
|
|
499
506
|
this.DecWorkers();
|
|
@@ -590,20 +597,19 @@ export class MasterProcessBase extends ProcessBase implements IMasterProcessBase
|
|
|
590
597
|
}
|
|
591
598
|
}
|
|
592
599
|
|
|
593
|
-
process.on('SIGINT', async () =>
|
|
594
|
-
|
|
600
|
+
process.on('SIGINT', async () => {
|
|
601
|
+
this.emit('processSigint');
|
|
595
602
|
await Terminate('SIGINT');
|
|
596
603
|
});
|
|
597
604
|
|
|
598
|
-
process.on('SIGTERM', async () =>
|
|
599
|
-
|
|
605
|
+
process.on('SIGTERM', async () => {
|
|
606
|
+
this.emit('processSigterm');
|
|
600
607
|
await Terminate('SIGTERM');
|
|
601
608
|
});
|
|
602
609
|
|
|
603
|
-
process.on('exit', (code) =>
|
|
604
|
-
|
|
605
|
-
if (code === 0)
|
|
606
|
-
{
|
|
610
|
+
process.on('exit', (code) => {
|
|
611
|
+
this.emit('processExit', code);
|
|
612
|
+
if (code === 0) {
|
|
607
613
|
this.LogInfoMessage(chalk.green(`Main Process: ${process.pid} terminated gracefully with code: ${code}`));
|
|
608
614
|
} else {
|
|
609
615
|
this.LogInfoMessage(chalk.red(`Main Process: ${process.pid} terminated with code: ${code}`));
|
|
@@ -616,15 +622,6 @@ export class MasterProcessBase extends ProcessBase implements IMasterProcessBase
|
|
|
616
622
|
}, 1000).unref();
|
|
617
623
|
}
|
|
618
624
|
|
|
619
|
-
/*
|
|
620
|
-
this.redisMessageHandler.AddGroup('primary');
|
|
621
|
-
|
|
622
|
-
this.redisMessageHandler.on('GetSystemInformation', async (args: JSONObject, callback: any) => {
|
|
623
|
-
const retVal = await this.#GetSystemInformation();
|
|
624
|
-
callback(retVal);
|
|
625
|
-
});
|
|
626
|
-
*/
|
|
627
|
-
|
|
628
625
|
this.MasterStarted();
|
|
629
626
|
|
|
630
627
|
this.LogInfoMessage(chalk.green(`Master process:${process.pid} started`));
|
package/src/processbase.ts
CHANGED
|
@@ -22,7 +22,7 @@ import { PublishInstrumentController, IPublishInstrumentControllerOptions, Instr
|
|
|
22
22
|
|
|
23
23
|
import os from 'os';
|
|
24
24
|
|
|
25
|
-
import { IProcessBase, ISocketIoServerHelper, CreateServiceProcessContext, ProcessOptions, STSServerType } from './commonTypes'
|
|
25
|
+
import { IProcessBase, ISocketIoServerHelper, CreateServiceProcessContext, ProcessOptions, STSServerType, IProcessBaseEvents } from './commonTypes'
|
|
26
26
|
|
|
27
27
|
//@@import { RedisMessageHandler } from '@nsshunt/stsmessaging'
|
|
28
28
|
import { TinyEmitter } from 'tiny-emitter';
|
|
@@ -428,6 +428,21 @@ export abstract class ProcessBase extends TinyEmitter implements IProcessBase
|
|
|
428
428
|
return msgcolor;
|
|
429
429
|
};
|
|
430
430
|
|
|
431
|
+
emit<K extends keyof IProcessBaseEvents>(event: K, ...arg: IProcessBaseEvents[K]): this {
|
|
432
|
+
super.emit(event, arg);
|
|
433
|
+
return this;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
on<K extends keyof IProcessBaseEvents>(event: K, callback: (...arg: IProcessBaseEvents[K]) => void): this {
|
|
437
|
+
super.on(event, callback);
|
|
438
|
+
return this;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
off<K extends keyof IProcessBaseEvents>(event: K, callback: (...arg: IProcessBaseEvents[K]) => void): this {
|
|
442
|
+
super.off(event, callback);
|
|
443
|
+
return this;
|
|
444
|
+
}
|
|
445
|
+
|
|
431
446
|
/*@@
|
|
432
447
|
get redisMessageHandler(): RedisMessageHandler {
|
|
433
448
|
return this.#redisMessageHandler as RedisMessageHandler;
|
package/src/serverprocessbase.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { createAdapter } from "@socket.io/redis-streams-adapter";
|
|
|
10
10
|
|
|
11
11
|
import { JSONObject, Sleep } from '@nsshunt/stsutils'
|
|
12
12
|
|
|
13
|
-
import { ProcessOptions, STSServerType } from './commonTypes'
|
|
13
|
+
import { ProcessOptions, STSServerType, IServerProcessBase } from './commonTypes'
|
|
14
14
|
import { ProcessBase } from './processbase';
|
|
15
15
|
|
|
16
16
|
import { register, Counter, collectDefaultMetrics, AggregatorRegistry } from 'prom-client'
|
|
@@ -28,12 +28,14 @@ import { createClient, RedisClientType } from 'redis';
|
|
|
28
28
|
|
|
29
29
|
import jayson from 'jayson'
|
|
30
30
|
|
|
31
|
+
import { STSTransportLoggerWinston } from './stsTransportLoggerWinston'
|
|
32
|
+
|
|
31
33
|
/**
|
|
32
34
|
* todo
|
|
33
35
|
* @typedef {Object} options - todo
|
|
34
36
|
* @property {boolean} [wssServer=false] - Create a web socket server on this worker instance
|
|
35
37
|
*/
|
|
36
|
-
export class ServerProcessBase extends ProcessBase
|
|
38
|
+
export abstract class ServerProcessBase extends ProcessBase implements IServerProcessBase
|
|
37
39
|
{
|
|
38
40
|
#masterProcessExitTime = goptions.masterProcessExitTime;
|
|
39
41
|
#io: Server | null = null;
|
|
@@ -363,6 +365,73 @@ export class ServerProcessBase extends ProcessBase
|
|
|
363
365
|
}
|
|
364
366
|
}
|
|
365
367
|
|
|
368
|
+
async SetupServer(): Promise<boolean> {
|
|
369
|
+
return new Promise((resolve, reject) => {
|
|
370
|
+
try {
|
|
371
|
+
this.SetupInstrumentation();
|
|
372
|
+
setTimeout(async () => {
|
|
373
|
+
try {
|
|
374
|
+
await this.SetupServerEx();
|
|
375
|
+
resolve(true);
|
|
376
|
+
} catch (error) {
|
|
377
|
+
reject(error);
|
|
378
|
+
}
|
|
379
|
+
}, 100);
|
|
380
|
+
} catch (error) {
|
|
381
|
+
reject(error);
|
|
382
|
+
}
|
|
383
|
+
})
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
ProcessStarted() {
|
|
387
|
+
const transport = new STSTransportLoggerWinston({
|
|
388
|
+
stsApp: this
|
|
389
|
+
});
|
|
390
|
+
setTimeout(() => {
|
|
391
|
+
(this.options.logger as any).add(transport);
|
|
392
|
+
}, 0);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
async SetupServerEx(): Promise<boolean> {
|
|
396
|
+
this.LogInfoMessage(chalk.green(`ServerProcessBase:SetupServerEx(): Main Process:${process.pid} Starting ...`));
|
|
397
|
+
|
|
398
|
+
this.ProcessStartup();
|
|
399
|
+
|
|
400
|
+
if (this.options.expressServerRouteFactory || this.options.expressServerRouteStaticFactory) {
|
|
401
|
+
this.expressServer = new STSExpressServer(this.options, this);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
this.LogInfoMessage(`ServerProcessBase:SetupServerEx(): Worker instance starting. Service instance Id: [${this.options.serviceInstanceId}]`);
|
|
405
|
+
|
|
406
|
+
// Signal Codes
|
|
407
|
+
// https://en.wikipedia.org/wiki/Signal_(IPC)
|
|
408
|
+
process.on('SIGTERM', async () => {
|
|
409
|
+
this.LogInfoMessage(`ServerProcessBase:SetupServerEx(): SIGTERM signal received for worker: ${process.pid}`);
|
|
410
|
+
await this.Terminate(true, true);
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
process.on('SIGINT', async () => {
|
|
414
|
+
this.LogInfoMessage(`ServerProcessBase:SetupServerEx(): SIGINT signal received for worker: ${process.pid}`);
|
|
415
|
+
await this.Terminate(true, true);
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
process.on('exit', (code) => {
|
|
419
|
+
if (code === 0) {
|
|
420
|
+
this.LogInfoMessage(chalk.green(`ServerProcessBase:SetupServerEx(): Process: ${process.pid} terminated gracefully with code: ${code}`));
|
|
421
|
+
} else {
|
|
422
|
+
this.LogInfoMessage(chalk.red(`ServerProcessBase:SetupServerEx(): Process: ${process.pid} terminated with code: ${code}`));
|
|
423
|
+
}
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
await this.SetupSTSServer();
|
|
427
|
+
|
|
428
|
+
this.ProcessStarted();
|
|
429
|
+
|
|
430
|
+
this.LogInfoMessage(chalk.green(`ServerProcessBase:SetupServerEx(): Main Process:${process.pid} Started`));
|
|
431
|
+
|
|
432
|
+
return true;
|
|
433
|
+
};
|
|
434
|
+
|
|
366
435
|
SetupSTSServer = async(): Promise<void> => {
|
|
367
436
|
switch (this.options.serverType) {
|
|
368
437
|
case STSServerType.EXPRESS :
|
package/src/singleprocessbase.ts
CHANGED
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
/* eslint @typescript-eslint/no-explicit-any: 0 */ // --> OFF
|
|
2
2
|
import { goptions } from '@nsshunt/stsconfig'
|
|
3
3
|
|
|
4
|
-
import chalk from 'chalk';
|
|
5
|
-
|
|
6
4
|
import { Gauge, GaugeTypes, InstrumentGaugeOptions, InstrumentGaugeTelemetry } from '@nsshunt/stsobservability'
|
|
7
5
|
|
|
8
6
|
import { ISingleProcessBase, ProcessOptions } from './commonTypes';
|
|
9
7
|
import { InstrumentDefinitions } from '@nsshunt/stsobservability'
|
|
10
|
-
import { STSExpressServer } from './server'
|
|
11
8
|
import { ServerProcessBase } from './serverprocessbase'
|
|
12
9
|
|
|
13
10
|
import si from 'systeminformation' // https://systeminformation.io/
|
|
14
11
|
|
|
15
|
-
import { STSTransportLoggerWinston } from './stsTransportLoggerWinston'
|
|
16
|
-
|
|
17
12
|
export type EventCb = (socket: any, data: any) => void
|
|
18
13
|
|
|
19
14
|
export class SingleProcessBase extends ServerProcessBase implements ISingleProcessBase
|
|
@@ -54,67 +49,12 @@ export class SingleProcessBase extends ServerProcessBase implements ISingleProce
|
|
|
54
49
|
return null;
|
|
55
50
|
}
|
|
56
51
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
stsApp: this
|
|
60
|
-
});
|
|
61
|
-
setTimeout(() => {
|
|
62
|
-
(this.options.logger as any).add(transport);
|
|
63
|
-
}, 0);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
SetupServer(): Promise<boolean>
|
|
67
|
-
{
|
|
68
|
-
return new Promise((resolve, reject) => {
|
|
69
|
-
try {
|
|
70
|
-
this.SetupInstrumentation();
|
|
71
|
-
setTimeout(async () => {
|
|
72
|
-
try {
|
|
73
|
-
await this.SetupServerEx();
|
|
74
|
-
resolve(true);
|
|
75
|
-
} catch (error) {
|
|
76
|
-
reject(error);
|
|
77
|
-
}
|
|
78
|
-
}, 100);
|
|
79
|
-
} catch (error) {
|
|
80
|
-
reject(error);
|
|
81
|
-
}
|
|
82
|
-
})
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
SetupServerEx = async () => {
|
|
86
|
-
this.ProcessStartup();
|
|
87
|
-
|
|
88
|
-
if (this.options.expressServerRouteFactory || this.options.expressServerRouteStaticFactory) {
|
|
89
|
-
this.expressServer = new STSExpressServer(this.options, this);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
this.LogInfoMessage(`Service instance starting. Instance Id: [${this.options.serviceInstanceId}]`);
|
|
93
|
-
this.LogInfoMessage(`Master process:${process.pid} started`);
|
|
52
|
+
override SetupServerEx = async (): Promise<boolean> => {
|
|
53
|
+
await super.SetupServerEx();
|
|
94
54
|
|
|
95
55
|
this.LogSystemTelemetry();
|
|
96
56
|
|
|
97
|
-
|
|
98
|
-
await this.Terminate(false, 'SIGINT');
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
process.on('SIGTERM', async () => {
|
|
102
|
-
await this.Terminate(false, 'SIGTERM');
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
process.on('exit', (code) => {
|
|
106
|
-
if (code === 0) {
|
|
107
|
-
this.LogInfoMessage(chalk.green(`Main Process: ${process.pid} terminated gracefully with code: ${code}`));
|
|
108
|
-
} else {
|
|
109
|
-
this.LogInfoMessage(chalk.red(`Main Process: ${process.pid} terminated with code: ${code}`));
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
await this.SetupSTSServer();
|
|
114
|
-
|
|
115
|
-
this.ProcessStarted();
|
|
116
|
-
|
|
117
|
-
this.LogInfoMessage(chalk.green(`Main process:${process.pid} started`));
|
|
57
|
+
return true;
|
|
118
58
|
}
|
|
119
59
|
|
|
120
60
|
async TerminateApplication()
|
package/src/workerprocessbase.ts
CHANGED
|
@@ -4,13 +4,10 @@ import chalk from 'chalk';
|
|
|
4
4
|
import { Gauge, InstrumentGaugeTelemetry } from '@nsshunt/stsobservability'
|
|
5
5
|
import { JSONObject } from '@nsshunt/stsutils'
|
|
6
6
|
import { IPCMessage, IPCMessages, IPCMessagePayload, IPCMessageCommand, IWorkerProcessBase, ProcessOptions } from './commonTypes'
|
|
7
|
-
import { STSExpressServer } from './server';
|
|
8
7
|
import { ServerProcessBase } from './serverprocessbase'
|
|
9
8
|
|
|
10
9
|
import { v4 as uuidv4 } from 'uuid';
|
|
11
10
|
|
|
12
|
-
import { STSTransportLoggerWinston } from './stsTransportLoggerWinston'
|
|
13
|
-
|
|
14
11
|
import { goptions } from '@nsshunt/stsconfig'
|
|
15
12
|
|
|
16
13
|
import si from 'systeminformation' // https://systeminformation.io/
|
|
@@ -31,15 +28,6 @@ export class WorkerProcessBase extends ServerProcessBase implements IWorkerProce
|
|
|
31
28
|
super(options);
|
|
32
29
|
}
|
|
33
30
|
|
|
34
|
-
WorkerStarted() {
|
|
35
|
-
const transport = new STSTransportLoggerWinston({
|
|
36
|
-
stsApp: this
|
|
37
|
-
});
|
|
38
|
-
setTimeout(() => {
|
|
39
|
-
(this.options.logger as any).add(transport);
|
|
40
|
-
}, 0);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
31
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
44
32
|
ReceivedMessageFromMaster(msg: any) {
|
|
45
33
|
// Override in subclass if required
|
|
@@ -96,7 +84,6 @@ export class WorkerProcessBase extends ServerProcessBase implements IWorkerProce
|
|
|
96
84
|
});
|
|
97
85
|
return workerResponse.workerId;
|
|
98
86
|
}
|
|
99
|
-
|
|
100
87
|
|
|
101
88
|
DeleteWorker = async (workerId: string, options: any): Promise<JSONObject> => {
|
|
102
89
|
const workerResponse: JSONObject = await this.#SendMessageToParentProcess({
|
|
@@ -121,13 +108,6 @@ export class WorkerProcessBase extends ServerProcessBase implements IWorkerProce
|
|
|
121
108
|
return parentResponse;
|
|
122
109
|
}
|
|
123
110
|
|
|
124
|
-
SetupServer = async () => {
|
|
125
|
-
this.SetupInstrumentation();
|
|
126
|
-
setTimeout(() => {
|
|
127
|
-
this.SetupServerEx();
|
|
128
|
-
}, 100);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
111
|
GetNumCPUs = async (): Promise<number> => {
|
|
132
112
|
// https://systeminformation.io/
|
|
133
113
|
const valueObject = {
|
|
@@ -191,16 +171,9 @@ export class WorkerProcessBase extends ServerProcessBase implements IWorkerProce
|
|
|
191
171
|
return sysInfo;
|
|
192
172
|
}
|
|
193
173
|
|
|
194
|
-
SetupServerEx = async () => {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
if (this.options.expressServerRouteFactory || this.options.expressServerRouteStaticFactory) {
|
|
198
|
-
this.expressServer = new STSExpressServer(this.options, this);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
this.LogInfoMessage(`Worker instance starting. Service instance Id: [${this.options.serviceInstanceId}]`);
|
|
174
|
+
override SetupServerEx = async (): Promise<boolean> => {
|
|
175
|
+
await super.SetupServerEx();
|
|
202
176
|
|
|
203
|
-
|
|
204
177
|
process.on('message', async (msg: any) => {
|
|
205
178
|
if (msg.requestResponse) {
|
|
206
179
|
const iPCMessagePayload: IPCMessagePayload = msg as IPCMessagePayload;
|
|
@@ -239,27 +212,7 @@ export class WorkerProcessBase extends ServerProcessBase implements IWorkerProce
|
|
|
239
212
|
}
|
|
240
213
|
});
|
|
241
214
|
|
|
242
|
-
|
|
243
|
-
// https://en.wikipedia.org/wiki/Signal_(IPC)
|
|
244
|
-
process.on('SIGTERM', async () =>
|
|
245
|
-
{
|
|
246
|
-
this.LogInfoMessage(`SIGTERM signal received for worker: ${process.pid}`);
|
|
247
|
-
await this.Terminate(true, true);
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
process.on('SIGINT', async () =>
|
|
251
|
-
{
|
|
252
|
-
this.LogInfoMessage(`SIGINT signal received for worker: ${process.pid}`);
|
|
253
|
-
await this.Terminate(true, true);
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
await this.SetupSTSServer();
|
|
257
|
-
|
|
258
|
-
//@@this.redisMessageHandler.AddGroup('worker');
|
|
259
|
-
|
|
260
|
-
this.WorkerStarted();
|
|
261
|
-
|
|
262
|
-
this.LogInfoMessage(chalk.green(`Worker process:${process.pid} started`));
|
|
215
|
+
return true;
|
|
263
216
|
};
|
|
264
217
|
|
|
265
218
|
override ProcessTerminate(): Promise<void> {
|
package/types/commonTypes.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { PublishInstrumentController, InstrumentDefinitions, IContextBase, Instr
|
|
|
5
5
|
import { IDBAccessLayer } from '@nsshunt/stsdatamanagement';
|
|
6
6
|
import { Consumer, KafkaMessage } from 'kafkajs';
|
|
7
7
|
import { TinyEmitter } from "tiny-emitter";
|
|
8
|
+
import { Worker, Address } from 'node:cluster';
|
|
8
9
|
export interface IServiceProcessContext extends IContextBase {
|
|
9
10
|
serviceId?: string;
|
|
10
11
|
serviceInstanceId?: string;
|
|
@@ -37,6 +38,21 @@ export interface IPCMessage {
|
|
|
37
38
|
timeout: NodeJS.Timeout;
|
|
38
39
|
}
|
|
39
40
|
export type IPCMessages = Record<string, IPCMessage>;
|
|
41
|
+
export interface IProcessBaseEvents {
|
|
42
|
+
'processSigint': [];
|
|
43
|
+
'processSigterm': [];
|
|
44
|
+
'processExit': [workerid: number];
|
|
45
|
+
'ProcessTerminate': [];
|
|
46
|
+
'clusterListening': [worker: Worker, address: Address];
|
|
47
|
+
'clusterOnline': [worker: Worker];
|
|
48
|
+
'clusterExit': [worker: Worker, code: number, signal: string];
|
|
49
|
+
'allListening': [];
|
|
50
|
+
'workerMessage': [id: number, payload: any];
|
|
51
|
+
'workerError': [error: Error];
|
|
52
|
+
'workerAdded': [id: number];
|
|
53
|
+
'workerExit': [code: number, signal: string];
|
|
54
|
+
'prometheusScrapesListening': [url: string, endpoint: string, prometheusClusterPort: string];
|
|
55
|
+
}
|
|
40
56
|
export interface IProcessBase extends TinyEmitter {
|
|
41
57
|
SetupInstrumentation(): void;
|
|
42
58
|
GetAdditionalInstruments(): InstrumentDefinitions;
|
|
@@ -56,6 +72,9 @@ export interface IProcessBase extends TinyEmitter {
|
|
|
56
72
|
TerminateDatabase(): Promise<void>;
|
|
57
73
|
get accessLayer(): IDBAccessLayer | null;
|
|
58
74
|
get shuttingDown(): boolean;
|
|
75
|
+
emit<K extends keyof IProcessBaseEvents>(event: K, ...arg: IProcessBaseEvents[K]): this;
|
|
76
|
+
on<K extends keyof IProcessBaseEvents>(event: K, callback: (...arg: IProcessBaseEvents[K]) => void): this;
|
|
77
|
+
off<K extends keyof IProcessBaseEvents>(event: K, callback: (...arg: IProcessBaseEvents[K]) => void): this;
|
|
59
78
|
}
|
|
60
79
|
export interface IMasterProcessBase extends IProcessBase {
|
|
61
80
|
WorkerMessageEvent(messageId: number, msg: any): any;
|
|
@@ -70,27 +89,25 @@ export interface IMasterProcessBase extends IProcessBase {
|
|
|
70
89
|
BroadcastDataToWorkers: (command: any, data: any) => void;
|
|
71
90
|
ProcessIPCCommand(iPCMessagePayload: IPCMessagePayload): Promise<IPCMessagePayload>;
|
|
72
91
|
}
|
|
73
|
-
export interface
|
|
92
|
+
export interface IServerProcessBase extends IProcessBase {
|
|
74
93
|
get httpServer(): any;
|
|
75
|
-
CollectAdditionalTelemetry(): void;
|
|
76
|
-
ProcessStarted(): void;
|
|
77
94
|
get io(): any;
|
|
78
|
-
get expressServer():
|
|
95
|
+
get expressServer(): STSExpressServer | null;
|
|
96
|
+
set expressServer(server: STSExpressServer | null);
|
|
97
|
+
Terminate: (clusterPerformExit: boolean, signal?: any) => Promise<void>;
|
|
98
|
+
SetupSTSServer: () => Promise<void>;
|
|
99
|
+
CollectAdditionalTelemetry(): void;
|
|
79
100
|
SetupServer(): Promise<boolean>;
|
|
80
|
-
SetupServerEx: () => Promise<
|
|
101
|
+
SetupServerEx: () => Promise<boolean>;
|
|
102
|
+
ProcessStarted(): void;
|
|
103
|
+
}
|
|
104
|
+
export interface ISingleProcessBase extends IServerProcessBase {
|
|
81
105
|
TerminateApplication(): Promise<void>;
|
|
82
106
|
}
|
|
83
|
-
export interface IWorkerProcessBase extends
|
|
84
|
-
get httpServer(): any;
|
|
85
|
-
WorkerStarted(): void;
|
|
107
|
+
export interface IWorkerProcessBase extends IServerProcessBase {
|
|
86
108
|
ReceivedMessageFromMaster(msg: any): void;
|
|
87
|
-
CollectAdditionalTelemetry(): void;
|
|
88
|
-
get io(): any;
|
|
89
109
|
AddWorker: (options: any) => Promise<string>;
|
|
90
110
|
DeleteWorker: (workerId: string, options: any) => Promise<JSONObject>;
|
|
91
|
-
get expressServer(): any;
|
|
92
|
-
SetupServer: () => Promise<void>;
|
|
93
|
-
SetupServerEx: () => Promise<void>;
|
|
94
111
|
GetMasterProcessOptions: () => Promise<JSONObject>;
|
|
95
112
|
}
|
|
96
113
|
export type ServerEventCb = (socket: any, data: any) => void;
|