Closed duydle closed 6 years ago
After posting this issue, member of my team found this article which answers my question. http://www.thepollyproject.org/2017/06/09/polly-and-synchronous-versus-asynchronous-policies/
Yes, async executions currently require using async variants of the policies.
Closing. Do however open another issue or re-open, if you need further support.
We just recently found that wrapping retry logic around async Dapper query call caused IIS to crashed. I wanted to ask if anyone has come across this before. Below is what I'm doing:
I make my method call with async await var missingListSubmissionLists = await _dataOpsRepository.GetListsWithMissingListSubmissionsAsync(effectiveDate, dataOpsManagedOnly);
Inside the method call, notice this is just a pass-through to DapperExtension.QueryAsyncWithRetry method: public async Task GetListsWithMissingListSubmissionsAsync(DateTime effectiveDate, bool dataOpsManagedOnly = true)
{
var data = new DataOpsListsToResolveOverview()
{
EffectiveDate = effectiveDate
};
Inside QueryAyncWithRetry method which wraps RetryPolicy.RetryForTimeout call public static async Task<IEnumerable> QueryAsyncWithRetry( IDbConnection dbConnection, string sql, CommandType commandType, DynamicParameters paramList, int maxRetries = 3, int commandTimeout = 120)
{
try
{
//Need to verify retry when method is implemented
var result = await (Task<IEnumerable>)RetryPolicy.RetryForTimeout(new Func<
string,
object,
IDbTransaction,
int?,
CommandType?,
Task<IEnumerable>>(dbConnection.QueryAsync),
maxRetries,
sql,
paramList,
null,
commandTimeout,
commandType
);
return result;
}
catch (Exception ex)
{
_logger.Fatal(ex, $"DapperExtenions.QueryAsyncWithRetry failed on {sql}");
throw;
}
}
Inside RetryForTimeout method that wraps my Retry Policy. Note that this is a generic function that executes method.DynamicInvoke based on the delegate method passed in.
private static Logger _logger = LogManager.GetCurrentClassLogger(); private static string timeout = "timeout expired"; private static string deadlock = "deadlock"; public static object RetryForTimeout(Delegate method, int maxRetries = 3, params object[] args) { var policy = Policy .Handle(ex => ExceptionMiner.FullMessageChain(ex).ToLower().Contains(timeout))
.Or(ex => ExceptionMiner.FullMessageChain(ex).ToLower().Contains(deadlock))
.Retry(maxRetries, (ex, retryCount) =>
{
_logger.Error(ex, $"Attempting retry {retryCount} of maxRetry {maxRetries} for timeout/deadlock on method {method.Method.Name}. Parameter List Info: {GetPropertyValues(args)}");
});