Example #1
0
 // Sync retry
 internal static Func <TRequest, CallSettings, TResponse> WithRetry <TRequest, TResponse>(
     this Func <TRequest, CallSettings, TResponse> fn,
     IClock clock, IScheduler scheduler) =>
 (request, callSettings) =>
 {
     RetrySettings retrySettings = callSettings.Retry;
     if (retrySettings == null)
     {
         return(fn(request, callSettings));
     }
     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);
     }
     foreach (var attempt in RetryAttempt.CreateRetrySequence(retrySettings, scheduler, overallDeadline, clock))
     {
         try
         {
             return(fn(request, callSettings));
         }
         catch (Exception e) when(attempt.ShouldRetry(e))
         {
             attempt.Backoff(callSettings.CancellationToken.GetValueOrDefault());
         }
     }
     throw new InvalidOperationException("Bug in GAX retry handling: finished sequence of attempts");
 };
        // By design, the code is mostly duplicated between the async and sync calls.

        // Async retry
        internal static Func <TRequest, CallSettings, Task <TResponse> > WithRetry <TRequest, TResponse>(
            this Func <TRequest, CallSettings, Task <TResponse> > fn,
            IClock clock, IScheduler scheduler, ILogger logger, string methodName) =>
        async(request, callSettings) =>
        {
            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);
            }
            foreach (var attempt in RetryAttempt.CreateRetrySequence(retrySettings, scheduler, overallDeadline, clock))
            {
                try
                {
                    return(await fn(request, callSettings).ConfigureAwait(false));
                }
                catch (Exception e) when(attempt.ShouldRetry(e))
                {
                    logger.LogDebug("Backing off before retry of method {method}", methodName);
                    await attempt.BackoffAsync(callSettings.CancellationToken.GetValueOrDefault()).ConfigureAwait(false);
                }
            }
            throw new InvalidOperationException("Bug in GAX retry handling: finished sequence of attempts");
        };