Skip to content

Commit 030d72d

Browse files
update
1 parent 855e909 commit 030d72d

File tree

5 files changed

+48
-6
lines changed

5 files changed

+48
-6
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
"dev": "rollup --config --watch",
2626
"lint": "eslint src/ test/",
2727
"fix-lint": "eslint src/ test/ --fix",
28-
"test": "mocha out/test/featureFlag.test.{js,cjs,mjs} --parallel"
28+
"test": "mocha out/test/*.test.{js,cjs,mjs} --parallel"
2929
},
3030
"repository": {
3131
"type": "git",

src/AzureAppConfigurationImpl.ts

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
ListConfigurationSettingsOptions,
1111
featureFlagPrefix,
1212
isFeatureFlag,
13+
isSecretReference,
1314
GetSnapshotOptions,
1415
GetSnapshotResponse,
1516
KnownSnapshotComposition
@@ -102,6 +103,9 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
102103
#ffRefreshInterval: number = DEFAULT_REFRESH_INTERVAL_IN_MS;
103104
#ffRefreshTimer: RefreshTimer;
104105

106+
// Key Vault references
107+
#resolveSecretsInParallel: boolean = false;
108+
105109
/**
106110
* Selectors of key-values obtained from @see AzureAppConfigurationOptions.selectors
107111
*/
@@ -182,6 +186,10 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
182186
}
183187
}
184188

189+
if (options?.keyVaultOptions?.parallelSecretResolutionEnabled) {
190+
this.#resolveSecretsInParallel = options.keyVaultOptions.parallelSecretResolutionEnabled;
191+
}
192+
185193
this.#adapters.push(new AzureKeyVaultKeyValueAdapter(options?.keyVaultOptions));
186194
this.#adapters.push(new JsonKeyValueAdapter());
187195
}
@@ -526,7 +534,7 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
526534
*/
527535
async #loadSelectedAndWatchedKeyValues() {
528536
const keyValues: [key: string, value: unknown][] = [];
529-
const loadedSettings = await this.#loadConfigurationSettings();
537+
const loadedSettings: ConfigurationSetting[] = await this.#loadConfigurationSettings();
530538
if (this.#refreshEnabled && !this.#watchAll) {
531539
await this.#updateWatchedKeyValuesEtag(loadedSettings);
532540
}
@@ -536,11 +544,25 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
536544
this.#aiConfigurationTracing.reset();
537545
}
538546

539-
// adapt configuration settings to key-values
547+
const secretResolutionPromises: Promise<void>[] = [];
540548
for (const setting of loadedSettings) {
549+
if (this.#resolveSecretsInParallel && isSecretReference(setting)) {
550+
// secret references are resolved asynchronously to improve performance
551+
const secretResolutionPromise = this.#processKeyValue(setting)
552+
.then(([key, value]) => {
553+
keyValues.push([key, value]);
554+
});
555+
secretResolutionPromises.push(secretResolutionPromise);
556+
continue;
557+
}
558+
// adapt configuration settings to key-values
541559
const [key, value] = await this.#processKeyValue(setting);
542560
keyValues.push([key, value]);
543561
}
562+
if (secretResolutionPromises.length > 0) {
563+
// wait for all secret resolution promises to be resolved
564+
await Promise.all(secretResolutionPromises);
565+
}
544566

545567
this.#clearLoadedKeyValues(); // clear existing key-values in case of configuration setting deletion
546568
for (const [k, v] of keyValues) {
@@ -585,7 +607,7 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
585607
*/
586608
async #loadFeatureFlags() {
587609
const loadFeatureFlag = true;
588-
const featureFlagSettings = await this.#loadConfigurationSettings(loadFeatureFlag);
610+
const featureFlagSettings: ConfigurationSetting[] = await this.#loadConfigurationSettings(loadFeatureFlag);
589611

590612
if (this.#requestTracingEnabled && this.#featureFlagTracing !== undefined) {
591613
// Reset old feature flag tracing in order to track the information present in the current response from server.

src/keyvault/KeyVaultOptions.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,12 @@ export interface KeyVaultOptions {
3232
* @returns The secret value.
3333
*/
3434
secretResolver?: (keyVaultReference: URL) => string | Promise<string>;
35+
36+
/**
37+
* Specifies whether to resolve the secret value in parallel.
38+
*
39+
* @remarks
40+
* If not specified, the default value is false.
41+
*/
42+
parallelSecretResolutionEnabled?: boolean;
3543
}

test/keyvault.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,4 +127,16 @@ describe("key vault reference", function () {
127127
expect(settings.get("TestKey")).eq("SecretValue");
128128
expect(settings.get("TestKey2")).eq("SecretValue2");
129129
});
130+
131+
it("should resolve key vault reference in parallel", async () => {
132+
const settings = await load(createMockedConnectionString(), {
133+
keyVaultOptions: {
134+
credential: createMockedTokenCredential(),
135+
parallelSecretResolutionEnabled: true
136+
}
137+
});
138+
expect(settings).not.undefined;
139+
expect(settings.get("TestKey")).eq("SecretValue");
140+
expect(settings.get("TestKeyFixedVersion")).eq("OldSecretValue");
141+
});
130142
});

test/load.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ describe("load", function () {
126126
const connectionString = createMockedConnectionString();
127127
return expect(load(connectionString, {
128128
selectors: [{
129-
labelFilter: "\0"
129+
labelFilter: "\0"
130130
}]
131131
})).eventually.rejectedWith("Key filter cannot be null or empty.");
132132
});
@@ -136,7 +136,7 @@ describe("load", function () {
136136
return expect(load(connectionString, {
137137
selectors: [{
138138
snapshotName: "Test",
139-
labelFilter: "\0"
139+
labelFilter: "\0"
140140
}]
141141
})).eventually.rejectedWith("Key or label filter should not be used for a snapshot.");
142142
});

0 commit comments

Comments
 (0)