in src/Microsoft.ServiceFabric.Services/Communication/Client/ServicePartitionClient.cs [159:262]
public async Task<TResult> InvokeWithRetryAsync<TResult>(
Func<TCommunicationClient, Task<TResult>> func,
CancellationToken cancellationToken,
params Type[] doNotRetryExceptionTypes)
{
var totalretryCount = 0;
string currentExceptionId = null;
CancellationTokenSource cancellationTokenSource = null;
var traceId = Guid.NewGuid().ToString();
ClientRequestTracker.Set(traceId);
try
{
// This code will execute when user has specified client retry timeout
if (this.retrySettings.ClientRetryTimeout != Timeout.InfiniteTimeSpan)
{
cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
cancellationTokenSource.CancelAfter(this.retrySettings.ClientRetryTimeout);
cancellationToken = cancellationTokenSource.Token;
}
while (true)
{
Exception exception;
var client = await this.GetCommunicationClientAsync(cancellationToken);
// throw if cancellation has been requested.
cancellationToken.ThrowIfCancellationRequested();
try
{
var result = await func.Invoke(client);
return result;
}
catch (AggregateException ae)
{
ServiceTrace.Source.WriteNoiseWithId(
TraceType,
traceId,
"AggregateException While Invoking API {0}",
ae);
ae.Handle(x => !doNotRetryExceptionTypes.Contains(x.GetType()));
exception = ae;
}
catch (Exception e)
{
ServiceTrace.Source.WriteNoiseWithId(
TraceType,
traceId,
"Exception While Invoking API {0}",
e);
if (doNotRetryExceptionTypes.Contains(e.GetType()))
{
throw;
}
exception = e;
}
// The exception that is being processed by the factory could be because of the cancellation
// requested to the remote call, so not passing the same cancellation token to the api below
// to not let the regular exception processing be interrupted.
var exceptionReportResult = await this.communicationClientFactory.ReportOperationExceptionAsync(
client,
new ExceptionInformation(exception, this.targetReplicaSelector),
this.retrySettings,
CancellationToken.None);
if (!exceptionReportResult.ShouldRetry ||
!Utility.ShouldRetryOperation(
exceptionReportResult.ExceptionId,
exceptionReportResult.MaxRetryCount,
ref currentExceptionId,
ref totalretryCount))
{
throw exceptionReportResult.Exception ?? exception;
}
var retrydelay = exceptionReportResult.GetRetryDelay(totalretryCount);
ServiceTrace.Source.WriteInfoWithId(
TraceType,
traceId,
"Exception report result Id: {0} IsTransient : {1} Delay : {2}",
exceptionReportResult.ExceptionId,
exceptionReportResult.IsTransient,
retrydelay);
if (!exceptionReportResult.IsTransient)
{
await this.ResetCommunicationClientAsync();
}
await Task.Delay(retrydelay, cancellationToken);
}
}
finally
{
if (cancellationTokenSource != null)
{
cancellationTokenSource.Dispose();
cancellationTokenSource = null;
}
}
}