@nsshunt/ststestrunner 1.1.14 → 1.1.16

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.
@@ -80,24 +80,25 @@ var TestCaseFhirBase = class {
80
80
  return new node_https.default.Agent(options);
81
81
  }
82
82
  });
83
+ const agentManager = (0, _nsshunt_stsutils.createAgentManager)({
84
+ agentOptions: {
85
+ keepAlive: true,
86
+ maxFreeSockets: 10,
87
+ maxSockets: 10,
88
+ maxTotalSockets: 20,
89
+ timeout: 6e4,
90
+ rejectUnauthorized: false
91
+ },
92
+ httpAgentFactory(options) {
93
+ return new node_http.default.Agent(options);
94
+ },
95
+ httpsAgentFactory(options) {
96
+ return new node_https.default.Agent(options);
97
+ }
98
+ });
83
99
  this.authUtilsNode = new _nsshunt_stsauthclient.AuthUtilsNode({
84
100
  logger: _nsshunt_stsutils.defaultLogger,
85
- agentManager: (0, _nsshunt_stsutils.createAgentManager)({
86
- agentOptions: {
87
- keepAlive: true,
88
- maxFreeSockets: 10,
89
- maxSockets: 10,
90
- maxTotalSockets: 20,
91
- timeout: 6e4,
92
- rejectUnauthorized: false
93
- },
94
- httpAgentFactory(options) {
95
- return new node_http.default.Agent(options);
96
- },
97
- httpsAgentFactory(options) {
98
- return new node_https.default.Agent(options);
99
- }
100
- })
101
+ agentManager
101
102
  });
102
103
  }
103
104
  get runnerExecutionWorker() {
@@ -1357,11 +1358,837 @@ var TestCaseFhir10 = class extends TestCaseFhirQueryBase {
1357
1358
  };
1358
1359
  };
1359
1360
  //#endregion
