@@ -60,6 +60,7 @@ import { AIConfigurationTracingOptions } from "./requestTracing/aiConfigurationT
6060import { KeyFilter , LabelFilter , SettingWatcher , SettingSelector , PagedSettingsWatcher , WatchedSetting } from "./types.js" ;
6161import { ConfigurationClientManager } from "./configurationClientManager.js" ;
6262import { getFixedBackoffDuration , getExponentialBackoffDuration } from "./common/backoffUtils.js" ;
63+ import { getStatusCode } from "./common/utils.js" ;
6364import { InvalidOperationError , ArgumentError , isFailoverableError , isInputError , SnapshotReferenceError } from "./common/errors.js" ;
6465import { ErrorMessages } from "./common/errorMessages.js" ;
6566
@@ -110,7 +111,6 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
110111 #secretRefreshEnabled: boolean = false ;
111112 #secretReferences: ConfigurationSetting [ ] = [ ] ; // cached key vault references
112113 #secretRefreshTimer: RefreshTimer | undefined = undefined ;
113- #resolveSecretsInParallel: boolean = false ;
114114
115115 /**
116116 * Selectors of key-values obtained from @see AzureAppConfigurationOptions.selectors
@@ -202,7 +202,6 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
202202 this . #secretRefreshEnabled = true ;
203203 this . #secretRefreshTimer = new RefreshTimer ( secretRefreshIntervalInMs ) ;
204204 }
205- this . #resolveSecretsInParallel = options . keyVaultOptions . parallelSecretResolutionEnabled ?? false ;
206205 }
207206 this . #adapters. push ( new AzureKeyVaultKeyValueAdapter ( options ?. keyVaultOptions , this . #secretRefreshTimer) ) ;
208207 this . #adapters. push ( new JsonKeyValueAdapter ( ) ) ;
@@ -558,22 +557,19 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
558557 this . #aiConfigurationTracing. reset ( ) ;
559558 }
560559
560+ for ( const adapter of this . #adapters) {
561+ await adapter . preload ?.( loadedSettings . filter ( s => adapter . canProcess ( s ) ) ) ; // dedup and warm the secret cache
562+ }
563+
561564 for ( const setting of loadedSettings ) {
562565 if ( isSecretReference ( setting ) ) {
563566 this . #secretReferences. push ( setting ) ; // cache secret references for resolve/refresh secret separately
564- continue ;
565567 }
566568 // adapt configuration settings to key-values
567569 const [ key , value ] = await this . #processKeyValue( setting ) ;
568570 keyValues . push ( [ key , value ] ) ;
569571 }
570572
571- if ( this . #secretReferences. length > 0 ) {
572- await this . #resolveSecretReferences( this . #secretReferences, ( key , value ) => {
573- keyValues . push ( [ key , value ] ) ;
574- } ) ;
575- }
576-
577573 this . #clearLoadedKeyValues( ) ; // clear existing key-values in case of configuration setting deletion
578574 for ( const [ k , v ] of keyValues ) {
579575 this . #configMap. set ( k , v ) ; // reset the configuration
@@ -659,7 +655,7 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
659655
660656 const watcher : SettingWatcher = this . #sentinels. get ( watchedSetting ) ! ; // watcher should always exist for sentinels
661657 const isDeleted = response === undefined && watcher . etag !== undefined ; // previously existed, now deleted
662- const isChanged = response && Number ( response . statusCode ) === 200 && watcher . etag !== response . etag ; // etag changed
658+ const isChanged = response && getStatusCode ( response . statusCode ) === 200 && watcher . etag !== response . etag ; // etag changed
663659 if ( isDeleted || isChanged ) {
664660 changedSentinel = watchedSetting ;
665661 changedSentinelWatcher = { etag : isChanged ? response . etag : undefined } ;
@@ -671,7 +667,7 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
671667
672668 if ( needRefresh ) {
673669 for ( const adapter of this . #adapters) {
674- await adapter . onChangeDetected ( ) ;
670+ await adapter . onChangeDetected ?. ( ) ;
675671 }
676672 await this . #loadSelectedKeyValues( ) ;
677673
@@ -715,9 +711,16 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
715711 return Promise . resolve ( false ) ;
716712 }
717713
718- await this . #resolveSecretReferences( this . #secretReferences, ( key , value ) => {
714+ const keyVaultRefAdapter = this . #adapters. find ( adapter => adapter instanceof AzureKeyVaultKeyValueAdapter ) as AzureKeyVaultKeyValueAdapter | undefined ;
715+ if ( keyVaultRefAdapter ) {
716+ // dedup and warm the secret cache
717+ await keyVaultRefAdapter . preload ( this . #secretReferences) ;
718+ }
719+
720+ for ( const setting of this . #secretReferences) {
721+ const [ key , value ] = await this . #processKeyValue( setting ) ;
719722 this . #configMap. set ( key , value ) ;
720- } ) ;
723+ }
721724
722725 this . #secretRefreshTimer. reset ( ) ;
723726 return Promise . resolve ( true ) ;
@@ -750,7 +753,7 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
750753
751754 for await ( const page of pageIterator ) {
752755 // when conditional request is sent, the response will be 304 if not changed
753- if ( Number ( page . _response . status ) === 200 ) { // created or changed
756+ if ( getStatusCode ( page . _response . status ) === 200 ) { // created or changed
754757 return true ;
755758 }
756759 }
@@ -779,7 +782,7 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
779782 try {
780783 response = await this . #executeWithFailoverPolicy( funcToExecute ) ;
781784 } catch ( error ) {
782- if ( isRestError ( error ) && Number ( error . statusCode ) === 404 ) {
785+ if ( isRestError ( error ) && getStatusCode ( error . statusCode ) === 404 ) {
783786 response = undefined ;
784787 } else {
785788 throw error ;
@@ -822,7 +825,7 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
822825 try {
823826 response = await this . #executeWithFailoverPolicy( funcToExecute ) ;
824827 } catch ( error ) {
825- if ( isRestError ( error ) && Number ( error . statusCode ) === 404 ) {
828+ if ( isRestError ( error ) && getStatusCode ( error . statusCode ) === 404 ) {
826829 response = undefined ;
827830 } else {
828831 throw error ;
@@ -893,27 +896,6 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
893896 throw new Error ( ErrorMessages . ALL_FALLBACK_CLIENTS_FAILED ) ;
894897 }
895898
896- async #resolveSecretReferences( secretReferences : ConfigurationSetting [ ] , resultHandler : ( key : string , value : unknown ) => void ) : Promise < void > {
897- if ( this . #resolveSecretsInParallel) {
898- const secretResolutionPromises : Promise < void > [ ] = [ ] ;
899- for ( const setting of secretReferences ) {
900- const secretResolutionPromise = this . #processKeyValue( setting )
901- . then ( ( [ key , value ] ) => {
902- resultHandler ( key , value ) ;
903- } ) ;
904- secretResolutionPromises . push ( secretResolutionPromise ) ;
905- }
906-
907- // Wait for all secret resolution promises to be resolved
908- await Promise . all ( secretResolutionPromises ) ;
909- } else {
910- for ( const setting of secretReferences ) {
911- const [ key , value ] = await this . #processKeyValue( setting ) ;
912- resultHandler ( key , value ) ;
913- }
914- }
915- }
916-
917899 async #processKeyValue( setting : ConfigurationSetting < string > ) : Promise < [ string , unknown ] > {
918900 this . #setAIConfigurationTracing( setting ) ;
919901
0 commit comments