@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 = state(ctx);
        final int currentAttemptNo = state.currentAttemptNoWith(backoff);

        if (currentAttemptNo < 0) {
            logger.debug("Exceeded the default number of max attempt: {}", state.config.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;
    }
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.
core/src/main/java/com/linecorp/armeria/client/retry/AbstractRetryingClient.java