Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
Alternative to dotnet#20494
  • Loading branch information
roji committed Feb 22, 2021
1 parent 838e95e commit 72173ff
Showing 1 changed file with 122 additions and 1 deletion.
123 changes: 122 additions & 1 deletion src/EFCore/Storage/ExecutionStrategy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,128 @@ public virtual TResult Execute<TState, TResult>(

OnFirstExecution();

return ExecuteImplementation(operation, verifySucceeded, state);
while (true)
{
TimeSpan? delay;
try
{
Suspended = true;
var result = operation(Dependencies.CurrentContext.Context, state);
Suspended = false;
return result;
}
catch (Exception ex)
{
Suspended = false;
if (verifySucceeded != null
&& CallOnWrappedException(ex, ShouldVerifySuccessOn))
{
var result = ExecuteImplementation(verifySucceeded, null, state);
if (result.IsSuccessful)
{
return result.Result;
}
}

if (!CallOnWrappedException(ex, ShouldRetryOn))
{
throw;
}

ExceptionsEncountered.Add(ex);

delay = GetNextDelay(ex);
if (delay == null)
{
throw new RetryLimitExceededException(CoreStrings.RetryLimitExceeded(MaxRetryCount, GetType().Name), ex);
}

Dependencies.Logger.ExecutionStrategyRetrying(ExceptionsEncountered, delay.Value, async: true);

OnRetry();
}

using var waitEvent = new ManualResetEventSlim(false);
waitEvent.WaitHandle.WaitOne(delay.Value);
}
}

private TResult Foo<TState, TResult>(
Func<DbContext, TState, TResult> operation,
Func<DbContext, TState, ExecutionResult<TResult>> verifySucceeded,
TState state)
{
while (true)
{
try
{
Suspended = true;
var result = operation(Dependencies.CurrentContext.Context, state);
Suspended = false;
return result;
}
catch (Exception ex)
{
Suspended = false;
if (verifySucceeded != null
&& CallOnWrappedException(ex, ShouldVerifySuccessOn))
{
while (true)
{
try
{
Suspended = true;
var verifySucceededResult = verifySucceeded(Dependencies.CurrentContext.Context, state);
Suspended = false;
if (verifySucceededResult.IsSuccessful)
{
return verifySucceededResult.Result;
}
}
catch (Exception ex2)
{
Suspended = false;

if (!CallOnWrappedException(ex2, ShouldRetryOn))
{
throw;
}

PrepareRetry(ex2);
continue;
}

break;
}
}

if (!CallOnWrappedException(ex, ShouldRetryOn))
{
throw;
}

PrepareRetry(ex);
}
}

void PrepareRetry(Exception ex)
{
ExceptionsEncountered.Add(ex);

var delay = GetNextDelay(ex);
if (delay == null)
{
throw new RetryLimitExceededException(
CoreStrings.RetryLimitExceeded(MaxRetryCount, GetType().Name), ex);
}

Dependencies.Logger.ExecutionStrategyRetrying(ExceptionsEncountered, delay.Value, async: true);

OnRetry();

using var waitEvent = new ManualResetEventSlim(false);
waitEvent.WaitHandle.WaitOne(delay.Value);
}
}

private TResult ExecuteImplementation<TState, TResult>(
Expand Down

0 comments on commit 72173ff

Please sign in to comment.