@nsshunt/stsappframework 3.1.160 → 3.1.161

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 (41) hide show
  1. package/dist/testertesting/app.js +194 -0
  2. package/dist/testertesting/app.js.map +1 -0
  3. package/dist/testertesting/commonTypes.js +16 -0
  4. package/dist/testertesting/commonTypes.js.map +1 -0
  5. package/dist/testertesting/requestResponseHelper.js +83 -0
  6. package/dist/testertesting/requestResponseHelper.js.map +1 -0
  7. package/dist/testertesting/stsTestWorkerDefinitions.js +34 -0
  8. package/dist/testertesting/stsTestWorkerDefinitions.js.map +1 -0
  9. package/dist/testertesting/workerInstance.js +131 -0
  10. package/dist/testertesting/workerInstance.js.map +1 -0
  11. package/dist/testertesting/workerManager.js +417 -0
  12. package/dist/testertesting/workerManager.js.map +1 -0
  13. package/dist/testertesting/workerPrimaryTestRunner01.js +62 -0
  14. package/dist/testertesting/workerPrimaryTestRunner01.js.map +1 -0
  15. package/dist/testertesting/workerWorkerTestRunner01.js +146 -0
  16. package/dist/testertesting/workerWorkerTestRunner01.js.map +1 -0
  17. package/package.json +1 -1
  18. package/src/testertesting/app.ts +238 -0
  19. package/src/testertesting/commonTypes.ts +50 -0
  20. package/src/testertesting/requestResponseHelper.ts +95 -0
  21. package/src/testertesting/stsTestWorkerDefinitions.ts +150 -0
  22. package/src/testertesting/workerInstance.ts +154 -0
  23. package/src/testertesting/workerManager.ts +478 -0
  24. package/src/testertesting/workerPrimaryTestRunner01.ts +81 -0
  25. package/src/testertesting/workerWorkerTestRunner01.ts +184 -0
  26. package/types/testertesting/app.d.ts +2 -0
  27. package/types/testertesting/app.d.ts.map +1 -0
  28. package/types/testertesting/commonTypes.d.ts +44 -0
  29. package/types/testertesting/commonTypes.d.ts.map +1 -0
  30. package/types/testertesting/requestResponseHelper.d.ts +8 -0
  31. package/types/testertesting/requestResponseHelper.d.ts.map +1 -0
  32. package/types/testertesting/stsTestWorkerDefinitions.d.ts +124 -0
  33. package/types/testertesting/stsTestWorkerDefinitions.d.ts.map +1 -0
  34. package/types/testertesting/workerInstance.d.ts +18 -0
  35. package/types/testertesting/workerInstance.d.ts.map +1 -0
  36. package/types/testertesting/workerManager.d.ts +14 -0
  37. package/types/testertesting/workerManager.d.ts.map +1 -0
  38. package/types/testertesting/workerPrimaryTestRunner01.d.ts +8 -0
  39. package/types/testertesting/workerPrimaryTestRunner01.d.ts.map +1 -0
  40. package/types/testertesting/workerWorkerTestRunner01.d.ts +16 -0
  41. package/types/testertesting/workerWorkerTestRunner01.d.ts.map +1 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nsshunt/stsappframework",
