code: @SuppressWarnings("MethodMayBeStatic") // Intentionally left non-static for better user experience.
      protected final long getNextDelay(ClientRequestContext ctx, Backoff backoff, long millisAfterFromServer) {
          requireNonNull(ctx, "ctx");
          requireNonNull(backoff, "backoff");
          final State state = ctx.attr(STATE).get();
          final int currentAttemptNo = state.currentAttemptNoWith(backoff);
  
          if (currentAttemptNo < 0) {
              logger.debug("Exceeded the default number of max attempt: {}", state.maxTotalAttempts);
              return -1;
          }
  
          long nextDelay = backoff.nextDelayMillis(currentAttemptNo);
          if (nextDelay < 0) {
              logger.debug("Exceeded the number of max attempts in the backoff: {}", backoff);
              return -1;
          }
  
          nextDelay = Math.max(nextDelay, millisAfterFromServer);
          if (state.timeoutForWholeRetryEnabled() && nextDelay > state.actualResponseTimeoutMillis()) {
              // The nextDelay will be after the moment which timeout will happen. So return just -1.
              return -1;
          }
  
          return nextDelay;
      }
docs: Returns the next delay which retry will be made after. The delay will be:
  
  <p>{@code Math.min(responseTimeoutMillis, Math.max(Backoff.nextDelayMillis(int),
  millisAfterFromServer))}
  
  @return the number of milliseconds to wait for before attempting a retry. -1 if the
  {@code currentAttemptNo} exceeds the {@code maxAttempts} or the {@code nextDelay} is after
  the moment which timeout happens.