diff --git a/build/Common.props b/build/Common.props
index 65bf984d..11392376 100644
--- a/build/Common.props
+++ b/build/Common.props
@@ -19,6 +19,7 @@
Please sort alphabetically.
Refer to https://docs.microsoft.com/nuget/concepts/package-versioning for semver syntax.
-->
+ [8.0.0,)
[2.0,)
[1.0.0,2.0)
diff --git a/src/OpenFeature/Api.cs b/src/OpenFeature/Api.cs
index 440242da..e2690a7a 100644
--- a/src/OpenFeature/Api.cs
+++ b/src/OpenFeature/Api.cs
@@ -17,15 +17,13 @@ namespace OpenFeature
public sealed class Api : IEventBus
{
private EvaluationContext _evaluationContext = EvaluationContext.Empty;
- private readonly ProviderRepository _repository = new ProviderRepository();
+ private EventExecutor _eventExecutor = new EventExecutor();
+ private ProviderRepository _repository = new ProviderRepository();
private readonly ConcurrentStack _hooks = new ConcurrentStack();
/// The reader/writer locks are not disposed because the singleton instance should never be disposed.
private readonly ReaderWriterLockSlim _evaluationContextLock = new ReaderWriterLockSlim();
- internal readonly EventExecutor EventExecutor = new EventExecutor();
-
-
///
/// Singleton instance of Api
///
@@ -45,7 +43,7 @@ private Api() { }
/// Implementation of
public async Task SetProvider(FeatureProvider featureProvider)
{
- this.EventExecutor.RegisterDefaultFeatureProvider(featureProvider);
+ this._eventExecutor.RegisterDefaultFeatureProvider(featureProvider);
await this._repository.SetProvider(featureProvider, this.GetContext()).ConfigureAwait(false);
}
@@ -58,7 +56,7 @@ public async Task SetProvider(FeatureProvider featureProvider)
/// Implementation of
public async Task SetProvider(string clientName, FeatureProvider featureProvider)
{
- this.EventExecutor.RegisterClientFeatureProvider(clientName, featureProvider);
+ this._eventExecutor.RegisterClientFeatureProvider(clientName, featureProvider);
await this._repository.SetProvider(clientName, featureProvider, this.GetContext()).ConfigureAwait(false);
}
@@ -224,20 +222,28 @@ public EvaluationContext GetContext()
///
public async Task Shutdown()
{
- await this._repository.Shutdown().ConfigureAwait(false);
- await this.EventExecutor.Shutdown().ConfigureAwait(false);
+ await using (this._eventExecutor.ConfigureAwait(false))
+ await using (this._repository.ConfigureAwait(false))
+ {
+ this._evaluationContext = EvaluationContext.Empty;
+ this._hooks.Clear();
+
+ // TODO: make these lazy to avoid extra allocations on the common cleanup path?
+ this._eventExecutor = new EventExecutor();
+ this._repository = new ProviderRepository();
+ }
}
///
public void AddHandler(ProviderEventTypes type, EventHandlerDelegate handler)
{
- this.EventExecutor.AddApiLevelHandler(type, handler);
+ this._eventExecutor.AddApiLevelHandler(type, handler);
}
///
public void RemoveHandler(ProviderEventTypes type, EventHandlerDelegate handler)
{
- this.EventExecutor.RemoveApiLevelHandler(type, handler);
+ this._eventExecutor.RemoveApiLevelHandler(type, handler);
}
///
@@ -246,7 +252,13 @@ public void RemoveHandler(ProviderEventTypes type, EventHandlerDelegate handler)
/// The logger to be used
public void SetLogger(ILogger logger)
{
- this.EventExecutor.Logger = logger;
+ this._eventExecutor.Logger = logger;
}
+
+ internal void AddClientHandler(string client, ProviderEventTypes eventType, EventHandlerDelegate handler)
+ => this._eventExecutor.AddClientHandler(client, eventType, handler);
+
+ internal void RemoveClientHandler(string client, ProviderEventTypes eventType, EventHandlerDelegate handler)
+ => this._eventExecutor.RemoveClientHandler(client, eventType, handler);
}
}
diff --git a/src/OpenFeature/EventExecutor.cs b/src/OpenFeature/EventExecutor.cs
index 8a6df9a4..7bdfeb6e 100644
--- a/src/OpenFeature/EventExecutor.cs
+++ b/src/OpenFeature/EventExecutor.cs
@@ -10,19 +10,13 @@
namespace OpenFeature
{
-
- internal delegate Task ShutdownDelegate();
-
- internal class EventExecutor
+ internal class EventExecutor : IAsyncDisposable
{
private readonly object _lockObj = new object();
public readonly Channel