@nsshunt/stsrunnerframework 1.0.200 → 2.0.2
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/README.md +1059 -1
- package/dist/stsrunnerframework.mjs +8279 -4105
- package/dist/stsrunnerframework.mjs.map +1 -1
- package/dist/stsrunnerframework.umd.js +8304 -4119
- package/dist/stsrunnerframework.umd.js.map +1 -1
- package/package.json +4 -4
- package/types/abstractRunnerExecutionWorker.d.ts +194 -0
- package/types/abstractRunnerExecutionWorker.d.ts.map +1 -0
- package/types/archiveManager.d.ts +172 -0
- package/types/archiveManager.d.ts.map +1 -0
- package/types/asyncRunnerInstanceManager.d.ts +108 -0
- package/types/asyncRunnerInstanceManager.d.ts.map +1 -0
- package/types/commonTypes.d.ts +115 -35
- package/types/commonTypes.d.ts.map +1 -1
- package/types/index.d.ts +1 -1
- package/types/index.d.ts.map +1 -1
- package/types/messageBroker.d.ts +324 -0
- package/types/messageBroker.d.ts.map +1 -0
- package/types/runnerInstance.d.ts +245 -0
- package/types/runnerInstance.d.ts.map +1 -0
- package/types/runnerLifecycleManager.d.ts +210 -0
- package/types/runnerLifecycleManager.d.ts.map +1 -0
- package/types/telemetryProcessor.d.ts +67 -0
- package/types/telemetryProcessor.d.ts.map +1 -1
- package/types/testing/mockedWorkerTestRunner01.d.ts +129 -2
- package/types/testing/mockedWorkerTestRunner01.d.ts.map +1 -1
- package/types/testing/testCase01.d.ts +222 -2
- package/types/testing/testCase01.d.ts.map +1 -1
- package/types/testing/testCase02.d.ts +206 -2
- package/types/testing/testCase02.d.ts.map +1 -1
- package/types/testing/wmwokerProcess.test.d.ts +1 -0
- package/types/testing/wmwokerProcess2.test.d.ts +1 -0
- package/types/workerCommandCoordinator.d.ts +152 -0
- package/types/workerCommandCoordinator.d.ts.map +1 -0
- package/types/workerInstance.d.ts +340 -16
- package/types/workerInstance.d.ts.map +1 -1
- package/types/workerInstanceMannager.d.ts +170 -0
- package/types/workerInstanceMannager.d.ts.map +1 -0
- package/types/workerManager.d.ts +335 -24
- package/types/workerManager.d.ts.map +1 -1
- package/types/workerRegistry.d.ts +251 -0
- package/types/workerRegistry.d.ts.map +1 -0
- package/types/workerStateSynchroniser.d.ts +161 -0
- package/types/workerStateSynchroniser.d.ts.map +1 -0
package/README.md
CHANGED
|
@@ -1,4 +1,1062 @@
|
|
|
1
|
-
#
|
|
1
|
+
# STS Runner Framework
|
|
2
|
+
|
|
3
|
+
A **high-performance asynchronous runner orchestration framework** for Node.js and browser environments.
|
|
4
|
+
|
|
5
|
+
The framework enables you to build systems that execute large numbers of **concurrent test runners or workload generators** across **worker processes**, with:
|
|
6
|
+
|
|
7
|
+
* asynchronous runner lifecycle management
|
|
8
|
+
* distributed worker execution
|
|
9
|
+
* structured telemetry
|
|
10
|
+
* instrumentation integration
|
|
11
|
+
* dynamic runner configuration
|
|
12
|
+
* state synchronization
|
|
13
|
+
* archive history tracking
|
|
14
|
+
* event-driven observability
|
|
15
|
+
|
|
16
|
+
The framework is designed for scenarios such as:
|
|
17
|
+
|
|
18
|
+
* load testing
|
|
19
|
+
* distributed task execution
|
|
20
|
+
* asynchronous job orchestration
|
|
21
|
+
* testing frameworks
|
|
22
|
+
* automation systems
|
|
23
|
+
* telemetry-driven workload engines
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
# Table of Contents
|
|
28
|
+
|
|
29
|
+
* Overview
|
|
30
|
+
* Architecture
|
|
31
|
+
* Core Concepts
|
|
32
|
+
* System Components
|
|
33
|
+
* Execution Flow
|
|
34
|
+
* Telemetry and Observability
|
|
35
|
+
* Runner Lifecycle
|
|
36
|
+
* Worker Lifecycle
|
|
37
|
+
* State Synchronization
|
|
38
|
+
* Archiving
|
|
39
|
+
* Client Usage
|
|
40
|
+
* Creating Custom Runners
|
|
41
|
+
* Example Test Runner
|
|
42
|
+
* Example Client
|
|
43
|
+
* Threading Model
|
|
44
|
+
* Design Goals
|
|
45
|
+
* Future Enhancements
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
# Overview
|
|
50
|
+
|
|
51
|
+
The **STS Runner Framework** provides a scalable architecture for executing **multiple runners across multiple workers**, with centralized orchestration.
|
|
52
|
+
|
|
53
|
+
The system consists of three primary layers:
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
Client Application
|
|
57
|
+
│
|
|
58
|
+
▼
|
|
59
|
+
STSWorkerManager (Coordinator)
|
|
60
|
+
│
|
|
61
|
+
▼
|
|
62
|
+
Workers (Execution Hosts)
|
|
63
|
+
│
|
|
64
|
+
▼
|
|
65
|
+
Runners (User Workload Logic)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Key properties:
|
|
69
|
+
|
|
70
|
+
* **Workers isolate execution**
|
|
71
|
+
* **Runners perform actual work**
|
|
72
|
+
* **Manager coordinates everything**
|
|
73
|
+
* **Telemetry flows upward**
|
|
74
|
+
* **Commands flow downward**
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
# Architecture
|
|
79
|
+
|
|
80
|
+
The framework is composed of several subsystems:
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
Client Application
|
|
84
|
+
│
|
|
85
|
+
▼
|
|
86
|
+
STSWorkerManager
|
|
87
|
+
│
|
|
88
|
+
├── WorkerRegistry
|
|
89
|
+
├── WorkerInstanceManager
|
|
90
|
+
├── RunnerLifecycleManager
|
|
91
|
+
├── WorkerStateSynchroniser
|
|
92
|
+
├── WorkerCommandCoordinator
|
|
93
|
+
├── AsyncRunnerInstanceManager
|
|
94
|
+
├── STSMessageBroker
|
|
95
|
+
└── ArchiveManager
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Each subsystem has a clearly defined responsibility.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
# Core Concepts
|
|
103
|
+
|
|
104
|
+
## Worker
|
|
105
|
+
|
|
106
|
+
A **Worker** represents an execution host.
|
|
107
|
+
|
|
108
|
+
Workers may run:
|
|
109
|
+
|
|
110
|
+
* inside Node.js worker threads
|
|
111
|
+
* inside browser workers
|
|
112
|
+
* in mocked in-process environments
|
|
113
|
+
|
|
114
|
+
Workers host **multiple runners**.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Runner
|
|
119
|
+
|
|
120
|
+
A **Runner** is the unit that performs actual work.
|
|
121
|
+
|
|
122
|
+
Examples:
|
|
123
|
+
|
|
124
|
+
* HTTP load test
|
|
125
|
+
* API validation
|
|
126
|
+
* database operation
|
|
127
|
+
* workflow automation
|
|
128
|
+
* synthetic telemetry generator
|
|
129
|
+
|
|
130
|
+
Runners implement:
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
interface IRunnerInstance
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Typical methods:
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
ExecuteRunner()
|
|
140
|
+
StartRunner()
|
|
141
|
+
StopRunner()
|
|
142
|
+
PauseRunner()
|
|
143
|
+
ResumeRunner()
|
|
144
|
+
ResetRunner()
|
|
145
|
+
TerminateRunner()
|
|
146
|
+
UpdateRunner()
|
|
147
|
+
Completed()
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Manager
|
|
153
|
+
|
|
154
|
+
The **STSWorkerManager** is the central coordinator.
|
|
155
|
+
|
|
156
|
+
It:
|
|
157
|
+
|
|
158
|
+
* creates workers
|
|
159
|
+
* creates runners
|
|
160
|
+
* dispatches commands
|
|
161
|
+
* collects telemetry
|
|
162
|
+
* synchronizes state
|
|
163
|
+
* archives completed runners
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Telemetry
|
|
168
|
+
|
|
169
|
+
Telemetry represents runtime metrics generated by runners.
|
|
170
|
+
|
|
171
|
+
Examples:
|
|
172
|
+
|
|
173
|
+
```
|
|
174
|
+
requestCount
|
|
175
|
+
errorCount
|
|
176
|
+
velocity
|
|
177
|
+
latency
|
|
178
|
+
duration
|
|
179
|
+
activeRequestCount
|
|
180
|
+
tx
|
|
181
|
+
rx
|
|
182
|
+
message[]
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Telemetry flows from:
|
|
186
|
+
|
|
187
|
+
```
|
|
188
|
+
Runner → Worker → Manager → Client
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
# System Components
|
|
194
|
+
|
|
195
|
+
## STSWorkerManager
|
|
196
|
+
|
|
197
|
+
The **core orchestrator** of the framework.
|
|
198
|
+
|
|
199
|
+
Responsibilities:
|
|
200
|
+
|
|
201
|
+
* worker creation
|
|
202
|
+
* runner creation
|
|
203
|
+
* lifecycle command dispatch
|
|
204
|
+
* state synchronization
|
|
205
|
+
* archive management
|
|
206
|
+
* telemetry processing
|
|
207
|
+
|
|
208
|
+
Example initialization:
|
|
209
|
+
|
|
210
|
+
```ts
|
|
211
|
+
const wm = new STSWorkerManager({
|
|
212
|
+
workerFactory,
|
|
213
|
+
maxArchiveListLength: 200,
|
|
214
|
+
logger: defaultLogger,
|
|
215
|
+
logLevel: 4,
|
|
216
|
+
messageTimeout: 10000
|
|
217
|
+
});
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## WorkerRegistry
|
|
223
|
+
|
|
224
|
+
Stores the in-memory runtime graph of the system.
|
|
225
|
+
|
|
226
|
+
```
|
|
227
|
+
WorkerRegistry
|
|
228
|
+
├── WorkerEx
|
|
229
|
+
│ └── RunnerEx
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Provides:
|
|
233
|
+
|
|
234
|
+
```
|
|
235
|
+
AddWorker()
|
|
236
|
+
AddRunner()
|
|
237
|
+
DeleteWorker()
|
|
238
|
+
DeleteRunner()
|
|
239
|
+
GetWorkersMap()
|
|
240
|
+
GetWorkersCoreMap()
|
|
241
|
+
GetNextAvailableWorker()
|
|
242
|
+
GetBusiestWorker()
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## WorkerInstanceManager
|
|
248
|
+
|
|
249
|
+
Responsible for **creating worker instances** and wiring system events.
|
|
250
|
+
|
|
251
|
+
Handles:
|
|
252
|
+
|
|
253
|
+
* worker creation
|
|
254
|
+
* exit events
|
|
255
|
+
* error events
|
|
256
|
+
* message error events
|
|
257
|
+
|
|
258
|
+
Supports:
|
|
259
|
+
|
|
260
|
+
```
|
|
261
|
+
Node Worker Threads
|
|
262
|
+
Browser Workers
|
|
263
|
+
Mock Workers
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## STSMessageBroker
|
|
269
|
+
|
|
270
|
+
Provides **message routing between manager and workers**.
|
|
271
|
+
|
|
272
|
+
Responsibilities:
|
|
273
|
+
|
|
274
|
+
```
|
|
275
|
+
SendMessageToWorkerForRunnerWithCallBack()
|
|
276
|
+
SendMessageToWorkerForWorkerWithCallBack()
|
|
277
|
+
SetupMessagePort()
|
|
278
|
+
SetupMessagePortListener()
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
Uses `MessagePort` communication channels.
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## AsyncRunnerInstanceManager
|
|
286
|
+
|
|
287
|
+
Creates and manages **runner instances inside workers**.
|
|
288
|
+
|
|
289
|
+
Responsibilities:
|
|
290
|
+
|
|
291
|
+
* runner creation
|
|
292
|
+
* runner execution control
|
|
293
|
+
* instrument controller attachment
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## RunnerLifecycleManager
|
|
298
|
+
|
|
299
|
+
Handles **runner telemetry and lifecycle state updates**.
|
|
300
|
+
|
|
301
|
+
Responsibilities:
|
|
302
|
+
|
|
303
|
+
```
|
|
304
|
+
ProcessTelemetry()
|
|
305
|
+
RunnerStateChange()
|
|
306
|
+
EmitRunnerEvent()
|
|
307
|
+
SyncRunnerData()
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
Ensures the in-memory model stays synchronized.
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## WorkerCommandCoordinator
|
|
315
|
+
|
|
316
|
+
Handles **command dispatching**.
|
|
317
|
+
|
|
318
|
+
Two command scopes:
|
|
319
|
+
|
|
320
|
+
### Worker Commands
|
|
321
|
+
|
|
322
|
+
```
|
|
323
|
+
StartWorkers
|
|
324
|
+
StopWorkers
|
|
325
|
+
PauseWorkers
|
|
326
|
+
ResumeWorkers
|
|
327
|
+
ExecuteWorkers
|
|
328
|
+
ResetWorkers
|
|
329
|
+
TerminateWorkers
|
|
330
|
+
UpdateWorkers
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Runner Commands
|
|
334
|
+
|
|
335
|
+
```
|
|
336
|
+
StartRunners
|
|
337
|
+
StopRunners
|
|
338
|
+
PauseRunners
|
|
339
|
+
ResumeRunners
|
|
340
|
+
ExecuteRunners
|
|
341
|
+
ResetRunners
|
|
342
|
+
TerminateRunners
|
|
343
|
+
UpdateRunners
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
Commands are executed asynchronously across workers.
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
## WorkerStateSynchroniser
|
|
351
|
+
|
|
352
|
+
Ensures that the **manager's in-memory model matches actual worker state**.
|
|
353
|
+
|
|
354
|
+
Mechanism:
|
|
355
|
+
|
|
356
|
+
```
|
|
357
|
+
Manager → Worker : GetRunners
|
|
358
|
+
Worker → Manager : Runner states
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
Methods:
|
|
362
|
+
|
|
363
|
+
```
|
|
364
|
+
GetSyncedWorkers()
|
|
365
|
+
GetSyncedWorkersCore()
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
## ArchiveManager
|
|
371
|
+
|
|
372
|
+
Stores completed runner history.
|
|
373
|
+
|
|
374
|
+
Archived runners contain:
|
|
375
|
+
|
|
376
|
+
```
|
|
377
|
+
runnerId
|
|
378
|
+
runnerOptions
|
|
379
|
+
runnerHistory[]
|
|
380
|
+
telemetrySnapshots
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
Provides:
|
|
384
|
+
|
|
385
|
+
```
|
|
386
|
+
GetArchiveList()
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
# Execution Flow
|
|
392
|
+
|
|
393
|
+
### Worker Creation
|
|
394
|
+
|
|
395
|
+
```
|
|
396
|
+
Client → STSWorkerManager.AddWorker()
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
Flow:
|
|
400
|
+
|
|
401
|
+
```
|
|
402
|
+
Manager
|
|
403
|
+
↓
|
|
404
|
+
WorkerInstanceManager
|
|
405
|
+
↓
|
|
406
|
+
WorkerFactory
|
|
407
|
+
↓
|
|
408
|
+
WorkerInstance
|
|
409
|
+
↓
|
|
410
|
+
WorkerRegistry
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
---
|
|
414
|
+
|
|
415
|
+
### Runner Creation
|
|
416
|
+
|
|
417
|
+
```
|
|
418
|
+
Client → Worker.AddRunner()
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
Flow:
|
|
422
|
+
|
|
423
|
+
```
|
|
424
|
+
Manager
|
|
425
|
+
↓
|
|
426
|
+
AsyncRunnerInstanceManager
|
|
427
|
+
↓
|
|
428
|
+
Runner created
|
|
429
|
+
↓
|
|
430
|
+
Worker receives AddRunner command
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
---
|
|
434
|
+
|
|
435
|
+
### Runner Execution
|
|
436
|
+
|
|
437
|
+
```
|
|
438
|
+
StartRunner()
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
Execution loop:
|
|
442
|
+
|
|
443
|
+
```
|
|
444
|
+
Runner.ExecuteRunner()
|
|
445
|
+
↓
|
|
446
|
+
Update telemetry
|
|
447
|
+
↓
|
|
448
|
+
Sleep or perform work
|
|
449
|
+
↓
|
|
450
|
+
Publish telemetry
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
---
|
|
454
|
+
|
|
455
|
+
# Telemetry and Observability
|
|
456
|
+
|
|
457
|
+
Telemetry is buffered and published using a hybrid strategy:
|
|
458
|
+
|
|
459
|
+
```
|
|
460
|
+
Flush if:
|
|
461
|
+
buffer size reached
|
|
462
|
+
OR
|
|
463
|
+
timeout reached
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
Example logic:
|
|
467
|
+
|
|
468
|
+
```
|
|
469
|
+
maxBufferSize = 50
|
|
470
|
+
timeout = 1000ms
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
Telemetry metrics include:
|
|
474
|
+
|
|
475
|
+
```
|
|
476
|
+
requestCount
|
|
477
|
+
errorCount
|
|
478
|
+
retryCount
|
|
479
|
+
velocity
|
|
480
|
+
latency
|
|
481
|
+
duration
|
|
482
|
+
activeRequestCount
|
|
483
|
+
network RX/TX
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
Instrumentation integrates with:
|
|
487
|
+
|
|
488
|
+
```
|
|
489
|
+
@nsshunt/stsobservability
|
|
490
|
+
@nsshunt/stsinstrumentmanagerclient
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
---
|
|
494
|
+
|
|
495
|
+
# Runner Lifecycle
|
|
496
|
+
|
|
497
|
+
Runner states include:
|
|
498
|
+
|
|
499
|
+
```
|
|
500
|
+
initializing
|
|
501
|
+
running
|
|
502
|
+
paused
|
|
503
|
+
stopped
|
|
504
|
+
completed
|
|
505
|
+
error
|
|
506
|
+
terminated
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
Lifecycle transitions generate events:
|
|
510
|
+
|
|
511
|
+
```
|
|
512
|
+
Telemetry
|
|
513
|
+
StateChange
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
Example:
|
|
517
|
+
|
|
518
|
+
```ts
|
|
519
|
+
runner.on('Telemetry', handler)
|
|
520
|
+
runner.on('StateChange', handler)
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
---
|
|
524
|
+
|
|
525
|
+
# Worker Lifecycle
|
|
526
|
+
|
|
527
|
+
Worker events include:
|
|
528
|
+
|
|
529
|
+
```
|
|
530
|
+
exit
|
|
531
|
+
error
|
|
532
|
+
messageerror
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
The WorkerInstanceManager wires these events and forwards them to the manager.
|
|
536
|
+
|
|
537
|
+
---
|
|
538
|
+
|
|
539
|
+
# State Synchronization
|
|
540
|
+
|
|
541
|
+
The manager maintains an **in-memory graph**.
|
|
542
|
+
|
|
543
|
+
Before returning model queries:
|
|
544
|
+
|
|
545
|
+
```
|
|
546
|
+
GetWorkers()
|
|
547
|
+
GetWorkersCore()
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
The system performs:
|
|
551
|
+
|
|
552
|
+
```
|
|
553
|
+
SyncAllWorkers()
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
Which queries every worker for current runner state.
|
|
557
|
+
|
|
558
|
+
---
|
|
559
|
+
|
|
560
|
+
# Archiving
|
|
561
|
+
|
|
562
|
+
Completed runners are archived by the **ArchiveManager**.
|
|
563
|
+
|
|
564
|
+
The archive contains:
|
|
565
|
+
|
|
566
|
+
```
|
|
567
|
+
runner metadata
|
|
568
|
+
execution history
|
|
569
|
+
telemetry snapshots
|
|
570
|
+
state transitions
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
Example:
|
|
574
|
+
|
|
575
|
+
```ts
|
|
576
|
+
const archiveList = await wm.GetArchiveList({});
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
---
|
|
580
|
+
|
|
581
|
+
# Client Usage
|
|
582
|
+
|
|
583
|
+
Example initialization:
|
|
584
|
+
|
|
585
|
+
```ts
|
|
586
|
+
const wm = new STSWorkerManager({
|
|
587
|
+
workerFactory,
|
|
588
|
+
maxArchiveListLength: 200,
|
|
589
|
+
logger: defaultLogger,
|
|
590
|
+
logLevel: 4,
|
|
591
|
+
messageTimeout: 10000
|
|
592
|
+
});
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
---
|
|
596
|
+
|
|
597
|
+
## Create Worker
|
|
598
|
+
|
|
599
|
+
```ts
|
|
600
|
+
const worker = await wm.AddWorker({
|
|
601
|
+
hostName: "host01",
|
|
602
|
+
agentId: "agent01",
|
|
603
|
+
mocked: true,
|
|
604
|
+
tags: ["testing"],
|
|
605
|
+
logLevel: 4
|
|
606
|
+
});
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
---
|
|
610
|
+
|
|
611
|
+
## Create Runner
|
|
612
|
+
|
|
613
|
+
```ts
|
|
614
|
+
const runner = await worker.AddRunner({
|
|
615
|
+
testType: "TestCase01",
|
|
616
|
+
executionProfile: {
|
|
617
|
+
iterations: 40,
|
|
618
|
+
delayBetweenIterations: 250
|
|
619
|
+
}
|
|
620
|
+
});
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
---
|
|
624
|
+
|
|
625
|
+
## Runner Events
|
|
626
|
+
|
|
627
|
+
```ts
|
|
628
|
+
runner.on("Telemetry", handler);
|
|
629
|
+
runner.on("StateChange", handler);
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
---
|
|
633
|
+
|
|
634
|
+
## Start Runner
|
|
635
|
+
|
|
636
|
+
```ts
|
|
637
|
+
await runner.Start();
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
or
|
|
641
|
+
|
|
642
|
+
```ts
|
|
643
|
+
await wm.StartRunners(worker.id, [runner.id]);
|
|
644
|
+
```
|
|
645
|
+
|
|
646
|
+
---
|
|
647
|
+
|
|
648
|
+
## Pause / Resume
|
|
649
|
+
|
|
650
|
+
```ts
|
|
651
|
+
await runner.Pause();
|
|
652
|
+
await runner.Resume();
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
---
|
|
656
|
+
|
|
657
|
+
## Update Runner
|
|
658
|
+
|
|
659
|
+
```ts
|
|
660
|
+
await runner.Update({
|
|
661
|
+
executionProfile: {
|
|
662
|
+
iterations: 30
|
|
663
|
+
}
|
|
664
|
+
});
|
|
665
|
+
```
|
|
666
|
+
|
|
667
|
+
---
|
|
668
|
+
|
|
669
|
+
# Creating Custom Runners
|
|
670
|
+
|
|
671
|
+
Implement:
|
|
672
|
+
|
|
673
|
+
```ts
|
|
674
|
+
IRunnerInstance
|
|
675
|
+
```
|
|
676
|
+
|
|
677
|
+
Example skeleton:
|
|
678
|
+
|
|
679
|
+
```ts
|
|
680
|
+
class MyRunner implements IRunnerInstance {
|
|
681
|
+
|
|
682
|
+
async ExecuteRunner() {
|
|
683
|
+
// perform work
|
|
684
|
+
return true;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
async StartRunner() {}
|
|
688
|
+
async StopRunner() {}
|
|
689
|
+
async PauseRunner() {}
|
|
690
|
+
async ResumeRunner() {}
|
|
691
|
+
}
|
|
692
|
+
```
|
|
693
|
+
|
|
694
|
+
---
|
|
695
|
+
|
|
696
|
+
# Example Test Runner
|
|
697
|
+
|
|
698
|
+
Two reference implementations exist:
|
|
699
|
+
|
|
700
|
+
```
|
|
701
|
+
TestCase01
|
|
702
|
+
TestCase02
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
They demonstrate:
|
|
706
|
+
|
|
707
|
+
* telemetry batching
|
|
708
|
+
* simulated workload
|
|
709
|
+
* logging
|
|
710
|
+
* lifecycle transitions
|
|
711
|
+
|
|
712
|
+
---
|
|
713
|
+
|
|
714
|
+
# Example Client
|
|
715
|
+
|
|
716
|
+
Example scenarios included:
|
|
717
|
+
|
|
718
|
+
```
|
|
719
|
+
client test 1:
|
|
720
|
+
multiple workers + runners
|
|
721
|
+
|
|
722
|
+
client test 2:
|
|
723
|
+
single runner dynamic update
|
|
724
|
+
```
|
|
725
|
+
|
|
726
|
+
Both demonstrate full framework usage.
|
|
727
|
+
|
|
728
|
+
---
|
|
729
|
+
|
|
730
|
+
# Threading Model
|
|
731
|
+
|
|
732
|
+
The framework supports multiple execution models:
|
|
733
|
+
|
|
734
|
+
```
|
|
735
|
+
Node Worker Threads
|
|
736
|
+
Browser Workers
|
|
737
|
+
Mock Workers
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
Mock workers are useful for testing.
|
|
741
|
+
|
|
742
|
+
---
|
|
743
|
+
|
|
744
|
+
# Design Goals
|
|
745
|
+
|
|
746
|
+
The framework was designed with the following principles:
|
|
747
|
+
|
|
748
|
+
### Scalability
|
|
749
|
+
|
|
750
|
+
Supports large numbers of runners across workers.
|
|
751
|
+
|
|
752
|
+
---
|
|
753
|
+
|
|
754
|
+
### Observability
|
|
755
|
+
|
|
756
|
+
First-class telemetry and instrumentation integration.
|
|
757
|
+
|
|
758
|
+
---
|
|
759
|
+
|
|
760
|
+
### Flexibility
|
|
761
|
+
|
|
762
|
+
Works in:
|
|
763
|
+
|
|
764
|
+
* Node
|
|
765
|
+
* Browser
|
|
766
|
+
* test environments
|
|
767
|
+
|
|
768
|
+
---
|
|
769
|
+
|
|
770
|
+
### Isolation
|
|
771
|
+
|
|
772
|
+
Workers isolate execution workloads.
|
|
773
|
+
|
|
774
|
+
---
|
|
775
|
+
|
|
776
|
+
### Event-Driven
|
|
777
|
+
|
|
778
|
+
Runners emit structured events.
|
|
779
|
+
|
|
780
|
+
---
|
|
781
|
+
|
|
782
|
+
### Dynamic Control
|
|
783
|
+
|
|
784
|
+
Runners can be:
|
|
785
|
+
|
|
786
|
+
```
|
|
787
|
+
paused
|
|
788
|
+
resumed
|
|
789
|
+
reset
|
|
790
|
+
updated
|
|
791
|
+
terminated
|
|
792
|
+
```
|
|
793
|
+
|
|
794
|
+
at runtime.
|
|
795
|
+
|
|
796
|
+
---
|
|
797
|
+
|
|
798
|
+
# Future Enhancements
|
|
799
|
+
|
|
800
|
+
Potential roadmap features:
|
|
801
|
+
|
|
802
|
+
* distributed multi-machine worker clusters
|
|
803
|
+
* built-in load test profiles
|
|
804
|
+
* Web UI dashboard
|
|
805
|
+
* Prometheus exporters
|
|
806
|
+
* distributed tracing
|
|
807
|
+
* adaptive execution control
|
|
808
|
+
* auto-scaling workers
|
|
809
|
+
|
|
810
|
+
---
|
|
811
|
+
|
|
812
|
+
# License
|
|
813
|
+
|
|
814
|
+
MIT License.
|
|
815
|
+
|
|
816
|
+
|
|
817
|
+
# Architecture Diagrams
|
|
818
|
+
|
|
819
|
+
## System Architecture
|
|
820
|
+
|
|
821
|
+
```mermaid
|
|
822
|
+
flowchart TB
|
|
823
|
+
|
|
824
|
+
Client["Client Application"]
|
|
825
|
+
|
|
826
|
+
subgraph Manager["STSWorkerManager"]
|
|
827
|
+
WorkerRegistry
|
|
828
|
+
WorkerInstanceManager
|
|
829
|
+
RunnerLifecycleManager
|
|
830
|
+
WorkerCommandCoordinator
|
|
831
|
+
WorkerStateSynchroniser
|
|
832
|
+
AsyncRunnerInstanceManager
|
|
833
|
+
ArchiveManager
|
|
834
|
+
STSMessageBroker
|
|
835
|
+
end
|
|
836
|
+
|
|
837
|
+
subgraph Workers["Worker Threads / Web Workers"]
|
|
838
|
+
Worker1["WorkerInstance"]
|
|
839
|
+
Worker2["WorkerInstance"]
|
|
840
|
+
end
|
|
841
|
+
|
|
842
|
+
subgraph Runners["Runner Instances"]
|
|
843
|
+
Runner1["RunnerInstance"]
|
|
844
|
+
Runner2["RunnerInstance"]
|
|
845
|
+
Runner3["RunnerInstance"]
|
|
846
|
+
end
|
|
847
|
+
|
|
848
|
+
Client --> Manager
|
|
849
|
+
|
|
850
|
+
Manager --> WorkerRegistry
|
|
851
|
+
Manager --> WorkerInstanceManager
|
|
852
|
+
Manager --> RunnerLifecycleManager
|
|
853
|
+
Manager --> WorkerCommandCoordinator
|
|
854
|
+
Manager --> WorkerStateSynchroniser
|
|
855
|
+
Manager --> AsyncRunnerInstanceManager
|
|
856
|
+
Manager --> ArchiveManager
|
|
857
|
+
Manager --> STSMessageBroker
|
|
858
|
+
|
|
859
|
+
WorkerInstanceManager --> Worker1
|
|
860
|
+
WorkerInstanceManager --> Worker2
|
|
861
|
+
|
|
862
|
+
Worker1 --> Runner1
|
|
863
|
+
Worker1 --> Runner2
|
|
864
|
+
Worker2 --> Runner3
|
|
865
|
+
|
|
866
|
+
STSMessageBroker --> Worker1
|
|
867
|
+
STSMessageBroker --> Worker2
|
|
868
|
+
```
|
|
869
|
+
## Component Interaction
|
|
870
|
+
|
|
871
|
+
```mermaid
|
|
872
|
+
flowchart LR
|
|
873
|
+
|
|
874
|
+
Client --> STSWorkerManager
|
|
875
|
+
|
|
876
|
+
STSWorkerManager --> WorkerRegistry
|
|
877
|
+
STSWorkerManager --> WorkerInstanceManager
|
|
878
|
+
STSWorkerManager --> WorkerCommandCoordinator
|
|
879
|
+
STSWorkerManager --> RunnerLifecycleManager
|
|
880
|
+
STSWorkerManager --> WorkerStateSynchroniser
|
|
881
|
+
STSWorkerManager --> AsyncRunnerInstanceManager
|
|
882
|
+
STSWorkerManager --> ArchiveManager
|
|
883
|
+
STSWorkerManager --> STSMessageBroker
|
|
884
|
+
|
|
885
|
+
WorkerCommandCoordinator --> STSMessageBroker
|
|
886
|
+
WorkerStateSynchroniser --> STSMessageBroker
|
|
887
|
+
|
|
888
|
+
STSMessageBroker --> Worker
|
|
889
|
+
|
|
890
|
+
Worker --> Runner
|
|
891
|
+
|
|
892
|
+
Runner --> RunnerLifecycleManager
|
|
893
|
+
|
|
894
|
+
RunnerLifecycleManager --> WorkerRegistry
|
|
895
|
+
|
|
896
|
+
RunnerLifecycleManager --> ArchiveManager
|
|
897
|
+
```
|
|
898
|
+
|
|
899
|
+
## Runner Lifecycle
|
|
900
|
+
|
|
901
|
+
```mermaid
|
|
902
|
+
stateDiagram-v2
|
|
903
|
+
|
|
904
|
+
[*] --> initializing
|
|
905
|
+
|
|
906
|
+
initializing --> running : Start
|
|
907
|
+
|
|
908
|
+
running --> paused : Pause
|
|
909
|
+
|
|
910
|
+
paused --> running : Resume
|
|
911
|
+
|
|
912
|
+
running --> completed : Iterations reached
|
|
913
|
+
|
|
914
|
+
running --> stopped : Stop
|
|
915
|
+
|
|
916
|
+
running --> error : Exception
|
|
917
|
+
|
|
918
|
+
running --> terminated : Terminate
|
|
919
|
+
|
|
920
|
+
paused --> terminated : Terminate
|
|
921
|
+
|
|
922
|
+
completed --> [*]
|
|
923
|
+
|
|
924
|
+
stopped --> [*]
|
|
925
|
+
|
|
926
|
+
error --> [*]
|
|
927
|
+
|
|
928
|
+
terminated --> [*]
|
|
929
|
+
```
|
|
930
|
+
|
|
931
|
+
## Execution Sequence
|
|
932
|
+
|
|
933
|
+
```mermaid
|
|
934
|
+
sequenceDiagram
|
|
935
|
+
|
|
936
|
+
participant Client
|
|
937
|
+
participant Manager as STSWorkerManager
|
|
938
|
+
participant Broker as MessageBroker
|
|
939
|
+
participant Worker
|
|
940
|
+
participant Runner
|
|
941
|
+
|
|
942
|
+
Client->>Manager: AddWorker()
|
|
943
|
+
Manager->>Worker: Create WorkerInstance
|
|
944
|
+
|
|
945
|
+
Client->>Manager: AddRunner()
|
|
946
|
+
Manager->>Broker: Send AddRunner
|
|
947
|
+
Broker->>Worker: AddRunner message
|
|
948
|
+
Worker->>Runner: Create RunnerInstance
|
|
949
|
+
|
|
950
|
+
Client->>Manager: StartRunner()
|
|
951
|
+
|
|
952
|
+
Manager->>Broker: StartRunner command
|
|
953
|
+
Broker->>Worker: StartRunner
|
|
954
|
+
Worker->>Runner: ExecuteRunner()
|
|
955
|
+
|
|
956
|
+
loop Execution Loop
|
|
957
|
+
Runner->>Runner: Perform Work
|
|
958
|
+
Runner->>Worker: PostTelemetry
|
|
959
|
+
Worker->>Broker: Telemetry Message
|
|
960
|
+
Broker->>Manager: Telemetry Event
|
|
961
|
+
Manager->>Client: Emit Telemetry Event
|
|
962
|
+
end
|
|
963
|
+
|
|
964
|
+
Runner->>Worker: Completed
|
|
965
|
+
Worker->>Broker: RunnerCompleted
|
|
966
|
+
Broker->>Manager: StateChange
|
|
967
|
+
Manager->>Client: StateChange Event
|
|
968
|
+
```
|
|
969
|
+
|
|
970
|
+
## Worker Load Balancing / Runner Placement Diagram
|
|
971
|
+
|
|
972
|
+
This shows how the manager can choose a worker, typically by using the registry helpers like:
|
|
973
|
+
GetNextAvailableWorker()
|
|
974
|
+
GetBusiestWorker()
|
|
975
|
+
and then place runners onto workers.
|
|
976
|
+
|
|
977
|
+
```mermaid
|
|
978
|
+
flowchart TB
|
|
979
|
+
|
|
980
|
+
NewRunner["New Runner Request"]
|
|
981
|
+
|
|
982
|
+
subgraph Manager["STSWorkerManager"]
|
|
983
|
+
Registry["WorkerRegistry"]
|
|
984
|
+
Coordinator["Worker / Runner Coordination"]
|
|
985
|
+
Selector{"Select Worker"}
|
|
986
|
+
end
|
|
987
|
+
|
|
988
|
+
subgraph WorkerPool["Live Workers"]
|
|
989
|
+
W1["Worker A\n2 runners"]
|
|
990
|
+
W2["Worker B\n5 runners"]
|
|
991
|
+
W3["Worker C\n1 runner"]
|
|
992
|
+
end
|
|
993
|
+
|
|
994
|
+
NewRunner --> Manager
|
|
995
|
+
Manager --> Registry
|
|
996
|
+
Registry --> Selector
|
|
997
|
+
Coordinator --> Selector
|
|
998
|
+
|
|
999
|
+
Selector -->|"GetNextAvailableWorker()"| W3
|
|
1000
|
+
Selector -->|"GetBusiestWorker()"| W2
|
|
1001
|
+
|
|
1002
|
+
W3 -->|"AddRunner()"| Added["Runner assigned to least-loaded worker"]
|
|
1003
|
+
```
|
|
1004
|
+
|
|
1005
|
+
- The registry maintains the current live worker/runners graph
|
|
1006
|
+
- worker selection can be based on current runner counts
|
|
1007
|
+
- the least-loaded worker can be selected for simple balancing
|
|
1008
|
+
- after selection, the runner is created and attached to that worker
|
|
1009
|
+
|
|
1010
|
+
## Telemetry Pipeline Diagram
|
|
1011
|
+
|
|
1012
|
+
This shows the full telemetry path from a concrete runner up to the client.
|
|
1013
|
+
|
|
1014
|
+
```mermaid
|
|
1015
|
+
flowchart LR
|
|
1016
|
+
|
|
1017
|
+
subgraph WorkerRuntime["Worker Runtime"]
|
|
1018
|
+
Runner["RunnerInstance"]
|
|
1019
|
+
ExecWorker["AbstractRunnerExecutionWorker"]
|
|
1020
|
+
end
|
|
1021
|
+
|
|
1022
|
+
subgraph ManagerSide["Manager Side"]
|
|
1023
|
+
Broker["STSMessageBroker"]
|
|
1024
|
+
Lifecycle["RunnerLifecycleManager"]
|
|
1025
|
+
Registry["WorkerRegistry"]
|
|
1026
|
+
Sync["WorkerStateSynchroniser"]
|
|
1027
|
+
end
|
|
1028
|
+
|
|
1029
|
+
Client["Client Application"]
|
|
1030
|
+
Instrument["PublishInstrumentController / Telemetry Output"]
|
|
1031
|
+
|
|
1032
|
+
Runner -->|"updates instrumentData"| ExecWorker
|
|
1033
|
+
ExecWorker -->|"PostTelemetryById()"| Broker
|
|
1034
|
+
Broker -->|"InstrumentTelemetry message"| Lifecycle
|
|
1035
|
+
Lifecycle -->|"SyncRunnerData()"| Registry
|
|
1036
|
+
Lifecycle -->|"ProcessTelemetry()"| Instrument
|
|
1037
|
+
Registry --> Sync
|
|
1038
|
+
Sync --> Client
|
|
1039
|
+
Lifecycle -->|"runner.on('Telemetry')"| Client
|
|
1040
|
+
Lifecycle -->|"runner.on('StateChange')"| Client
|
|
1041
|
+
|
|
1042
|
+
```
|
|
1043
|
+
|
|
1044
|
+
- runners update their local instrumentData
|
|
1045
|
+
- the worker runtime posts telemetry upward via PostTelemetryById()
|
|
1046
|
+
- the message broker routes telemetry to the manager
|
|
1047
|
+
- the runner lifecycle manager applies the update into the live registry model
|
|
1048
|
+
- optional instrumentation publishers can also receive metric updates
|
|
1049
|
+
- clients can observe telemetry through:
|
|
1050
|
+
- event subscriptions
|
|
1051
|
+
- synchronized model queries like GetWorkers()
|
|
1052
|
+
|
|
1053
|
+
<br>
|
|
1054
|
+
──────────────────── ✦ ────────────────────
|
|
1055
|
+
<br>
|
|
1056
|
+
<br>
|
|
1057
|
+
<br>
|
|
1058
|
+
|
|
1059
|
+
# stsrunnerframework (Old Legacy Doco - Previous Version)
|
|
2
1060
|
|
|
3
1061
|
terminated - this means the process has been terminated and no end-of-process steps should execute such as reports etc.
|
|
4
1062
|
|