@@ -36,7 +36,7 @@ internal class AzureAppConfigurationProvider : ConfigurationProvider, IConfigura
3636 private Dictionary < KeyValueSelector , IEnumerable < MatchConditions > > _ffEtags = new Dictionary < KeyValueSelector , IEnumerable < MatchConditions > > ( ) ;
3737 private RequestTracingOptions _requestTracingOptions ;
3838 private Dictionary < Uri , ConfigurationClientBackoffStatus > _configClientBackoffs = new Dictionary < Uri , ConfigurationClientBackoffStatus > ( ) ;
39- private DateTimeOffset _registerAllNextRefreshTime ;
39+ private DateTimeOffset _nextCollectionRefreshTime ;
4040
4141 private readonly TimeSpan MinRefreshInterval ;
4242
@@ -119,9 +119,13 @@ public AzureAppConfigurationProvider(IConfigurationClientManager configClientMan
119119 {
120120 MinRefreshInterval = TimeSpan . FromTicks ( Math . Min ( minWatcherRefreshInterval . Ticks , options . KvCollectionRefreshInterval . Ticks ) ) ;
121121 }
122+ else if ( hasWatchers )
123+ {
124+ MinRefreshInterval = minWatcherRefreshInterval ;
125+ }
122126 else
123127 {
124- MinRefreshInterval = hasWatchers ? minWatcherRefreshInterval : RefreshConstants . DefaultRefreshInterval ;
128+ MinRefreshInterval = RefreshConstants . DefaultRefreshInterval ;
125129 }
126130
127131 // Enable request tracing if not opt-out
@@ -201,7 +205,7 @@ public async Task RefreshAsync(CancellationToken cancellationToken)
201205 var utcNow = DateTimeOffset . UtcNow ;
202206 IEnumerable < KeyValueWatcher > refreshableIndividualKvWatchers = _options . IndividualKvWatchers . Where ( kvWatcher => utcNow >= kvWatcher . NextRefreshTime ) ;
203207 IEnumerable < KeyValueWatcher > refreshableFfWatchers = _options . FeatureFlagWatchers . Where ( ffWatcher => utcNow >= ffWatcher . NextRefreshTime ) ;
204- bool isRefreshDue = utcNow >= _registerAllNextRefreshTime ;
208+ bool isRefreshDue = utcNow >= _nextCollectionRefreshTime ;
205209
206210 // Skip refresh if mappedData is loaded, but none of the watchers or adapters are refreshable.
207211 if ( _mappedData != null &&
@@ -287,7 +291,7 @@ await ExecuteWithFailOverPolicyAsync(clients, async (client) =>
287291 if ( isRefreshDue )
288292 {
289293 refreshAll = await HaveCollectionsChanged (
290- _options . Selectors . Where ( selector => ! selector . IsFeatureFlagSelector ) . ToList ( ) ,
294+ _options . Selectors . Where ( selector => ! selector . IsFeatureFlagSelector ) ,
291295 _kvEtags ,
292296 client ,
293297 cancellationToken ) . ConfigureAwait ( false ) ;
@@ -307,7 +311,8 @@ await ExecuteWithFailOverPolicyAsync(clients, async (client) =>
307311
308312 if ( refreshAll )
309313 {
310- // Trigger a single load-all operation if a change was detected in one or more key-values with refreshAll: true
314+ // Trigger a single load-all operation if a change was detected in one or more key-values with refreshAll: true,
315+ // or if any key-value collection change was detected.
311316 kvEtags = new Dictionary < KeyValueSelector , IEnumerable < MatchConditions > > ( ) ;
312317 ffEtags = new Dictionary < KeyValueSelector , IEnumerable < MatchConditions > > ( ) ;
313318
@@ -316,32 +321,30 @@ await ExecuteWithFailOverPolicyAsync(clients, async (client) =>
316321 logInfoBuilder . AppendLine ( LogHelper . BuildConfigurationUpdatedMessage ( ) ) ;
317322 return ;
318323 }
319- else
324+
325+ // Get feature flag changes
326+ ffCollectionUpdated = await HaveCollectionsChanged (
327+ refreshableFfWatchers . Select ( watcher => new KeyValueSelector { KeyFilter = watcher . Key , LabelFilter = watcher . Label } ) ,
328+ _ffEtags ,
329+ client ,
330+ cancellationToken ) . ConfigureAwait ( false ) ;
331+
332+ if ( ffCollectionUpdated )
320333 {
321- // Get feature flag changes
322- ffCollectionUpdated = await HaveCollectionsChanged (
323- refreshableFfWatchers . Select ( watcher => new KeyValueSelector { KeyFilter = watcher . Key , LabelFilter = watcher . Label } ) ,
324- _ffEtags ,
334+ ffEtags = new Dictionary < KeyValueSelector , IEnumerable < MatchConditions > > ( ) ;
335+
336+ ffCollectionData = await LoadSelected (
325337 client ,
338+ new Dictionary < KeyValueSelector , IEnumerable < MatchConditions > > ( ) ,
339+ ffEtags ,
340+ _options . Selectors . Where ( selector => selector . IsFeatureFlagSelector ) ,
326341 cancellationToken ) . ConfigureAwait ( false ) ;
327342
328- if ( ffCollectionUpdated )
329- {
330- ffEtags = new Dictionary < KeyValueSelector , IEnumerable < MatchConditions > > ( ) ;
331-
332- ffCollectionData = await LoadSelected (
333- client ,
334- new Dictionary < KeyValueSelector , IEnumerable < MatchConditions > > ( ) ,
335- ffEtags ,
336- _options . Selectors . Where ( selector => selector . IsFeatureFlagSelector ) ,
337- cancellationToken ) . ConfigureAwait ( false ) ;
338-
339- logInfoBuilder . Append ( LogHelper . BuildFeatureFlagsUpdatedMessage ( ) ) ;
340- }
341- else
342- {
343- logDebugBuilder . AppendLine ( LogHelper . BuildFeatureFlagsUnchangedMessage ( endpoint . ToString ( ) ) ) ;
344- }
343+ logInfoBuilder . Append ( LogHelper . BuildFeatureFlagsUpdatedMessage ( ) ) ;
344+ }
345+ else
346+ {
347+ logDebugBuilder . AppendLine ( LogHelper . BuildFeatureFlagsUnchangedMessage ( endpoint . ToString ( ) ) ) ;
345348 }
346349 } ,
347350 cancellationToken )
@@ -389,7 +392,7 @@ await ExecuteWithFailOverPolicyAsync(clients, async (client) =>
389392
390393 if ( isRefreshDue )
391394 {
392- _registerAllNextRefreshTime = DateTimeOffset . UtcNow . Add ( _options . KvCollectionRefreshInterval ) ;
395+ _nextCollectionRefreshTime = DateTimeOffset . UtcNow . Add ( _options . KvCollectionRefreshInterval ) ;
393396 }
394397
395398 if ( _options . Adapters . Any ( adapter => adapter . NeedsRefresh ( ) ) || keyValueChanges . Any ( ) || refreshAll || ffCollectionUpdated )
@@ -535,7 +538,7 @@ private void SetDirty(TimeSpan? maxDelay)
535538
536539 if ( _options . RegisterAllEnabled )
537540 {
538- _registerAllNextRefreshTime = nextRefreshTime ;
541+ _nextCollectionRefreshTime = nextRefreshTime ;
539542 }
540543 else
541544 {
@@ -725,7 +728,7 @@ await ExecuteWithFailOverPolicyAsync(
725728
726729 if ( _options . RegisterAllEnabled )
727730 {
728- _registerAllNextRefreshTime = DateTimeOffset . UtcNow . Add ( _options . KvCollectionRefreshInterval ) ;
731+ _nextCollectionRefreshTime = DateTimeOffset . UtcNow . Add ( _options . KvCollectionRefreshInterval ) ;
729732 }
730733
731734 if ( data != null )
@@ -772,7 +775,7 @@ await CallWithRequestTracing(async () =>
772775 {
773776 AsyncPageable < ConfigurationSetting > pageableSettings = client . GetConfigurationSettingsAsync ( selector , cancellationToken ) ;
774777
775- await foreach ( Page < ConfigurationSetting > page in pageableSettings . AsPages ( ) . ConfigureAwait ( false ) )
778+ await foreach ( Page < ConfigurationSetting > page in pageableSettings . AsPages ( _options . ConfigurationSettingPageIterator ) . ConfigureAwait ( false ) )
776779 {
777780 using Response response = page . GetRawResponse ( ) ;
778781
@@ -1190,30 +1193,6 @@ innerException is SocketException ||
11901193 innerException is IOException ;
11911194 }
11921195
1193- private IEnumerable < string > GetExistingKeys ( string key , IEnumerable < string > existingKeys )
1194- {
1195- IEnumerable < string > currentKeyValues ;
1196-
1197- if ( key . EndsWith ( "*" ) )
1198- {
1199- // Get current application settings starting with changeWatcher.Key, excluding the last * character
1200- string keyPrefix = key . Substring ( 0 , key . Length - 1 ) ;
1201- currentKeyValues = existingKeys . Where ( val =>
1202- {
1203- return val . StartsWith ( keyPrefix ) ;
1204- } ) ;
1205- }
1206- else
1207- {
1208- currentKeyValues = existingKeys . Where ( val =>
1209- {
1210- return val . Equals ( key ) ;
1211- } ) ;
1212- }
1213-
1214- return currentKeyValues ;
1215- }
1216-
12171196 private async Task < Dictionary < string , ConfigurationSetting > > MapConfigurationSettings ( Dictionary < string , ConfigurationSetting > data )
12181197 {
12191198 Dictionary < string , ConfigurationSetting > mappedData = new Dictionary < string , ConfigurationSetting > ( StringComparer . OrdinalIgnoreCase ) ;
@@ -1281,7 +1260,12 @@ private void UpdateClientBackoffStatus(Uri endpoint, bool successful)
12811260 _configClientBackoffs [ endpoint ] = clientBackoffStatus ;
12821261 }
12831262
1284- private async Task < bool > HaveCollectionsChanged ( IEnumerable < KeyValueSelector > selectors , Dictionary < KeyValueSelector , IEnumerable < MatchConditions > > pageEtags , ConfigurationClient client , CancellationToken cancellationToken )
1263+ private async Task < bool > HaveCollectionsChanged (
1264+ IEnumerable < KeyValueSelector > selectors ,
1265+ Dictionary < KeyValueSelector ,
1266+ IEnumerable < MatchConditions > > pageEtags ,
1267+ ConfigurationClient client ,
1268+ CancellationToken cancellationToken )
12851269 {
12861270 bool haveCollectionsChanged = false ;
12871271
@@ -1290,7 +1274,11 @@ private async Task<bool> HaveCollectionsChanged(IEnumerable<KeyValueSelector> se
12901274 if ( pageEtags . TryGetValue ( selector , out IEnumerable < MatchConditions > matchConditions ) )
12911275 {
12921276 await TracingUtils . CallWithRequestTracing ( _requestTracingEnabled , RequestType . Watch , _requestTracingOptions ,
1293- async ( ) => haveCollectionsChanged = await client . HaveCollectionsChanged ( selector , matchConditions , _options . PageableConfigurationSettings , cancellationToken ) . ConfigureAwait ( false ) ) . ConfigureAwait ( false ) ;
1277+ async ( ) => haveCollectionsChanged = await client . HaveCollectionsChanged (
1278+ selector ,
1279+ matchConditions ,
1280+ _options . ConfigurationSettingPageIterator ,
1281+ cancellationToken ) . ConfigureAwait ( false ) ) . ConfigureAwait ( false ) ;
12941282 }
12951283
12961284 if ( haveCollectionsChanged )
0 commit comments