Skip to content

Commit

Permalink
Update OpenFeatureClient.cs
Browse files Browse the repository at this point in the history
bugfix(feature-client): Added configure await to avoid deadlocks when executing synchronously

Signed-off-by: DouglasHammon-FV <132104255+DouglasHammon-FV@users.noreply.github.com>
  • Loading branch information
DouglasHammon-FV committed Sep 19, 2023
1 parent 3da02e6 commit e261d9b
Showing 1 changed file with 20 additions and 20 deletions.
40 changes: 20 additions & 20 deletions src/OpenFeature/OpenFeatureClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,63 +107,63 @@ public FeatureClient(string name, string version, ILogger logger = null, Evaluat
/// <inheritdoc />
public async Task<bool> GetBooleanValue(string flagKey, bool defaultValue, EvaluationContext context = null,
FlagEvaluationOptions config = null) =>
(await this.GetBooleanDetails(flagKey, defaultValue, context, config)).Value;
(await this.GetBooleanDetails(flagKey, defaultValue, context, config).ConfigureAwait(false)).Value;

/// <inheritdoc />
public async Task<FlagEvaluationDetails<bool>> GetBooleanDetails(string flagKey, bool defaultValue,
EvaluationContext context = null, FlagEvaluationOptions config = null) =>
await this.EvaluateFlag(this.ExtractProvider<bool>(provider => provider.ResolveBooleanValue),
FlagValueType.Boolean, flagKey,
defaultValue, context, config);
defaultValue, context, config).ConfigureAwait(false);

/// <inheritdoc />
public async Task<string> GetStringValue(string flagKey, string defaultValue, EvaluationContext context = null,
FlagEvaluationOptions config = null) =>
(await this.GetStringDetails(flagKey, defaultValue, context, config)).Value;
(await this.GetStringDetails(flagKey, defaultValue, context, config).ConfigureAwait(false)).Value;

/// <inheritdoc />
public async Task<FlagEvaluationDetails<string>> GetStringDetails(string flagKey, string defaultValue,
EvaluationContext context = null, FlagEvaluationOptions config = null) =>
await this.EvaluateFlag(this.ExtractProvider<string>(provider => provider.ResolveStringValue),
FlagValueType.String, flagKey,
defaultValue, context, config);
defaultValue, context, config).ConfigureAwait(false);

/// <inheritdoc />
public async Task<int> GetIntegerValue(string flagKey, int defaultValue, EvaluationContext context = null,
FlagEvaluationOptions config = null) =>
(await this.GetIntegerDetails(flagKey, defaultValue, context, config)).Value;
(await this.GetIntegerDetails(flagKey, defaultValue, context, config).ConfigureAwait(false)).Value;

/// <inheritdoc />
public async Task<FlagEvaluationDetails<int>> GetIntegerDetails(string flagKey, int defaultValue,
EvaluationContext context = null, FlagEvaluationOptions config = null) =>
await this.EvaluateFlag(this.ExtractProvider<int>(provider => provider.ResolveIntegerValue),
FlagValueType.Number, flagKey,
defaultValue, context, config);
defaultValue, context, config).ConfigureAwait(false);

/// <inheritdoc />
public async Task<double> GetDoubleValue(string flagKey, double defaultValue,
EvaluationContext context = null,
FlagEvaluationOptions config = null) =>
(await this.GetDoubleDetails(flagKey, defaultValue, context, config)).Value;
(await this.GetDoubleDetails(flagKey, defaultValue, context, config).ConfigureAwait(false)).Value;

/// <inheritdoc />
public async Task<FlagEvaluationDetails<double>> GetDoubleDetails(string flagKey, double defaultValue,
EvaluationContext context = null, FlagEvaluationOptions config = null) =>
await this.EvaluateFlag(this.ExtractProvider<double>(provider => provider.ResolveDoubleValue),
FlagValueType.Number, flagKey,
defaultValue, context, config);
defaultValue, context, config).ConfigureAwait(false);

/// <inheritdoc />
public async Task<Value> GetObjectValue(string flagKey, Value defaultValue, EvaluationContext context = null,
FlagEvaluationOptions config = null) =>
(await this.GetObjectDetails(flagKey, defaultValue, context, config)).Value;
(await this.GetObjectDetails(flagKey, defaultValue, context, config).ConfigureAwait(false)).Value;

