@@ -15,6 +15,13 @@ import { RefreshTimer } from "./refresh/RefreshTimer";
1515import { getConfigurationSettingWithTrace , listConfigurationSettingsWithTrace , requestTracingEnabled } from "./requestTracing/utils" ;
1616import { KeyFilter , LabelFilter , SettingSelector } from "./types" ;
1717
18+ type PagedSettingSelector = SettingSelector & {
19+ /**
20+ * Key: page eTag, Value: feature flag configurations
21+ */
22+ pages ?: Map < string , ConfigurationSetting [ ] >
23+ } ;
24+
1825export class AzureAppConfigurationImpl implements AzureAppConfiguration {
1926 /**
2027 * Hosting key-value pairs in the configuration store.
@@ -45,6 +52,9 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
4552 #featureFlagRefreshInterval: number = DEFAULT_REFRESH_INTERVAL_IN_MS ;
4653 #featureFlagRefreshTimer: RefreshTimer ;
4754
55+ // selectors
56+ #featureFlagSelectors: PagedSettingSelector [ ] = [ ] ;
57+
4858 constructor (
4959 client : AppConfigurationClient ,
5060 options : AzureAppConfigurationOptions | undefined
@@ -103,6 +113,9 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
103113 }
104114
105115 this . #featureFlagRefreshTimer = new RefreshTimer ( this . #featureFlagRefreshInterval) ;
116+
117+ // validate feature flag selectors
118+ this . #featureFlagSelectors = getValidFeatureFlagSelectors ( options . featureFlagOptions . selectors ) ;
106119 }
107120
108121 this . #adapters. push ( new AzureKeyVaultKeyValueAdapter ( options ?. keyVaultOptions ) ) ;
@@ -233,7 +246,7 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
233246 }
234247
235248 async #clearLoadedKeyValues( ) {
236- for ( const key of this . #configMap. keys ( ) ) {
249+ for ( const key of this . #configMap. keys ( ) ) {
237250 if ( key !== FEATURE_MANAGEMENT_KEY_NAME ) {
238251 this . #configMap. delete ( key ) ;
239252 }
@@ -243,20 +256,44 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
243256 async #loadFeatureFlags( ) {
244257 // Temporary map to store feature flags, key is the key of the setting, value is the raw value of the setting
245258 const featureFlagsMap = new Map < string , any > ( ) ;
246- const featureFlagSelectors = getValidFeatureFlagSelectors ( this . #options ?. featureFlagOptions ?. selectors ) ;
247- for ( const selector of featureFlagSelectors ) {
259+ for ( const selector of this . #featureFlagSelectors ) {
260+ const pageEtags = selector . pages ? Array . from ( selector . pages . keys ( ) ) : undefined ;
248261 const listOptions : ListConfigurationSettingsOptions = {
249262 keyFilter : `${ featureFlagPrefix } ${ selector . keyFilter } ` ,
250- labelFilter : selector . labelFilter
263+ labelFilter : selector . labelFilter ,
264+ pageEtags : pageEtags
251265 } ;
252- const settings = listConfigurationSettingsWithTrace (
266+
267+ const pageIterator = listConfigurationSettingsWithTrace (
253268 this . #requestTraceOptions,
254269 this . #client,
255270 listOptions
256- ) ;
257- for await ( const setting of settings ) {
258- if ( isFeatureFlag ( setting ) ) {
259- featureFlagsMap . set ( setting . key , setting . value ) ;
271+ ) . byPage ( ) ;
272+ const newPages = new Map < string , any [ ] > ( ) ;
273+ for await ( const page of pageIterator ) {
274+ if ( page . _response . status === 200 ) {
275+ if ( page . etag ) {
276+ newPages . set ( page . etag , page . items ) ;
277+ }
278+ } else if ( page . _response . status === 304 ) {
279+ if ( page . etag ) {
280+ // No change, keep the existing page
281+ const existingPage = selector . pages ?. get ( page . etag ) ;
282+ if ( existingPage ) {
283+ newPages . set ( page . etag , existingPage ) ;
284+ }
285+ }
286+ } else {
287+ // TODO: any other cases? deletion?
288+ }
289+ }
290+ selector . pages = newPages ;
291+
292+ for ( const page of selector . pages . values ( ) ) {
293+ for ( const setting of page ) {
294+ if ( isFeatureFlag ( setting ) ) {
295+ featureFlagsMap . set ( setting . key , setting . value ) ;
296+ }
260297 }
261298 }
262299 }
0 commit comments