Skip to content

Commit b3610b5

Browse files
Bug fix - Respect root configuration fallback (#547)
* use Lazy<T> to ensure lazy initialization * use ensureinit pattern without lock
1 parent 7cb0654 commit b3610b5

File tree

2 files changed

+22
-9
lines changed

2 files changed

+22
-9
lines changed

src/Microsoft.FeatureManagement/ConfigurationFeatureDefinitionProvider.cs

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public sealed class ConfigurationFeatureDefinitionProvider : IFeatureDefinitionP
2828
private readonly ConcurrentDictionary<string, Task<FeatureDefinition>> _definitions;
2929
private IDisposable _changeSubscription;
3030
private int _stale = 0;
31+
private int _initialized = 0;
3132
private readonly Func<string, Task<FeatureDefinition>> _getFeatureDefinitionFunc;
3233

3334
const string ParseValueErrorString = "Invalid setting '{0}' with value '{1}' for feature '{2}'.";
@@ -49,10 +50,6 @@ public ConfigurationFeatureDefinitionProvider(IConfiguration configuration)
4950
{
5051
return Task.FromResult(GetMicrosoftSchemaFeatureDefinition(featureName) ?? GetDotnetSchemaFeatureDefinition(featureName));
5152
};
52-
53-
_dotnetFeatureDefinitionSections = GetDotnetFeatureDefinitionSections();
54-
55-
_microsoftFeatureDefinitionSections = GetMicrosoftFeatureDefinitionSections();
5653
}
5754

5855
/// <summary>
@@ -92,13 +89,15 @@ public Task<FeatureDefinition> GetFeatureDefinitionAsync(string featureName)
9289
throw new ArgumentException($"The value '{ConfigurationPath.KeyDelimiter}' is not allowed in the feature name.", nameof(featureName));
9390
}
9491

92+
EnsureInit();
93+
9594
if (Interlocked.Exchange(ref _stale, 0) != 0)
9695
{
97-
_definitions.Clear();
98-
9996
_dotnetFeatureDefinitionSections = GetDotnetFeatureDefinitionSections();
10097

10198
_microsoftFeatureDefinitionSections = GetMicrosoftFeatureDefinitionSections();
99+
100+
_definitions.Clear();
102101
}
103102

104103
return _definitions.GetOrAdd(featureName, _getFeatureDefinitionFunc);
@@ -115,13 +114,15 @@ public Task<FeatureDefinition> GetFeatureDefinitionAsync(string featureName)
115114
public async IAsyncEnumerable<FeatureDefinition> GetAllFeatureDefinitionsAsync()
116115
#pragma warning restore CS1998
117116
{
117+
EnsureInit();
118+
118119
if (Interlocked.Exchange(ref _stale, 0) != 0)
119120
{
120-
_definitions.Clear();
121-
122121
_dotnetFeatureDefinitionSections = GetDotnetFeatureDefinitionSections();
123122

124123
_microsoftFeatureDefinitionSections = GetMicrosoftFeatureDefinitionSections();
124+
125+
_definitions.Clear();
125126
}
126127

127128
foreach (IConfigurationSection featureSection in _microsoftFeatureDefinitionSections)
@@ -163,6 +164,18 @@ public async IAsyncEnumerable<FeatureDefinition> GetAllFeatureDefinitionsAsync()
163164
}
164165
}
165166

167+
private void EnsureInit()
168+
{
169+
if (_initialized == 0)
170+
{
171+
_dotnetFeatureDefinitionSections = GetDotnetFeatureDefinitionSections();
172+
173+
_microsoftFeatureDefinitionSections = GetMicrosoftFeatureDefinitionSections();
174+
175+
_initialized = 1;
176+
}
177+
}
178+
166179
private FeatureDefinition GetDotnetSchemaFeatureDefinition(string featureName)
167180
{
168181
IConfigurationSection dotnetFeatureDefinitionConfiguration = _dotnetFeatureDefinitionSections

tests/Tests.FeatureManagement/FeatureManagementTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public async Task ReadsTopLevelConfiguration()
9090

9191
IFeatureManager featureManager = serviceProvider.GetRequiredService<IFeatureManager>();
9292

93-
//Assert.True(await featureManager.IsEnabledAsync("FeatureX"));
93+
Assert.True(await featureManager.IsEnabledAsync("FeatureX"));
9494

9595
string json = @"
9696
{

0 commit comments

Comments
 (0)