1361
+ //#region src/libmodule/testCase01.ts
1362
+ /**
1363
+ * Concrete synthetic test runner implementation.
1364
+ *
1365
+ * This runner:
1366
+ * - simulates work
1367
+ * - updates telemetry counters
1368
+ * - batches telemetry publishing
1369
+ * - emits lifecycle log messages
1370
+ */
1371
+ var TestCase01 = class {
1372
+ /**
1373
+ * The live serialisable runner model/state owned by this test runner.
1374
+ *
1375
+ * This object is mutated as telemetry and execution progress change.
1376
+ */
1377
+ #runner;
1378
+ /**
1379
+ * Owning worker-side execution host.
1380
+ *
1381
+ * Used primarily to publish telemetry back to the manager by runner id.
1382
+ */
1383
+ #runnerExecutionWorker;
1384
+ /**
1385
+ * Per-runner state used for animated/indented generated log messages.
1386
+ */
1387
+ #logMessageDataSet = {};
1388
+ /**
1389
+ * Timeout handle used to perform delayed telemetry publication.
1390
+ *
1391
+ * This supports the "publish on timeout if buffer threshold is not reached"
1392
+ * batching strategy.
1393
+ */
1394
+ #publishTelemetryTimeout = null;
1395
+ /**
1396
+ * Counter of buffered telemetry publication events since the last publish.
1397
+ *
1398
+ * When this reaches `#maxBufferSize`, telemetry is published immediately.
1399
+ */
1400
+ #publishTelemetryCount = 0;
1401
+ /**
1402
+ * Maximum number of telemetry buffer events allowed before forcing a publish.
1403
+ *
1404
+ * This is intended to remain lower than the logging/instrument buffer size
1405
+ * used elsewhere in the observability stack.
1406
+ */
1407
+ #maxBufferSize = 50;
1408
+ /**
1409
+ * Maximum time in milliseconds to wait before publishing buffered telemetry.
1410
+ *
1411
+ * Telemetry publish strategy:
1412
+ * - whichever happens first wins:
1413
+ * - max buffer count reached
1414
+ * - timeout reached
1415
+ */
1416
+ #publishTelemetryTimeoutVal = 1e3;
1417
+ /**
1418
+ * Construct a new synthetic test runner.
1419
+ *
1420
+ * @param runnerExecutionWorker Owning worker-side execution host.
1421
+ * @param runner Live runner model/state for this test runner.
1422
+ */
1423
+ constructor(runnerExecutionWorker, runner) {
1424
+ this.#runnerExecutionWorker = runnerExecutionWorker;
1425
+ this.#runner = runner;
1426
+ }
1427
+ /**
1428
+ * Internal low-level log sink used by this test case.
1429
+ *
1430
+ * Currently disabled/commented out to avoid noisy console output during tests.
1431
+ *
1432
+ * @param message Message to output.
1433
+ */
1434
+ #LogMessage = (message) => {};
1435
+ /**
1436
+ * Generate an animated indented log message for the runner.
1437
+ *
1438
+ * Behaviour:
1439
+ * - lazily initialises per-runner indentation state
1440
+ * - creates a message with varying indentation
1441
+ * - appends that message to runner telemetry messages
1442
+ * - updates indentation direction when bounds are reached
1443
+ *
1444
+ * Indentation behaviour:
1445
+ * - increases from 0 upward
1446
+ * - reverses direction after passing 20
1447
+ * - reverses again when returning to 0
1448
+ *
1449
+ * This exists purely to generate visually changing test log output.
1450
+ *
1451
+ * @param runner Runner whose message should be generated.
1452
+ * @param iteration Current runner iteration number.
1453
+ */
1454
+ #GenLogMessage = (runner, iteration) => {
1455
+ if (!this.#logMessageDataSet[runner.id]) this.#logMessageDataSet[runner.id] = {
1456
+ adder: 1,
1457
+ indent: 0
1458
+ };
1459
+ const logMessageData = this.#logMessageDataSet[runner.id];
1460
+ const message = `${" ".repeat(logMessageData.indent)} [${runner.id}] >> Hello World << ${iteration}`;
1461
+ this.#LogMessage(message);
1462
+ runner.instrumentData.message.push(message);
1463
+ logMessageData.indent += logMessageData.adder;
1464
+ if (logMessageData.indent > 20) logMessageData.adder = -1;
1465
+ else if (logMessageData.indent === 0) logMessageData.adder = 1;
1466
+ };
1467
+ /**
1468
+ * Ensure a timeout-based telemetry publish is scheduled.
1469
+ *
1470
+ * Behaviour:
1471
+ * - if no publish timeout exists, creates one
1472
+ * - when the timeout fires:
1473
+ * - publishes telemetry
1474
+ * - resets buffered publish count
1475
+ * - clears the timeout handle
1476
+ *
1477
+ * In Node.js the timer is `unref()`'d so it does not keep the process alive.
1478
+ */
1479
+ #SetupTimeout = async () => {
1480
+ if (!this.#publishTelemetryTimeout) {
1481
+ this.#publishTelemetryTimeout = setTimeout(async () => {
1482
+ this.#LogMessage(chalk.default.yellow(` PublishTelemetryData - Normal Behaviour (**** TIMEOUT ****) `));
1483
+ await this.#PublishTelemetryData();
1484
+ this.#publishTelemetryCount = 0;
1485
+ this.#publishTelemetryTimeout = null;
1486
+ }, this.#publishTelemetryTimeoutVal);
1487
+ if (_nsshunt_stsutils.isNode) this.#publishTelemetryTimeout.unref();
1488
+ }
1489
+ };
1490
+ /**
1491
+ * Publish the current runner telemetry snapshot immediately.
1492
+ *
1493
+ * Behaviour:
1494
+ * - asks the owning worker execution host to post telemetry for this runner
1495
+ * - writes a separator line to the local log sink
1496
+ * - resets selected per-cycle telemetry fields ready for the next publish window
1497
+ * - yields immediately before returning
1498
+ *
1499
+ * Telemetry fields reset after publish:
1500
+ * - `velocity`
1501
+ * - `message`
1502
+ * - `tx`
1503
+ * - `rx`
1504
+ *
1505
+ * Notes:
1506
+ * - not all telemetry fields are reset here; only those intended to behave
1507
+ * as per-publish-window accumulators
1508
+ */
1509
+ #PublishTelemetryData = async () => {
1510
+ this.#runnerExecutionWorker.PostTelemetryById(this.#runner.id);
1511
+ this.#LogMessage(chalk.default.red(`------------------------------------------------------------------------------------------------------------`));
1512
+ this.#runner.instrumentData.velocity = 0;
1513
+ this.#runner.instrumentData.message = [];
1514
+ this.#runner.instrumentData.tx = 0;
1515
+ this.#runner.instrumentData.rx = 0;
1516
+ await this.SleepImmediate();
1517
+ };
1518
+ /**
1519
+ * Force an immediate telemetry publish regardless of current buffer count.
1520
+ *
1521
+ * Used for important lifecycle transitions such as:
1522
+ * - start
1523
+ * - stop
1524
+ * - pause
1525
+ * - resume
1526
+ * - reset
1527
+ * - terminate
1528
+ * - complete
1529
+ */
1530
+ #ForcePublishTelemetryData = async () => {
1531
+ this.#LogMessage(chalk.default.magenta(` **** FORCED PUBLISH **** `));
1532
+ await this.#PublishTelemetryData();
1533
+ };
1534
+ /**
1535
+ * Buffer and publish telemetry using a mixed threshold/timeout strategy.
1536
+ *
1537
+ * Behaviour:
1538
+ * - increments the buffered telemetry count
1539
+ * - if the count reaches `#maxBufferSize`:
1540
+ * - clears any pending timeout
1541
+ * - publishes immediately
1542
+ * - resets the buffered count
1543
+ * - otherwise ensures a timeout is scheduled
1544
+ *
1545
+ * This creates a "whichever happens first" batching model:
1546
+ * - count threshold
1547
+ * - timeout threshold
1548
+ */
1549
+ #PublishTelemetry = async () => {
1550
+ this.#publishTelemetryCount++;
1551
+ if (this.#publishTelemetryCount % this.#maxBufferSize === 0) {
1552
+ this.#LogMessage(chalk.default.cyan(` **** MAX COUNT REACHED **** `));
1553
+ this.#publishTelemetryCount = 0;
1554
+ if (this.#publishTelemetryTimeout) {
1555
+ clearTimeout(this.#publishTelemetryTimeout);
1556
+ this.#publishTelemetryTimeout = null;
1557
+ }
1558
+ await this.#PublishTelemetryData();
1559
+ }
1560
+ if (!this.#publishTelemetryTimeout) this.#SetupTimeout();
1561
+ };
1562
+ /**
1563
+ * Yield immediately to the event loop/microtask queue.
1564
+ *
1565
+ * Used when the runner wants to behave asynchronously but does not need
1566
+ * a real delay.
1567
+ *
1568
+ * @returns Resolved promise.
1569
+ */
1570
+ SleepImmediate() {
1571
+ return new Promise((resolve, reject) => {
1572
+ resolve();
1573
+ });
1574
+ }
1575
+ /**
1576
+ * Execute one synthetic unit of work for this runner.
1577
+ *
1578
+ * Behaviour
1579
+ * ---------
1580
+ * - captures start time
1581
+ * - reads extended runner options
1582
+ * - updates telemetry counters/metrics
1583
+ * - optionally generates log messages
1584
+ * - optionally emits status/progress messages
1585
+ * - simulates actual work using:
1586
+ * - `Sleep(options.sleepDuration)`, or
1587
+ * - immediate yield
1588
+ * - decrements active request count
1589
+ * - records duration
1590
+ * - publishes telemetry using buffered publish logic
1591
+ *
1592
+ * Telemetry updates performed
1593
+ * ---------------------------
1594
+ * - `coreCount = 1`
1595
+ * - `activeRequestCount++`
1596
+ * - `requestCount++`
1597
+ * - `velocity++`
1598
+ * - `tx += 256000`
1599
+ * - `rx += 6500000`
1600
+ * - `duration = measured execution time`
1601
+ *
1602
+ * Notes
1603
+ * -----
1604
+ * - This method simulates real work rather than performing domain logic
1605
+ * - It is intended to validate the framework's runner/telemetry lifecycle
1606
+ * - After the awaited work delay, the actual framework runner state may have
1607
+ * changed externally, but this test implementation does not directly react here
1608
+ *
1609
+ * @returns `true` when the synthetic work cycle completes.
1610
+ */
1611
+ ExecuteRunner = async () => {
1612
+ const start = performance.now();
1613
+ const options = this.#runner.options;
1614
+ this.#runner.instrumentData.coreCount = 1;
1615
+ this.#runner.instrumentData.activeRequestCount++;
1616
+ this.#runner.instrumentData.requestCount++;
1617
+ this.#runner.instrumentData.velocity++;
1618
+ this.#runner.instrumentData.tx += 256e3;
1619
+ this.#runner.instrumentData.rx += 65e5;
1620
+ if (this.#runner.instrumentData.requestCount % options.logMessageMod === 0) this.#GenLogMessage(this.#runner, this.#runner.iteration);
1621
+ if (this.#runner.instrumentData.requestCount % 1 === 0) {
1622
+ const message = `Worker: [${this.#runner.asyncRunnerContext.threadId}], Runner: [${this.#runner.asyncRunnerContext.id}] has completed: [${this.#runner.instrumentData.requestCount}] iterations of max: [${options.executionProfile.iterations}]`;
1623
+ this.#LogMessage(message);
1624
+ this.#runner.instrumentData.message = [message];
1625
+ }
1626
+ /**
1627
+ * Simulate actual work.
1628
+ *
1629
+ * In real runner implementations this is where domain-specific work would occur:
1630
+ * - REST calls
1631
+ * - DB access
1632
+ * - browser automation
1633
+ * - file processing
1634
+ * etc.
1635
+ */
1636
+ if (options.sleepDuration > 0) await (0, _nsshunt_stsutils.Sleep)(options.sleepDuration);
1637
+ else await this.SleepImmediate();
1638
+ this.#runner.instrumentData.activeRequestCount--;
1639
+ const diff = performance.now() - start;
1640
+ this.#runner.instrumentData.duration = diff;
1641
+ await this.#PublishTelemetry();
1642
+ return true;
1643
+ };
1644
+ /**
1645
+ * Write a grey-coloured lifecycle message into the runner telemetry message buffer
1646
+ * and publish telemetry using normal buffered publish logic.
1647
+ *
1648
+ * @param message Lifecycle/status message to emit.
1649
+ */
1650
+ #OutputLogMessage = async (message) => {
1651
+ const messageOutput = chalk.default.grey(message);
1652
+ this.#LogMessage(messageOutput);
1653
+ this.#runner.instrumentData.message.push(messageOutput);
1654
+ await this.#PublishTelemetry();
1655
+ };
1656
+ /**
1657
+ * Handle framework "start" lifecycle event for this runner.
1658
+ *
1659
+ * Behaviour:
1660
+ * - writes a lifecycle message
1661
+ * - forces immediate telemetry publication
1662
+ *
1663
+ * @returns `true`
1664
+ */
1665
+ StartRunner = async () => {
1666
+ await this.#OutputLogMessage(`StartRunner [${this.#runner.id}]`);
1667
+ await this.#ForcePublishTelemetryData();
1668
+ return true;
1669
+ };
1670
+ /**
1671
+ * Handle framework "stop" lifecycle event for this runner.
1672
+ *
1673
+ * Behaviour:
1674
+ * - writes a lifecycle message
1675
+ * - forces immediate telemetry publication
1676
+ *
1677
+ * @returns `true`
1678
+ */
1679
+ StopRunner = async () => {
1680
+ await this.#OutputLogMessage(`StopRunner [${this.#runner.id}]`);
1681
+ await this.#ForcePublishTelemetryData();
1682
+ return true;
1683
+ };
1684
+ /**
1685
+ * Handle framework "terminate" lifecycle event for this runner.
1686
+ *
1687
+ * Behaviour:
1688
+ * - writes a lifecycle message
1689
+ * - forces immediate telemetry publication
1690
+ *
1691
+ * @returns `true`
1692
+ */
1693
+ TerminateRunner = async () => {
1694
+ await this.#OutputLogMessage(`TerminateRunner [${this.#runner.id}]`);
1695
+ await this.#ForcePublishTelemetryData();
1696
+ return true;
1697
+ };
1698
+ /**
1699
+ * Handle framework "completed" lifecycle event for this runner.
1700
+ *
1701
+ * Behaviour:
1702
+ * - writes a completion lifecycle message including current telemetry snapshot
1703
+ * - forces immediate telemetry publication
1704
+ *
1705
+ * @returns `true`
1706
+ */
1707
+ Completed = async () => {
1708
+ await this.#OutputLogMessage(`Completed [${this.#runner.id}] [${JSON.stringify(this.#runner.instrumentData)}]`);
1709
+ await this.#ForcePublishTelemetryData();
1710
+ return true;
1711
+ };
1712
+ /**
1713
+ * Handle framework "pause" lifecycle event for this runner.
1714
+ *
1715
+ * Behaviour:
1716
+ * - writes a lifecycle message
1717
+ * - forces immediate telemetry publication
1718
+ * - returns a descriptive diagnostic string
1719
+ *
1720
+ * @returns Diagnostic pause message.
1721
+ */
1722
+ PauseRunner = async () => {
1723
+ await this.#OutputLogMessage(`PauseRunner [${this.#runner.id}]`);
1724
+ await this.#ForcePublishTelemetryData();
1725
+ return `I have been paused at iteration: [${this.#runner.iteration}] Date: [${/* @__PURE__ */ new Date()}] Performance: [${performance.now()}]`;
1726
+ };
1727
+ /**
1728
+ * Handle framework "resume" lifecycle event for this runner.
1729
+ *
1730
+ * Behaviour:
1731
+ * - writes a lifecycle message
1732
+ * - forces immediate telemetry publication
1733
+ * - returns a descriptive diagnostic string
1734
+ *
1735
+ * @returns Diagnostic resume message.
1736
+ */
1737
+ ResumeRunner = async () => {
1738
+ await this.#OutputLogMessage(`ResumeRunner [${this.#runner.id}]`);
1739
+ await this.#ForcePublishTelemetryData();
1740
+ return `I have been resumed at iteration: [${this.#runner.iteration}] Date: [${/* @__PURE__ */ new Date()}] Performance: [${performance.now()}]`;
1741
+ };
1742
+ /**
1743
+ * Handle framework "reset" lifecycle event for this runner.
1744
+ *
1745
+ * Behaviour:
1746
+ * - writes a lifecycle message
1747
+ * - resets `requestCount` to zero
1748
+ * - forces immediate telemetry publication
1749
+ *
1750
+ * @returns `true`
1751
+ */
1752
+ ResetRunner = async () => {
1753
+ await this.#OutputLogMessage(`ResetRunner [${this.#runner.id}]`);
1754
+ this.#runner.instrumentData.requestCount = 0;
1755
+ await this.#ForcePublishTelemetryData();
1756
+ return true;
1757
+ };
1758
+ /**
1759
+ * Handle framework "update" lifecycle event for this runner.
1760
+ *
1761
+ * Behaviour:
1762
+ * - writes a lifecycle message
1763
+ * - forces immediate telemetry publication
1764
+ *
1765
+ * Note:
1766
+ * - this implementation does not directly apply option changes itself;
1767
+ * it simply acknowledges the lifecycle event for framework testing
1768
+ *
1769
+ * @returns `true`
1770
+ */
1771
+ UpdateRunner = async () => {
1772
+ await this.#OutputLogMessage(`UpdateOptions [${this.#runner.id}]`);
1773
+ await this.#ForcePublishTelemetryData();
1774
+ return true;
1775
+ };
1776
+ };
1777
+ //#endregion
1778
+ //#region src/libmodule/testCase02.ts
1779
+ /**
1780
+ * Concrete synthetic test runner implementation.
1781
+ *
1782
+ * This runner simulates work, updates telemetry, batches telemetry publishing,
1783
+ * and writes both internal telemetry messages and visible console progress.
1784
+ */
1785
+ var TestCase02 = class {
1786
+ /**
1787
+ * Live serialisable runner model/state for this test runner.
1788
+ *
1789
+ * This object is mutated as execution and telemetry progress.
1790
+ */
1791
+ #runner;
1792
+ /**
1793
+ * Owning worker-side execution host.
1794
+ *
1795
+ * Used primarily to publish telemetry for this runner back to the manager.
1796
+ */
1797
+ #runnerExecutionWorker;
1798
+ /**
1799
+ * Per-runner animated log message state.
1800
+ */
1801
+ #logMessageDataSet = {};
1802
+ /**
1803
+ * Timeout handle used for delayed telemetry publication.
1804
+ *
1805
+ * Supports timeout-based flush behaviour when the publish count threshold
1806
+ * has not yet been reached.
1807
+ */
1808
+ #publishTelemetryTimeout = null;
1809
+ /**
1810
+ * Count of buffered telemetry-publish requests since the last flush.
1811
+ */
1812
+ #publishTelemetryCount = 0;
1813
+ /**
1814
+ * Maximum buffered publish count before telemetry is flushed immediately.
1815
+ *
1816
+ * This should remain lower than the maximum observability/logging buffer size
1817
+ * used elsewhere in the framework.
1818
+ */
1819
+ #maxBufferSize = 50;
1820
+ /**
1821
+ * Maximum time in milliseconds to wait before flushing telemetry.
1822
+ *
1823
+ * Publish strategy:
1824
+ * - whichever happens first:
1825
+ * - max buffer size reached
1826
+ * - timeout reached
1827
+ */
1828
+ #publishTelemetryTimeoutVal = 1e3;
1829
+ /**
1830
+ * Construct a new `TestCase02` runner.
1831
+ *
1832
+ * @param runnerExecutionWorker Owning worker-side execution host.
1833
+ * @param runner Live runner model/state.
1834
+ */
1835
+ constructor(runnerExecutionWorker, runner) {
1836
+ this.#runnerExecutionWorker = runnerExecutionWorker;
1837
+ this.#runner = runner;
1838
+ }
1839
+ /**
1840
+ * Internal low-level log sink.
1841
+ *
1842
+ * Currently disabled/commented out to avoid noisy console output during normal testing.
1843
+ * The class still uses `console.log(...)` directly in `ExecuteRunner()` for visible progress.
1844
+ *
1845
+ * @param message Message to output.
1846
+ */
1847
+ #LogMessage = (message) => {};
1848
+ /**
1849
+ * Generate an animated indented "Hello World" style log message.
1850
+ *
1851
+ * Behaviour:
1852
+ * - initialises per-runner indentation state if needed
1853
+ * - builds a message with variable indentation
1854
+ * - appends the message to the runner telemetry message buffer
1855
+ * - updates indentation direction when bounds are reached
1856
+ *
1857
+ * Indentation pattern:
1858
+ * - grows from 0 upward
1859
+ * - reverses after exceeding 20
1860
+ * - reverses again when returning to 0
1861
+ *
1862
+ * @param runner Runner whose message should be generated.
1863
+ * @param iteration Current iteration number.
1864
+ */
1865
+ #GenLogMessage = (runner, iteration) => {
1866
+ if (!this.#logMessageDataSet[runner.id]) this.#logMessageDataSet[runner.id] = {
1867
+ adder: 1,
1868
+ indent: 0
1869
+ };
1870
+ const logMessageData = this.#logMessageDataSet[runner.id];
1871
+ const message = `${" ".repeat(logMessageData.indent)} [${runner.id}] >> Hello World << ${iteration}`;
1872
+ this.#LogMessage(message);
1873
+ runner.instrumentData.message.push(message);
1874
+ logMessageData.indent += logMessageData.adder;
1875
+ if (logMessageData.indent > 20) logMessageData.adder = -1;
1876
+ else if (logMessageData.indent === 0) logMessageData.adder = 1;
1877
+ };
1878
+ /**
1879
+ * Schedule a timeout-based telemetry flush if one is not already active.
1880
+ *
1881
+ * Behaviour:
1882
+ * - creates a timeout only when no current timeout exists
1883
+ * - when the timeout fires:
1884
+ * - telemetry is published
1885
+ * - buffered publish count is reset
1886
+ * - timeout handle is cleared
1887
+ *
1888
+ * In Node.js, the timer is `unref()`'d so it does not keep the process alive.
1889
+ */
1890
+ #SetupTimeout = async () => {
1891
+ if (!this.#publishTelemetryTimeout) {
1892
+ this.#publishTelemetryTimeout = setTimeout(async () => {
1893
+ this.#LogMessage(chalk.default.yellow(` PublishTelemetryData - Normal Behaviour (**** TIMEOUT ****) `));
1894
+ await this.#PublishTelemetryData();
1895
+ this.#publishTelemetryCount = 0;
1896
+ this.#publishTelemetryTimeout = null;
1897
+ }, this.#publishTelemetryTimeoutVal);
1898
+ if (_nsshunt_stsutils.isNode) this.#publishTelemetryTimeout.unref();
1899
+ }
1900
+ };
1901
+ /**
1902
+ * Publish the current telemetry snapshot immediately.
1903
+ *
1904
+ * Behaviour:
1905
+ * - asks the owning execution worker to post telemetry for this runner
1906
+ * - writes a separator line to the local test log sink
1907
+ * - resets transient per-publish telemetry fields
1908
+ * - yields immediately before returning
1909
+ *
1910
+ * Reset after publish:
1911
+ * - `velocity`
1912
+ * - `message`
1913
+ * - `tx`
1914
+ * - `rx`
1915
+ */
1916
+ #PublishTelemetryData = async () => {
1917
+ this.#runnerExecutionWorker.PostTelemetryById(this.#runner.id);
1918
+ this.#LogMessage(chalk.default.red(`------------------------------------------------------------------------------------------------------------`));
1919
+ this.#runner.instrumentData.velocity = 0;
1920
+ this.#runner.instrumentData.message = [];
1921
+ this.#runner.instrumentData.tx = 0;
1922
+ this.#runner.instrumentData.rx = 0;
1923
+ await this.SleepImmediate();
1924
+ };
1925
+ /**
1926
+ * Force an immediate telemetry publication.
1927
+ *
1928
+ * Used for lifecycle transitions where immediate visibility is desirable.
1929
+ */
1930
+ #ForcePublishTelemetryData = async () => {
1931
+ this.#LogMessage(chalk.default.magenta(` **** FORCED PUBLISH **** `));
1932
+ await this.#PublishTelemetryData();
1933
+ };
1934
+ /**
1935
+ * Buffer telemetry and publish using a threshold-or-timeout strategy.
1936
+ *
1937
+ * Behaviour:
1938
+ * - increments buffered telemetry count
1939
+ * - when the count reaches `#maxBufferSize`:
1940
+ * - clears any pending timeout
1941
+ * - immediately publishes telemetry
1942
+ * - resets buffered count
1943
+ * - otherwise ensures a timeout flush is scheduled
1944
+ *
1945
+ * This gives a "first trigger wins" strategy:
1946
+ * - count threshold reached
1947
+ * - timeout reached
1948
+ */
1949
+ #PublishTelemetry = async () => {
1950
+ this.#publishTelemetryCount++;
1951
+ if (this.#publishTelemetryCount % this.#maxBufferSize === 0) {
1952
+ this.#LogMessage(chalk.default.cyan(` **** MAX COUNT REACHED **** `));
1953
+ this.#publishTelemetryCount = 0;
1954
+ if (this.#publishTelemetryTimeout) {
1955
+ clearTimeout(this.#publishTelemetryTimeout);
1956
+ this.#publishTelemetryTimeout = null;
1957
+ }
1958
+ await this.#PublishTelemetryData();
1959
+ }
1960
+ if (!this.#publishTelemetryTimeout) this.#SetupTimeout();
1961
+ };
1962
+ /**
1963
+ * Yield immediately to the event loop/microtask queue.
1964
+ *
1965
+ * Used when asynchronous behaviour is desired but no real delay is needed.
1966
+ *
1967
+ * @returns Resolved promise.
1968
+ */
1969
+ SleepImmediate() {
1970
+ return new Promise((resolve, reject) => {
1971
+ resolve();
1972
+ });
1973
+ }
1974
+ /**
1975
+ * Execute one synthetic unit of work for this runner.
1976
+ *
1977
+ * Behaviour
1978
+ * ---------
1979
+ * - captures start time
1980
+ * - reads extended test options
1981
+ * - updates runner telemetry
1982
+ * - optionally generates animated telemetry messages
1983
+ * - always generates a progress message for telemetry
1984
+ * - always writes a progress message to `console.log(...)`
1985
+ * - simulates work with either:
1986
+ * - `Sleep(options.sleepDuration)`, or
1987
+ * - immediate yield
1988
+ * - decrements active request count
1989
+ * - calculates and stores execution duration
1990
+ * - performs buffered telemetry publication
1991
+ *
1992
+ * Telemetry fields updated
1993
+ * ------------------------
1994
+ * - `coreCount = 1`
1995
+ * - `activeRequestCount++`
1996
+ * - `requestCount++`
1997
+ * - `velocity++`
1998
+ * - `tx += 256000`
1999
+ * - `rx += 6500000`
2000
+ * - `duration = measured elapsed time`
2001
+ *
2002
+ * Additional visible behaviour
2003
+ * ----------------------------
2004
+ * Unlike `TestCase01`, this implementation always writes a progress message
2005
+ * directly to the process/browser console using `console.log(...)`.
2006
+ *
2007
+ * This makes it more useful for manually watching test progress while the
2008
+ * framework is running.
2009
+ *
2010
+ * @returns `true` when the simulated work cycle completes.
2011
+ */
2012
+ ExecuteRunner = async () => {
2013
+ const start = performance.now();
2014
+ const options = this.#runner.options;
2015
+ this.#runner.instrumentData.coreCount = 1;
2016
+ this.#runner.instrumentData.activeRequestCount++;
2017
+ this.#runner.instrumentData.requestCount++;
2018
+ this.#runner.instrumentData.velocity++;
2019
+ this.#runner.instrumentData.tx += 256e3;
2020
+ this.#runner.instrumentData.rx += 65e5;
2021
+ if (this.#runner.instrumentData.requestCount % options.logMessageMod === 0) this.#GenLogMessage(this.#runner, this.#runner.iteration);
2022
+ if (this.#runner.instrumentData.requestCount % 1 === 0) {
2023
+ const message = `Worker: [${this.#runner.asyncRunnerContext.threadId}], Runner: [${this.#runner.asyncRunnerContext.id}] has completed: [${this.#runner.instrumentData.requestCount}] iterations of max: [${options.executionProfile.iterations}]`;
2024
+ this.#LogMessage(message);
2025
+ this.#runner.instrumentData.message = [message];
2026
+ }
2027
+ /**
2028
+ * Visible console output for manual observation/debugging.
2029
+ *
2030
+ * This is the main behavioural difference from `TestCase01`.
2031
+ */
2032
+ const message = `Worker: [${this.#runner.asyncRunnerContext.threadId}], Runner: [${this.#runner.asyncRunnerContext.id}] has completed: [${this.#runner.instrumentData.requestCount}] iterations of max: [${options.executionProfile.iterations}]`;
2033
+ console.log(message);
2034
+ /**
2035
+ * Simulate actual work.
2036
+ *
2037
+ * In a real runner implementation this would be replaced with
2038
+ * domain-specific work such as:
2039
+ * - REST/API calls
2040
+ * - browser interactions
2041
+ * - DB operations
2042
+ * - file processing
2043
+ * etc.
2044
+ */
2045
+ if (options.sleepDuration > 0) await (0, _nsshunt_stsutils.Sleep)(options.sleepDuration);
2046
+ else await this.SleepImmediate();
2047
+ this.#runner.instrumentData.activeRequestCount--;
2048
+ const diff = performance.now() - start;
2049
+ this.#runner.instrumentData.duration = diff;
2050
+ await this.#PublishTelemetry();
2051
+ return true;
2052
+ };
2053
+ /**
2054
+ * Write a grey-coloured lifecycle message into the runner telemetry message buffer
2055
+ * and publish telemetry using normal buffered publish rules.
2056
+ *
2057
+ * @param message Lifecycle/status message to emit.
2058
+ */
2059
+ #OutputLogMessage = async (message) => {
2060
+ const messageOutput = chalk.default.grey(message);
2061
+ this.#LogMessage(messageOutput);
2062
+ this.#runner.instrumentData.message.push(messageOutput);
2063
+ await this.#PublishTelemetry();
2064
+ };
2065
+ /**
2066
+ * Handle framework "start" lifecycle event.
2067
+ *
2068
+ * Behaviour:
2069
+ * - writes a lifecycle message
2070
+ * - forces immediate telemetry publication
2071
+ *
2072
+ * @returns `true`
2073
+ */
2074
+ StartRunner = async () => {
2075
+ await this.#OutputLogMessage(`StartRunner [${this.#runner.id}]`);
2076
+ await this.#ForcePublishTelemetryData();
2077
+ return true;
2078
+ };
2079
+ /**
2080
+ * Handle framework "stop" lifecycle event.
2081
+ *
2082
+ * Behaviour:
2083
+ * - writes a lifecycle message
2084
+ * - forces immediate telemetry publication
2085
+ *
2086
+ * @returns `true`
2087
+ */
2088
+ StopRunner = async () => {
2089
+ await this.#OutputLogMessage(`StopRunner [${this.#runner.id}]`);
2090
+ await this.#ForcePublishTelemetryData();
2091
+ return true;
2092
+ };
2093
+ /**
2094
+ * Handle framework "terminate" lifecycle event.
2095
+ *
2096
+ * Behaviour:
2097
+ * - writes a lifecycle message
2098
+ * - forces immediate telemetry publication
2099
+ *
2100
+ * @returns `true`
2101
+ */
2102
+ TerminateRunner = async () => {
2103
+ await this.#OutputLogMessage(`TerminateRunner [${this.#runner.id}]`);
2104
+ await this.#ForcePublishTelemetryData();
2105
+ return true;
2106
+ };
2107
+ /**
2108
+ * Handle framework "completed" lifecycle event.
2109
+ *
2110
+ * Behaviour:
2111
+ * - writes a completion message including the current telemetry snapshot
2112
+ * - forces immediate telemetry publication
2113
+ *
2114
+ * @returns `true`
2115
+ */
2116
+ Completed = async () => {
2117
+ await this.#OutputLogMessage(`Completed [${this.#runner.id}] [${JSON.stringify(this.#runner.instrumentData)}]`);
2118
+ await this.#ForcePublishTelemetryData();
2119
+ return true;
2120
+ };
2121
+ /**
2122
+ * Handle framework "pause" lifecycle event.
2123
+ *
2124
+ * Behaviour:
2125
+ * - writes a lifecycle message
2126
+ * - forces immediate telemetry publication
2127
+ *
2128
+ * @returns `true`
2129
+ */
2130
+ PauseRunner = async () => {
2131
+ await this.#OutputLogMessage(`PauseRunner [${this.#runner.id}]`);
2132
+ await this.#ForcePublishTelemetryData();
2133
+ return true;
2134
+ };
2135
+ /**
2136
+ * Handle framework "resume" lifecycle event.
2137
+ *
2138
+ * Behaviour:
2139
+ * - writes a lifecycle message
2140
+ * - forces immediate telemetry publication
2141
+ *
2142
+ * @returns `true`
2143
+ */
2144
+ ResumeRunner = async () => {
2145
+ await this.#OutputLogMessage(`ResumeRunner [${this.#runner.id}]`);
2146
+ await this.#ForcePublishTelemetryData();
2147
+ return true;
2148
+ };
2149
+ /**
2150
+ * Handle framework "reset" lifecycle event.
2151
+ *
2152
+ * Behaviour:
2153
+ * - writes a lifecycle message
2154
+ * - resets `requestCount` to zero
2155
+ * - forces immediate telemetry publication
2156
+ *
2157
+ * @returns `true`
2158
+ */
2159
+ ResetRunner = async () => {
2160
+ await this.#OutputLogMessage(`ResetRunner [${this.#runner.id}]`);
2161
+ this.#runner.instrumentData.requestCount = 0;
2162
+ await this.#ForcePublishTelemetryData();
2163
+ return true;
2164
+ };
2165
+ /**
2166
+ * Handle framework "update" lifecycle event.
2167
+ *
2168
+ * Behaviour:
2169
+ * - writes a lifecycle message
2170
+ * - forces immediate telemetry publication
2171
+ *
2172
+ * Note:
2173
+ * - this implementation acknowledges the update event but does not apply
2174
+ * custom update logic itself
2175
+ *
2176
+ * @returns `true`
2177
+ */
2178
+ UpdateRunner = async () => {
2179
+ await this.#OutputLogMessage(`UpdateOptions [${this.#runner.id}]`);
2180
+ await this.#ForcePublishTelemetryData();
2181
+ return true;
2182
+ };
2183
+ };
2184
+ //#endregion
1360
2185
  //#region src/libmodule/asyncRunnerFactory.ts
1361
2186
  var AsyncRunnerFactory = class {
1362
2187
  static CreateAsyncRunner = async (runnerExecutionWorker, testRunnerTelemetryPayload) => {
1363
2188
  const { runner } = testRunnerTelemetryPayload;
1364
2189
  switch (runner.options.testType) {
2190
+ case "TestCase01": return new TestCase01(runnerExecutionWorker, runner);
2191
+ case "TestCase02": return new TestCase02(runnerExecutionWorker, runner);
1365
2192
  case "TestCaseFhir01": return new TestCaseFhir01(runnerExecutionWorker, runner);
1366
2193
  case "TestCaseFhir02": return new TestCaseFhir02(runnerExecutionWorker, runner);
1367
2194
  case "TestCaseFhir03": return new TestCaseFhir03(runnerExecutionWorker, runner);