2
2
using System . Collections . Generic ;
3
3
using System . Linq ;
4
4
using System . Threading ;
5
+ using System . Threading . Tasks ;
5
6
using Microsoft . Extensions . Logging ;
6
7
using OpenFeature . Model ;
7
8
@@ -15,14 +16,12 @@ namespace OpenFeature
15
16
public sealed class Api
16
17
{
17
18
private EvaluationContext _evaluationContext = EvaluationContext . Empty ;
18
- private FeatureProvider _defaultProvider = new NoOpFeatureProvider ( ) ;
19
- private readonly ConcurrentDictionary < string , FeatureProvider > _featureProviders =
20
- new ConcurrentDictionary < string , FeatureProvider > ( ) ;
19
+ private readonly ProviderRepository _repository = new ProviderRepository ( ) ;
21
20
private readonly ConcurrentStack < Hook > _hooks = new ConcurrentStack < Hook > ( ) ;
22
21
23
22
/// The reader/writer locks are not disposed because the singleton instance should never be disposed.
24
23
private readonly ReaderWriterLockSlim _evaluationContextLock = new ReaderWriterLockSlim ( ) ;
25
- private readonly ReaderWriterLockSlim _featureProviderLock = new ReaderWriterLockSlim ( ) ;
24
+
26
25
27
26
/// <summary>
28
27
/// Singleton instance of Api
@@ -36,31 +35,26 @@ static Api() { }
36
35
private Api ( ) { }
37
36
38
37
/// <summary>
39
- /// Sets the feature provider
38
+ /// Sets the feature provider. In order to wait for the provider to be set, and initialization to complete,
39
+ /// await the returned task.
40
40
/// </summary>
41
+ /// <remarks>The provider cannot be set to null. Attempting to set the provider to null has no effect.</remarks>
41
42
/// <param name="featureProvider">Implementation of <see cref="FeatureProvider"/></param>
42
- public void SetProvider ( FeatureProvider featureProvider )
43
+ public async Task SetProvider ( FeatureProvider featureProvider )
43
44
{
44
- this . _featureProviderLock . EnterWriteLock ( ) ;
45
- try
46
- {
47
- this . _defaultProvider = featureProvider ?? this . _defaultProvider ;
48
- }
49
- finally
50
- {
51
- this . _featureProviderLock . ExitWriteLock ( ) ;
52
- }
45
+ await this . _repository . SetProvider ( featureProvider , this . GetContext ( ) ) . ConfigureAwait ( false ) ;
53
46
}
54
47
48
+
55
49
/// <summary>
56
- /// Sets the feature provider to given clientName
50
+ /// Sets the feature provider to given clientName. In order to wait for the provider to be set, and
51
+ /// initialization to complete, await the returned task.
57
52
/// </summary>
58
53
/// <param name="clientName">Name of client</param>
59
54
/// <param name="featureProvider">Implementation of <see cref="FeatureProvider"/></param>
60
- public void SetProvider ( string clientName , FeatureProvider featureProvider )
55
+ public async Task SetProvider ( string clientName , FeatureProvider featureProvider )
61
56
{
62
- this . _featureProviders . AddOrUpdate ( clientName , featureProvider ,
63
- ( key , current ) => featureProvider ) ;
57
+ await this . _repository . SetProvider ( clientName , featureProvider , this . GetContext ( ) ) . ConfigureAwait ( false ) ;
64
58
}
65
59
66
60
/// <summary>
@@ -76,15 +70,7 @@ public void SetProvider(string clientName, FeatureProvider featureProvider)
76
70
/// <returns><see cref="FeatureProvider"/></returns>
77
71
public FeatureProvider GetProvider ( )
78
72
{
79
- this . _featureProviderLock . EnterReadLock ( ) ;
80
- try
81
- {
82
- return this . _defaultProvider ;
83
- }
84
- finally
85
- {
86
- this . _featureProviderLock . ExitReadLock ( ) ;
87
- }
73
+ return this . _repository . GetProvider ( ) ;
88
74
}
89
75
90
76
/// <summary>
@@ -95,17 +81,9 @@ public FeatureProvider GetProvider()
95
81
/// have a corresponding provider the default provider will be returned</returns>
96
82
public FeatureProvider GetProvider ( string clientName )
97
83
{
98
- if ( string . IsNullOrEmpty ( clientName ) )
99
- {
100
- return this . GetProvider ( ) ;
101
- }
102
-
103
- return this . _featureProviders . TryGetValue ( clientName , out var featureProvider )
104
- ? featureProvider
105
- : this . GetProvider ( ) ;
84
+ return this . _repository . GetProvider ( clientName ) ;
106
85
}
107
86
108
-
109
87
/// <summary>
110
88
/// Gets providers metadata
111
89
/// <para>
@@ -210,5 +188,19 @@ public EvaluationContext GetContext()
210
188
this . _evaluationContextLock . ExitReadLock ( ) ;
211
189
}
212
190
}
191
+
192
+ /// <summary>
193
+ /// <para>
194
+ /// Shut down and reset the current status of OpenFeature API.
195
+ /// </para>
196
+ /// <para>
197
+ /// This call cleans up all active providers and attempts to shut down internal event handling mechanisms.
198
+ /// Once shut down is complete, API is reset and ready to use again.
199
+ /// </para>
200
+ /// </summary>
201
+ public async Task Shutdown ( )
202
+ {
203
+ await this . _repository . Shutdown ( ) . ConfigureAwait ( false ) ;
204
+ }
213
205
}
214
206
}
0 commit comments