@@ -11,6 +11,9 @@ import {
1111 featureFlagPrefix ,
1212 isFeatureFlag ,
1313 isSecretReference ,
14+ isSnapshotReference ,
15+ parseSnapshotReference ,
16+ SnapshotReferenceValue ,
1417 GetSnapshotOptions ,
1518 ListConfigurationSettingsForSnapshotOptions ,
1619 GetSnapshotResponse ,
@@ -57,7 +60,7 @@ import { AIConfigurationTracingOptions } from "./requestTracing/aiConfigurationT
5760import { KeyFilter , LabelFilter , SettingWatcher , SettingSelector , PagedSettingsWatcher , WatchedSetting } from "./types.js" ;
5861import { ConfigurationClientManager } from "./configurationClientManager.js" ;
5962import { getFixedBackoffDuration , getExponentialBackoffDuration } from "./common/backoffUtils.js" ;
60- import { InvalidOperationError , ArgumentError , isFailoverableError , isInputError } from "./common/errors.js" ;
63+ import { InvalidOperationError , ArgumentError , isFailoverableError , isInputError , SnapshotReferenceError } from "./common/errors.js" ;
6164import { ErrorMessages } from "./common/errorMessages.js" ;
6265
6366const MIN_DELAY_FOR_UNHANDLED_FAILURE = 5_000 ; // 5 seconds
@@ -82,6 +85,7 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
8285 #featureFlagTracing: FeatureFlagTracingOptions | undefined ;
8386 #fmVersion: string | undefined ;
8487 #aiConfigurationTracing: AIConfigurationTracingOptions | undefined ;
88+ #useSnapshotReference: boolean = false ;
8589
8690 // Refresh
8791 #refreshInProgress: boolean = false ;
@@ -213,7 +217,8 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
213217 isFailoverRequest : this . #isFailoverRequest,
214218 featureFlagTracing : this . #featureFlagTracing,
215219 fmVersion : this . #fmVersion,
216- aiConfigurationTracing : this . #aiConfigurationTracing
220+ aiConfigurationTracing : this . #aiConfigurationTracing,
221+ useSnapshotReference : this . #useSnapshotReference
217222 } ;
218223 }
219224
@@ -504,17 +509,29 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
504509 selector . pageWatchers = pageWatchers ;
505510 settings = items ;
506511 } else { // snapshot selector
507- const snapshot = await this . #getSnapshot( selector . snapshotName ) ;
508- if ( snapshot === undefined ) {
509- throw new InvalidOperationError ( `Could not find snapshot with name ${ selector . snapshotName } .` ) ;
510- }
511- if ( snapshot . compositionType != KnownSnapshotComposition . Key ) {
512- throw new InvalidOperationError ( `Composition type for the selected snapshot with name ${ selector . snapshotName } must be 'key'.` ) ;
513- }
514- settings = await this . #listConfigurationSettingsForSnapshot( selector . snapshotName ) ;
512+ settings = await this . #loadConfigurationSettingsFromSnapshot( selector . snapshotName ) ;
515513 }
516514
517515 for ( const setting of settings ) {
516+ if ( isSnapshotReference ( setting ) && ! loadFeatureFlag ) {
517+ this . #useSnapshotReference = true ;
518+
519+ const snapshotRef : ConfigurationSetting < SnapshotReferenceValue > = parseSnapshotReference ( setting ) ;
520+ const snapshotName = snapshotRef . value . snapshotName ;
521+ if ( ! snapshotName ) {
522+ throw new SnapshotReferenceError ( `Invalid format for Snapshot reference setting '${ setting . key } '.` ) ;
523+ }
524+ const settingsFromSnapshot = await this . #loadConfigurationSettingsFromSnapshot( snapshotName ) ;
525+
526+ for ( const snapshotSetting of settingsFromSnapshot ) {
527+ if ( ! isFeatureFlag ( snapshotSetting ) ) {
528+ // Feature flags inside snapshot are ignored. This is consistent the behavior that key value selectors ignore feature flags.
529+ loadedSettings . set ( snapshotSetting . key , snapshotSetting ) ;
530+ }
531+ }
532+ continue ;
533+ }
534+
518535 if ( loadFeatureFlag === isFeatureFlag ( setting ) ) {
519536 loadedSettings . set ( setting . key , setting ) ;
520537 }
@@ -575,6 +592,18 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
575592 }
576593 }
577594
595+ async #loadConfigurationSettingsFromSnapshot( snapshotName : string ) : Promise < ConfigurationSetting [ ] > {
596+ const snapshot = await this . #getSnapshot( snapshotName ) ;
597+ if ( snapshot === undefined ) {
598+ return [ ] ; // treat non-existing snapshot as empty
599+ }
600+ if ( snapshot . compositionType != KnownSnapshotComposition . Key ) {
601+ throw new InvalidOperationError ( `Composition type for the selected snapshot with name ${ snapshotName } must be 'key'.` ) ;
602+ }
603+ const settings : ConfigurationSetting [ ] = await this . #listConfigurationSettingsForSnapshot( snapshotName ) ;
604+ return settings ;
605+ }
606+
578607 /**
579608 * Clears all existing key-values in the local configuration except feature flags.
580609 */
0 commit comments