diff --git a/CHANGELOG.md b/CHANGELOG.md index 20d1ccd..3f426a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.0.7] + +- Added async versions of EvalFeature/GetFeatureValue and a flag on the originals for backwards compatibility. + ## [1.0.6] - Set hash version with rule diff --git a/GrowthBook/GrowthBook.cs b/GrowthBook/GrowthBook.cs index cc794c9..68db10b 100644 --- a/GrowthBook/GrowthBook.cs +++ b/GrowthBook/GrowthBook.cs @@ -166,9 +166,24 @@ public bool IsOff(string key) } /// - public T GetFeatureValue(string key, T fallback) + public T GetFeatureValue(string key, T fallback, bool alwaysLoadFeatures = false) { - var value = EvalFeature(key).Value; + if (alwaysLoadFeatures) + { + LoadFeatures().Wait(); + } + + var result = EvaluateFeature(key); + var value = result.Value; + + return value.IsNull() ? fallback : value.ToObject(); + } + + /// + public async Task GetFeatureValueAsync(string key, T fallback, CancellationToken? cancellationToken = null) + { + var result = await EvalFeatureAsync(key, cancellationToken); + var value = result.Value; return value.IsNull() ? fallback : value.ToObject(); } @@ -187,8 +202,25 @@ public Action Subscribe(Action callback) } /// - public FeatureResult EvalFeature(string featureId) + public FeatureResult EvalFeature(string featureId, bool alwaysLoadFeatures = false) { + if (alwaysLoadFeatures) + { + LoadFeatures().Wait(); + } + + return EvaluateFeature(featureId); + } + + public async Task EvalFeatureAsync(string featureId, CancellationToken? cancellationToken = null) + { + await LoadFeatures(cancellationToken: cancellationToken); + + return EvaluateFeature(featureId); + } + + private FeatureResult EvaluateFeature(string featureId) + { try { if (!Features.TryGetValue(featureId, out Feature feature)) @@ -288,7 +320,7 @@ public ExperimentResult Run(Experiment experiment) return result; } - catch(Exception ex) + catch (Exception ex) { _logger.LogError(ex, $"Encountered an unhandled exception while executing '{nameof(Run)}'"); diff --git a/GrowthBook/GrowthBook.csproj b/GrowthBook/GrowthBook.csproj index 5fee0f3..7768c33 100644 --- a/GrowthBook/GrowthBook.csproj +++ b/GrowthBook/GrowthBook.csproj @@ -11,7 +11,7 @@ https://github.com/growthbook/growthbook-csharp.git git GrowthBook,A/B test,feature toggle,flag - 1.0.6 + 1.0.7 GrowthBook C# SDK https://www.growthbook.io/ README.md diff --git a/GrowthBook/IGrowthBook.cs b/GrowthBook/IGrowthBook.cs index 90ad0f5..c7bda61 100644 --- a/GrowthBook/IGrowthBook.cs +++ b/GrowthBook/IGrowthBook.cs @@ -25,13 +25,28 @@ public interface IGrowthBook : IDisposable bool IsOff(string key); /// - /// Gets the value of a feature cast to the specified type. + /// Gets the value of a feature cast to the specified type. This is a blocking operation and should not be used from a UI thread. /// /// /// The feature key. /// Fallback value to return if the feature is not on. + /// + /// Loads all features from the repository/cache prior to executing. + /// This is included for backwards compatibility and, when set to true, becomes a blocking operation and should not be used from a UI thread. + /// If possible, please use the async version of this method: + /// /// Value of a feature cast to the specified type. - T GetFeatureValue(string key, T fallback); + T GetFeatureValue(string key, T fallback, bool alwaysLoadFeatures = false); + + /// + /// Asynchronously gets the value of a feature cast to the specified type. + /// + /// + /// The feature key. + /// Fallback value to return if the feature is not on. + /// The cancellation token for this operation. + /// Value of a feature cast to the specified type. + Task GetFeatureValueAsync(string key, T fallback, CancellationToken? cancellationToken = null); /// /// Returns a map of the latest results indexed by experiment key. @@ -51,8 +66,21 @@ public interface IGrowthBook : IDisposable /// Evaluates a feature and returns a feature result. /// /// The feature key. + /// + /// Loads all features from the feature repository/cache prior to executing. + /// This is included for backwards compatibility and, when set to true, becomes a blocking operation and should not be used from a UI thread. + /// If possible, please use the async version of this method: + /// + /// The feature result. + FeatureResult EvalFeature(string key, bool alwaysLoadFeatures = false); + + /// + /// Asynchronously loads and evaluates a feature and returns a feature result. + /// + /// The feature ID. + /// The cancellation token for the operation. /// The feature result. - FeatureResult EvalFeature(string key); + Task EvalFeatureAsync(string featureId, CancellationToken? cancellationToken = null); /// /// Evaluates an experiment and returns an experiment result.