/// <summary>
/// Runs the given function, and retries it on a new connection when I/O or node errors occur
/// </summary>
/// <param name="executeFunc">The function to execute.</param>
/// <param name="state">The state.</param>
/// <param name="logger">The logger.</param>
/// <returns></returns>
/// <exception cref="CqlException">Failed to return query result after max amount of attempts</exception>
private async Task <ResultFrame> RunWithRetry(
Func <Connection, QueryExecutionState, Logger, Task <ResultFrame> > executeFunc, QueryExecutionState state, Logger logger)
{
int attempts = _connection.Config.MaxQueryRetries;
//keep trying until faulted
for (int attempt = 0; attempt < attempts; attempt++)
{
//get me a connection
Connection connection;
using (logger.ThreadBinding())
connection = _connection.GetConnection(state.PartitionKey);
//execute
try
{
return(await executeFunc(connection, state, logger).ConfigureAwait(false));
}
catch (ProtocolException pex)
{
if (attempt == attempts - 1)
{
logger.LogError("Query failed after {0} attempts with error {1}", attempts, pex);
throw;
}
switch (pex.Code)
{
case ErrorCode.IsBootstrapping:
case ErrorCode.Overloaded:
//IO or node status related error, go for rerun
logger.LogWarning("Query to {0} failed because server returned {1}, going for retry", connection, pex.Code.ToString());
continue;
default:
logger.LogWarning("Query failed with {0} error: {1}", pex.Code.ToString(), pex.Message);
//some other Cql error (syntax ok?), quit
throw;
}
}
catch (Exception ex)
{
if (attempt == attempts - 1)
{
//out of attempts
logger.LogError("Query failed after {0} attempts with error {1}", attempts, ex);
throw;
}
if (_connection.Config.ConnectionStrategy == ConnectionStrategy.Exclusive)
{
//using exclusive connection strategy. If connection fails, do not recover
logger.LogError("Query failed on exclusive connection with error {0}", ex);
throw;
}
//connection probable collapsed, go an try again
logger.LogWarning("Query to {0} failed, going for retry. {1}", connection, ex);
}
}
throw new CqlException("Failed to return query result after max amount of attempts");
}