@nsshunt/ststestrunner 1.1.103 → 1.1.105
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ststestrunner.cjs +370 -387
- package/dist/ststestrunner.cjs.map +1 -1
- package/dist/ststestrunner.mjs +369 -386
- package/dist/ststestrunner.mjs.map +1 -1
- package/package.json +1 -1
- package/types/libmodule/testCaseFhirBase.d.ts +6 -27
- package/types/libmodule/testCaseFhirBase.d.ts.map +1 -1
- package/types/libmodule/workerFhirTestCases.d.ts +34 -5
- package/types/libmodule/workerFhirTestCases.d.ts.map +1 -1
package/dist/ststestrunner.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { AbstractRunnerExecutionWorker } from "@nsshunt/stsrunnerframework";
|
|
2
|
-
import chalk from "chalk";
|
|
3
2
|
import { STSAxiosConfig, Sleep, createAgentManager, isNode } from "@nsshunt/stsutils";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
import axios from "axios";
|
|
4
5
|
import { FhirRESTClient, FhirSocketClientAllInOne, FhirSocketClientIndividual, createRetryAxiosClient } from "@nsshunt/stsfhirclient";
|
|
5
6
|
import http from "node:http";
|
|
6
7
|
import https from "node:https";
|
|
7
|
-
import axios from "axios";
|
|
8
8
|
//#region \0rolldown/runtime.js
|
|
9
9
|
var __defProp = Object.defineProperty;
|
|
10
10
|
var __exportAll = (all, no_symbols) => {
|
|
@@ -379,190 +379,40 @@ var StatusCodes;
|
|
|
379
379
|
//#region src/libmodule/testCaseFhirBase.ts
|
|
380
380
|
var TestCaseFhirBase = class {
|
|
381
381
|
#options;
|
|
382
|
-
#randomDataRecordset = [];
|
|
383
382
|
#runner;
|
|
384
383
|
#runnerExecutionWorker;
|
|
385
|
-
#accesssToken = null;
|
|
386
384
|
#publishTelemetryCount = 0;
|
|
387
385
|
#maxBufferSize = 50;
|
|
388
386
|
#publishTelemetryTimeout = null;
|
|
389
387
|
#publishTelemetryTimeoutVal = 1e3;
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
388
|
+
_RetryMap = [
|
|
389
|
+
100,
|
|
390
|
+
250,
|
|
391
|
+
500,
|
|
392
|
+
1e3,
|
|
393
|
+
2e3,
|
|
394
|
+
3e3
|
|
395
|
+
];
|
|
394
396
|
_id = crypto.randomUUID();
|
|
395
397
|
retryCount = 0;
|
|
396
398
|
maxAuthRetryCount = 5;
|
|
397
399
|
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
400
|
constructor(runnerExecutionWorker, runner) {
|
|
427
401
|
this.#options = runner.options;
|
|
428
402
|
this.#runnerExecutionWorker = runnerExecutionWorker;
|
|
429
403
|
this.#runner = runner;
|
|
430
|
-
this.#authAgentManager = this.GetAuthAgentManager();
|
|
431
404
|
}
|
|
432
405
|
get runnerExecutionWorker() {
|
|
433
406
|
return this.#runnerExecutionWorker;
|
|
434
407
|
}
|
|
435
408
|
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(): 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(`GetFhirSocketClient(): 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}] 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}] 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}] Getting existing fhir client (post hold release)`));
|
|
510
|
-
return fhirClient;
|
|
511
|
-
} else {
|
|
512
|
-
this.Error(chalk.red(`[${this.runnerExecutionWorker.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}] fhir client does not exist - setting up new client`));
|
|
521
|
-
this.Debug(chalk.yellow(`[${this.runnerExecutionWorker.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}] setting fhir client into object`));
|
|
543
|
-
this.runnerExecutionWorker.SetFhirClient(fhirClient);
|
|
544
|
-
this.runnerExecutionWorker.ReleaseOnHold("fhirclient");
|
|
545
|
-
this.Debug(chalk.yellow(`[${this.runnerExecutionWorker.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
409
|
Error = (message) => {
|
|
557
410
|
this.#runnerExecutionWorker.logger.error(message);
|
|
558
411
|
this.#runner.instrumentData.message.push(chalk.red(`${message}`));
|
|
559
412
|
};
|
|
560
|
-
|
|
561
|
-
this.#runnerExecutionWorker.logger.
|
|
413
|
+
Debug = (message) => {
|
|
414
|
+
this.#runnerExecutionWorker.logger.debug(message);
|
|
562
415
|
};
|
|
563
|
-
get accesssToken() {
|
|
564
|
-
return this.#accesssToken;
|
|
565
|
-
}
|
|
566
416
|
get runner() {
|
|
567
417
|
return this.#runner;
|
|
568
418
|
}
|
|
@@ -605,187 +455,32 @@ var TestCaseFhirBase = class {
|
|
|
605
455
|
this.#runner.instrumentData.rx = 0;
|
|
606
456
|
await this.SleepImmediate();
|
|
607
457
|
};
|
|
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(): 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(): 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(): Error: [${error}], Stage: [${stage}], Details: [${details}]`;
|
|
695
|
-
throw error;
|
|
696
|
-
}
|
|
697
|
-
};
|
|
698
|
-
GetAccessTokenForSocketClientAccess = async () => {
|
|
699
|
-
const timeout = setTimeout(() => {
|
|
700
|
-
this.Warning(`TestCaseFhirBase:GetAccessTokenForSocketClientAccess(): 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(): The total time for getting the access token: [${totalTime}]`));
|
|
715
|
-
return retVal;
|
|
716
|
-
} catch (error) {
|
|
717
|
-
clearTimeout(timeout);
|
|
718
|
-
error.message = `TestCaseFhirBase:GetAccessTokenForSocketClientAccess(): Error: [${error}], Duration until error: [${performance.now() - start}]`;
|
|
719
|
-
this.Error(error);
|
|
720
|
-
return "";
|
|
721
|
-
}
|
|
722
|
-
};
|
|
723
|
-
ResetAccessToken = () => {
|
|
724
|
-
console.log(chalk.magenta(`************************************************************************* start `));
|
|
725
|
-
console.log(chalk.magenta(`Old Token: ${this._id} : ${this.#accesssToken}`));
|
|
726
|
-
this.#accesssToken = null;
|
|
727
|
-
console.log(chalk.magenta(`New Token: ${this._id} : ${this.#accesssToken}`));
|
|
728
|
-
console.log(chalk.magenta(`************************************************************************* end `));
|
|
729
|
-
};
|
|
730
458
|
HandleError = (error) => {
|
|
731
|
-
this.Error(chalk.red(`TestCaseFhirBase:HandleError(): Error: [${error}]`));
|
|
732
|
-
this.Error(chalk.red(`TestCaseFhirBase:HandleError():
|
|
733
|
-
this.Error(chalk.red(`TestCaseFhirBase:HandleError():
|
|
734
|
-
this.Error(chalk.red(`TestCaseFhirBase:HandleError():
|
|
459
|
+
this.Error(chalk.red(`TestCaseFhirBase:HandleError(): [${this._id}] Error: [${error}]`));
|
|
460
|
+
this.Error(chalk.red(`TestCaseFhirBase:HandleError(): [${this._id}] description: [${this.runner.options.description}]`));
|
|
461
|
+
this.Error(chalk.red(`TestCaseFhirBase:HandleError(): [${this._id}] iteration: [${this.runner.iteration}]`));
|
|
462
|
+
this.Error(chalk.red(`TestCaseFhirBase:HandleError(): [${this._id}] asyncRunnerContext: [${JSON.stringify(this.runner.asyncRunnerContext)}]`));
|
|
735
463
|
if (axios.isAxiosError(error)) {
|
|
736
464
|
const axiosError = error;
|
|
737
465
|
if (axiosError.response) {
|
|
738
|
-
this.Error(chalk.red(`TestCaseFhirBase:HandleError():
|
|
739
|
-
if (axiosError.response.headers) this.Error(chalk.red(`TestCaseFhirBase:HandleError():
|
|
740
|
-
if (axiosError.response.data) this.Error(chalk.red(`TestCaseFhirBase:HandleError():
|
|
466
|
+
this.Error(chalk.red(`TestCaseFhirBase:HandleError(): [${this._id}] AXIOS Error Response.Status = [${axiosError.response.status}]`));
|
|
467
|
+
if (axiosError.response.headers) this.Error(chalk.red(`TestCaseFhirBase:HandleError(): [${this._id}] headers: [${JSON.stringify(axiosError.response.headers)}]`));
|
|
468
|
+
if (axiosError.response.data) this.Error(chalk.red(`TestCaseFhirBase:HandleError(): [${this._id}] data: [${JSON.stringify(axiosError.response.data)}]`));
|
|
741
469
|
if (axiosError.response.status === StatusCodes.UNAUTHORIZED) {
|
|
742
470
|
this.runner.instrumentData.authenticationErrorCount++;
|
|
743
|
-
this.Error(chalk.red(`TestCaseFhirBase:HandleError():
|
|
744
|
-
this.ResetAccessToken();
|
|
471
|
+
this.Error(chalk.red(`TestCaseFhirBase:HandleError(): [${this._id}] UNAUTHORIZED - Reset Access Token`));
|
|
472
|
+
this.runnerExecutionWorker.ResetAccessToken();
|
|
745
473
|
return true;
|
|
746
474
|
}
|
|
747
|
-
} else this.Error(chalk.red(`TestCaseFhirBase:HandleError():
|
|
475
|
+
} else this.Error(chalk.red(`TestCaseFhirBase:HandleError(): [${this._id}] AXIOS Error = [${axiosError}]`));
|
|
748
476
|
} else if (error.message === "UNAUTHORIZED") {
|
|
749
477
|
this.runner.instrumentData.authenticationErrorCount++;
|
|
750
|
-
this.Error(chalk.red(`TestCaseFhirBase:HandleError():
|
|
751
|
-
this.ResetAccessToken();
|
|
478
|
+
this.Error(chalk.red(`TestCaseFhirBase:HandleError(): [${this._id}] UNAUTHORIZED - Reset Access Token`));
|
|
479
|
+
this.runnerExecutionWorker.ResetAccessToken();
|
|
752
480
|
return true;
|
|
753
481
|
}
|
|
754
482
|
return false;
|
|
755
483
|
};
|
|
756
|
-
GetAccessToken = async () => {
|
|
757
|
-
let timeout = void 0;
|
|
758
|
-
let start = performance.now();
|
|
759
|
-
try {
|
|
760
|
-
if (this.#accesssToken) {
|
|
761
|
-
this.Debug(`TestCaseFhirBase:GetAccessToken(): ${this._id} : ${this.#accesssToken}`);
|
|
762
|
-
return this.#accesssToken;
|
|
763
|
-
}
|
|
764
|
-
this.Debug(`TestCaseFhirBase:GetAccessToken(): Getting new access token`);
|
|
765
|
-
timeout = setTimeout(() => {
|
|
766
|
-
this.Warning(chalk.magenta(`TestCaseFhirBase:GetAccessToken(): Timeout: [${this._authMaxTimeout}] exceeded for getting access token ...`));
|
|
767
|
-
}, this._authMaxTimeout);
|
|
768
|
-
const scopes = `api://fb6513e4-16fe-4931-bed8-33b82b404a14/_.stsfhir5:All`.split(" ").sort().join(" ");
|
|
769
|
-
const authendpointUrl = `${this.#options.authOptions.asendpoint}:${this.#options.authOptions.asport}`;
|
|
770
|
-
const retVal = await this.GetAPITokenFromAuthServerUsingScope({
|
|
771
|
-
clientId: "d8277fce-bb48-44c2-bbf1-257fe13a444b",
|
|
772
|
-
authClientSecret: "64e3ef37-c7b8-4cb1-880a-e6ad3ab36e3c",
|
|
773
|
-
scope: scopes,
|
|
774
|
-
endPoint: authendpointUrl
|
|
775
|
-
});
|
|
776
|
-
this.accessTokenTime = performance.now();
|
|
777
|
-
this.#accesssToken = retVal;
|
|
778
|
-
if (timeout) clearTimeout(timeout);
|
|
779
|
-
const totalTime = performance.now() - start;
|
|
780
|
-
if (totalTime > this._authMaxTimeout) this.Warning(chalk.magenta(`TestCaseFhirBase:GetAccessToken(): The total time for getting the access token: [${totalTime}]`));
|
|
781
|
-
return retVal;
|
|
782
|
-
} catch (error) {
|
|
783
|
-
if (timeout) clearTimeout(timeout);
|
|
784
|
-
error.message = `TestCaseFhirBase:GetAccessToken(): Error: [${error}], Duration until error: [${performance.now() - start}]`;
|
|
785
|
-
this.Error(error);
|
|
786
|
-
return "";
|
|
787
|
-
}
|
|
788
|
-
};
|
|
789
484
|
GetPersonRecord = async (prefix, index, version) => {
|
|
790
485
|
const { workerIndex, runnerIndex, runId } = this.#options;
|
|
791
486
|
const useId = `${prefix}-${index}`;
|
|
@@ -812,37 +507,12 @@ var TestCaseFhirBase = class {
|
|
|
812
507
|
}
|
|
813
508
|
};
|
|
814
509
|
};
|
|
815
|
-
StartTestDataLoad = async () => {
|
|
816
|
-
this.Debug(chalk.magenta(`StartTestDataLoad(): Start ...`));
|
|
817
|
-
let VU = 0;
|
|
818
|
-
const blockNum = VU * 200;
|
|
819
|
-
const blocksToLoad = 20;
|
|
820
|
-
for (let i = 0; i < blocksToLoad; i++) {
|
|
821
|
-
const recordId = `stsres_${blockNum + i}`;
|
|
822
|
-
const retVal = await (await this.GetFhirSocketClient()).GetResource("Person", recordId);
|
|
823
|
-
if (retVal) {
|
|
824
|
-
const recordsetData = retVal.body.address;
|
|
825
|
-
if (recordsetData) {
|
|
826
|
-
const qqq = recordsetData[0].text;
|
|
827
|
-
for (let j = 0; j < qqq.length; j++) this.#randomDataRecordset.push(qqq[j]);
|
|
828
|
-
this.Error(chalk.magenta(this.#randomDataRecordset.length));
|
|
829
|
-
}
|
|
830
|
-
} else this.Error(chalk.magenta(`StartTestDataLoad(): Could not get person records.`));
|
|
831
|
-
await Sleep(10);
|
|
832
|
-
}
|
|
833
|
-
this.Debug(`Finished load for VU: [${VU}]`);
|
|
834
|
-
this.Debug(`First 10 entries`);
|
|
835
|
-
for (let i = 0; i < 10; i++) this.Debug(this.#randomDataRecordset[i].id);
|
|
836
|
-
this.Debug(`block num: [${blockNum}] length: [${this.#randomDataRecordset.length}] VU: [${VU}]`);
|
|
837
|
-
this.Debug(chalk.magenta(`StartTestDataLoad(): End`));
|
|
838
|
-
};
|
|
839
510
|
#ForcePublishTelemetryData = async () => {
|
|
840
511
|
await this.#PublishTelemetryData();
|
|
841
512
|
};
|
|
842
513
|
#SetupTimeout = async () => {
|
|
843
514
|
if (!this.#publishTelemetryTimeout) {
|
|
844
515
|
this.#publishTelemetryTimeout = setTimeout(async () => {
|
|
845
|
-
this.#LogMessage(chalk.yellow(` **** TIMEOUT **** `));
|
|
846
516
|
await this.#PublishTelemetryData();
|
|
847
517
|
this.#publishTelemetryCount = 0;
|
|
848
518
|
this.#publishTelemetryTimeout = null;
|
|
@@ -852,7 +522,6 @@ var TestCaseFhirBase = class {
|
|
|
852
522
|
};
|
|
853
523
|
PublishTelemetry = async () => {
|
|
854
524
|
this.#publishTelemetryCount++;
|
|
855
|
-
this.#LogMessage(chalk.red(this.#publishTelemetryCount));
|
|
856
525
|
if (this.#publishTelemetryCount % this.#maxBufferSize === 0) {
|
|
857
526
|
this.#publishTelemetryCount = 0;
|
|
858
527
|
if (this.#publishTelemetryTimeout) {
|
|
@@ -865,7 +534,6 @@ var TestCaseFhirBase = class {
|
|
|
865
534
|
};
|
|
866
535
|
#OutputLogMessage = async (message) => {
|
|
867
536
|
const messageOutput = chalk.grey(message);
|
|
868
|
-
this.#LogMessage(messageOutput);
|
|
869
537
|
this.#runner.instrumentData.message.push(messageOutput);
|
|
870
538
|
await this.PublishTelemetry();
|
|
871
539
|
};
|
|
@@ -913,21 +581,15 @@ var TestCaseFhirBase = class {
|
|
|
913
581
|
await this.#ForcePublishTelemetryData();
|
|
914
582
|
return true;
|
|
915
583
|
};
|
|
916
|
-
GetClient = async () => {
|
|
917
|
-
let client;
|
|
918
|
-
if (this.runner.options.fhirOptions.stsfhirsocketclientmode === "no-socket-client") client = await this.GetRESTClient();
|
|
919
|
-
else client = await this.GetFhirSocketClient();
|
|
920
|
-
return client;
|
|
921
|
-
};
|
|
922
584
|
_GetDetail = () => {
|
|
923
585
|
return `testType: [${this.runner.options.testType}], description: [${this.runner.options.description}], workerManagerId: [${this.runner.workerManagerId}], Iteration: [${this.runner.iteration}]`;
|
|
924
586
|
};
|
|
925
587
|
_CheckOutputLongDurationError = (snapshotStart, message) => {
|
|
926
588
|
const snapShotEnd = performance.now();
|
|
927
589
|
if (snapShotEnd - snapshotStart > 1e3) {
|
|
928
|
-
this.Error(chalk.red(`
|
|
929
|
-
this.Error(chalk.red(`
|
|
930
|
-
this.Error(chalk.red(`
|
|
590
|
+
this.Error(chalk.red(`TestCaseFhirBase:_CheckOutputLongDurationError(): [${this._id}] *** ==> Long execution: [${snapShotEnd - snapshotStart}] message: [${message}]`));
|
|
591
|
+
this.Error(chalk.red(`TestCaseFhirBase:_CheckOutputLongDurationError(): [${this._id}] ==> ${this._GetDetail()}`));
|
|
592
|
+
this.Error(chalk.red(`TestCaseFhirBase:_CheckOutputLongDurationError(): [${this._id}] ==> Note: While not specifically an error, this is logged as an error.`));
|
|
931
593
|
}
|
|
932
594
|
return snapShotEnd;
|
|
933
595
|
};
|
|
@@ -935,14 +597,6 @@ var TestCaseFhirBase = class {
|
|
|
935
597
|
this.retryCount = 0;
|
|
936
598
|
return this._ExecuteQuery();
|
|
937
599
|
};
|
|
938
|
-
_RetryMap = [
|
|
939
|
-
100,
|
|
940
|
-
250,
|
|
941
|
-
500,
|
|
942
|
-
1e3,
|
|
943
|
-
2e3,
|
|
944
|
-
3e3
|
|
945
|
-
];
|
|
946
600
|
_ExecuteQuery = async () => {
|
|
947
601
|
try {
|
|
948
602
|
return await this.PerformExecuteQuery();
|
|
@@ -951,13 +605,13 @@ var TestCaseFhirBase = class {
|
|
|
951
605
|
if (this.HandleError(error) === true) if (this.retryCount < this.maxAuthRetryCount) {
|
|
952
606
|
this.retryCount++;
|
|
953
607
|
this.runner.instrumentData.authenticationRetryCount++;
|
|
954
|
-
const message = `
|
|
608
|
+
const message = `TestCaseFhirBase:ExecuteQuery(): [${this._id}] Retry auth attempt: retryCount: [${this.retryCount}], maxAuthRetryCount: [${this.maxAuthRetryCount}]`;
|
|
955
609
|
this.Error(message);
|
|
956
610
|
if (this.retryCount > this._RetryMap.length) await Sleep(this._RetryMap[this._RetryMap.length - 1]);
|
|
957
611
|
else await Sleep(this._RetryMap[this.retryCount - 1]);
|
|
958
612
|
return await this._ExecuteQuery();
|
|
959
613
|
} else {
|
|
960
|
-
const message = `
|
|
614
|
+
const message = `TestCaseFhirBase:_ExecuteQuery(): [${this._id}] Max auth retries exceeded: retryCount: [${this.retryCount}], maxAuthRetryCount: [${this.maxAuthRetryCount}], Error: [${error}]`;
|
|
961
615
|
this.Error(message);
|
|
962
616
|
error.message = message;
|
|
963
617
|
throw error;
|
|
@@ -965,6 +619,9 @@ var TestCaseFhirBase = class {
|
|
|
965
619
|
else throw error;
|
|
966
620
|
}
|
|
967
621
|
};
|
|
622
|
+
GetClient = async () => {
|
|
623
|
+
return this.runnerExecutionWorker.GetClient();
|
|
624
|
+
};
|
|
968
625
|
};
|
|
969
626
|
//#endregion
|
|
970
627
|
//#region src/libmodule/testCaseFhirQueryBase.ts
|
|
@@ -1046,9 +703,9 @@ var TestCaseFhirQueryBase = class extends TestCaseFhirBase {
|
|
|
1046
703
|
var TestCaseFhir01 = class extends TestCaseFhirQueryBase {
|
|
1047
704
|
PerformExecuteQuery = async () => {
|
|
1048
705
|
const __snapshot1 = performance.now();
|
|
1049
|
-
await this.GetAccessToken();
|
|
706
|
+
await this.runnerExecutionWorker.GetAccessToken();
|
|
1050
707
|
this._CheckOutputLongDurationError(__snapshot1, "await this.GetAccessToken()");
|
|
1051
|
-
this.ResetAccessToken();
|
|
708
|
+
this.runnerExecutionWorker.ResetAccessToken();
|
|
1052
709
|
return null;
|
|
1053
710
|
};
|
|
1054
711
|
};
|
|
@@ -36383,20 +36040,30 @@ var WorkerFhirTestCases = class extends AbstractRunnerExecutionWorker {
|
|
|
36383
36040
|
fhirClient = void 0;
|
|
36384
36041
|
_id = crypto.randomUUID();
|
|
36385
36042
|
_onHoldKeys = {};
|
|
36043
|
+
#accesssToken = null;
|
|
36044
|
+
_authMaxTimeout = 5e3;
|
|
36045
|
+
#originRegex = /^(api:\/\/\w+)/;
|
|
36046
|
+
#authAgentManager;
|
|
36047
|
+
restFhirClient = null;
|
|
36048
|
+
logPrefix = `WorkerFhirTestCases:[${this._id}]:`;
|
|
36386
36049
|
constructor(options) {
|
|
36387
36050
|
super();
|
|
36388
36051
|
this._options = options;
|
|
36389
36052
|
this._resourceDataGenerator = new ResourceDataGenerator();
|
|
36053
|
+
this.#authAgentManager = this.GetAuthAgentManager();
|
|
36390
36054
|
}
|
|
36055
|
+
Warning = (message) => {
|
|
36056
|
+
this.logger.warn(`${this.logPrefix}${message}`);
|
|
36057
|
+
};
|
|
36058
|
+
Error = (message) => {
|
|
36059
|
+
this.logger.error(`${this.logPrefix}${message}`);
|
|
36060
|
+
};
|
|
36061
|
+
Debug = (message) => {
|
|
36062
|
+
this.logger.debug(`${this.logPrefix}${message}`);
|
|
36063
|
+
};
|
|
36391
36064
|
get id() {
|
|
36392
36065
|
return this._id;
|
|
36393
36066
|
}
|
|
36394
|
-
GetFhirClient = () => {
|
|
36395
|
-
return this.fhirClient;
|
|
36396
|
-
};
|
|
36397
|
-
SetFhirClient = (fhirClient) => {
|
|
36398
|
-
this.fhirClient = fhirClient;
|
|
36399
|
-
};
|
|
36400
36067
|
get resourceDataGenerator() {
|
|
36401
36068
|
return this._resourceDataGenerator;
|
|
36402
36069
|
}
|
|
@@ -36407,9 +36074,9 @@ var WorkerFhirTestCases = class extends AbstractRunnerExecutionWorker {
|
|
|
36407
36074
|
return AsyncRunnerFactory.CreateAsyncRunner(this, testRunnerTelemetryPayload);
|
|
36408
36075
|
};
|
|
36409
36076
|
async ProcessPreTerminateWorkerMessage(messagePayload) {
|
|
36410
|
-
this.logger.debug(chalk.rgb(220, 100, 0)(`ProcessPreTerminateWorkerMessage: [${JSON.stringify(messagePayload, null, 2)}]`));
|
|
36077
|
+
this.logger.debug(chalk.rgb(220, 100, 0)(`ProcessPreTerminateWorkerMessage(): [${JSON.stringify(messagePayload, null, 2)}]`));
|
|
36411
36078
|
if (this.fhirClient) {
|
|
36412
|
-
this.logger.debug(chalk.rgb(220, 100, 0)(`ProcessPreTerminateWorkerMessage: ResetSocket()`));
|
|
36079
|
+
this.logger.debug(chalk.rgb(220, 100, 0)(`ProcessPreTerminateWorkerMessage(): ResetSocket()`));
|
|
36413
36080
|
this.fhirClient.ResetSocket();
|
|
36414
36081
|
this.fhirClient = void 0;
|
|
36415
36082
|
}
|
|
@@ -36428,7 +36095,7 @@ var WorkerFhirTestCases = class extends AbstractRunnerExecutionWorker {
|
|
|
36428
36095
|
for (;;) {
|
|
36429
36096
|
if (this._onHoldKeys[holdKey]) await Sleep(100);
|
|
36430
36097
|
else break;
|
|
36431
|
-
if (performance.now() - start > timeout) throw new Error(`WaitOnHold
|
|
36098
|
+
if (performance.now() - start > timeout) throw new Error(`WorkerFhirTestCases:WaitOnHold(): Timeout: [${timeout}] reached.`);
|
|
36432
36099
|
}
|
|
36433
36100
|
return true;
|
|
36434
36101
|
};
|
|
@@ -36438,6 +36105,322 @@ var WorkerFhirTestCases = class extends AbstractRunnerExecutionWorker {
|
|
|
36438
36105
|
ReleaseOnHold = (holdKey) => {
|
|
36439
36106
|
delete this._onHoldKeys[holdKey];
|
|
36440
36107
|
};
|
|
36108
|
+
defaultAgentOptions = {
|
|
36109
|
+
keepAlive: true,
|
|
36110
|
+
maxSockets: 10,
|
|
36111
|
+
maxTotalSockets: 20,
|
|
36112
|
+
maxFreeSockets: 10,
|
|
36113
|
+
timeout: 6e4,
|
|
36114
|
+
rejectUnauthorized: false
|
|
36115
|
+
};
|
|
36116
|
+
stressTestAgentOptions = {
|
|
36117
|
+
keepAlive: true,
|
|
36118
|
+
maxSockets: 200,
|
|
36119
|
+
maxTotalSockets: 500,
|
|
36120
|
+
maxFreeSockets: 50,
|
|
36121
|
+
timeout: 3e4,
|
|
36122
|
+
rejectUnauthorized: false
|
|
36123
|
+
};
|
|
36124
|
+
stressTestExtremeAgentOptions = {
|
|
36125
|
+
keepAlive: true,
|
|
36126
|
+
maxSockets: 500,
|
|
36127
|
+
maxTotalSockets: 1e3,
|
|
36128
|
+
maxFreeSockets: 500,
|
|
36129
|
+
timeout: 3e4,
|
|
36130
|
+
rejectUnauthorized: false
|
|
36131
|
+
};
|
|
36132
|
+
GetAgentManager = (testingAgentOptions) => {
|
|
36133
|
+
let agentManager = void 0;
|
|
36134
|
+
let agentOptions = void 0;
|
|
36135
|
+
switch (testingAgentOptions.nodeAgentMode) {
|
|
36136
|
+
case "no-agent": break;
|
|
36137
|
+
case "custom-agent-options":
|
|
36138
|
+
if (testingAgentOptions.nodeAgentCustomOptions) agentOptions = { ...testingAgentOptions.nodeAgentCustomOptions };
|
|
36139
|
+
else agentOptions = { ...this.defaultAgentOptions };
|
|
36140
|
+
break;
|
|
36141
|
+
case "default-agent-options":
|
|
36142
|
+
agentOptions = { ...this.defaultAgentOptions };
|
|
36143
|
+
break;
|
|
36144
|
+
case "stress-test-agent-options":
|
|
36145
|
+
agentOptions = { ...this.stressTestAgentOptions };
|
|
36146
|
+
break;
|
|
36147
|
+
case "stress-test-extreme-agent-options":
|
|
36148
|
+
agentOptions = { ...this.stressTestExtremeAgentOptions };
|
|
36149
|
+
break;
|
|
36150
|
+
default: throw new Error(`TestCaseFhirBase:GetAgentManager(): [${this._id}] unknown nodeAgentMode: [${testingAgentOptions.nodeAgentMode}]`);
|
|
36151
|
+
}
|
|
36152
|
+
if (agentOptions) agentManager = createAgentManager({
|
|
36153
|
+
agentOptions,
|
|
36154
|
+
httpAgentFactory(options) {
|
|
36155
|
+
return new http.Agent(options);
|
|
36156
|
+
},
|
|
36157
|
+
httpsAgentFactory(options) {
|
|
36158
|
+
return new https.Agent(options);
|
|
36159
|
+
}
|
|
36160
|
+
});
|
|
36161
|
+
return agentManager;
|
|
36162
|
+
};
|
|
36163
|
+
GetFhirAgentManager = () => {
|
|
36164
|
+
return this.GetAgentManager(this._options.fhirOptions.stsfhiragentOptions);
|
|
36165
|
+
};
|
|
36166
|
+
GetAuthAgentManager = () => {
|
|
36167
|
+
return this.GetAgentManager(this._options.authOptions.asagentoptions);
|
|
36168
|
+
};
|
|
36169
|
+
ExtractOrigin = (uri) => {
|
|
36170
|
+
const match = uri.match(this.#originRegex);
|
|
36171
|
+
return match ? match[1] : null;
|
|
36172
|
+
};
|
|
36173
|
+
GetAPITokenFromAuthServerUsingScope = async (options) => {
|
|
36174
|
+
const { scope, clientId, authClientSecret, endPoint } = options;
|
|
36175
|
+
let stage = "1";
|
|
36176
|
+
try {
|
|
36177
|
+
stage = "2";
|
|
36178
|
+
const scopes = scope.split(" ");
|
|
36179
|
+
let origin = null;
|
|
36180
|
+
let error = null;
|
|
36181
|
+
stage = "3";
|
|
36182
|
+
for (let i = 0; i < scopes.length; i++) {
|
|
36183
|
+
const s = scopes[i];
|
|
36184
|
+
if (!origin) {
|
|
36185
|
+
origin = this.ExtractOrigin(s);
|
|
36186
|
+
if (!origin) {
|
|
36187
|
+
error = /* @__PURE__ */ new Error(`Scope: [${scope}] not in required format. Must use (space seperated) api://<client id>[/<resource>.<permission>].`);
|
|
36188
|
+
break;
|
|
36189
|
+
}
|
|
36190
|
+
} else {
|
|
36191
|
+
const nextOrigin = this.ExtractOrigin(s);
|
|
36192
|
+
if (!nextOrigin) {
|
|
36193
|
+
error = /* @__PURE__ */ new Error(`Scope: [${scope}] not in required format. Must use (space seperated) api://<client id>[/<resource>.<permission>].`);
|
|
36194
|
+
break;
|
|
36195
|
+
} else if (origin.localeCompare(nextOrigin) !== 0) {
|
|
36196
|
+
error = /* @__PURE__ */ new Error(`Scope: [${scope}] not all from the same client API. All scopes must come from the same client API.`);
|
|
36197
|
+
break;
|
|
36198
|
+
}
|
|
36199
|
+
}
|
|
36200
|
+
}
|
|
36201
|
+
stage = "4";
|
|
36202
|
+
if (error) throw error;
|
|
36203
|
+
stage = "5";
|
|
36204
|
+
const payload = {
|
|
36205
|
+
client_id: clientId,
|
|
36206
|
+
client_secret: authClientSecret,
|
|
36207
|
+
scope,
|
|
36208
|
+
grant_type: "client_credentials"
|
|
36209
|
+
};
|
|
36210
|
+
stage = "6";
|
|
36211
|
+
const url = endPoint ? `${endPoint}${this._options.authOptions.asoauthapiroot}/token` : `${this._options.authOptions.asendpoint}:${this._options.authOptions.asport}${this._options.authOptions.asoauthapiroot}/token`;
|
|
36212
|
+
stage = `6.5: url: [${url}] payload: [${JSON.stringify(payload)}]`;
|
|
36213
|
+
const axiosConfig = new STSAxiosConfig(url, "post").withDefaultHeaders().withData(payload);
|
|
36214
|
+
if (this.#authAgentManager) axiosConfig.withAgentManager(this.#authAgentManager);
|
|
36215
|
+
const retVal = await createRetryAxiosClient({
|
|
36216
|
+
maxRetries: 4,
|
|
36217
|
+
retryDelayMs: 300,
|
|
36218
|
+
retryJitterMs: 150,
|
|
36219
|
+
maxRetryDurationMs: 5e3,
|
|
36220
|
+
onRetryAttempt: (attempt, error, delayMs) => {
|
|
36221
|
+
this._options.runner.instrumentData.authenticationErrorCount++;
|
|
36222
|
+
this._options.runner.instrumentData.authenticationRetryCount++;
|
|
36223
|
+
const message = `GetAPITokenFromAuthServerUsingScope(): [${this._id}] Retry #${attempt} after ${delayMs}ms due to ${error.code || error.response?.status}`;
|
|
36224
|
+
this.Warning(message);
|
|
36225
|
+
this._options.runner.instrumentData.message.push(chalk.red(message));
|
|
36226
|
+
}
|
|
36227
|
+
})(url, axiosConfig.config);
|
|
36228
|
+
this._options.runner.instrumentData.authenticationCount++;
|
|
36229
|
+
stage = "7";
|
|
36230
|
+
if (retVal.status) {
|
|
36231
|
+
if (retVal.status !== 200) this.Warning(chalk.magenta(`GetAPITokenFromAuthServerUsingScope(): [${this._id}] Invalid response from server: [${retVal.status}]`));
|
|
36232
|
+
} else throw new Error(chalk.red(`No retVal.status)`));
|
|
36233
|
+
stage = "8";
|
|
36234
|
+
if (retVal.data) {
|
|
36235
|
+
stage = "9";
|
|
36236
|
+
if (retVal.data.access_token) {
|
|
36237
|
+
stage = "12";
|
|
36238
|
+
return retVal.data.access_token;
|
|
36239
|
+
} else {
|
|
36240
|
+
stage = "13";
|
|
36241
|
+
throw new Error(`No retVal.data.access_token)`);
|
|
36242
|
+
}
|
|
36243
|
+
} else {
|
|
36244
|
+
stage = "14";
|
|
36245
|
+
throw new Error(`No retVal.data)`);
|
|
36246
|
+
}
|
|
36247
|
+
} catch (error) {
|
|
36248
|
+
this.Error(error);
|
|
36249
|
+
let details = "None available.";
|
|
36250
|
+
if (error.response && error.response.data) try {
|
|
36251
|
+
details = JSON.stringify(error.response.data);
|
|
36252
|
+
} catch (error) {
|
|
36253
|
+
details = `Could not JSON.stringify(error.response.data)`;
|
|
36254
|
+
}
|
|
36255
|
+
error.message = `${this.logPrefix}GetAPITokenFromAuthServerUsingScope(): Error: [${error}], Stage: [${stage}], Details: [${details}]`;
|
|
36256
|
+
throw error;
|
|
36257
|
+
}
|
|
36258
|
+
};
|
|
36259
|
+
GetAccessToken = async () => {
|
|
36260
|
+
let timeout = void 0;
|
|
36261
|
+
const start = performance.now();
|
|
36262
|
+
try {
|
|
36263
|
+
if (this.#accesssToken) return this.#accesssToken;
|
|
36264
|
+
const lockKey = "GetAccessToken";
|
|
36265
|
+
const lockTimeout = 6e4;
|
|
36266
|
+
if (this.GetOnHold(lockKey) === true) {
|
|
36267
|
+
this.Debug(chalk.magenta(`GetAccessToken(): accesssToken does not exist - some other client setting up the new accesssToken (on hold/lock), lock key: [${lockKey}] - waiting ...`));
|
|
36268
|
+
try {
|
|
36269
|
+
const miniStart = performance.now();
|
|
36270
|
+
await this.WaitOnHold(lockKey, lockTimeout);
|
|
36271
|
+
this.Debug(chalk.yellow(`GetAccessToken(): hold (lock) released after: [${performance.now() - miniStart}ms], lock key: [${lockKey}]`));
|
|
36272
|
+
if (this.#accesssToken) {
|
|
36273
|
+
this.Debug(chalk.green(`GetAccessToken(): Getting existing accesssToken (post hold release), lock key: [${lockKey}]`));
|
|
36274
|
+
return this.#accesssToken;
|
|
36275
|
+
} else {
|
|
36276
|
+
this.Error(chalk.red(`GetAccessToken(): Could not get existing accesssToken (post hold release), lock key: [${lockKey}]`));
|
|
36277
|
+
this.Error(chalk.red(`GetAccessToken(): continue anyway ...`));
|
|
36278
|
+
}
|
|
36279
|
+
} catch (error) {
|
|
36280
|
+
this.Error(chalk.red(`GetAccessToken(): Error: [${error}]`));
|
|
36281
|
+
}
|
|
36282
|
+
}
|
|
36283
|
+
this.Debug(chalk.yellow(`GetAccessToken(): accesssToken does not exist - setting up new accesssToken`));
|
|
36284
|
+
this.Debug(chalk.yellow(`GetAccessToken(): setting hold (lock), lock key: [${lockKey}]`));
|
|
36285
|
+
this.SetOnHold(lockKey);
|
|
36286
|
+
timeout = setTimeout(() => {
|
|
36287
|
+
this.Warning(chalk.magenta(`GetAccessToken(): Timeout: [${this._authMaxTimeout}] exceeded for getting access token ...`));
|
|
36288
|
+
}, this._authMaxTimeout);
|
|
36289
|
+
const scopes = `api://fb6513e4-16fe-4931-bed8-33b82b404a14/_.stsfhir5:All`.split(" ").sort().join(" ");
|
|
36290
|
+
const authendpointUrl = `${this._options.authOptions.asendpoint}:${this._options.authOptions.asport}`;
|
|
36291
|
+
const workingAaccesssToken = await this.GetAPITokenFromAuthServerUsingScope({
|
|
36292
|
+
clientId: "d8277fce-bb48-44c2-bbf1-257fe13a444b",
|
|
36293
|
+
authClientSecret: "64e3ef37-c7b8-4cb1-880a-e6ad3ab36e3c",
|
|
36294
|
+
scope: scopes,
|
|
36295
|
+
endPoint: authendpointUrl
|
|
36296
|
+
});
|
|
36297
|
+
if (timeout) clearTimeout(timeout);
|
|
36298
|
+
const totalTime = performance.now() - start;
|
|
36299
|
+
if (totalTime > this._authMaxTimeout) this.Warning(chalk.magenta(`GetAccessToken(): The total time for getting the access token: [${totalTime}]`));
|
|
36300
|
+
this.#accesssToken = workingAaccesssToken;
|
|
36301
|
+
this.ReleaseOnHold(lockKey);
|
|
36302
|
+
this.Debug(chalk.yellow(`GetAccessToken(): release hold (lock) Time taken for get access token: [${performance.now() - start}ms]`));
|
|
36303
|
+
return this.#accesssToken;
|
|
36304
|
+
} catch (error) {
|
|
36305
|
+
if (timeout) clearTimeout(timeout);
|
|
36306
|
+
error.message = `GetAccessToken(): Error: [${error}], Duration until error: [${performance.now() - start}]`;
|
|
36307
|
+
this.Error(error);
|
|
36308
|
+
return "";
|
|
36309
|
+
}
|
|
36310
|
+
};
|
|
36311
|
+
GetAccessTokenForSocketClientAccess = async () => {
|
|
36312
|
+
const timeout = setTimeout(() => {
|
|
36313
|
+
this.Warning(`GetAccessTokenForSocketClientAccess(): Timeout: [${this._authMaxTimeout}] exceeded for getting access token ...`);
|
|
36314
|
+
}, this._authMaxTimeout);
|
|
36315
|
+
const start = performance.now();
|
|
36316
|
+
try {
|
|
36317
|
+
const scopes = `api://fb6513e4-16fe-4931-bed8-33b82b404a14/_.stsfhir5:SocketConnection`.split(" ").sort().join(" ");
|
|
36318
|
+
const authendpointUrl = `${this._options.authOptions.asendpoint}:${this._options.authOptions.asport}`;
|
|
36319
|
+
const retVal = await this.GetAPITokenFromAuthServerUsingScope({
|
|
36320
|
+
clientId: "d8277fce-bb48-44c2-bbf1-257fe13a444b",
|
|
36321
|
+
authClientSecret: "64e3ef37-c7b8-4cb1-880a-e6ad3ab36e3c",
|
|
36322
|
+
scope: scopes,
|
|
36323
|
+
endPoint: authendpointUrl
|
|
36324
|
+
});
|
|
36325
|
+
clearTimeout(timeout);
|
|
36326
|
+
const totalTime = performance.now() - start;
|
|
36327
|
+
if (totalTime > this._authMaxTimeout) this.Warning(chalk.magenta(`GetAccessTokenForSocketClientAccess(): The total time for getting the access token: [${totalTime}]`));
|
|
36328
|
+
return retVal;
|
|
36329
|
+
} catch (error) {
|
|
36330
|
+
clearTimeout(timeout);
|
|
36331
|
+
error.message = `GetAccessTokenForSocketClientAccess(): Error: [${error}], Duration until error: [${performance.now() - start}]`;
|
|
36332
|
+
this.Error(error);
|
|
36333
|
+
return "";
|
|
36334
|
+
}
|
|
36335
|
+
};
|
|
36336
|
+
ResetAccessToken = () => {
|
|
36337
|
+
this.#accesssToken = null;
|
|
36338
|
+
};
|
|
36339
|
+
GetFhirSocketClient = async () => {
|
|
36340
|
+
try {
|
|
36341
|
+
if (this.fhirClient) return this.fhirClient;
|
|
36342
|
+
const lockKey = "GetFhirSocketClient";
|
|
36343
|
+
const lockTimeout = 6e4;
|
|
36344
|
+
if (this.GetOnHold(lockKey) === true) {
|
|
36345
|
+
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 ...`));
|
|
36346
|
+
try {
|
|
36347
|
+
const start = performance.now();
|
|
36348
|
+
await this.WaitOnHold(lockKey, lockTimeout);
|
|
36349
|
+
this.Debug(chalk.yellow(`GetFhirSocketClient(): hold (lock) released after: [${performance.now() - start}ms], lock key: [${lockKey}]`));
|
|
36350
|
+
if (this.fhirClient) {
|
|
36351
|
+
this.Debug(chalk.green(`GetFhirSocketClient(): Getting existing fhir client (post hold release), lock key: [${lockKey}]`));
|
|
36352
|
+
return this.fhirClient;
|
|
36353
|
+
} else {
|
|
36354
|
+
this.Error(chalk.red(`GetFhirSocketClient(): Could not get existing fhir client (post hold release), lock key: [${lockKey}]`));
|
|
36355
|
+
this.Error(chalk.red(`GetFhirSocketClient(): continue anyway ...`));
|
|
36356
|
+
}
|
|
36357
|
+
} catch (error) {
|
|
36358
|
+
this.Error(chalk.red(`GetFhirSocketClient(): Error: [${error}]`));
|
|
36359
|
+
}
|
|
36360
|
+
}
|
|
36361
|
+
const start = performance.now();
|
|
36362
|
+
this.Debug(chalk.yellow(`GetFhirSocketClient(): fhir client does not exist - setting up new client`));
|
|
36363
|
+
this.Debug(chalk.yellow(`GetFhirSocketClient(): setting hold (lock), lock key: [${lockKey}]`));
|
|
36364
|
+
this.SetOnHold(lockKey);
|
|
36365
|
+
const fhirOptions = this._options.fhirOptions;
|
|
36366
|
+
const options = {
|
|
36367
|
+
fhirServerEndpoint: fhirOptions.stsfhirserverendpoint,
|
|
36368
|
+
fhirapiroot: fhirOptions.stsfhirapiroot,
|
|
36369
|
+
fhirServerPort: fhirOptions.stsfhirport,
|
|
36370
|
+
socketClientName: fhirOptions.stsfhirsocketname,
|
|
36371
|
+
socketIoCustomPath: fhirOptions.stsfhirsocketcustompath,
|
|
36372
|
+
timeout: fhirOptions.stsfhirsockettimeout,
|
|
36373
|
+
baseUrl: fhirOptions.stsfhirbaseurl,
|
|
36374
|
+
agentManager: this.GetFhirAgentManager(),
|
|
36375
|
+
joinRooms: [],
|
|
36376
|
+
logger: this.logger,
|
|
36377
|
+
verboseLogging: true,
|
|
36378
|
+
GetConnectionAccessToken: this.GetAccessTokenForSocketClientAccess,
|
|
36379
|
+
GetAccessToken: this.GetAccessToken
|
|
36380
|
+
};
|
|
36381
|
+
let workingFhirClient;
|
|
36382
|
+
if (this._options.runner.options.fhirOptions.stsfhirsocketclientmode === "socket-client-all-in-one") workingFhirClient = new FhirSocketClientAllInOne("FhirSocketClient", options);
|
|
36383
|
+
else workingFhirClient = new FhirSocketClientIndividual("FhirSocketClient", options);
|
|
36384
|
+
await workingFhirClient.WaitForSocketConnected();
|
|
36385
|
+
this.Debug(chalk.yellow(`GetFhirSocketClient(): setting fhir client into object`));
|
|
36386
|
+
this.fhirClient = workingFhirClient;
|
|
36387
|
+
this.ReleaseOnHold(lockKey);
|
|
36388
|
+
this.Debug(chalk.yellow(`GetFhirSocketClient(): release hold (lock) Time taken for socket connection and set object: [${performance.now() - start}ms], lock key: [${lockKey}]`));
|
|
36389
|
+
return this.fhirClient;
|
|
36390
|
+
} catch (error) {
|
|
36391
|
+
this.Error(error);
|
|
36392
|
+
throw error;
|
|
36393
|
+
}
|
|
36394
|
+
};
|
|
36395
|
+
GetRESTClient = async () => {
|
|
36396
|
+
if (this.restFhirClient) return this.restFhirClient;
|
|
36397
|
+
const onRetryAttempt = (attempt, error, delayMs) => {
|
|
36398
|
+
this._options.runner.instrumentData.errorCount++;
|
|
36399
|
+
this._options.runner.instrumentData.requestCount++;
|
|
36400
|
+
const message = `TestCaseFhirBase:onRetryAttempt(): [${this._id}] Retry #${attempt} after ${delayMs}ms due to ${error.code || error.response?.status}`;
|
|
36401
|
+
this.Warning(message);
|
|
36402
|
+
this._options.runner.instrumentData.message.push(chalk.red(message));
|
|
36403
|
+
};
|
|
36404
|
+
const fhirOptions = this._options.fhirOptions;
|
|
36405
|
+
const fhirRESTClient = new FhirRESTClient({
|
|
36406
|
+
GetAccessToken: this.GetAccessToken,
|
|
36407
|
+
user: "USR_user01@stsmda.com.au",
|
|
36408
|
+
endpoint: fhirOptions.stsfhirserverendpoint,
|
|
36409
|
+
stsfhirapiroot: fhirOptions.stsfhirapiroot,
|
|
36410
|
+
stsfhirport: fhirOptions.stsfhirport,
|
|
36411
|
+
logger: this.logger,
|
|
36412
|
+
agentManager: this.GetFhirAgentManager(),
|
|
36413
|
+
onRetryAttempt
|
|
36414
|
+
});
|
|
36415
|
+
this.restFhirClient = fhirRESTClient;
|
|
36416
|
+
return fhirRESTClient;
|
|
36417
|
+
};
|
|
36418
|
+
GetClient = async () => {
|
|
36419
|
+
let client;
|
|
36420
|
+
if (this._options.runner.options.fhirOptions.stsfhirsocketclientmode === "no-socket-client") client = await this.GetRESTClient();
|
|
36421
|
+
else client = await this.GetFhirSocketClient();
|
|
36422
|
+
return client;
|
|
36423
|
+
};
|
|
36441
36424
|
};
|
|
36442
36425
|
//#endregion
|
|
36443
36426
|
export { WorkerFhirTestCases };
|