code: public final void retry(final ConnectionState state, final RetryHandler retryHandler, final ConnectionFailHandler failHandler) throws RetryCancelled {
      if (state.retryCount == 0) {
        state.msBeforeRetry = this.startRetryTime;
      }
  
      state.retryCount++;
      state.uriIndex = state.retryCount % state.uris.length;
  
      if (this.shouldRetry(state)) {
        if (logger.isDebugEnabled()) {
          logger.debug("Retry {} to send command", state.retryCount);
        }
  
        if(state.msBeforeRetry > 0) {
          try {
            state.loop.schedule(new Runnable() {
              @Override
              public void run() {
                try {
                  retryHandler.doRetry(state);
                } catch (IOException e) {
                  failHandler.catchException(e);
                }
              }
            }, state.msBeforeRetry, TimeUnit.MILLISECONDS);
          } catch (IllegalStateException e) {
            failHandler.catchException(
              new IOException(new CancellationException("Etcd client was closed"))
            );
          }
        } else {
          try {
            retryHandler.doRetry(state);
          } catch (IOException e) {
            failHandler.catchException(e);
          }
        }
      } else {
        throw new RetryCancelled();
      }
    }
docs: Does the retry. Will always try all URIs before throwing an exception.
  
  @param state        of connection
  @param retryHandler handles the retry itself
  @param failHandler  handles the fail
  @throws RetryCancelled if retry is cancelled