diff --git a/src/Microsoft.FeatureManagement/ConfigurationFeatureDefinitionProvider.cs b/src/Microsoft.FeatureManagement/ConfigurationFeatureDefinitionProvider.cs index d8dbd996..44b2bcc3 100644 --- a/src/Microsoft.FeatureManagement/ConfigurationFeatureDefinitionProvider.cs +++ b/src/Microsoft.FeatureManagement/ConfigurationFeatureDefinitionProvider.cs @@ -28,6 +28,7 @@ public sealed class ConfigurationFeatureDefinitionProvider : IFeatureDefinitionP private readonly ConcurrentDictionary> _definitions; private IDisposable _changeSubscription; private int _stale = 0; + private int _initialized = 0; private readonly Func> _getFeatureDefinitionFunc; const string ParseValueErrorString = "Invalid setting '{0}' with value '{1}' for feature '{2}'."; @@ -49,10 +50,6 @@ public ConfigurationFeatureDefinitionProvider(IConfiguration configuration) { return Task.FromResult(GetMicrosoftSchemaFeatureDefinition(featureName) ?? GetDotnetSchemaFeatureDefinition(featureName)); }; - - _dotnetFeatureDefinitionSections = GetDotnetFeatureDefinitionSections(); - - _microsoftFeatureDefinitionSections = GetMicrosoftFeatureDefinitionSections(); } /// @@ -92,13 +89,15 @@ public Task GetFeatureDefinitionAsync(string featureName) throw new ArgumentException($"The value '{ConfigurationPath.KeyDelimiter}' is not allowed in the feature name.", nameof(featureName)); } + EnsureInit(); + if (Interlocked.Exchange(ref _stale, 0) != 0) { - _definitions.Clear(); - _dotnetFeatureDefinitionSections = GetDotnetFeatureDefinitionSections(); _microsoftFeatureDefinitionSections = GetMicrosoftFeatureDefinitionSections(); + + _definitions.Clear(); } return _definitions.GetOrAdd(featureName, _getFeatureDefinitionFunc); @@ -115,13 +114,15 @@ public Task GetFeatureDefinitionAsync(string featureName) public async IAsyncEnumerable GetAllFeatureDefinitionsAsync() #pragma warning restore CS1998 { + EnsureInit(); + if (Interlocked.Exchange(ref _stale, 0) != 0) { - _definitions.Clear(); - _dotnetFeatureDefinitionSections = GetDotnetFeatureDefinitionSections(); _microsoftFeatureDefinitionSections = GetMicrosoftFeatureDefinitionSections(); + + _definitions.Clear(); } foreach (IConfigurationSection featureSection in _microsoftFeatureDefinitionSections) @@ -163,6 +164,18 @@ public async IAsyncEnumerable GetAllFeatureDefinitionsAsync() } } + private void EnsureInit() + { + if (_initialized == 0) + { + _dotnetFeatureDefinitionSections = GetDotnetFeatureDefinitionSections(); + + _microsoftFeatureDefinitionSections = GetMicrosoftFeatureDefinitionSections(); + + _initialized = 1; + } + } + private FeatureDefinition GetDotnetSchemaFeatureDefinition(string featureName) { IConfigurationSection dotnetFeatureDefinitionConfiguration = _dotnetFeatureDefinitionSections diff --git a/tests/Tests.FeatureManagement/FeatureManagementTest.cs b/tests/Tests.FeatureManagement/FeatureManagementTest.cs index b9c3d7c1..5c71a60b 100644 --- a/tests/Tests.FeatureManagement/FeatureManagementTest.cs +++ b/tests/Tests.FeatureManagement/FeatureManagementTest.cs @@ -90,7 +90,7 @@ public async Task ReadsTopLevelConfiguration() IFeatureManager featureManager = serviceProvider.GetRequiredService(); - //Assert.True(await featureManager.IsEnabledAsync("FeatureX")); + Assert.True(await featureManager.IsEnabledAsync("FeatureX")); string json = @" {