Skip to content

Commit 7eb0d2f

Browse files
use ensure init pattern to make sure root configuration fallback is respected
1 parent 7cb0654 commit 7eb0d2f

File tree

1 file changed

+28
-4
lines changed

1 file changed

+28
-4
lines changed

src/Microsoft.FeatureManagement/ConfigurationFeatureDefinitionProvider.cs

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ public sealed class ConfigurationFeatureDefinitionProvider : IFeatureDefinitionP
2828
private readonly ConcurrentDictionary<string, Task<FeatureDefinition>> _definitions;
2929
private IDisposable _changeSubscription;
3030
private int _stale = 0;
31+
private long _initialized = 0;
32+
private readonly object _lock = new object();
3133
private readonly Func<string, Task<FeatureDefinition>> _getFeatureDefinitionFunc;
3234

3335
const string ParseValueErrorString = "Invalid setting '{0}' with value '{1}' for feature '{2}'.";
@@ -49,10 +51,6 @@ public ConfigurationFeatureDefinitionProvider(IConfiguration configuration)
4951
{
5052
return Task.FromResult(GetMicrosoftSchemaFeatureDefinition(featureName) ?? GetDotnetSchemaFeatureDefinition(featureName));
5153
};
52-
53-
_dotnetFeatureDefinitionSections = GetDotnetFeatureDefinitionSections();
54-
55-
_microsoftFeatureDefinitionSections = GetMicrosoftFeatureDefinitionSections();
5654
}
5755

5856
/// <summary>
@@ -92,6 +90,8 @@ public Task<FeatureDefinition> GetFeatureDefinitionAsync(string featureName)
9290
throw new ArgumentException($"The value '{ConfigurationPath.KeyDelimiter}' is not allowed in the feature name.", nameof(featureName));
9391
}
9492

93+
EnsureInit();
94+
9595
if (Interlocked.Exchange(ref _stale, 0) != 0)
9696
{
9797
_definitions.Clear();
@@ -115,6 +115,8 @@ public Task<FeatureDefinition> GetFeatureDefinitionAsync(string featureName)
115115
public async IAsyncEnumerable<FeatureDefinition> GetAllFeatureDefinitionsAsync()
116116
#pragma warning restore CS1998
117117
{
118+
EnsureInit();
119+
118120
if (Interlocked.Exchange(ref _stale, 0) != 0)
119121
{
120122
_definitions.Clear();
@@ -163,6 +165,28 @@ public async IAsyncEnumerable<FeatureDefinition> GetAllFeatureDefinitionsAsync()
163165
}
164166
}
165167

168+
private void EnsureInit()
169+
{
170+
if (_initialized == 0)
171+
{
172+
IEnumerable<IConfigurationSection> dotnetFeatureDefinitionSections = GetDotnetFeatureDefinitionSections();
173+
174+
IEnumerable<IConfigurationSection> microsoftFeatureDefinitionSections = GetMicrosoftFeatureDefinitionSections();
175+
176+
lock (_lock)
177+
{
178+
if (Interlocked.Read(ref _initialized) == 0)
179+
{
180+
_dotnetFeatureDefinitionSections = dotnetFeatureDefinitionSections;
181+
182+
_microsoftFeatureDefinitionSections = microsoftFeatureDefinitionSections;
183+
184+
Interlocked.Exchange(ref _initialized, 1);
185+
}
186+
}
187+
}
188+
}
189+
166190
private FeatureDefinition GetDotnetSchemaFeatureDefinition(string featureName)
167191
{
168192
IConfigurationSection dotnetFeatureDefinitionConfiguration = _dotnetFeatureDefinitionSections

0 commit comments

Comments
 (0)