diff --git a/DevCycle.SDK.Server.Cloud.Example/DevCycle.SDK.Server.Cloud.Example.csproj b/DevCycle.SDK.Server.Cloud.Example/DevCycle.SDK.Server.Cloud.Example.csproj
index 45a6c36b..b2a13e08 100644
--- a/DevCycle.SDK.Server.Cloud.Example/DevCycle.SDK.Server.Cloud.Example.csproj
+++ b/DevCycle.SDK.Server.Cloud.Example/DevCycle.SDK.Server.Cloud.Example.csproj
@@ -18,7 +18,7 @@
-
+
diff --git a/DevCycle.SDK.Server.Cloud.MSTests/DevCycle.SDK.Server.Cloud.MSTests.csproj b/DevCycle.SDK.Server.Cloud.MSTests/DevCycle.SDK.Server.Cloud.MSTests.csproj
index e263c47e..5d3c03a0 100644
--- a/DevCycle.SDK.Server.Cloud.MSTests/DevCycle.SDK.Server.Cloud.MSTests.csproj
+++ b/DevCycle.SDK.Server.Cloud.MSTests/DevCycle.SDK.Server.Cloud.MSTests.csproj
@@ -18,7 +18,7 @@
-
+
diff --git a/DevCycle.SDK.Server.Cloud/DevCycle.SDK.Server.Cloud.csproj b/DevCycle.SDK.Server.Cloud/DevCycle.SDK.Server.Cloud.csproj
index 6d167d1c..4d2b517b 100644
--- a/DevCycle.SDK.Server.Cloud/DevCycle.SDK.Server.Cloud.csproj
+++ b/DevCycle.SDK.Server.Cloud/DevCycle.SDK.Server.Cloud.csproj
@@ -43,7 +43,7 @@
-
+
diff --git a/DevCycle.SDK.Server.Common/API/DevCycleBaseClient.cs b/DevCycle.SDK.Server.Common/API/DevCycleBaseClient.cs
index 8af1d7be..31cba2a6 100644
--- a/DevCycle.SDK.Server.Common/API/DevCycleBaseClient.cs
+++ b/DevCycle.SDK.Server.Common/API/DevCycleBaseClient.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Net;
+using System.Threading;
using System.Threading.Tasks;
using DevCycle.SDK.Server.Common.Exception;
using DevCycle.SDK.Server.Common.Model;
@@ -22,6 +23,7 @@ public abstract class DevCycleBaseClient : IDevCycleClient
public abstract string Platform();
public abstract IDevCycleApiClient GetApiClient();
public abstract DevCycleProvider GetOpenFeatureProvider();
+ public virtual Task InitializeAsync(CancellationToken cancellationToken = default) => Task.CompletedTask;
public abstract Task> AllFeatures(DevCycleUser user);
public abstract Task>> AllVariables(DevCycleUser user);
public abstract Task> Variable(DevCycleUser user, string key, T defaultValue);
diff --git a/DevCycle.SDK.Server.Common/API/DevCycleProvider.cs b/DevCycle.SDK.Server.Common/API/DevCycleProvider.cs
index 7c70a6a0..3304b90d 100644
--- a/DevCycle.SDK.Server.Common/API/DevCycleProvider.cs
+++ b/DevCycle.SDK.Server.Common/API/DevCycleProvider.cs
@@ -24,6 +24,11 @@ public override Metadata GetMetadata()
return new Metadata(Client.SdkPlatform);
}
+ public override Task InitializeAsync(EvaluationContext context, CancellationToken cancellationToken = default)
+ {
+ return Client.InitializeAsync(cancellationToken);
+ }
+
public override async Task> ResolveBooleanValueAsync(string flagKey, bool defaultValue, EvaluationContext context = null,
CancellationToken cancellationToken = new CancellationToken())
{
diff --git a/DevCycle.SDK.Server.Common/DevCycle.SDK.Server.Common.csproj b/DevCycle.SDK.Server.Common/DevCycle.SDK.Server.Common.csproj
index 4a688d03..02ec9d9d 100644
--- a/DevCycle.SDK.Server.Common/DevCycle.SDK.Server.Common.csproj
+++ b/DevCycle.SDK.Server.Common/DevCycle.SDK.Server.Common.csproj
@@ -15,12 +15,12 @@
-
+
-
+
-
+
diff --git a/DevCycle.SDK.Server.Local.Benchmark/DevCycle.SDK.Server.Local.Benchmark.csproj b/DevCycle.SDK.Server.Local.Benchmark/DevCycle.SDK.Server.Local.Benchmark.csproj
index ec797201..f08a697c 100644
--- a/DevCycle.SDK.Server.Local.Benchmark/DevCycle.SDK.Server.Local.Benchmark.csproj
+++ b/DevCycle.SDK.Server.Local.Benchmark/DevCycle.SDK.Server.Local.Benchmark.csproj
@@ -14,7 +14,7 @@
-
+
diff --git a/DevCycle.SDK.Server.Local.Example/DevCycle.SDK.Server.Local.Example.csproj b/DevCycle.SDK.Server.Local.Example/DevCycle.SDK.Server.Local.Example.csproj
index 41dfd88c..21c83fce 100644
--- a/DevCycle.SDK.Server.Local.Example/DevCycle.SDK.Server.Local.Example.csproj
+++ b/DevCycle.SDK.Server.Local.Example/DevCycle.SDK.Server.Local.Example.csproj
@@ -18,7 +18,7 @@
-
+
diff --git a/DevCycle.SDK.Server.Local.MSTests/DevCycle.SDK.Server.Local.MSTests.csproj b/DevCycle.SDK.Server.Local.MSTests/DevCycle.SDK.Server.Local.MSTests.csproj
index 8495f0ec..6a352e27 100644
--- a/DevCycle.SDK.Server.Local.MSTests/DevCycle.SDK.Server.Local.MSTests.csproj
+++ b/DevCycle.SDK.Server.Local.MSTests/DevCycle.SDK.Server.Local.MSTests.csproj
@@ -19,7 +19,7 @@
-
+
diff --git a/DevCycle.SDK.Server.Local.MSTests/DevCycleTest.cs b/DevCycle.SDK.Server.Local.MSTests/DevCycleTest.cs
index 7d4ba834..a276a473 100644
--- a/DevCycle.SDK.Server.Local.MSTests/DevCycleTest.cs
+++ b/DevCycle.SDK.Server.Local.MSTests/DevCycleTest.cs
@@ -624,5 +624,15 @@ public async Task EvalHooks_MultipleHooksInOptions()
Assert.AreEqual(1, hook2.FinallyCallCount);
Assert.IsNotNull(result);
}
+
+ [TestMethod]
+ public async Task TestOpenFeatureProviderWaitsForClientInit()
+ {
+ using var dvcClient = DevCycleTestClient.getTestClient();
+ await OpenFeature.Api.Instance.SetProviderAsync(dvcClient.GetOpenFeatureProvider());
+ var ctx = EvaluationContext.Builder().Set("user_id", "j_test").Build();
+ var result = await OpenFeature.Api.Instance.GetClient().GetBooleanValueAsync("test", false, ctx);
+ Assert.IsTrue(result);
+ }
}
}
diff --git a/DevCycle.SDK.Server.Local/Api/DevCycleLocalClient.cs b/DevCycle.SDK.Server.Local/Api/DevCycleLocalClient.cs
index 01cf24c0..60c8bb29 100644
--- a/DevCycle.SDK.Server.Local/Api/DevCycleLocalClient.cs
+++ b/DevCycle.SDK.Server.Local/Api/DevCycleLocalClient.cs
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
+using System.Threading;
using System.Threading.Tasks;
using System.Timers;
+using SystemTimer = System.Timers.Timer;
using DevCycle.SDK.Server.Common.API;
using DevCycle.SDK.Server.Common.Model;
using DevCycle.SDK.Server.Common.Model.Local;
@@ -73,8 +75,9 @@ public class DevCycleLocalClient : DevCycleBaseClient
private readonly EventQueue eventQueue;
private readonly ILocalBucketing localBucketing;
private readonly ILogger logger;
- private readonly Timer timer;
+ private readonly SystemTimer timer;
private bool closing;
+ private readonly Task initializeTask;
private DevCycleProvider OpenFeatureProvider { get; }
private readonly EvalHooksRunner evalHooksRunner;
@@ -103,11 +106,11 @@ internal DevCycleLocalClient(
logger.LogWarning("The config CDN slug is being overriden, please ensure to update the config to v2 according to the config CDN updates documentation.");
}
- timer = new Timer(dvcLocalOptions.EventFlushIntervalMs);
+ timer = new SystemTimer(dvcLocalOptions.EventFlushIntervalMs);
timer.Elapsed += OnTimedEvent;
timer.AutoReset = true;
timer.Enabled = true;
- Task.Run(async delegate { await this.configManager.InitializeConfigAsync(); });
+ initializeTask = this.configManager.InitializeConfigAsync();
OpenFeatureProvider = new DevCycleProvider(this);
}
@@ -259,6 +262,23 @@ public override DevCycleProvider GetOpenFeatureProvider()
return OpenFeatureProvider;
}
+ public override async Task InitializeAsync(CancellationToken cancellationToken = default)
+ {
+ if (cancellationToken.CanBeCanceled)
+ {
+ var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
+ using (cancellationToken.Register(() => tcs.TrySetResult(true)))
+ {
+ var completed = await Task.WhenAny(initializeTask, tcs.Task).ConfigureAwait(false);
+ if (completed != initializeTask)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ }
+ }
+ }
+ await initializeTask.ConfigureAwait(false);
+ }
+
public override Task> AllFeatures(DevCycleUser user)
{
if (!configManager.Initialized)
diff --git a/DevCycle.SDK.Server.Local/DevCycle.SDK.Server.Local.csproj b/DevCycle.SDK.Server.Local/DevCycle.SDK.Server.Local.csproj
index 120e8e10..2d10b015 100644
--- a/DevCycle.SDK.Server.Local/DevCycle.SDK.Server.Local.csproj
+++ b/DevCycle.SDK.Server.Local/DevCycle.SDK.Server.Local.csproj
@@ -50,13 +50,13 @@
all
-
-
+
+
-
-
+
+