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"); }
internal static async Task RetryOperationUntilCompleted( Func <CallSettings, Task <bool> > fn, IClock clock, IScheduler scheduler, CallSettings callSettings, RetrySettings retrySettings) { 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); } var deadlineException = new RpcException(new Status(StatusCode.DeadlineExceeded, "Deadline Exceeded")); foreach (var attempt in RetryAttempt.CreateRetrySequence(retrySettings, scheduler, overallDeadline, clock)) { try { bool isResponseOk = await fn(callSettings).ConfigureAwait(false); if (isResponseOk) { return; } if (!attempt.ShouldRetry(deadlineException)) { throw deadlineException; } } catch (RpcException e) when(attempt.ShouldRetry(e)) { // We back off below... } await attempt.BackoffAsync(callSettings.CancellationToken.GetValueOrDefault()).ConfigureAwait(false); } throw new InvalidOperationException("Bug in GAX retry handling: finished sequence of attempts"); }