@@ -12,6 +12,7 @@ import {
1212 isFeatureFlag ,
1313 isSecretReference ,
1414 GetSnapshotOptions ,
15+ ListConfigurationSettingsForSnapshotOptions ,
1516 GetSnapshotResponse ,
1617 KnownSnapshotComposition ,
1718 ListConfigurationSettingPage
@@ -502,84 +503,64 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
502503 */
503504 async #loadConfigurationSettings( loadFeatureFlag : boolean = false ) : Promise < ConfigurationSetting [ ] > {
504505 const selectors : PagedSettingsWatcher [ ] = loadFeatureFlag ? this . #ffSelectors : this . #kvSelectors;
505- const funcToExecute = async ( client ) => {
506- // Use a Map to deduplicate configuration settings by key. When multiple selectors return settings with the same key,
507- // the configuration setting loaded by the later selector in the iteration order will override the one from the earlier selector.
508- const loadedSettings : Map < string , ConfigurationSetting > = new Map < string , ConfigurationSetting > ( ) ;
509- // deep copy selectors to avoid modification if current client fails
510- const selectorsToUpdate : PagedSettingsWatcher [ ] = JSON . parse (
511- JSON . stringify ( selectors )
512- ) ;
513506
514- for ( const selector of selectorsToUpdate ) {
515- if ( selector . snapshotName === undefined ) {
516- const listOptions : ListConfigurationSettingsOptions = {
517- keyFilter : selector . keyFilter ,
518- labelFilter : selector . labelFilter ,
519- tagsFilter : selector . tagFilters
520- } ;
521- const pageWatchers : SettingWatcher [ ] = [ ] ;
522- const pageIterator = listConfigurationSettingsWithTrace (
523- this . #requestTraceOptions,
524- client ,
525- listOptions
526- ) . byPage ( ) ;
527-
528- for await ( const page of pageIterator ) {
529- pageWatchers . push ( { etag : page . etag , timestamp : this . #getResponseTimestamp( page ) } ) ;
530- for ( const setting of page . items ) {
531- if ( loadFeatureFlag === isFeatureFlag ( setting ) ) {
532- loadedSettings . set ( setting . key , setting ) ;
533- }
507+ // Use a Map to deduplicate configuration settings by key. When multiple selectors return settings with the same key,
508+ // the configuration setting loaded by the later selector in the iteration order will override the one from the earlier selector.
509+ const loadedSettings : Map < string , ConfigurationSetting > = new Map < string , ConfigurationSetting > ( ) ;
510+ // deep copy selectors to avoid modification if current client fails
511+ const selectorsToUpdate : PagedSettingsWatcher [ ] = JSON . parse (
512+ JSON . stringify ( selectors )
513+ ) ;
514+
515+ for ( const selector of selectorsToUpdate ) {
516+ let settings : ConfigurationSetting [ ] = [ ] ;
517+ if ( selector . snapshotName === undefined ) {
518+ const listOptions : ListConfigurationSettingsOptions = {
519+ keyFilter : selector . keyFilter ,
520+ labelFilter : selector . labelFilter ,
521+ tagsFilter : selector . tagFilters
522+ } ;
523+ const { items, pageWatchers } = await this . #listConfigurationSettings( listOptions ) ;
524+
525+ for ( const pageWatcher of pageWatchers ) {
526+ if ( loadFeatureFlag ) {
527+ this . #isFfStale = pageWatcher . timestamp < this . #lastFfChangeDetectedTime;
528+ if ( this . #isFfStale) {
529+ return [ ] ;
534530 }
535- const timestamp = this . #getResponseTimestamp( page ) ;
536- // all pages must be later than last change detected to be considered up-to-date
537- if ( loadFeatureFlag ) {
538- this . #isFfStale = timestamp < this . #lastFfChangeDetectedTime;
539- if ( this . #isFfStale) {
540- return [ ] ;
541- }
542- } else {
543- this . #isKvStale = timestamp < this . #lastKvChangeDetectedTime;
544- if ( this . #isKvStale) {
545- return [ ] ;
546- }
547- }
548- }
549- selector . pageWatchers = pageWatchers ;
550- } else { // snapshot selector
551- const snapshot = await this . #getSnapshot( selector . snapshotName ) ;
552- if ( snapshot === undefined ) {
553- throw new InvalidOperationError ( `Could not find snapshot with name ${ selector . snapshotName } .` ) ;
554- }
555- if ( snapshot . compositionType != KnownSnapshotComposition . Key ) {
556- throw new InvalidOperationError ( `Composition type for the selected snapshot with name ${ selector . snapshotName } must be 'key'.` ) ;
557- }
558- const pageIterator = listConfigurationSettingsForSnapshotWithTrace (
559- this . #requestTraceOptions,
560- client ,
561- selector . snapshotName
562- ) . byPage ( ) ;
563-
564- for await ( const page of pageIterator ) {
565- for ( const setting of page . items ) {
566- if ( loadFeatureFlag === isFeatureFlag ( setting ) ) {
567- loadedSettings . set ( setting . key , setting ) ;
568- }
531+ } else {
532+ this . #isKvStale = pageWatcher . timestamp < this . #lastKvChangeDetectedTime;
533+ if ( this . #isKvStale) {
534+ return [ ] ;
569535 }
570536 }
571537 }
538+ selector . pageWatchers = pageWatchers ;
539+ settings = items ;
540+ } else { // snapshot selector
541+ const snapshot = await this . #getSnapshot( selector . snapshotName ) ;
542+ if ( snapshot === undefined ) {
543+ throw new InvalidOperationError ( `Could not find snapshot with name ${ selector . snapshotName } .` ) ;
544+ }
545+ if ( snapshot . compositionType != KnownSnapshotComposition . Key ) {
546+ throw new InvalidOperationError ( `Composition type for the selected snapshot with name ${ selector . snapshotName } must be 'key'.` ) ;
547+ }
548+ settings = await this . #listConfigurationSettingsForSnapshot( selector . snapshotName ) ;
572549 }
573550
574- if ( loadFeatureFlag ) {
575- this . #ffSelectors = selectorsToUpdate ;
576- } else {
577- this . #kvSelectors = selectorsToUpdate ;
551+ for ( const setting of settings ) {
552+ if ( loadFeatureFlag === isFeatureFlag ( setting ) ) {
553+ loadedSettings . set ( setting . key , setting ) ;
554+ }
578555 }
579- return Array . from ( loadedSettings . values ( ) ) ;
580- } ;
556+ }
581557
582- return await this . #executeWithFailoverPolicy( funcToExecute ) as ConfigurationSetting [ ] ;
558+ if ( loadFeatureFlag ) {
559+ this . #ffSelectors = selectorsToUpdate ;
560+ } else {
561+ this . #kvSelectors = selectorsToUpdate ;
562+ }
563+ return Array . from ( loadedSettings . values ( ) ) ;
583564 }
584565
585566 /**
@@ -653,6 +634,10 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
653634 const loadFeatureFlag = true ;
654635 const featureFlagSettings : ConfigurationSetting [ ] = await this . #loadConfigurationSettings( loadFeatureFlag ) ;
655636
637+ if ( featureFlagSettings . length === 0 ) {
638+ return ;
639+ }
640+
656641 if ( this . #requestTracingEnabled && this . #featureFlagTracing !== undefined ) {
657642 // Reset old feature flag tracing in order to track the information present in the current response from server.
658643 this . #featureFlagTracing. reset ( ) ;
@@ -832,13 +817,13 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
832817 /**
833818 * Gets a configuration setting by key and label. If the setting is not found, return the error instead of throwing it.
834819 */
835- async #getConfigurationSetting( configurationSettingId : ConfigurationSettingId , customOptions ?: GetConfigurationSettingOptions ) : Promise < GetConfigurationSettingResponse | RestError > {
820+ async #getConfigurationSetting( configurationSettingId : ConfigurationSettingId , getOptions ?: GetConfigurationSettingOptions ) : Promise < GetConfigurationSettingResponse | RestError > {
836821 const funcToExecute = async ( client ) => {
837822 return getConfigurationSettingWithTrace (
838823 this . #requestTraceOptions,
839824 client ,
840825 configurationSettingId ,
841- customOptions
826+ getOptions
842827 ) ;
843828 } ;
844829
@@ -856,13 +841,33 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
856841 return response ;
857842 }
858843
859- async #getSnapshot( snapshotName : string , customOptions ?: GetSnapshotOptions ) : Promise < GetSnapshotResponse | undefined > {
844+ async #listConfigurationSettings( listOptions : ListConfigurationSettingsOptions ) : Promise < { items : ConfigurationSetting [ ] ; pageWatchers : SettingWatcher [ ] } > {
845+ const funcToExecute = async ( client ) => {
846+ const pageWatchers : SettingWatcher [ ] = [ ] ;
847+ const pageIterator = listConfigurationSettingsWithTrace (
848+ this . #requestTraceOptions,
849+ client ,
850+ listOptions
851+ ) . byPage ( ) ;
852+
853+ const items : ConfigurationSetting [ ] = [ ] ;
854+ for await ( const page of pageIterator ) {
855+ pageWatchers . push ( { etag : page . etag , timestamp : this . #getResponseTimestamp( page ) } ) ;
856+ items . push ( ...page . items ) ;
857+ }
858+ return { items, pageWatchers } ;
859+ } ;
860+
861+ return await this . #executeWithFailoverPolicy( funcToExecute ) ;
862+ }
863+
864+ async #getSnapshot( snapshotName : string , getOptions ?: GetSnapshotOptions ) : Promise < GetSnapshotResponse | undefined > {
860865 const funcToExecute = async ( client ) => {
861866 return getSnapshotWithTrace (
862867 this . #requestTraceOptions,
863868 client ,
864869 snapshotName ,
865- customOptions
870+ getOptions
866871 ) ;
867872 } ;
868873
@@ -879,6 +884,25 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
879884 return response ;
880885 }
881886
887+ async #listConfigurationSettingsForSnapshot( snapshotName : string , listOptions ?: ListConfigurationSettingsForSnapshotOptions ) : Promise < ConfigurationSetting [ ] > {
888+ const funcToExecute = async ( client ) => {
889+ const pageIterator = listConfigurationSettingsForSnapshotWithTrace (
890+ this . #requestTraceOptions,
891+ client ,
892+ snapshotName ,
893+ listOptions
894+ ) . byPage ( ) ;
895+
896+ const items : ConfigurationSetting [ ] = [ ] ;
897+ for await ( const page of pageIterator ) {
898+ items . push ( ...page . items ) ;
899+ }
900+ return items ;
901+ } ;
902+
903+ return await this . #executeWithFailoverPolicy( funcToExecute ) ;
904+ }
905+
882906 // Only operations related to Azure App Configuration should be executed with failover policy.
883907 async #executeWithFailoverPolicy( funcToExecute : ( client : AppConfigurationClient ) => Promise < any > ) : Promise < any > {
884908 let clientWrappers = await this . #clientManager. getClients ( ) ;
@@ -954,7 +978,7 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
954978 #setAIConfigurationTracing( setting : ConfigurationSetting < string > ) : void {
955979 if ( this . #requestTracingEnabled && this . #aiConfigurationTracing !== undefined ) {
956980 const contentType = parseContentType ( setting . contentType ) ;
957- // content type: "application/json; profile=\"https://azconfig.io/mime-profiles/ai\"""
981+ // content type: "application/json; profile=\"https://azconfig.io/mime-profiles/ai\""
958982 if ( isJsonContentType ( contentType ) &&
959983 ! isFeatureFlagContentType ( contentType ) &&
960984 ! isSecretReferenceContentType ( contentType ) ) {
0 commit comments