public async Task InvokeWithRetryAsync()

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;
                }
            }
        }