/// <inheritdoc />
public async Task<FlagEvaluationDetails<Value>> GetObjectDetails(string flagKey, Value defaultValue,
EvaluationContext context = null, FlagEvaluationOptions config = null) =>
await this.EvaluateFlag(this.ExtractProvider<Value>(provider => provider.ResolveStructureValue),
FlagValueType.Object, flagKey,
defaultValue, context, config);
defaultValue, context, config).ConfigureAwait(false);

private async Task<FlagEvaluationDetails<T>> EvaluateFlag<T>(
(Func<string, T, EvaluationContext, Task<ResolutionDetails<T>>>, FeatureProvider) providerInfo,
Expand Down Expand Up @@ -211,32 +211,32 @@ private async Task<FlagEvaluationDetails<T>> EvaluateFlag<T>(
FlagEvaluationDetails<T> evaluation;
try
{
var contextFromHooks = await this.TriggerBeforeHooks(allHooks, hookContext, options);
var contextFromHooks = await this.TriggerBeforeHooks(allHooks, hookContext, options).ConfigureAwait(false);

evaluation =
(await resolveValueDelegate.Invoke(flagKey, defaultValue, contextFromHooks.EvaluationContext))
(await resolveValueDelegate.Invoke(flagKey, defaultValue, contextFromHooks.EvaluationContext).ConfigureAwait(false))
.ToFlagEvaluationDetails();

await this.TriggerAfterHooks(allHooksReversed, hookContext, evaluation, options);
await this.TriggerAfterHooks(allHooksReversed, hookContext, evaluation, options).ConfigureAwait(false);
}
catch (FeatureProviderException ex)
{
this._logger.LogError(ex, "Error while evaluating flag {FlagKey}. Error {ErrorType}", flagKey,
ex.ErrorType.GetDescription());
evaluation = new FlagEvaluationDetails<T>(flagKey, defaultValue, ex.ErrorType, Reason.Error,
string.Empty, ex.Message);
await this.TriggerErrorHooks(allHooksReversed, hookContext, ex, options);
await this.TriggerErrorHooks(allHooksReversed, hookContext, ex, options).ConfigureAwait(false);
}
catch (Exception ex)
{
this._logger.LogError(ex, "Error while evaluating flag {FlagKey}", flagKey);
var errorCode = ex is InvalidCastException ? ErrorType.TypeMismatch : ErrorType.General;
evaluation = new FlagEvaluationDetails<T>(flagKey, defaultValue, errorCode, Reason.Error, string.Empty);
await this.TriggerErrorHooks(allHooksReversed, hookContext, ex, options);
await this.TriggerErrorHooks(allHooksReversed, hookContext, ex, options).ConfigureAwait(false);
}
finally
{
await this.TriggerFinallyHooks(allHooksReversed, hookContext, options);
await this.TriggerFinallyHooks(allHooksReversed, hookContext, options).ConfigureAwait(false);
}

return evaluation;
Expand All @@ -250,7 +250,7 @@ private async Task<HookContext<T>> TriggerBeforeHooks<T>(IReadOnlyList<Hook> hoo

foreach (var hook in hooks)
{
var resp = await hook.Before(context, options?.HookHints);
var resp = await hook.Before(context, options?.HookHints).ConfigureAwait(false);
if (resp != null)
{
evalContextBuilder.Merge(resp);
Expand All @@ -271,7 +271,7 @@ private async Task TriggerAfterHooks<T>(IReadOnlyList<Hook> hooks, HookContext<T
{
foreach (var hook in hooks)
{
await hook.After(context, evaluationDetails, options?.HookHints);
await hook.After(context, evaluationDetails, options?.HookHints).ConfigureAwait(false);
}
}

Expand All @@ -282,7 +282,7 @@ private async Task TriggerErrorHooks<T>(IReadOnlyList<Hook> hooks, HookContext<T
{
try
{
await hook.Error(context, exception, options?.HookHints);
await hook.Error(context, exception, options?.HookHints).ConfigureAwait(false);
}
catch (Exception e)
{
Expand All @@ -298,7 +298,7 @@ private async Task TriggerFinallyHooks<T>(IReadOnlyList<Hook> hooks, HookContext
{
try
{
await hook.Finally(context, options?.HookHints);
await hook.Finally(context, options?.HookHints).ConfigureAwait(false);
}
catch (Exception e)
{
Expand Down

0 comments on commit e261d9b

Please sign in to comment.