code: public <T> T execute(final Callable<T> callable) throws Exception {
          int attempts = 0;
          int maxAttempts = retryPolicy.getMaxAttempts();
          long delay = retryPolicy.getDelay();
          TimeUnit timeUnit = retryPolicy.getTimeUnit();
          while(attempts < maxAttempts) {
              try {
                  attempts++;
                  beforeCall();
                  T result = callable.call();
                  afterCall(result);
                  return result;
              } catch (Exception e) {
                  onException(e);
                  if (attempts >= maxAttempts) {
                      onMaxAttempts(e);
                      throw e;
                  }
                  beforeWait();
                  sleep(timeUnit.toMillis(delay));
                  afterWait();
              }
          }
          return null;
      }
docs: Execute the callable with retries.
  
  @param callable to execute
  @param <T> the return type of the callable
  @return the result of the callable
  @throws Exception if the callable still throw an exception after all retries