@nsshunt/ststestrunner 1.1.104 → 1.1.106

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.
@@ -1,12 +1,13 @@
1
1
  import { AbstractRunnerExecutionWorker } from "@nsshunt/stsrunnerframework";
2
- import chalk from "chalk";
3
2
  import { STSAxiosConfig, Sleep, createAgentManager, isNode } from "@nsshunt/stsutils";
4
- import { FhirRESTClient, FhirSocketClientAllInOne, FhirSocketClientIndividual, createRetryAxiosClient } from "@nsshunt/stsfhirclient";
3
+ import chalk from "chalk";
4
+ import axios from "axios";
5
5
  import http from "node:http";
6
6
  import https from "node:https";
7
- import axios from "axios";
7
+ import { FhirRESTClient, FhirSocketClientAllInOne, FhirSocketClientIndividual, createRetryAxiosClient } from "@nsshunt/stsfhirclient";
8
8
  //#region \0rolldown/runtime.js
9
9
  var __defProp = Object.defineProperty;
10
+ var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
10
11
  var __exportAll = (all, no_symbols) => {
11
12
  let target = {};
12
13
  for (var name in all) __defProp(target, name, {
@@ -379,190 +380,40 @@ var StatusCodes;
379
380
  //#region src/libmodule/testCaseFhirBase.ts
380
381
  var TestCaseFhirBase = class {
381
382
  #options;
382
- #randomDataRecordset = [];
383
383
  #runner;
384
384
  #runnerExecutionWorker;
385
- #accesssToken = null;
386
385
  #publishTelemetryCount = 0;
387
386
  #maxBufferSize = 50;
388
387
  #publishTelemetryTimeout = null;
389
388
  #publishTelemetryTimeoutVal = 1e3;
390
- #originRegex = /^(api:\/\/\w+)/;
391
- #resetSocketClientTrigger = 50;
392
- #clientSocketFetchCount = 0;
393
- #authAgentManager;
389
+ _RetryMap = [
390
+ 100,
391
+ 250,
392
+ 500,
393
+ 1e3,
394
+ 2e3,
395
+ 3e3
396
+ ];
394
397
  _id = crypto.randomUUID();
395
398
  retryCount = 0;
396
399
  maxAuthRetryCount = 5;
397
400
  runnerDurationList = [];
398
- _authMaxTimeout = 5e3;
399
- accessTokenTime = performance.now();
400
- newTokenLimitTime = 30;
401
- restFhirClient = null;
402
- defaultAgentOptions = {
403
- keepAlive: true,
404
- maxSockets: 10,
405
- maxTotalSockets: 20,
406
- maxFreeSockets: 10,
407
- timeout: 6e4,
408
- rejectUnauthorized: false
409
- };
410
- stressTestAgentOptions = {
411
- keepAlive: true,
412
- maxSockets: 200,
413
- maxTotalSockets: 500,
414
- maxFreeSockets: 50,
415
- timeout: 3e4,
416
- rejectUnauthorized: false
417
- };
418
- stressTestExtremeAgentOptions = {
419
- keepAlive: true,
420
- maxSockets: 500,
421
- maxTotalSockets: 1e3,
422
- maxFreeSockets: 500,
423
- timeout: 3e4,
424
- rejectUnauthorized: false
425
- };
426
401
  constructor(runnerExecutionWorker, runner) {
427
402
  this.#options = runner.options;
428
403
  this.#runnerExecutionWorker = runnerExecutionWorker;
429
404
  this.#runner = runner;
430
- this.#authAgentManager = this.GetAuthAgentManager();
431
405
  }
432
406
  get runnerExecutionWorker() {
433
407
  return this.#runnerExecutionWorker;
434
408
  }
435
409
  ResetClient = () => {};
436
- GetRESTClient = async () => {
437
- if (this.restFhirClient) return this.restFhirClient;
438
- const onRetryAttempt = (attempt, error, delayMs) => {
439
- this.#runner.instrumentData.errorCount++;
440
- this.#runner.instrumentData.requestCount++;
441
- const message = `TestCaseFhirBase:onRetryAttempt(): [${this._id}] Retry #${attempt} after ${delayMs}ms due to ${error.code || error.response?.status}`;
442
- this.Warning(message);
443
- this.#runner.instrumentData.message.push(chalk.red(message));
444
- };
445
- const fhirOptions = this.#options.fhirOptions;
446
- const fhirRESTClient = new FhirRESTClient({
447
- GetAccessToken: this.GetAccessToken,
448
- user: "USR_user01@stsmda.com.au",
449
- endpoint: fhirOptions.stsfhirserverendpoint,
450
- stsfhirapiroot: fhirOptions.stsfhirapiroot,
451
- stsfhirport: fhirOptions.stsfhirport,
452
- logger: this.#runnerExecutionWorker.logger,
453
- agentManager: this.GetFhirAgentManager(),
454
- onRetryAttempt
455
- });
456
- this.restFhirClient = fhirRESTClient;
457
- return fhirRESTClient;
458
- };
459
- GetAgentManager = (testingAgentOptions) => {
460
- let agentManager = void 0;
461
- let agentOptions = void 0;
462
- switch (testingAgentOptions.nodeAgentMode) {
463
- case "no-agent": break;
464
- case "custom-agent-options":
465
- if (testingAgentOptions.nodeAgentCustomOptions) agentOptions = { ...testingAgentOptions.nodeAgentCustomOptions };
466
- else agentOptions = { ...this.defaultAgentOptions };
467
- break;
468
- case "default-agent-options":
469
- agentOptions = { ...this.defaultAgentOptions };
470
- break;
471
- case "stress-test-agent-options":
472
- agentOptions = { ...this.stressTestAgentOptions };
473
- break;
474
- case "stress-test-extreme-agent-options":
475
- agentOptions = { ...this.stressTestExtremeAgentOptions };
476
- break;
477
- default: throw new Error(`TestCaseFhirBase:GetAgentManager(): [${this._id}] unknown nodeAgentMode: [${testingAgentOptions.nodeAgentMode}]`);
478
- }
479
- if (agentOptions) agentManager = createAgentManager({
480
- agentOptions,
481
- httpAgentFactory(options) {
482
- return new http.Agent(options);
483
- },
484
- httpsAgentFactory(options) {
485
- return new https.Agent(options);
486
- }
487
- });
488
- return agentManager;
489
- };
490
- GetFhirAgentManager = () => {
491
- return this.GetAgentManager(this.#options.fhirOptions.stsfhiragentOptions);
492
- };
493
- GetAuthAgentManager = () => {
494
- return this.GetAgentManager(this.#options.authOptions.asagentoptions);
495
- };
496
- GetFhirSocketClient = async () => {
497
- try {
498
- this.#clientSocketFetchCount++;
499
- let fhirClient = this.runnerExecutionWorker.GetFhirClient();
500
- if (fhirClient) return fhirClient;
501
- if (this.runnerExecutionWorker.GetOnHold("fhirclient") === true) {
502
- this.Debug(chalk.magenta(`[${this.runnerExecutionWorker.id}] [${this._id}] fhir client does not exist - some other client setting up the new client (on hold/lock) - waiting ...`));
503
- try {
504
- const start = performance.now();
505
- await this.runnerExecutionWorker.WaitOnHold("fhirclient", 6e4);
506
- this.Debug(chalk.yellow(`[${this.runnerExecutionWorker.id}] [${this._id}] hold (lock) released after: [${performance.now() - start}ms]`));
507
- const fhirClient = this.runnerExecutionWorker.GetFhirClient();
508
- if (fhirClient) {
509
- this.Debug(chalk.green(`[${this.runnerExecutionWorker.id}] [${this._id}] Getting existing fhir client (post hold release)`));
510
- return fhirClient;
511
- } else {
512
- this.Error(chalk.red(`[${this.runnerExecutionWorker.id}] [${this._id}] Could not get existing fhir client (post hold release)`));
513
- this.Error(chalk.red(`continue anyway ...`));
514
- }
515
- } catch (error) {
516
- this.Error(chalk.red(`GetFhirSocketClient(): Error: [${error}]`));
517
- }
518
- }
519
- const start = performance.now();
520
- this.Debug(chalk.yellow(`[${this.runnerExecutionWorker.id}] [${this._id}] fhir client does not exist - setting up new client`));
521
- this.Debug(chalk.yellow(`[${this.runnerExecutionWorker.id}] [${this._id}] setting hold (lock)`));
522
- this.runnerExecutionWorker.SetOnHold("fhirclient");
523
- const fhirOptions = this.#options.fhirOptions;
524
- const options = {
525
- fhirServerEndpoint: fhirOptions.stsfhirserverendpoint,
526
- fhirapiroot: fhirOptions.stsfhirapiroot,
527
- fhirServerPort: fhirOptions.stsfhirport,
528
- socketClientName: fhirOptions.stsfhirsocketname,
529
- socketIoCustomPath: fhirOptions.stsfhirsocketcustompath,
530
- timeout: fhirOptions.stsfhirsockettimeout,
531
- baseUrl: fhirOptions.stsfhirbaseurl,
532
- agentManager: this.GetFhirAgentManager(),
533
- joinRooms: [],
534
- logger: this.#runnerExecutionWorker.logger,
535
- verboseLogging: true,
536
- GetConnectionAccessToken: this.GetAccessTokenForSocketClientAccess,
537
- GetAccessToken: this.GetAccessToken
538
- };
539
- if (this.runner.options.fhirOptions.stsfhirsocketclientmode === "socket-client-all-in-one") fhirClient = new FhirSocketClientAllInOne("FhirSocketClient", options);
540
- else fhirClient = new FhirSocketClientIndividual("FhirSocketClient", options);
541
- await fhirClient.WaitForSocketConnected();
542
- this.Debug(chalk.yellow(`[${this.runnerExecutionWorker.id}] [${this._id}] setting fhir client into object`));
543
- this.runnerExecutionWorker.SetFhirClient(fhirClient);
544
- this.runnerExecutionWorker.ReleaseOnHold("fhirclient");
545
- this.Debug(chalk.yellow(`[${this.runnerExecutionWorker.id}] [${this._id}] release hold (lock) Time taken for socket connection and set object: [${performance.now() - start}ms]`));
546
- return fhirClient;
547
- } catch (error) {
548
- this.Error(error);
549
- throw error;
550
- }
551
- };
552
- #LogMessage = (message) => {};
553
- Debug = (message) => {
554
- this.#runnerExecutionWorker.logger.debug(message);
555
- };
556
410
  Error = (message) => {
557
411
  this.#runnerExecutionWorker.logger.error(message);
558
412
  this.#runner.instrumentData.message.push(chalk.red(`${message}`));
559
413
  };
560
- Warning = (message) => {
561
- this.#runnerExecutionWorker.logger.warn(message);
414
+ Debug = (message) => {
415
+ this.#runnerExecutionWorker.logger.debug(message);
562
416
  };
563
- get accesssToken() {
564
- return this.#accesssToken;
565
- }
566
417
  get runner() {
567
418
  return this.#runner;
568
419
  }
@@ -605,125 +456,6 @@ var TestCaseFhirBase = class {
605
456
  this.#runner.instrumentData.rx = 0;
606
457
  await this.SleepImmediate();
607
458
  };
608
- ExtractOrigin = (uri) => {
609
- const match = uri.match(this.#originRegex);
610
- return match ? match[1] : null;
611
- };
612
- GetAPITokenFromAuthServerUsingScope = async (options) => {
613
- const { scope, clientId, authClientSecret, endPoint } = options;
614
- let stage = "1";
615
- try {
616
- stage = "2";
617
- const scopes = scope.split(" ");
618
- let origin = null;
619
- let error = null;
620
- stage = "3";
621
- for (let i = 0; i < scopes.length; i++) {
622
- const s = scopes[i];
623
- if (!origin) {
624
- origin = this.ExtractOrigin(s);
625
- if (!origin) {
626
- error = /* @__PURE__ */ new Error(`Scope: [${scope}] not in required format. Must use (space seperated) api://<client id>[/<resource>.<permission>].`);
627
- break;
628
- }
629
- } else {
630
- const nextOrigin = this.ExtractOrigin(s);
631
- if (!nextOrigin) {
632
- error = /* @__PURE__ */ new Error(`Scope: [${scope}] not in required format. Must use (space seperated) api://<client id>[/<resource>.<permission>].`);
633
- break;
634
- } else if (origin.localeCompare(nextOrigin) !== 0) {
635
- error = /* @__PURE__ */ new Error(`Scope: [${scope}] not all from the same client API. All scopes must come from the same client API.`);
636
- break;
637
- }
638
- }
639
- }
640
- stage = "4";
641
- if (error) throw error;
642
- stage = "5";
643
- const payload = {
644
- client_id: clientId,
645
- client_secret: authClientSecret,
646
- scope,
647
- grant_type: "client_credentials"
648
- };
649
- stage = "6";
650
- const url = endPoint ? `${endPoint}${this.#options.authOptions.asoauthapiroot}/token` : `${this.#options.authOptions.asendpoint}:${this.#options.authOptions.asport}${this.#options.authOptions.asoauthapiroot}/token`;
651
- stage = `6.5: url: [${url}] payload: [${JSON.stringify(payload)}]`;
652
- const axiosConfig = new STSAxiosConfig(url, "post").withDefaultHeaders().withData(payload);
653
- if (this.#authAgentManager) axiosConfig.withAgentManager(this.#authAgentManager);
654
- const retVal = await createRetryAxiosClient({
655
- maxRetries: 4,
656
- retryDelayMs: 300,
657
- retryJitterMs: 150,
658
- maxRetryDurationMs: 5e3,
659
- onRetryAttempt: (attempt, error, delayMs) => {
660
- this.#runner.instrumentData.authenticationErrorCount++;
661
- this.#runner.instrumentData.authenticationRetryCount++;
662
- const message = `TestCaseFhirBase:GetAPITokenFromAuthServerUsingScope(): [${this._id}] Retry #${attempt} after ${delayMs}ms due to ${error.code || error.response?.status}`;
663
- this.Warning(message);
664
- this.#runner.instrumentData.message.push(chalk.red(message));
665
- }
666
- })(url, axiosConfig.config);
667
- this.#runner.instrumentData.authenticationCount++;
668
- stage = "7";
669
- if (retVal.status) {
670
- if (retVal.status !== 200) this.Warning(chalk.magenta(`TestCaseFhirBase:GetAPITokenFromAuthServerUsingScope(): [${this._id}] Invalid response from server: [${retVal.status}]`));
671
- } else throw new Error(chalk.red(`No retVal.status)`));
672
- stage = "8";
673
- if (retVal.data) {
674
- stage = "9";
675
- if (retVal.data.access_token) {
676
- stage = "12";
677
- return retVal.data.access_token;
678
- } else {
679
- stage = "13";
680
- throw new Error(`No retVal.data.access_token)`);
681
- }
682
- } else {
683
- stage = "14";
684
- throw new Error(`No retVal.data)`);
685
- }
686
- } catch (error) {
687
- this.Error(error);
688
- let details = "None available.";
689
- if (error.response && error.response.data) try {
690
- details = JSON.stringify(error.response.data);
691
- } catch (error) {
692
- details = `Could not JSON.stringify(error.response.data)`;
693
- }
694
- error.message = `TestCaseFhirBase:GetAPITokenFromAuthServerUsingScope(): [${this._id}] Error: [${error}], Stage: [${stage}], Details: [${details}]`;
695
- throw error;
696
- }
697
- };
698
- GetAccessTokenForSocketClientAccess = async () => {
699
- const timeout = setTimeout(() => {
700
- this.Warning(`TestCaseFhirBase:GetAccessTokenForSocketClientAccess(): [${this._id}] Timeout: [${this._authMaxTimeout}] exceeded for getting access token ...`);
701
- }, this._authMaxTimeout);
702
- const start = performance.now();
703
- try {
704
- const scopes = `api://fb6513e4-16fe-4931-bed8-33b82b404a14/_.stsfhir5:SocketConnection`.split(" ").sort().join(" ");
705
- const authendpointUrl = `${this.#options.authOptions.asendpoint}:${this.#options.authOptions.asport}`;
706
- const retVal = await this.GetAPITokenFromAuthServerUsingScope({
707
- clientId: "d8277fce-bb48-44c2-bbf1-257fe13a444b",
708
- authClientSecret: "64e3ef37-c7b8-4cb1-880a-e6ad3ab36e3c",
709
- scope: scopes,
710
- endPoint: authendpointUrl
711
- });
712
- clearTimeout(timeout);
713
- const totalTime = performance.now() - start;
714
- if (totalTime > this._authMaxTimeout) this.Warning(chalk.magenta(`TestCaseFhirBase:GetAccessTokenForSocketClientAccess(): [${this._id}] The total time for getting the access token: [${totalTime}]`));
715
- return retVal;
716
- } catch (error) {
717
- clearTimeout(timeout);
718
- const totalTime = performance.now() - start;
719
- error.message = `TestCaseFhirBase:GetAccessTokenForSocketClientAccess(): [${this._id}] Error: [${error}], Duration until error: [${totalTime}]`;
720
- this.Error(error);
721
- return "";
722
- }
723
- };
724
- ResetAccessToken = () => {
725
- this.#accesssToken = null;
726
- };
727
459
  HandleError = (error) => {
728
460
  this.Error(chalk.red(`TestCaseFhirBase:HandleError(): [${this._id}] Error: [${error}]`));
729
461
  this.Error(chalk.red(`TestCaseFhirBase:HandleError(): [${this._id}] description: [${this.runner.options.description}]`));
@@ -738,48 +470,18 @@ var TestCaseFhirBase = class {
738
470
  if (axiosError.response.status === StatusCodes.UNAUTHORIZED) {
739
471
  this.runner.instrumentData.authenticationErrorCount++;
740
472
  this.Error(chalk.red(`TestCaseFhirBase:HandleError(): [${this._id}] UNAUTHORIZED - Reset Access Token`));
741
- this.ResetAccessToken();
473
+ this.runnerExecutionWorker.authHelper.ResetAccessToken();
742
474
  return true;
743
475
  }
744
476
  } else this.Error(chalk.red(`TestCaseFhirBase:HandleError(): [${this._id}] AXIOS Error = [${axiosError}]`));
745
477
  } else if (error.message === "UNAUTHORIZED") {
746
478
  this.runner.instrumentData.authenticationErrorCount++;
747
479
  this.Error(chalk.red(`TestCaseFhirBase:HandleError(): [${this._id}] UNAUTHORIZED - Reset Access Token`));
748
- this.ResetAccessToken();
480
+ this.runnerExecutionWorker.authHelper.ResetAccessToken();
749
481
  return true;
750
482
  }
751
483
  return false;
752
484
  };
753
- GetAccessToken = async () => {
754
- let timeout = void 0;
755
- let start = performance.now();
756
- try {
757
- if (this.#accesssToken) return this.#accesssToken;
758
- timeout = setTimeout(() => {
759
- this.Warning(chalk.magenta(`TestCaseFhirBase:GetAccessToken(): [${this._id}] Timeout: [${this._authMaxTimeout}] exceeded for getting access token ...`));
760
- }, this._authMaxTimeout);
761
- const scopes = `api://fb6513e4-16fe-4931-bed8-33b82b404a14/_.stsfhir5:All`.split(" ").sort().join(" ");
762
- const authendpointUrl = `${this.#options.authOptions.asendpoint}:${this.#options.authOptions.asport}`;
763
- const retVal = await this.GetAPITokenFromAuthServerUsingScope({
764
- clientId: "d8277fce-bb48-44c2-bbf1-257fe13a444b",
765
- authClientSecret: "64e3ef37-c7b8-4cb1-880a-e6ad3ab36e3c",
766
- scope: scopes,
767
- endPoint: authendpointUrl
768
- });
769
- this.accessTokenTime = performance.now();
770
- this.#accesssToken = retVal;
771
- if (timeout) clearTimeout(timeout);
772
- const totalTime = performance.now() - start;
773
- if (totalTime > this._authMaxTimeout) this.Warning(chalk.magenta(`TestCaseFhirBase:GetAccessToken(): [${this._id}] The total time for getting the access token: [${totalTime}]`));
774
- return retVal;
775
- } catch (error) {
776
- if (timeout) clearTimeout(timeout);
777
- const totalTime = performance.now() - start;
778
- error.message = `TestCaseFhirBase:GetAccessToken(): [${this._id}] Error: [${error}], Duration until error: [${totalTime}]`;
779
- this.Error(error);
780
- return "";
781
- }
782
- };
783
485
  GetPersonRecord = async (prefix, index, version) => {
784
486
  const { workerIndex, runnerIndex, runId } = this.#options;
785
487
  const useId = `${prefix}-${index}`;
@@ -806,37 +508,12 @@ var TestCaseFhirBase = class {
806
508
  }
807
509
  };
808
510
  };
809
- StartTestDataLoad = async () => {
810
- this.Debug(chalk.magenta(`StartTestDataLoad(): Start ...`));
811
- let VU = 0;
812
- const blockNum = VU * 200;
813
- const blocksToLoad = 20;
814
- for (let i = 0; i < blocksToLoad; i++) {
815
- const recordId = `stsres_${blockNum + i}`;
816
- const retVal = await (await this.GetFhirSocketClient()).GetResource("Person", recordId);
817
- if (retVal) {
818
- const recordsetData = retVal.body.address;
819
- if (recordsetData) {
820
- const qqq = recordsetData[0].text;
821
- for (let j = 0; j < qqq.length; j++) this.#randomDataRecordset.push(qqq[j]);
822
- this.Error(chalk.magenta(this.#randomDataRecordset.length));
823
- }
824
- } else this.Error(chalk.magenta(`StartTestDataLoad(): Could not get person records.`));
825
- await Sleep(10);
826
- }
827
- this.Debug(`Finished load for VU: [${VU}]`);
828
- this.Debug(`First 10 entries`);
829
- for (let i = 0; i < 10; i++) this.Debug(this.#randomDataRecordset[i].id);
830
- this.Debug(`block num: [${blockNum}] length: [${this.#randomDataRecordset.length}] VU: [${VU}]`);
831
- this.Debug(chalk.magenta(`StartTestDataLoad(): End`));
832
- };
833
511
  #ForcePublishTelemetryData = async () => {
834
512
  await this.#PublishTelemetryData();
835
513
  };
836
514
  #SetupTimeout = async () => {
837
515
  if (!this.#publishTelemetryTimeout) {
838
516
  this.#publishTelemetryTimeout = setTimeout(async () => {
839
- this.#LogMessage(chalk.yellow(` **** TIMEOUT **** `));
840
517
  await this.#PublishTelemetryData();
841
518
  this.#publishTelemetryCount = 0;
842
519
  this.#publishTelemetryTimeout = null;
@@ -846,7 +523,6 @@ var TestCaseFhirBase = class {
846
523
  };
847
524
  PublishTelemetry = async () => {
848
525
  this.#publishTelemetryCount++;
849
- this.#LogMessage(chalk.red(this.#publishTelemetryCount));
850
526
  if (this.#publishTelemetryCount % this.#maxBufferSize === 0) {
851
527
  this.#publishTelemetryCount = 0;
852
528
  if (this.#publishTelemetryTimeout) {
@@ -859,7 +535,6 @@ var TestCaseFhirBase = class {
859
535
  };
860
536
  #OutputLogMessage = async (message) => {
861
537
  const messageOutput = chalk.grey(message);
862
- this.#LogMessage(messageOutput);
863
538
  this.#runner.instrumentData.message.push(messageOutput);
864
539
  await this.PublishTelemetry();
865
540
  };
@@ -907,12 +582,6 @@ var TestCaseFhirBase = class {
907
582
  await this.#ForcePublishTelemetryData();
908
583
  return true;
909
584
  };
910
- GetClient = async () => {
911
- let client;
912
- if (this.runner.options.fhirOptions.stsfhirsocketclientmode === "no-socket-client") client = await this.GetRESTClient();
913
- else client = await this.GetFhirSocketClient();
914
- return client;
915
- };
916
585
  _GetDetail = () => {
917
586
  return `testType: [${this.runner.options.testType}], description: [${this.runner.options.description}], workerManagerId: [${this.runner.workerManagerId}], Iteration: [${this.runner.iteration}]`;
918
587
  };
@@ -929,14 +598,6 @@ var TestCaseFhirBase = class {
929
598
  this.retryCount = 0;
930
599
  return this._ExecuteQuery();
931
600
  };
932
- _RetryMap = [
933
- 100,
934
- 250,
935
- 500,
936
- 1e3,
937
- 2e3,
938
- 3e3
939
- ];
940
601
  _ExecuteQuery = async () => {
941
602
  try {
942
603
  return await this.PerformExecuteQuery();
@@ -959,6 +620,9 @@ var TestCaseFhirBase = class {
959
620
  else throw error;
960
621
  }
961
622
  };
623
+ GetClient = async () => {
624
+ return this.runnerExecutionWorker.GetClient();
625
+ };
962
626
  };
963
627
  //#endregion
964
628
  //#region src/libmodule/testCaseFhirQueryBase.ts
@@ -1040,9 +704,9 @@ var TestCaseFhirQueryBase = class extends TestCaseFhirBase {
1040
704
  var TestCaseFhir01 = class extends TestCaseFhirQueryBase {
1041
705
  PerformExecuteQuery = async () => {
1042
706
  const __snapshot1 = performance.now();
1043
- await this.GetAccessToken();
707
+ await this.runnerExecutionWorker.authHelper.GetAccessToken();
1044
708
  this._CheckOutputLongDurationError(__snapshot1, "await this.GetAccessToken()");
1045
- this.ResetAccessToken();
709
+ this.runnerExecutionWorker.authHelper.ResetAccessToken();
1046
710
  return null;
1047
711
  };
1048
712
  };
@@ -36370,27 +36034,535 @@ var ResourceDataGenerator = class {
36370
36034
  };
36371
36035
  };
36372
36036
  //#endregion
36037
+ //#region src/libmodule/lockHelper.ts
36038
+ var import_tiny_emitter = (/* @__PURE__ */ __commonJSMin(((exports, module) => {
36039
+ function E() {}
36040
+ E.prototype = {
36041
+ on: function(name, callback, ctx) {
36042
+ var e = this.e || (this.e = {});
36043
+ (e[name] || (e[name] = [])).push({
36044
+ fn: callback,
36045
+ ctx
36046
+ });
36047
+ return this;
36048
+ },
36049
+ once: function(name, callback, ctx) {
36050
+ var self = this;
36051
+ function listener() {
36052
+ self.off(name, listener);
36053
+ callback.apply(ctx, arguments);
36054
+ }
36055
+ listener._ = callback;
36056
+ return this.on(name, listener, ctx);
36057
+ },
36058
+ emit: function(name) {
36059
+ var data = [].slice.call(arguments, 1);
36060
+ var evtArr = ((this.e || (this.e = {}))[name] || []).slice();
36061
+ var i = 0;
36062
+ var len = evtArr.length;
36063
+ for (; i < len; i++) evtArr[i].fn.apply(evtArr[i].ctx, data);
36064
+ return this;
36065
+ },
36066
+ off: function(name, callback) {
36067
+ var e = this.e || (this.e = {});
36068
+ var evts = e[name];
36069
+ var liveEvents = [];
36070
+ if (evts && callback) {
36071
+ for (var i = 0, len = evts.length; i < len; i++) if (evts[i].fn !== callback && evts[i].fn._ !== callback) liveEvents.push(evts[i]);
36072
+ }
36073
+ liveEvents.length ? e[name] = liveEvents : delete e[name];
36074
+ return this;
36075
+ }
36076
+ };
36077
+ module.exports = E;
36078
+ module.exports.TinyEmitter = E;
36079
+ })))();
36080
+ var LockHelper = class {
36081
+ _onHoldKeys = {};
36082
+ GetOnHold = (holdKey) => {
36083
+ if (this._onHoldKeys[holdKey]) return true;
36084
+ return false;
36085
+ };
36086
+ WaitOnHold = async (holdKey, timeout) => {
36087
+ const start = performance.now();
36088
+ for (;;) {
36089
+ if (this._onHoldKeys[holdKey]) await Sleep(100);
36090
+ else break;
36091
+ if (performance.now() - start > timeout) throw new Error(`WorkerFhirTestCases:WaitOnHold(): Timeout: [${timeout}] reached.`);
36092
+ }
36093
+ return true;
36094
+ };
36095
+ SetOnHold = (holdKey) => {
36096
+ this._onHoldKeys[holdKey] = true;
36097
+ };
36098
+ ReleaseOnHold = (holdKey) => {
36099
+ delete this._onHoldKeys[holdKey];
36100
+ };
36101
+ };
36102
+ //#endregion
36103
+ //#region src/libmodule/authHelper.ts
36104
+ var AuthHelper = class extends import_tiny_emitter.TinyEmitter {
36105
+ _options;
36106
+ _id = crypto.randomUUID();
36107
+ _lockHelper = new LockHelper();
36108
+ #accesssToken = null;
36109
+ _authMaxTimeout = 5e3;
36110
+ #originRegex = /^(api:\/\/\w+)/;
36111
+ #authAgentManager;
36112
+ logPrefix = `WorkerFhirTestCases:[${this._id}]:`;
36113
+ constructor(options) {
36114
+ super();
36115
+ this._options = options;
36116
+ this.#authAgentManager = this.GetAuthAgentManager();
36117
+ }
36118
+ Warning = (message) => {
36119
+ this._options.logger.warn(`${this.logPrefix}${message}`);
36120
+ };
36121
+ Error = (message) => {
36122
+ this._options.logger.error(`${this.logPrefix}${message}`);
36123
+ };
36124
+ Debug = (message) => {
36125
+ this._options.logger.debug(`${this.logPrefix}${message}`);
36126
+ };
36127
+ get id() {
36128
+ return this._id;
36129
+ }
36130
+ defaultAgentOptions = {
36131
+ keepAlive: true,
36132
+ maxSockets: 10,
36133
+ maxTotalSockets: 20,
36134
+ maxFreeSockets: 10,
36135
+ timeout: 6e4,
36136
+ rejectUnauthorized: false
36137
+ };
36138
+ stressTestAgentOptions = {
36139
+ keepAlive: true,
36140
+ maxSockets: 200,
36141
+ maxTotalSockets: 500,
36142
+ maxFreeSockets: 50,
36143
+ timeout: 3e4,
36144
+ rejectUnauthorized: false
36145
+ };
36146
+ stressTestExtremeAgentOptions = {
36147
+ keepAlive: true,
36148
+ maxSockets: 500,
36149
+ maxTotalSockets: 1e3,
36150
+ maxFreeSockets: 500,
36151
+ timeout: 3e4,
36152
+ rejectUnauthorized: false
36153
+ };
36154
+ GetAgentManager = (testingAgentOptions) => {
36155
+ let agentManager = void 0;
36156
+ let agentOptions = void 0;
36157
+ switch (testingAgentOptions.nodeAgentMode) {
36158
+ case "no-agent": break;
36159
+ case "custom-agent-options":
36160
+ if (testingAgentOptions.nodeAgentCustomOptions) agentOptions = { ...testingAgentOptions.nodeAgentCustomOptions };
36161
+ else agentOptions = { ...this.defaultAgentOptions };
36162
+ break;
36163
+ case "default-agent-options":
36164
+ agentOptions = { ...this.defaultAgentOptions };
36165
+ break;
36166
+ case "stress-test-agent-options":
36167
+ agentOptions = { ...this.stressTestAgentOptions };
36168
+ break;
36169
+ case "stress-test-extreme-agent-options":
36170
+ agentOptions = { ...this.stressTestExtremeAgentOptions };
36171
+ break;
36172
+ default: throw new Error(`TestCaseFhirBase:GetAgentManager(): [${this._id}] unknown nodeAgentMode: [${testingAgentOptions.nodeAgentMode}]`);
36173
+ }
36174
+ if (agentOptions) agentManager = createAgentManager({
36175
+ agentOptions,
36176
+ httpAgentFactory(options) {
36177
+ return new http.Agent(options);
36178
+ },
36179
+ httpsAgentFactory(options) {
36180
+ return new https.Agent(options);
36181
+ }
36182
+ });
36183
+ return agentManager;
36184
+ };
36185
+ GetAuthAgentManager = () => {
36186
+ return this.GetAgentManager(this._options.authOptions.asagentoptions);
36187
+ };
36188
+ ExtractOrigin = (uri) => {
36189
+ const match = uri.match(this.#originRegex);
36190
+ return match ? match[1] : null;
36191
+ };
36192
+ GetAPITokenFromAuthServerUsingScope = async (options) => {
36193
+ const { scope, clientId, authClientSecret, endPoint } = options;
36194
+ let stage = "1";
36195
+ try {
36196
+ stage = "2";
36197
+ const scopes = scope.split(" ");
36198
+ let origin = null;
36199
+ let error = null;
36200
+ stage = "3";
36201
+ for (let i = 0; i < scopes.length; i++) {
36202
+ const s = scopes[i];
36203
+ if (!origin) {
36204
+ origin = this.ExtractOrigin(s);
36205
+ if (!origin) {
36206
+ error = /* @__PURE__ */ new Error(`Scope: [${scope}] not in required format. Must use (space seperated) api://<client id>[/<resource>.<permission>].`);
36207
+ break;
36208
+ }
36209
+ } else {
36210
+ const nextOrigin = this.ExtractOrigin(s);
36211
+ if (!nextOrigin) {
36212
+ error = /* @__PURE__ */ new Error(`Scope: [${scope}] not in required format. Must use (space seperated) api://<client id>[/<resource>.<permission>].`);
36213
+ break;
36214
+ } else if (origin.localeCompare(nextOrigin) !== 0) {
36215
+ error = /* @__PURE__ */ new Error(`Scope: [${scope}] not all from the same client API. All scopes must come from the same client API.`);
36216
+ break;
36217
+ }
36218
+ }
36219
+ }
36220
+ stage = "4";
36221
+ if (error) throw error;
36222
+ stage = "5";
36223
+ const payload = {
36224
+ client_id: clientId,
36225
+ client_secret: authClientSecret,
36226
+ scope,
36227
+ grant_type: "client_credentials"
36228
+ };
36229
+ stage = "6";
36230
+ const url = endPoint ? `${endPoint}${this._options.authOptions.asoauthapiroot}/token` : `${this._options.authOptions.asendpoint}:${this._options.authOptions.asport}${this._options.authOptions.asoauthapiroot}/token`;
36231
+ stage = `6.5: url: [${url}] payload: [${JSON.stringify(payload)}]`;
36232
+ const axiosConfig = new STSAxiosConfig(url, "post").withDefaultHeaders().withData(payload);
36233
+ if (this.#authAgentManager) axiosConfig.withAgentManager(this.#authAgentManager);
36234
+ const retVal = await createRetryAxiosClient({
36235
+ maxRetries: 4,
36236
+ retryDelayMs: 300,
36237
+ retryJitterMs: 150,
36238
+ maxRetryDurationMs: 5e3,
36239
+ onRetryAttempt: (attempt, error, delayMs) => {
36240
+ this.emit("authenticationErrorCount", 1);
36241
+ this.emit("authenticationRetryCount", 1);
36242
+ const message = `GetAPITokenFromAuthServerUsingScope(): [${this._id}] Retry #${attempt} after ${delayMs}ms due to ${error.code || error.response?.status}`;
36243
+ this.Warning(message);
36244
+ this.emit("logMessage", chalk.red(message));
36245
+ }
36246
+ })(url, axiosConfig.config);
36247
+ this.emit("authenticationCount", 1);
36248
+ stage = "7";
36249
+ if (retVal.status) {
36250
+ if (retVal.status !== 200) this.Warning(chalk.magenta(`GetAPITokenFromAuthServerUsingScope(): [${this._id}] Invalid response from server: [${retVal.status}]`));
36251
+ } else throw new Error(chalk.red(`No retVal.status)`));
36252
+ stage = "8";
36253
+ if (retVal.data) {
36254
+ stage = "9";
36255
+ if (retVal.data.access_token) {
36256
+ stage = "12";
36257
+ return retVal.data.access_token;
36258
+ } else {
36259
+ stage = "13";
36260
+ throw new Error(`No retVal.data.access_token)`);
36261
+ }
36262
+ } else {
36263
+ stage = "14";
36264
+ throw new Error(`No retVal.data)`);
36265
+ }
36266
+ } catch (error) {
36267
+ this.Error(error);
36268
+ let details = "None available.";
36269
+ if (error.response && error.response.data) try {
36270
+ details = JSON.stringify(error.response.data);
36271
+ } catch (error) {
36272
+ details = `Could not JSON.stringify(error.response.data)`;
36273
+ }
36274
+ error.message = `${this.logPrefix}GetAPITokenFromAuthServerUsingScope(): Error: [${error}], Stage: [${stage}], Details: [${details}]`;
36275
+ throw error;
36276
+ }
36277
+ };
36278
+ GetAccessToken = async () => {
36279
+ let timeout = void 0;
36280
+ const start = performance.now();
36281
+ try {
36282
+ if (this.#accesssToken) return this.#accesssToken;
36283
+ const lockKey = "GetAccessToken";
36284
+ const lockTimeout = 6e4;
36285
+ if (this._lockHelper.GetOnHold(lockKey) === true) {
36286
+ this.Debug(chalk.magenta(`GetAccessToken(): accesssToken does not exist - some other client setting up the new accesssToken (on hold/lock), lock key: [${lockKey}] - waiting ...`));
36287
+ try {
36288
+ const miniStart = performance.now();
36289
+ await this._lockHelper.WaitOnHold(lockKey, lockTimeout);
36290
+ this.Debug(chalk.yellow(`GetAccessToken(): hold (lock) released after: [${performance.now() - miniStart}ms], lock key: [${lockKey}]`));
36291
+ if (this.#accesssToken) {
36292
+ this.Debug(chalk.green(`GetAccessToken(): Getting existing accesssToken (post hold release), lock key: [${lockKey}]`));
36293
+ return this.#accesssToken;
36294
+ } else {
36295
+ this.Error(chalk.red(`GetAccessToken(): Could not get existing accesssToken (post hold release), lock key: [${lockKey}]`));
36296
+ this.Error(chalk.red(`GetAccessToken(): continue anyway ...`));
36297
+ }
36298
+ } catch (error) {
36299
+ this.Error(chalk.red(`GetAccessToken(): Error: [${error}]`));
36300
+ }
36301
+ }
36302
+ this.Debug(chalk.yellow(`GetAccessToken(): accesssToken does not exist - setting up new accesssToken`));
36303
+ this.Debug(chalk.yellow(`GetAccessToken(): setting hold (lock), lock key: [${lockKey}]`));
36304
+ this._lockHelper.SetOnHold(lockKey);
36305
+ timeout = setTimeout(() => {
36306
+ this.Warning(chalk.magenta(`GetAccessToken(): Timeout: [${this._authMaxTimeout}] exceeded for getting access token ...`));
36307
+ }, this._authMaxTimeout);
36308
+ const scopes = `api://fb6513e4-16fe-4931-bed8-33b82b404a14/_.stsfhir5:All`.split(" ").sort().join(" ");
36309
+ const authendpointUrl = `${this._options.authOptions.asendpoint}:${this._options.authOptions.asport}`;
36310
+ const workingAaccesssToken = await this.GetAPITokenFromAuthServerUsingScope({
36311
+ clientId: "d8277fce-bb48-44c2-bbf1-257fe13a444b",
36312
+ authClientSecret: "64e3ef37-c7b8-4cb1-880a-e6ad3ab36e3c",
36313
+ scope: scopes,
36314
+ endPoint: authendpointUrl
36315
+ });
36316
+ if (timeout) clearTimeout(timeout);
36317
+ const totalTime = performance.now() - start;
36318
+ if (totalTime > this._authMaxTimeout) this.Warning(chalk.magenta(`GetAccessToken(): The total time for getting the access token: [${totalTime}]`));
36319
+ this.#accesssToken = workingAaccesssToken;
36320
+ this._lockHelper.ReleaseOnHold(lockKey);
36321
+ this.Debug(chalk.yellow(`GetAccessToken(): release hold (lock) Time taken for get access token: [${performance.now() - start}ms]`));
36322
+ return this.#accesssToken;
36323
+ } catch (error) {
36324
+ if (timeout) clearTimeout(timeout);
36325
+ error.message = `GetAccessToken(): Error: [${error}], Duration until error: [${performance.now() - start}]`;
36326
+ this.Error(error);
36327
+ return "";
36328
+ }
36329
+ };
36330
+ GetAccessTokenForSocketClientAccess = async () => {
36331
+ const timeout = setTimeout(() => {
36332
+ this.Warning(`GetAccessTokenForSocketClientAccess(): Timeout: [${this._authMaxTimeout}] exceeded for getting access token ...`);
36333
+ }, this._authMaxTimeout);
36334
+ const start = performance.now();
36335
+ try {
36336
+ const scopes = `api://fb6513e4-16fe-4931-bed8-33b82b404a14/_.stsfhir5:SocketConnection`.split(" ").sort().join(" ");
36337
+ const authendpointUrl = `${this._options.authOptions.asendpoint}:${this._options.authOptions.asport}`;
36338
+ const retVal = await this.GetAPITokenFromAuthServerUsingScope({
36339
+ clientId: "d8277fce-bb48-44c2-bbf1-257fe13a444b",
36340
+ authClientSecret: "64e3ef37-c7b8-4cb1-880a-e6ad3ab36e3c",
36341
+ scope: scopes,
36342
+ endPoint: authendpointUrl
36343
+ });
36344
+ clearTimeout(timeout);
36345
+ const totalTime = performance.now() - start;
36346
+ if (totalTime > this._authMaxTimeout) this.Warning(chalk.magenta(`GetAccessTokenForSocketClientAccess(): The total time for getting the access token: [${totalTime}]`));
36347
+ return retVal;
36348
+ } catch (error) {
36349
+ clearTimeout(timeout);
36350
+ error.message = `GetAccessTokenForSocketClientAccess(): Error: [${error}], Duration until error: [${performance.now() - start}]`;
36351
+ this.Error(error);
36352
+ return "";
36353
+ }
36354
+ };
36355
+ ResetAccessToken = () => {
36356
+ this.#accesssToken = null;
36357
+ };
36358
+ };
36359
+ //#endregion
36360
+ //#region src/libmodule/clientHelper.ts
36361
+ var ClientHelper = class extends import_tiny_emitter.TinyEmitter {
36362
+ _options;
36363
+ fhirClient = void 0;
36364
+ _id = crypto.randomUUID();
36365
+ _lockHelper = new LockHelper();
36366
+ restFhirClient = null;
36367
+ logPrefix = `WorkerFhirTestCases:[${this._id}]:`;
36368
+ constructor(options) {
36369
+ super();
36370
+ this._options = options;
36371
+ }
36372
+ Warning = (message) => {
36373
+ this._options.logger.warn(`${this.logPrefix}${message}`);
36374
+ };
36375
+ Error = (message) => {
36376
+ this._options.logger.error(`${this.logPrefix}${message}`);
36377
+ };
36378
+ Debug = (message) => {
36379
+ this._options.logger.debug(`${this.logPrefix}${message}`);
36380
+ };
36381
+ get id() {
36382
+ return this._id;
36383
+ }
36384
+ defaultAgentOptions = {
36385
+ keepAlive: true,
36386
+ maxSockets: 10,
36387
+ maxTotalSockets: 20,
36388
+ maxFreeSockets: 10,
36389
+ timeout: 6e4,
36390
+ rejectUnauthorized: false
36391
+ };
36392
+ stressTestAgentOptions = {
36393
+ keepAlive: true,
36394
+ maxSockets: 200,
36395
+ maxTotalSockets: 500,
36396
+ maxFreeSockets: 50,
36397
+ timeout: 3e4,
36398
+ rejectUnauthorized: false
36399
+ };
36400
+ stressTestExtremeAgentOptions = {
36401
+ keepAlive: true,
36402
+ maxSockets: 500,
36403
+ maxTotalSockets: 1e3,
36404
+ maxFreeSockets: 500,
36405
+ timeout: 3e4,
36406
+ rejectUnauthorized: false
36407
+ };
36408
+ GetAgentManager = (testingAgentOptions) => {
36409
+ let agentManager = void 0;
36410
+ let agentOptions = void 0;
36411
+ switch (testingAgentOptions.nodeAgentMode) {
36412
+ case "no-agent": break;
36413
+ case "custom-agent-options":
36414
+ if (testingAgentOptions.nodeAgentCustomOptions) agentOptions = { ...testingAgentOptions.nodeAgentCustomOptions };
36415
+ else agentOptions = { ...this.defaultAgentOptions };
36416
+ break;
36417
+ case "default-agent-options":
36418
+ agentOptions = { ...this.defaultAgentOptions };
36419
+ break;
36420
+ case "stress-test-agent-options":
36421
+ agentOptions = { ...this.stressTestAgentOptions };
36422
+ break;
36423
+ case "stress-test-extreme-agent-options":
36424
+ agentOptions = { ...this.stressTestExtremeAgentOptions };
36425
+ break;
36426
+ default: throw new Error(`TestCaseFhirBase:GetAgentManager(): [${this._id}] unknown nodeAgentMode: [${testingAgentOptions.nodeAgentMode}]`);
36427
+ }
36428
+ if (agentOptions) agentManager = createAgentManager({
36429
+ agentOptions,
36430
+ httpAgentFactory(options) {
36431
+ return new http.Agent(options);
36432
+ },
36433
+ httpsAgentFactory(options) {
36434
+ return new https.Agent(options);
36435
+ }
36436
+ });
36437
+ return agentManager;
36438
+ };
36439
+ GetFhirAgentManager = () => {
36440
+ return this.GetAgentManager(this._options.fhirOptions.stsfhiragentOptions);
36441
+ };
36442
+ GetFhirSocketClient = async () => {
36443
+ try {
36444
+ if (this.fhirClient) return this.fhirClient;
36445
+ const lockKey = "GetFhirSocketClient";
36446
+ const lockTimeout = 6e4;
36447
+ if (this._lockHelper.GetOnHold(lockKey) === true) {
36448
+ this.Debug(chalk.magenta(`GetFhirSocketClient(): fhir client does not exist - some other client setting up the new client (on hold/lock), lock key: [${lockKey}] - waiting ...`));
36449
+ try {
36450
+ const start = performance.now();
36451
+ await this._lockHelper.WaitOnHold(lockKey, lockTimeout);
36452
+ this.Debug(chalk.yellow(`GetFhirSocketClient(): hold (lock) released after: [${performance.now() - start}ms], lock key: [${lockKey}]`));
36453
+ if (this.fhirClient) {
36454
+ this.Debug(chalk.green(`GetFhirSocketClient(): Getting existing fhir client (post hold release), lock key: [${lockKey}]`));
36455
+ return this.fhirClient;
36456
+ } else {
36457
+ this.Error(chalk.red(`GetFhirSocketClient(): Could not get existing fhir client (post hold release), lock key: [${lockKey}]`));
36458
+ this.Error(chalk.red(`GetFhirSocketClient(): continue anyway ...`));
36459
+ }
36460
+ } catch (error) {
36461
+ this.Error(chalk.red(`GetFhirSocketClient(): Error: [${error}]`));
36462
+ }
36463
+ }
36464
+ const start = performance.now();
36465
+ this.Debug(chalk.yellow(`GetFhirSocketClient(): fhir client does not exist - setting up new client`));
36466
+ this.Debug(chalk.yellow(`GetFhirSocketClient(): setting hold (lock), lock key: [${lockKey}]`));
36467
+ this._lockHelper.SetOnHold(lockKey);
36468
+ const fhirOptions = this._options.fhirOptions;
36469
+ const options = {
36470
+ fhirServerEndpoint: fhirOptions.stsfhirserverendpoint,
36471
+ fhirapiroot: fhirOptions.stsfhirapiroot,
36472
+ fhirServerPort: fhirOptions.stsfhirport,
36473
+ socketClientName: fhirOptions.stsfhirsocketname,
36474
+ socketIoCustomPath: fhirOptions.stsfhirsocketcustompath,
36475
+ timeout: fhirOptions.stsfhirsockettimeout,
36476
+ baseUrl: fhirOptions.stsfhirbaseurl,
36477
+ agentManager: this.GetFhirAgentManager(),
36478
+ joinRooms: [],
36479
+ logger: this._options.logger,
36480
+ verboseLogging: true,
36481
+ GetConnectionAccessToken: this._options.authHelper.GetAccessTokenForSocketClientAccess,
36482
+ GetAccessToken: this._options.authHelper.GetAccessToken
36483
+ };
36484
+ let workingFhirClient;
36485
+ if (this._options.fhirOptions.stsfhirsocketclientmode === "socket-client-all-in-one") workingFhirClient = new FhirSocketClientAllInOne("FhirSocketClient", options);
36486
+ else workingFhirClient = new FhirSocketClientIndividual("FhirSocketClient", options);
36487
+ await workingFhirClient.WaitForSocketConnected();
36488
+ this.Debug(chalk.yellow(`GetFhirSocketClient(): setting fhir client into object`));
36489
+ this.fhirClient = workingFhirClient;
36490
+ this._lockHelper.ReleaseOnHold(lockKey);
36491
+ this.Debug(chalk.yellow(`GetFhirSocketClient(): release hold (lock) Time taken for socket connection and set object: [${performance.now() - start}ms], lock key: [${lockKey}]`));
36492
+ return this.fhirClient;
36493
+ } catch (error) {
36494
+ this.Error(error);
36495
+ throw error;
36496
+ }
36497
+ };
36498
+ GetRESTClient = async () => {
36499
+ if (this.restFhirClient) return this.restFhirClient;
36500
+ const onRetryAttempt = (attempt, error, delayMs) => {
36501
+ const message = `TestCaseFhirBase:onRetryAttempt(): [${this._id}] Retry #${attempt} after ${delayMs}ms due to ${error.code || error.response?.status}`;
36502
+ this.Warning(message);
36503
+ this.emit("retry", message);
36504
+ };
36505
+ const fhirOptions = this._options.fhirOptions;
36506
+ const fhirRESTClient = new FhirRESTClient({
36507
+ GetAccessToken: this._options.authHelper.GetAccessToken,
36508
+ user: "USR_user01@stsmda.com.au",
36509
+ endpoint: fhirOptions.stsfhirserverendpoint,
36510
+ stsfhirapiroot: fhirOptions.stsfhirapiroot,
36511
+ stsfhirport: fhirOptions.stsfhirport,
36512
+ logger: this._options.logger,
36513
+ agentManager: this.GetFhirAgentManager(),
36514
+ onRetryAttempt
36515
+ });
36516
+ this.restFhirClient = fhirRESTClient;
36517
+ return fhirRESTClient;
36518
+ };
36519
+ GetClient = async () => {
36520
+ let client;
36521
+ if (this._options.fhirOptions.stsfhirsocketclientmode === "no-socket-client") client = await this.GetRESTClient();
36522
+ else client = await this.GetFhirSocketClient();
36523
+ return client;
36524
+ };
36525
+ };
36526
+ //#endregion
36373
36527
  //#region src/libmodule/workerFhirTestCases.ts
36374
36528
  var WorkerFhirTestCases = class extends AbstractRunnerExecutionWorker {
36375
36529
  _options;
36376
36530
  _resourceDataGenerator;
36377
36531
  fhirClient = void 0;
36378
36532
  _id = crypto.randomUUID();
36379
- _onHoldKeys = {};
36533
+ _clientHelper;
36534
+ _authHelper;
36535
+ restFhirClient = null;
36536
+ logPrefix = `WorkerFhirTestCases:[${this._id}]:`;
36380
36537
  constructor(options) {
36381
36538
  super();
36382
36539
  this._options = options;
36383
36540
  this._resourceDataGenerator = new ResourceDataGenerator();
36541
+ this._authHelper = new AuthHelper({
36542
+ authOptions: options.authOptions,
36543
+ logger: options.logger
36544
+ });
36545
+ this._clientHelper = new ClientHelper({
36546
+ authHelper: this._authHelper,
36547
+ logger: options.logger,
36548
+ fhirOptions: options.fhirOptions
36549
+ });
36384
36550
  }
36385
- get id() {
36386
- return this._id;
36551
+ get authHelper() {
36552
+ return this._authHelper;
36387
36553
  }
36388
- GetFhirClient = () => {
36389
- return this.fhirClient;
36554
+ Warning = (message) => {
36555
+ this.logger.warn(`${this.logPrefix}${message}`);
36390
36556
  };
36391
- SetFhirClient = (fhirClient) => {
36392
- this.fhirClient = fhirClient;
36557
+ Error = (message) => {
36558
+ this.logger.error(`${this.logPrefix}${message}`);
36393
36559
  };
36560
+ Debug = (message) => {
36561
+ this.logger.debug(`${this.logPrefix}${message}`);
36562
+ };
36563
+ get id() {
36564
+ return this._id;
36565
+ }
36394
36566
  get resourceDataGenerator() {
36395
36567
  return this._resourceDataGenerator;
36396
36568
  }
@@ -36401,9 +36573,9 @@ var WorkerFhirTestCases = class extends AbstractRunnerExecutionWorker {
36401
36573
  return AsyncRunnerFactory.CreateAsyncRunner(this, testRunnerTelemetryPayload);
36402
36574
  };
36403
36575
  async ProcessPreTerminateWorkerMessage(messagePayload) {
36404
- this.logger.debug(chalk.rgb(220, 100, 0)(`ProcessPreTerminateWorkerMessage: [${JSON.stringify(messagePayload, null, 2)}]`));
36576
+ this.logger.debug(chalk.rgb(220, 100, 0)(`ProcessPreTerminateWorkerMessage(): [${JSON.stringify(messagePayload, null, 2)}]`));
36405
36577
  if (this.fhirClient) {
36406
- this.logger.debug(chalk.rgb(220, 100, 0)(`ProcessPreTerminateWorkerMessage: ResetSocket()`));
36578
+ this.logger.debug(chalk.rgb(220, 100, 0)(`ProcessPreTerminateWorkerMessage(): ResetSocket()`));
36407
36579
  this.fhirClient.ResetSocket();
36408
36580
  this.fhirClient = void 0;
36409
36581
  }
@@ -36413,24 +36585,66 @@ var WorkerFhirTestCases = class extends AbstractRunnerExecutionWorker {
36413
36585
  myresponsepreterminate: `I got: [${JSON.stringify(messagePayload.payload.data)}]`
36414
36586
  };
36415
36587
  }
36416
- GetOnHold = (holdKey) => {
36417
- if (this._onHoldKeys[holdKey]) return true;
36418
- return false;
36588
+ defaultAgentOptions = {
36589
+ keepAlive: true,
36590
+ maxSockets: 10,
36591
+ maxTotalSockets: 20,
36592
+ maxFreeSockets: 10,
36593
+ timeout: 6e4,
36594
+ rejectUnauthorized: false
36419
36595
  };
36420
- WaitOnHold = async (holdKey, timeout) => {
36421
- const start = performance.now();
36422
- for (;;) {
36423
- if (this._onHoldKeys[holdKey]) await Sleep(100);
36424
- else break;
36425
- if (performance.now() - start > timeout) throw new Error(`WaitOnHold timeout: [${timeout}] reached.`);
36596
+ stressTestAgentOptions = {
36597
+ keepAlive: true,
36598
+ maxSockets: 200,
36599
+ maxTotalSockets: 500,
36600
+ maxFreeSockets: 50,
36601
+ timeout: 3e4,
36602
+ rejectUnauthorized: false
36603
+ };
36604
+ stressTestExtremeAgentOptions = {
36605
+ keepAlive: true,
36606
+ maxSockets: 500,
36607
+ maxTotalSockets: 1e3,
36608
+ maxFreeSockets: 500,
36609
+ timeout: 3e4,
36610
+ rejectUnauthorized: false
36611
+ };
36612
+ GetAgentManager = (testingAgentOptions) => {
36613
+ let agentManager = void 0;
36614
+ let agentOptions = void 0;
36615
+ switch (testingAgentOptions.nodeAgentMode) {
36616
+ case "no-agent": break;
36617
+ case "custom-agent-options":
36618
+ if (testingAgentOptions.nodeAgentCustomOptions) agentOptions = { ...testingAgentOptions.nodeAgentCustomOptions };
36619
+ else agentOptions = { ...this.defaultAgentOptions };
36620
+ break;
36621
+ case "default-agent-options":
36622
+ agentOptions = { ...this.defaultAgentOptions };
36623
+ break;
36624
+ case "stress-test-agent-options":
36625
+ agentOptions = { ...this.stressTestAgentOptions };
36626
+ break;
36627
+ case "stress-test-extreme-agent-options":
36628
+ agentOptions = { ...this.stressTestExtremeAgentOptions };
36629
+ break;
36630
+ default: throw new Error(`TestCaseFhirBase:GetAgentManager(): [${this._id}] unknown nodeAgentMode: [${testingAgentOptions.nodeAgentMode}]`);
36426
36631
  }
36427
- return true;
36632
+ if (agentOptions) agentManager = createAgentManager({
36633
+ agentOptions,
36634
+ httpAgentFactory(options) {
36635
+ return new http.Agent(options);
36636
+ },
36637
+ httpsAgentFactory(options) {
36638
+ return new https.Agent(options);
36639
+ }
36640
+ });
36641
+ return agentManager;
36428
36642
  };
36429
- SetOnHold = (holdKey) => {
36430
- this._onHoldKeys[holdKey] = true;
36643
+ GetFhirAgentManager = () => {
36644
+ return this.GetAgentManager(this._options.fhirOptions.stsfhiragentOptions);
36431
36645
  };
36432
- ReleaseOnHold = (holdKey) => {
36433
- delete this._onHoldKeys[holdKey];
36646
+ GetClient = async () => {
36647
+ return this._clientHelper.GetClient();
36434
36648
  };
36435
36649
  };
36436
36650
  //#endregion