3
- "version": "3.1.160",
3
+ "version": "3.1.161",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "./types/index.d.ts",
@@ -0,0 +1,238 @@
1
+ /* eslint @typescript-eslint/no-explicit-any: 0, @typescript-eslint/no-unused-vars: 0 */ // --> OFF
2
+ import cluster from 'cluster';
3
+ import { Worker, MessageChannel } from 'worker_threads';
4
+
5
+ import { IWorkerFactory, IWorkerOptions, IPrimaryWorker, IRunnerOptions } from './stsTestWorkerDefinitions'
6
+
7
+ import { WorkerPrimaryTestRunner01 } from './workerPrimaryTestRunner01'
8
+ import { STSWorkerManager } from './workerManager';
9
+
10
+ import chalk from 'chalk';
11
+ // Force chalk level
12
+ chalk.level = 3;
13
+
14
+ import { IContextBase, AgentInstrumentController, IPublishInstrumentControllerOptions, Gauge, GaugeTypes,
15
+ InstrumentDefinitions, InstrumentLogOptions, InstrumentGaugeOptions, PublishTransportRESTServer,
16
+ TransportType, IPublishTransportRESTServerOptions } from '@nsshunt/stsobservability'
17
+
18
+ import { ModelDelimeter, type ISTSLogger, defaultLogger } from '@nsshunt/stsutils'
19
+
20
+ import { v4 as uuidv4 } from 'uuid';
21
+
22
+ import { goptions } from '@nsshunt/stsconfig'
23
+
24
+ declare interface IAsyncRunnerContext extends IContextBase {
25
+ id: string;
26
+ hostName: string;
27
+ agentName: string;
28
+ threadId: string;
29
+ asyncRunnerId: number;
30
+ }
31
+
32
+ const LogInfoMessage = (message: any) => console.log(chalk.grey(message))
33
+ const LogErrorMessage = (message: any) => console.error(chalk.red(message))
34
+
35
+ if (cluster.isPrimary) {
36
+
37
+ //new MasterProcessBase(ServiceConfigOptions(true, cluster.isPrimary)).SetupServer();
38
+
39
+ LogInfoMessage(`Primary ${process.pid} is running`);
40
+
41
+ // Fork workers.
42
+ cluster.fork();
43
+
44
+ cluster.on('exit', (worker, code, signal) => {
45
+ LogInfoMessage(`worker ${worker.process.pid} died`);
46
+ });
47
+
48
+
49
+ /*
50
+ const fileName ='./dist/webworkertesting/worker.js';
51
+
52
+ const publishCollectorWebWorker = new Worker(fileName);
53
+ publishCollectorWebWorker.unref();
54
+
55
+ publishCollectorWebWorker.postMessage({cmd: 'text', message: 'Hello World'});
56
+
57
+ publishCollectorWebWorker.on('message', (data) => {
58
+ LogInfoMessage(`cluster.primary (${process.pid}): message from worker = [${JSON.stringify(data)}]`);
59
+ });
60
+
61
+ const { port1, port2 } = new MessageChannel();
62
+
63
+ publishCollectorWebWorker.postMessage({cmd: 'portmessage', port: port2}, [ port2 ]);
64
+ port1.postMessage('sending to port1');
65
+ port1.on('message', (data) => {
66
+ LogInfoMessage(`cluster.primary (${process.pid}): message from message port = [${data}]`);
67
+ });
68
+ */
69
+
70
+ LogInfoMessage(`cluster primary completed ...`);
71
+
72
+
73
+ } else {
74
+
75
+
76
+ LogInfoMessage(`Worker ${process.pid} started`);
77
+
78
+ //const worker = new WorkerProcessBase(ServiceConfigOptions(true, cluster.isPrimary));
79
+ //worker.SetupServer();
80
+
81
+ const hostName = 'host01';
82
+ const agentId = 'agent01';
83
+ const userAgent = 'userAgent01'
84
+
85
+ const asyncRunnerContext: IAsyncRunnerContext = {
86
+ nid: `\
87
+ ${hostName}${ModelDelimeter.COMPONENT_SEPERATOR}${agentId}-${userAgent}\
88
+ ${ModelDelimeter.NID_SEPERATOR}\
89
+ MainProcess\
90
+ ${ModelDelimeter.SEPERATOR}\
91
+ 0`,
92
+ id: uuidv4(),
93
+ // id: `${applicationStore.applicationConfig.HOST}${ModelDelimeter.COMPONENT_SEPERATOR}${applicationStore.applicationConfig.AGENT_ID}-${applicationStore.applicationConfig.USER_AGENT}`,
94
+ hostName: (hostName ? hostName : 'host01'),
95
+ agentName: `${agentId}-${userAgent}`,
96
+ threadId: 'MainProcess',
97
+ asyncRunnerId: 0
98
+ }
99
+
100
+ const url = `https://stscore.stsmda.org:3001/stsinstrumentmanager/v1/publishmessage`;
101
+
102
+ const publishTransportOptions: IPublishTransportRESTServerOptions = {
103
+ transportType: TransportType.RESTAPI,
104
+ //url: `${goptions.imendpoint}:${goptions.import}${goptions.imapiroot}/publishmessage`,
105
+ url,
106
+ logger: defaultLogger,
107
+ agentOptions: {
108
+ keepAlive: goptions.keepAlive,
109
+ maxSockets: goptions.maxSockets,
110
+ maxTotalSockets: goptions.maxTotalSockets,
111
+ maxFreeSockets: goptions.maxFreeSockets,
112
+ timeout: 30000, //@@ config
113
+ rejectUnauthorized: goptions.isProduction // Allows self signed certs in non production mode(s)
114
+ },
115
+ showPublishPayload: false
116
+ };
117
+
118
+ LogInfoMessage(`publishTransportOptions: [${publishTransportOptions.url}]`);
119
+
120
+ const standardInstruments: InstrumentDefinitions = [
121
+ [ Gauge.TIMER_GAUGE, GaugeTypes.INSTRUMENT_TIMER ],
122
+ [ Gauge.LOGGER, GaugeTypes.INSTRUMENT_LOG, {
123
+ consoleLogging: process.env.consoleLogging,
124
+ instrumentLogging: process.env.instrumentLogging } as InstrumentLogOptions],
125
+ [ Gauge.NETWORK_RX_GAUGE , GaugeTypes.INSTRUMENT_VELOCITY ],
126
+ [ Gauge.NETWORK_TX_GAUGE, GaugeTypes.INSTRUMENT_VELOCITY ]
127
+ ];
128
+
129
+ const agentInstruments: InstrumentDefinitions = [
130
+ [ Gauge.REQUEST_COUNT_GAUGE, GaugeTypes.INSTRUMENT_GAUGE ], // Total number of requests serviced
131
+ [ Gauge.ERROR_COUNT_GAUGE, GaugeTypes.INSTRUMENT_GAUGE ],
132
+ [ Gauge.RETRY_COUNT_GAUGE, GaugeTypes.INSTRUMENT_GAUGE ],
133
+ [ Gauge.AUTHENTICATION_COUNT_GAUGE, GaugeTypes.INSTRUMENT_GAUGE ], // Total number of new token requests
134
+ [ Gauge.AUTHENTICATION_ERROR_COUNT_GAUGE, GaugeTypes.INSTRUMENT_GAUGE ], // Total number of new token requests errors
135
+ [ Gauge.AUTHENTICATION_RETRY_COUNT_GAUGE, GaugeTypes.INSTRUMENT_GAUGE ], // Total number of new token requests retries
136
+ [ Gauge.ACTIVE_REQUEST_GAUGE, GaugeTypes.INSTRUMENT_GAUGE, { // Total number of runners (in-flight) requests
137
+ interval: process.env.instrumentationObservationInterval,
138
+ sampleSize: process.env.instrumentationTimeWindow } as InstrumentGaugeOptions],
139
+ [ Gauge.DURATION_GAUGE, GaugeTypes.INSTRUMENT_GAUGE, { // Duration of latest http(s) request.
140
+ interval: process.env.instrumentationObservationInterval,
141
+ sampleSize: process.env.instrumentationTimeWindow } as InstrumentGaugeOptions],
142
+ [ Gauge.DURATION_HISTOGRAM_GAUGE, GaugeTypes.INSTRUMENT_HISTOGRAM ],
143
+ [ Gauge.VELOCITY_GAUGE, GaugeTypes.INSTRUMENT_VELOCITY ], // Requests per second
144
+ [ Gauge.CORE_COUNT_GAUGE, GaugeTypes.INSTRUMENT_GAUGE ], // Thread count (for http agents)
145
+ [ Gauge.LATENCY_GAUGE, GaugeTypes.INSTRUMENT_GAUGE, {
146
+ interval: process.env.instrumentationObservationInterval,
147
+ sampleSize: process.env.instrumentationTimeWindow } as InstrumentGaugeOptions],
148
+ [ Gauge.LATENCY_HISTOGRAM_GAUGE, GaugeTypes.INSTRUMENT_HISTOGRAM ],
149
+ [ Gauge.CHILD_COUNT, GaugeTypes.INSTRUMENT_GAUGE ] // Number of async runners idle or running
150
+ ]
151
+
152
+ const instrumentControllerOptions: IPublishInstrumentControllerOptions = {
153
+ processContext: asyncRunnerContext,
154
+ instrumentationObservationInterval: 1000, //@@
155
+ instrumentationTimeWindow: 600, //@@
156
+ publisherTransport: new PublishTransportRESTServer(publishTransportOptions),
157
+ logger: defaultLogger,
158
+ publishInterval: 1000, //@@
159
+ //instrumentDefinitions: GetInstruments('agent')
160
+ instrumentDefinitions: [
161
+ ...standardInstruments,
162
+ ...agentInstruments
163
+ ]
164
+ }
165
+
166
+ const agentInstrumentController = new AgentInstrumentController(instrumentControllerOptions);
167
+ agentInstrumentController.StartPublish();
168
+
169
+ const workerFactory: IWorkerFactory = {
170
+
171
+ createPrimaryThreadWorker: (app: any, options: IWorkerOptions): IPrimaryWorker => {
172
+ return new WorkerPrimaryTestRunner01(app, options);
173
+ },
174
+ createWorkerThreadWorker: (): Worker => {
175
+
176
+ LogInfoMessage(`createWorkerThreadWorker`);
177
+
178
+ const fileName ='./dist/testertesting/workerWorkerTestRunner01.js';
179
+
180
+ const publishCollectorWebWorker = new Worker(fileName);
181
+ publishCollectorWebWorker.unref();
182
+
183
+ return publishCollectorWebWorker;
184
+ },
185
+ get workerThreadWorkerOptions(): IWorkerOptions {
186
+ return {
187
+ agentId,
188
+ hostName,
189
+ userAgent,
190
+ workdata: 'worker - hello world'
191
+ } as IWorkerOptions;
192
+ },
193
+ get primaryThreadWorkerOptions(): IWorkerOptions {
194
+ return {
195
+ agentId,
196
+ hostName,
197
+ userAgent,
198
+ primaryoptions: 'primary - hello world'
199
+ } as IWorkerOptions;
200
+ }
201
+ }
202
+
203
+ const xx = async () => {
204
+ const wm = new STSWorkerManager(null, {
205
+ workerFactory,
206
+ publishInstrumentController: agentInstrumentController
207
+ });
208
+ const worker = await wm.AddWorker();
209
+
210
+ const runnerOptions: IRunnerOptions = {
211
+ iterations: 100000,
212
+ sleepDuration: 250,
213
+ messageMod: 1,
214
+ logMessageMod: 1
215
+ } as IRunnerOptions;
216
+
217
+ const runner = wm.AddRunnerToWorker(worker, runnerOptions);
218
+
219
+ };
220
+ xx();
221
+
222
+
223
+ /*
224
+ const fileName ='./dist/webworkertesting/worker.js';
225
+
226
+ const clusterWorker = new Worker(fileName);
227
+ clusterWorker.unref();
228
+
229
+ clusterWorker.postMessage({cmd: 'text', message: 'Hello World'});
230
+
231
+ clusterWorker.on('message', (data: any) => {
232
+ LogInfoMessage(`cluster.worker (${process.pid}): message from worker = [${JSON.stringify(data)}]`);
233
+ });
234
+ */
235
+
236
+ LogInfoMessage(`cluster work completed ...`);
237
+
238
+ }
@@ -0,0 +1,50 @@
1
+ import { IContextBase } from '@nsshunt/stsobservability'
2
+
3
+ export const URI_BASE_VUEUTILS: string = '/';
4
+
5
+ export interface IAsyncRunnerContext extends IContextBase {
6
+ id: string
7
+ hostName: string
8
+ agentName: string
9
+ threadId: string
10
+ asyncRunnerId: number
11
+ }
12
+
13
+ /**
14
+ * Inter-Worker (IW) Payload context base.
15
+ */
16
+ export interface IIWMessagePayloadContentBase {
17
+ messageId?: string
18
+ }
19
+
20
+ /**
21
+ * Inter-Worker (IW) message commands.
22
+ */
23
+ export enum eIWMessageCommands {
24
+ InstrumentTelemetry ='__STS__InstrumentTelemetry', // Used to send instrument telemetry
25
+ MessagePort = '__STS__MessagePort',
26
+ MessagePortResponse = '__STS__MessagePortResponse',
27
+ AddAsyncRunner = '__STS__AddAsyncRunner',
28
+ StopAllAsyncRunners = '__STS__StopAllAsyncRunners',
29
+ }
30
+
31
+ /**
32
+ * Inter-Worker (IW) message command.
33
+ */
34
+ export type IIWMessageCommand = eIWMessageCommands
35
+
36
+ /**
37
+ * Inter-Worker (IW) message payload.
38
+ */
39
+ export interface IIWMessagePayload {
40
+ command: IIWMessageCommand
41
+ payload: IIWMessagePayloadContentBase
42
+ }
43
+
44
+ export interface IObservabilitySubscriberManagerOptions {
45
+ modelId: string
46
+ consumeInstrumentationMode: string
47
+ instrumentManagerEndpoint: string
48
+ instrumentManagerPort: string
49
+ instrumentManagerAPIRoot: string
50
+ }
@@ -0,0 +1,95 @@
1
+ /* eslint @typescript-eslint/no-explicit-any: 0, @typescript-eslint/no-unused-vars: 0 */ // --> OFF
2
+ import { MessagePort } from 'worker_threads';
3
+
4
+ import type { IIWMessagePayload } from './commonTypes'
5
+
6
+ import { defaultLogger } from '@nsshunt/stsutils'
7
+
8
+ declare interface RequestResponseMessage {
9
+ publishMessagePayload: IIWMessagePayload
10
+ publishMessagePayloadResponse?: IIWMessagePayload
11
+ cb: () => void,
12
+ timeout: NodeJS.Timeout
13
+ }
14
+
15
+ declare type RequestResponseMessages = Record<string, RequestResponseMessage>;
16
+
17
+ //@@ this should become a low level stsutils type helper
18
+ export class RequestResponseHelper
19
+ {
20
+ #requestResponseMessages: RequestResponseMessages = { }
21
+ #requestResponseMessageTimeout = 10000; //@@ config
22
+ #port: MessagePort
23
+
24
+ constructor(port: MessagePort) {
25
+ this.#port = port
26
+ this.#SetupListener();
27
+ }
28
+
29
+
30
+ #debug = (message: any) => {
31
+ defaultLogger.debug(message);
32
+ }
33
+
34
+ PostMessage = (message: IIWMessagePayload): Promise<IIWMessagePayload> => {
35
+ return new Promise((resolve, reject) => {
36
+ const { messageId } = message.payload;
37
+ if (messageId) {
38
+ if (this.#requestResponseMessages[messageId]) {
39
+ reject(`RequestResponseHelper: Message with id: [${messageId}] already exists within the Request/Response record structure`);
40
+ } else {
41
+ this.#requestResponseMessages[messageId] = {
42
+ publishMessagePayload: { ...message },
43
+ cb: () => {
44
+ const detail = this.#requestResponseMessages[messageId].publishMessagePayloadResponse;
45
+ clearTimeout(this.#requestResponseMessages[messageId].timeout);
46
+ setTimeout(() => {
47
+ delete this.#requestResponseMessages[messageId];
48
+ }, 0);
49
+ if (detail) {
50
+ this.#debug(`RequestResponseHelper: Resolving response message with id: [${messageId}] from target worker port. Details: [${JSON.stringify(detail)}]`);
51
+ resolve(detail);
52
+ } else {
53
+ const msg = `Could not get detail from this.#requestResponseMessages[messageId].publishMessagePayloadResponse`;
54
+ this.#debug(msg);
55
+ reject(msg);
56
+ }
57
+ },
58
+ timeout: setTimeout(() => {
59
+ setTimeout(() => {
60
+ delete this.#requestResponseMessages[messageId];
61
+ }, 0);
62
+ this.#debug(`RequestResponseHelper: Timeout has occurred after: [${this.#requestResponseMessageTimeout}]ms with message id: [${messageId}]. Details: [${JSON.stringify(this.#requestResponseMessages[messageId].publishMessagePayload)}]`);
63
+ reject('RequestResponseHelper: Did not receive response form parent process.');
64
+ }, this.#requestResponseMessageTimeout) // max message timeout allowed
65
+ };
66
+ //debug(`RequestResponseHelper: Sending message with id: [${messageId}] to target worker port. Details: [${JSON.stringify(this.#requestResponseMessages[messageId].publishMessagePayload)}]`);
67
+ this.#port.postMessage(message);
68
+ }
69
+ } else {
70
+ const msg = `RequestResponseHelper: Response did not include a message id`;
71
+ this.#debug(msg);
72
+ reject(msg);
73
+ }
74
+ });
75
+ }
76
+
77
+ #SetupListener = () => {
78
+ //this.#port.onmessage = async (msg: MessageEvent) => {
79
+ this.#port.on('message', (msg: any) => {
80
+ const publishMessagePayload: IIWMessagePayload = msg.data as IIWMessagePayload;
81
+ if (publishMessagePayload.payload.messageId) {
82
+ const messageId = publishMessagePayload.payload.messageId;
83
+ if (messageId && messageId !== '') {
84
+ if (this.#requestResponseMessages[messageId]) {
85
+ const requestResponseMessage: RequestResponseMessage = this.#requestResponseMessages[messageId];
86
+ requestResponseMessage.publishMessagePayloadResponse = { ...publishMessagePayload };
87
+ requestResponseMessage.cb();
88
+ } else {
89
+ throw new Error(`RequestResponseHelper: Could not find Request/Response message with id: [${messageId}]`);
90
+ }
91
+ }
92
+ }
93
+ });
94
+ }
95
+ }
@@ -0,0 +1,150 @@
1
+ import { Worker, MessagePort } from 'worker_threads';
2
+
3
+ import { PublishInstrumentController } from '@nsshunt/stsobservability'
4
+
5
+ import { IAsyncRunnerContext } from './commonTypes'
6
+
7
+ export interface ISTSAgentWorkerMessagePort extends IIWMessagePayloadContentBase {
8
+ port: MessagePort
9
+ options: IWorkerOptions
10
+ }
11
+
12
+ export enum IRunnerState {
13
+ created = 'created',
14
+ running = 'running',
15
+ stopped = 'stopped',
16
+ paused = 'paused',
17
+ error = 'error',
18
+ }
19
+
20
+ export interface IRunnerTelemetry {
21
+ requestCount: number // requestCount
22
+ errorCount: number
23
+ retryCount: number
24
+ authenticationCount: number
25
+ authenticationErrorCount: number
26
+ authenticationRetryCount: number
27
+ velocity: number
28
+ coreCount: number
29
+ timer: number
30
+ duration: number
31
+ latency: number
32
+ activeRequestCount: number
33
+ message: string[]
34
+ childCount: number
35
+ rx: number
36
+ tx: number
37
+ }
38
+
39
+ export interface IRunner {
40
+ id: number
41
+ asyncRunnerContext: IAsyncRunnerContext
42
+ options: IRunnerOptions
43
+ state: IRunnerState
44
+ instrumentData: IRunnerTelemetry
45
+ }
46
+
47
+ export interface IRunnerEx extends IRunner {
48
+ publishInstrumentController: PublishInstrumentController
49
+ Stop: () => Promise<boolean>
50
+ }
51
+
52
+ export enum IWorkerState {
53
+ starting = 'starting',
54
+ started = 'started',
55
+ stopped = 'stopped'
56
+ }
57
+
58
+
59
+ export interface IWorkerOptions {
60
+ hostName: string
61
+ agentId: string
62
+ userAgent: string
63
+ }
64
+
65
+ export type Runners = Record<string, IRunner>
66
+
67
+ export interface IWorker {
68
+ id: number
69
+ state: IWorkerState
70
+ primaryThreadWorkerOptions: IWorkerOptions
71
+ workerThreadWorkerOptions: IWorkerOptions
72
+ runners?: Runners // Will be created by utility helper
73
+ }
74
+
75
+ export type Workers = Record<string, IWorker>
76
+
77
+ export interface IPrimaryWorker {
78
+ ProcessMessageFromWorker(workerPort: MessagePort, publishMessagePayload: IIWMessagePayload): Promise<void>
79
+ }
80
+
81
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
82
+ export interface IRunnerOptions {
83
+
84
+ }
85
+
86
+ export interface IWorkerEx extends IWorker {
87
+ worker: Worker
88
+ primaryWorker: IPrimaryWorker
89
+ runnersEx: Record<string, IRunnerEx>
90
+ AddRunner: (runnerOptions: IRunnerOptions) => IRunnerEx
91
+ StopRunner: (runner: IRunnerEx) => Promise<boolean>
92
+ Stop: () => Promise<boolean>
93
+ }
94
+
95
+ export interface ISTSTestWorkerOptions {
96
+ messageMod: number
97
+ iterations: number
98
+ }
99
+
100
+ export interface ITelemetryStore {
101
+ workers: Workers
102
+ }
103
+
104
+ export interface ITestRunnerTelemetryPayload extends IIWMessagePayloadContentBase {
105
+ runner: IRunner
106
+ }
107
+
108
+ export interface IWorkerFactory {
109
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
110
+ createPrimaryThreadWorker: (app: any, options: IWorkerOptions) => IPrimaryWorker
111
+ createWorkerThreadWorker: () => Worker // | wt.Worker
112
+ get workerThreadWorkerOptions(): IWorkerOptions // These options will be passed as a message to the thread worker once setup
113
+ get primaryThreadWorkerOptions(): IWorkerOptions // These options will be passed as a message to the thread worker once setup
114
+ }
115
+
116
+ export interface IWorkerManagerOptions {
117
+ workerFactory: IWorkerFactory
118
+ publishInstrumentController: PublishInstrumentController
119
+ }
120
+
121
+ export enum eIWMessageCommands {
122
+ InstrumentTelemetry = "__STS__InstrumentTelemetry",// Used to send instrument telemetry
123
+ MessagePort = "__STS__MessagePort",
124
+ MessagePortResponse = "__STS__MessagePortResponse",
125
+ AddAsyncRunner = "__STS__AddAsyncRunner",
126
+ StopAllAsyncRunners = "__STS__StopAllAsyncRunners"
127
+ }
128
+
129
+ export const PublishMessageCommandsTestRunner = {
130
+ ...eIWMessageCommands,
131
+ GetAccessToken: '__GetAccessToken',
132
+ GetAccessTokenResponse: '__GetAccessTokenResponse',
133
+ GetDataFromPrimary: '__GetDataFromPrimary',
134
+ ExecuteRefreshToken: '__ExecuteRefreshToken',
135
+ ExecuteRefreshTokenResponse: '__ExecuteRefreshTokenResponse'
136
+ } as const
137
+
138
+ export type PublishMessageCommandsTestRunner = typeof PublishMessageCommandsTestRunner[keyof typeof PublishMessageCommandsTestRunner];
139
+
140
+ export type IIWMessageCommand = eIWMessageCommands;
141
+
142
+ export interface IIWMessagePayloadContentBase {
143
+ messageId?: string;
144
+ }
145
+
146
+ export interface IIWMessagePayload {
147
+ command: IIWMessageCommand;
148
+ payload: IIWMessagePayloadContentBase;
149
+ }
150
+
@@ -0,0 +1,154 @@
1
+ /* eslint @typescript-eslint/no-explicit-any: 0, @typescript-eslint/no-unused-vars: 0 */ // --> OFF
2
+ import { MessagePort } from 'worker_threads';
3
+
4
+ import { IIWMessagePayload, eIWMessageCommands, IIWMessagePayloadContentBase } from './commonTypes'
5
+
6
+ import type { ISTSAgentWorkerMessagePort, IRunner, ITestRunnerTelemetryPayload } from './stsTestWorkerDefinitions'
7
+ import { IRunnerState } from './stsTestWorkerDefinitions'
8
+
9
+ import { RequestResponseHelper } from './requestResponseHelper'
10
+
11
+ import chalk from 'chalk';
12
+ // Force chalk level
13
+ chalk.level = 3;
14
+
15
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
16
+ export interface IWorkerInstanceOptions {
17
+
18
+ }
19
+
20
+ export abstract class WorkerInstance {
21
+ #collectorCollectorPort: MessagePort | null = null;
22
+ #requestResponseHelper: RequestResponseHelper | null = null;
23
+ #runners: Record<string, IRunner> = { };
24
+ #options: IWorkerInstanceOptions | null = null;
25
+
26
+ #debug = (message: string) => {
27
+ console.log(chalk.green(`pid: [${process.pid}] WorkerInstance::${message}`));
28
+ }
29
+
30
+
31
+ constructor() {
32
+ this.#debug(`constructor`)
33
+ }
34
+
35
+ GetRandomInt = (max: number) => {
36
+ this.#debug(`GetRandomInt`)
37
+ return Math.floor(Math.random() * Math.floor(max));
38
+ };
39
+
40
+
41
+ StartWork = async (runner: IRunner): Promise<void> => {
42
+ this.#debug(`StartWork`)
43
+ return;
44
+ }
45
+
46
+ PostTelemetry = (runner: IRunner) => {
47
+ //debug(`WorkerInstance::PostTelemetry`)
48
+ if (this.#collectorCollectorPort) {
49
+ const message: IIWMessagePayload = {
50
+ command: eIWMessageCommands.InstrumentTelemetry,
51
+ payload: {
52
+ runner
53
+ } as ITestRunnerTelemetryPayload
54
+ }
55
+ this.#collectorCollectorPort.postMessage(message);
56
+ }
57
+ }
58
+
59
+ get RequestResponseHelper(): RequestResponseHelper | null {
60
+ return this.#requestResponseHelper;
61
+ }
62
+
63
+ get CollectorCollectorPort(): MessagePort | null {
64
+ return this.#collectorCollectorPort;
65
+ }
66
+
67
+ get Options(): IWorkerInstanceOptions | null {
68
+ return this.#options;
69
+ }
70
+
71
+ #SetMessagePort = (workerMessagePort: ISTSAgentWorkerMessagePort) => {
72
+ this.#debug(`SetMessagePort`)
73
+ this.#collectorCollectorPort = workerMessagePort.port as MessagePort;
74
+
75
+ // NodeJS version
76
+ this.#collectorCollectorPort.on('message', (data: any) => {
77
+ this.#debug(`collectorCollectorPort onmessage: ${data.data}`);
78
+ });
79
+
80
+ // Browser Version
81
+ /*
82
+ this.#collectorCollectorPort.onmessage = function(data: MessageEvent) {
83
+ console.log(`collectorCollectorPort onmessage: ${data.data}`);
84
+ }
85
+ */
86
+
87
+ this.#requestResponseHelper = new RequestResponseHelper(this.#collectorCollectorPort);
88
+
89
+ const response: IIWMessagePayload = {
90
+ command: eIWMessageCommands.MessagePortResponse,
91
+ payload: { } as IIWMessagePayloadContentBase
92
+ }
93
+
94
+ this.#collectorCollectorPort.postMessage(response);
95
+ }
96
+
97
+ StartRunner = async (runner: IRunner) => {
98
+ this.#debug(`StartRunner`)
99
+ this.#debug(`StartTests: [${JSON.stringify(runner)}]`);
100
+ runner.state = IRunnerState.running;
101
+ this.StartWork(runner);
102
+ }
103
+
104
+ #AddAsyncRunner = (testRunnerTelemetryPayload: ITestRunnerTelemetryPayload) => {
105
+ this.#debug(`AddAsyncRunner`)
106
+ const { runner } = testRunnerTelemetryPayload;
107
+ this.#runners[runner.id] = runner;
108
+ this.StartRunner(runner);
109
+ }
110
+
111
+ #StopRunners = (testRunnerTelemetryPayload: ITestRunnerTelemetryPayload) => {
112
+ this.#debug(`StopRunners`)
113
+ if (testRunnerTelemetryPayload === null) {
114
+ for (const [, testRunner] of Object.entries(this.#runners)) {
115
+ testRunner.state = IRunnerState.stopped;
116
+ }
117
+ } else {
118
+ const runner: IRunner = this.#runners[testRunnerTelemetryPayload.runner.id];
119
+ if (runner) {
120
+ runner.state = IRunnerState.stopped;
121
+ }
122
+ }
123
+ }
124
+
125
+ // ProcessMessage = async(data: MessageEvent) => { // Browser version
126
+ ProcessMessage = async(data: any) => {
127
+ this.#debug(`ProcessMessage: data: [${JSON.stringify(data)}]`)
128
+ try {
129
+ // const payloadMessage: IIWMessagePayload = data.data as IIWMessagePayload; // browser version
130
+ const payloadMessage: IIWMessagePayload = data as IIWMessagePayload;
131
+ switch (payloadMessage.command) {
132
+ case eIWMessageCommands.MessagePort :
133
+ this.#debug(`ProcessMessage::MessagePort`)
134
+ this.#SetMessagePort(payloadMessage.payload as ISTSAgentWorkerMessagePort);
135
+ this.#options = (payloadMessage.payload as ISTSAgentWorkerMessagePort).options;
136
+ this.#debug(`ProcessMessage::#options: [${JSON.stringify(this.#options)}]`)
137
+ break;
138
+ case eIWMessageCommands.AddAsyncRunner :
139
+ this.#debug(`ProcessMessage::AddAsyncRunner`)
140
+ this.#AddAsyncRunner(payloadMessage.payload as ITestRunnerTelemetryPayload);
141
+ break;
142
+ case eIWMessageCommands.StopAllAsyncRunners :
143
+ this.#debug(`ProcessMessage::StopAllAsyncRunners`)
144
+ this.#StopRunners(payloadMessage.payload as ITestRunnerTelemetryPayload);
145
+ break;
146
+ default :
147
+ this.#debug(`ProcessMessage::default`)
148
+ this.#debug(`Invalid payloadMessage.command: [${payloadMessage.command}] - Ignoring`);
149
+ }
150
+ } catch (error) {
151
+ console.log(error);
152
+ }
153
+ }
154
+ }