Beispiel #1
0
        internal static async Task <TResponse> Retry <TRequest, TResponse>(
            Func <TRequest, CallSettings, Task <TResponse> > fn,
            TRequest request, CallSettings callSettings, IClock clock, IScheduler scheduler)
        {
            RetrySettings retrySettings = callSettings.Retry;

            if (retrySettings == null)
            {
                return(await fn(request, callSettings).ConfigureAwait(false));
            }
            DateTime?overallDeadline = callSettings.Expiration.CalculateDeadline(clock);

            // Every attempt should use the same deadline, calculated from the start of the call.
            if (callSettings.Expiration?.Type == ExpirationType.Timeout)
            {
                callSettings = callSettings.WithDeadline(overallDeadline.Value);
            }
            // Remove retry from the call settings we pass into the function, so that the settings
            // can be used even for a streaming call.
            callSettings = callSettings.WithRetry(null);

            foreach (var attempt in RetryAttempt.CreateRetrySequence(retrySettings, scheduler, overallDeadline, clock))
            {
                try
                {
                    return(await fn(request, callSettings).ConfigureAwait(false));
                }
                catch (RpcException e) when(attempt.ShouldRetry(e))
                {
                    await attempt.BackoffAsync(callSettings.CancellationToken.GetValueOrDefault()).ConfigureAwait(false);
                }
            }
            throw new InvalidOperationException("Bug in GAX retry handling: finished sequence of attempts");
        }