diff --git a/src/OpenFeature/Api.cs b/src/OpenFeature/Api.cs
index 33a7c79d..3532e99e 100644
--- a/src/OpenFeature/Api.cs
+++ b/src/OpenFeature/Api.cs
@@ -40,12 +40,39 @@ internal Api() { }
///
/// The provider cannot be set to null. Attempting to set the provider to null has no effect. May throw an exception if cannot be initialized.
/// Implementation of
- public async Task SetProviderAsync(FeatureProvider featureProvider)
+ /// A that completes once Provider initialization is complete.
+ public Task SetProviderAsync(FeatureProvider featureProvider)
+ {
+ return this.SetProviderAsync(featureProvider, CancellationToken.None);
+ }
+
+ ///
+ /// Sets the default feature provider. In order to wait for the provider to be set, and initialization to complete,
+ /// await the returned task.
+ ///
+ /// The provider cannot be set to null. Attempting to set the provider to null has no effect. May throw an exception if cannot be initialized.
+ /// Implementation of
+ /// Propagates notification that the provider initialization should be canceled.
+ /// A that completes once Provider initialization is complete.
+ public async Task SetProviderAsync(FeatureProvider featureProvider, CancellationToken cancellationToken)
{
this._eventExecutor.RegisterDefaultFeatureProvider(featureProvider);
- await this._repository.SetProviderAsync(featureProvider, this.GetContext(), this.AfterInitializationAsync, this.AfterErrorAsync)
+ await this._repository.SetProviderAsync(featureProvider, this.GetContext(), this.AfterInitializationAsync, this.AfterErrorAsync, cancellationToken)
.ConfigureAwait(false);
+ }
+ ///
+ /// Binds the feature provider to the given domain. In order to wait for the provider to be set, and
+ /// initialization to complete, await the returned task.
+ ///
+ /// The provider cannot be set to null. Attempting to set the provider to null has no effect. May throw an exception if cannot be initialized.
+ /// An identifier which logically binds clients with providers
+ /// Implementation of
+ /// domain cannot be null or empty
+ /// A that completes once Provider initialization is complete.
+ public Task SetProviderAsync(string domain, FeatureProvider featureProvider)
+ {
+ return this.SetProviderAsync(domain, featureProvider, CancellationToken.None);
}
///
@@ -55,15 +82,17 @@ await this._repository.SetProviderAsync(featureProvider, this.GetContext(), this
/// The provider cannot be set to null. Attempting to set the provider to null has no effect. May throw an exception if cannot be initialized.
/// An identifier which logically binds clients with providers
/// Implementation of
+ /// Propagates notification that the provider initialization should be canceled.
/// domain cannot be null or empty
- public async Task SetProviderAsync(string domain, FeatureProvider featureProvider)
+ /// A that completes once Provider initialization is complete.
+ public async Task SetProviderAsync(string domain, FeatureProvider featureProvider, CancellationToken cancellationToken)
{
if (string.IsNullOrWhiteSpace(domain))
{
throw new ArgumentNullException(nameof(domain));
}
this._eventExecutor.RegisterClientFeatureProvider(domain, featureProvider);
- await this._repository.SetProviderAsync(domain, featureProvider, this.GetContext(), this.AfterInitializationAsync, this.AfterErrorAsync)
+ await this._repository.SetProviderAsync(domain, featureProvider, this.GetContext(), this.AfterInitializationAsync, this.AfterErrorAsync, cancellationToken)
.ConfigureAwait(false);
}
diff --git a/test/OpenFeature.Tests/OpenFeatureTests.cs b/test/OpenFeature.Tests/OpenFeatureTests.cs
index 9eb0aa40..835406ef 100644
--- a/test/OpenFeature.Tests/OpenFeatureTests.cs
+++ b/test/OpenFeature.Tests/OpenFeatureTests.cs
@@ -34,6 +34,43 @@ public async Task OpenFeature_Should_Initialize_Provider()
await providerMockNamed.Received(1).InitializeAsync(Api.Instance.GetContext());
}
+ [Fact]
+ public async Task OpenFeature_Should_Initialize_Provider_WithCancellationToken()
+ {
+ var providerMockDefault = Substitute.For();
+ providerMockDefault.Status.Returns(ProviderStatus.NotReady);
+
+ using var cancellationTokenSource = new CancellationTokenSource();
+ var cancellationToken = cancellationTokenSource.Token;
+
+ await Api.Instance.SetProviderAsync(providerMockDefault, cancellationToken);
+ await providerMockDefault.Received(1).InitializeAsync(Api.Instance.GetContext(), cancellationToken);
+
+ var providerMockNamed = Substitute.For();
+ providerMockNamed.Status.Returns(ProviderStatus.NotReady);
+
+ await Api.Instance.SetProviderAsync("the-name", providerMockNamed, cancellationToken);
+ await providerMockNamed.Received(1).InitializeAsync(Api.Instance.GetContext(), cancellationToken);
+ }
+
+ [Fact]
+ public async Task OpenFeature_Should_Handle_Cancellation_During_Initialization()
+ {
+ using var cancellationTokenSource = new CancellationTokenSource();
+ cancellationTokenSource.Cancel();
+ var cancellationToken = cancellationTokenSource.Token;
+
+ var providerMockDefault = Substitute.For();
+ providerMockDefault.InitializeAsync(Arg.Any(), cancellationToken)
+ .Returns(ci => Task.FromCanceled(cancellationToken));
+
+ await Assert.ThrowsAsync(() =>
+ Api.Instance.SetProviderAsync(providerMockDefault, cancellationToken));
+
+ await providerMockDefault.Received(1).InitializeAsync(Api.Instance.GetContext(), cancellationToken);
+ Assert.Equal(ProviderStatus.Error, providerMockDefault.Status);
+ }
+
[Fact]
[Specification("1.1.2.3",
"The provider mutator function MUST invoke the shutdown function on the previously registered provider once it's no longer being used to resolve flag values.")]