Skip to content

Commit 9135d42

Browse files
committed
PR comments
1 parent 1928357 commit 9135d42

File tree

9 files changed

+106
-112
lines changed

9 files changed

+106
-112
lines changed

src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationOptions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ internal IEnumerable<IKeyValueAdapter> Adapters
114114
/// <summary>
115115
/// For use in tests only. An optional class used to process pageable results from Azure App Configuration.
116116
/// </summary>
117-
internal IPageableConfigurationSettings PageableConfigurationSettings { get; set; }
117+
internal IConfigurationSettingPageIterator ConfigurationSettingPageIterator { get; set; }
118118

119119
/// <summary>
120120
/// An optional timespan value to set the minimum backoff duration to a value other than the default.

src/Microsoft.Extensions.Configuration.AzureAppConfiguration/AzureAppConfigurationProvider.cs

Lines changed: 45 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -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)
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using Azure.Data.AppConfiguration;
2+
using Azure;
3+
using System.Collections.Generic;
4+
5+
namespace Microsoft.Extensions.Configuration.AzureAppConfiguration
6+
{
7+
static class ConfigurationSettingPageExtensions
8+
{
9+
public static IAsyncEnumerable<Page<ConfigurationSetting>> AsPages(this AsyncPageable<ConfigurationSetting> pageable, IConfigurationSettingPageIterator pageIterator)
10+
{
11+
//
12+
// Allow custom iteration
13+
if (pageIterator != null)
14+
{
15+
return pageIterator.IteratePages(pageable);
16+
}
17+
18+
return pageable.AsPages();
19+
}
20+
21+
public static IAsyncEnumerable<Page<ConfigurationSetting>> AsPages(this AsyncPageable<ConfigurationSetting> pageable, IConfigurationSettingPageIterator pageIterator, IEnumerable<MatchConditions> matchConditions)
22+
{
23+
//
24+
// Allow custom iteration
25+
if (pageIterator != null)
26+
{
27+
return pageIterator.IteratePages(pageable, matchConditions);
28+
}
29+
30+
return pageable.AsPages(matchConditions);
31+
}
32+
}
33+
}

src/Microsoft.Extensions.Configuration.AzureAppConfiguration/Extensions/ConfigurationClientExtensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public static async Task<KeyValueChange> GetKeyValueChange(this ConfigurationCli
6363
};
6464
}
6565

66-
public static async Task<bool> HaveCollectionsChanged(this ConfigurationClient client, KeyValueSelector keyValueSelector, IEnumerable<MatchConditions> matchConditions, IPageableConfigurationSettings pageableConfigurationSettings, CancellationToken cancellationToken)
66+
public static async Task<bool> HaveCollectionsChanged(this ConfigurationClient client, KeyValueSelector keyValueSelector, IEnumerable<MatchConditions> matchConditions, IConfigurationSettingPageIterator pageIterator, CancellationToken cancellationToken)
6767
{
6868
if (matchConditions == null)
6969
{
@@ -90,7 +90,7 @@ public static async Task<bool> HaveCollectionsChanged(this ConfigurationClient c
9090

9191
using IEnumerator<MatchConditions> existingMatchConditionsEnumerator = matchConditions.GetEnumerator();
9292

93-
await foreach (Page<ConfigurationSetting> page in pageable.AsPages(pageableConfigurationSettings, matchConditions).ConfigureAwait(false))
93+
await foreach (Page<ConfigurationSetting> page in pageable.AsPages(pageIterator, matchConditions).ConfigureAwait(false))
9494
{
9595
using Response response = page.GetRawResponse();
9696

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using Azure.Data.AppConfiguration;
2+
using Azure;
3+
using System.Collections.Generic;
4+
5+
namespace Microsoft.Extensions.Configuration.AzureAppConfiguration
6+
{
7+
internal interface IConfigurationSettingPageIterator
8+
{
9+
IAsyncEnumerable<Page<ConfigurationSetting>> IteratePages(AsyncPageable<ConfigurationSetting> pageable);
10+
11+
IAsyncEnumerable<Page<ConfigurationSetting>> IteratePages(AsyncPageable<ConfigurationSetting> pageable, IEnumerable<MatchConditions> matchConditions);
12+
}
13+
}

src/Microsoft.Extensions.Configuration.AzureAppConfiguration/IPageableConfigurationSettings.cs

Lines changed: 0 additions & 40 deletions
This file was deleted.

0 commit comments

Comments
 (0)