Example #1
0
        /// <summary>
        /// Given a service request, retries the request up to 10 times using an exponential
        /// backoff strategy. Also takes an enumeration of status codes for which requests should be
        /// retried (that is, HTTP errors that are expected to occur transiently).
        /// </summary>
        internal TResponse ExecuteWithRetries <TResponse>(
            IClientServiceRequest <TResponse> request, IEnumerable <HttpStatusCode> statusCodes)
        {
            var backOff    = new Google.Apis.Util.ExponentialBackOff();
            int numRetries = 0;

            while (true)
            {
                try
                {
                    return(request.Execute());
                }
                catch (Google.GoogleApiException e)
                {
                    if (!statusCodes.Contains(e.HttpStatusCode))
                    {
                        throw e;
                    }
                    numRetries++;
                    var nextSpan = backOff.GetNextBackOff(numRetries);
                    if (nextSpan == TimeSpan.MinValue)
                    {
                        throw e;
                    }
                    Console.WriteLine("Attempt {0} failed, retrying in {1}.", numRetries, nextSpan);
                    System.Threading.Thread.Sleep(nextSpan);
                }
            }
        }
Example #2
0
        private static TResponse SafeExecuteSync <TResponse>(IClientServiceRequest <TResponse> request, int attemptOrderNumber)
        {
            // Attempt to execute provided request.
            try { return(request.Execute()); }

            // On request operation canceled
            catch (OperationCanceledException ex)
            {
                // Increase attempt order number by one.
                attemptOrderNumber++;

                // Validate whether request reattempt limit hasn't been exceeded
                if (RequestsExecutor._cancellationErrorAttemptsLimit < attemptOrderNumber)
                {
                    // ... and throw appropriate exception if has. attempt
                    throw new RequestExecutionUnexpectedException(request, ex);
                }

                // Await appropriate cooldown period.
                Thread.Sleep(RequestsExecutor._cancellationErrorCooldown);

                // Reattempt.
                return(RequestsExecutor.SafeExecuteSync(request, attemptOrderNumber));
            }

            // On google internal error encounter, retry
            catch (Google.GoogleApiException ex) when(ex.Message.Contains("Internal error encountered. [500]"))
            {
                // Increase attempt order number by one.
                attemptOrderNumber++;

                // Validate whether request reattempt limit hasn't been exceeded
                if (RequestsExecutor._internalErrorAttemptsLimit < attemptOrderNumber)
                {
                    // ... and throw appropriate exception if has. attempt
                    throw new RequestExecutionUnexpectedException(request, ex);
                }

                // Await appropriate cooldown period.
                Thread.Sleep(RequestsExecutor._internalErrorCooldown);

                // Reattempt.
                return(RequestsExecutor.SafeExecuteSync <TResponse>(request, attemptOrderNumber));
            }

            // On used all available requests quota
            catch (Google.GoogleApiException ex) when(ex.Message.Contains("Quota exceeded for quota group"))
            {
                // Set session request limiter state to indicate no available google requests quota at this time.
                SessionRequestsLimiter.Instance.ClearAvailableQuota();

                // Reattempt.
                return(RequestsExecutor.SafeExecuteSync <TResponse>(request, attemptOrderNumber));
            }

            // On any other unexpected database error
            catch (Google.GoogleApiException ex) { throw new RequestExecutionUnexpectedException(request, ex); }
        }