code: public V callWithRetries() throws ApiInvocationException {
      V result = null;
      Throwable lastError = null;
      
      for (int kthAttempt = 1; retryStrategy.canDoThisAttempt(kthAttempt); ++kthAttempt) {
        // Wait if the previous attempt failed.
        long waitForMillis =
            retryStrategy.calcWaitTimeBeforeCall(clientCustomerId, kthAttempt, lastError);
        if (waitForMillis > 0) {
          logger.info(
              "Thread \"{}\" is sleeping for {} millis.",
              Thread.currentThread().getName(),
              waitForMillis);
          try {
            Thread.sleep(waitForMillis);
          } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new ApiInvocationException(
                "InterruptedException occurs while waiting to " + actionDescription, e.getCause());
          }
        }
        
        try {
          lastError = null;
          result = callable.call();
          break;
        } catch (IllegalAccessException e) {
          throw new RateLimiterException("Illegal access to invoke: " + actionDescription, e);
        } catch (InvocationTargetException e) {
          lastError = e.getCause();
        } catch (Exception e) {
          lastError = e;
        }
        
        // Check whether the error is retriable
        if (retryStrategy.shouldRetryOnError(clientCustomerId, lastError)) {
          logger.error(
              "Failed to call {} at exception check, attempt #{}.", actionDescription, kthAttempt);
        } else {
          logger.error(
              "Failed to call {} at exception check: encountered non-retriable {}, skip retry!",
              actionDescription,
              lastError.getClass().getName());
          throw new ApiInvocationException("Encountered non-retriable exception.", lastError);
        }
      }
  
      if (result == null) {
        String msg = "Failed to " + actionDescription + " after all retries.";
        logger.error(msg, lastError);
        throw new ApiInvocationException(msg, lastError);
      }
  
      return result;
    }
docs: Invoke the AdWords API call with retry logic.
  
  @throws ApiInvocationException the exception during AdWords API invocation
  @return the returned result of the callable other than AlertProcessingException occurs, the
  thread is interrupted during waiting, or all retries are exhausted.