org.apache.cassandra.sidecar.client.retry.ExponentialBackoffRetryPolicy Maven / Gradle / Ivy
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.sidecar.client.retry;
/**
* A retry policy that will perform an exponential backoff. The backoff period increases for each retry attempt.
*
* Example: For a configured {@code maxRetries} of {@code 10}, {@code retryDelayMillis} of {@code 200}
* milliseconds, and {@code maxRetryDelayMillis} of {@code 20,000} milliseconds, the sequence is as follows:
*
*
* request backoff
*
* 1 200
* 2 400
* 3 800
* 4 1600
* 5 3200
* 6 6400
* 7 12800
* 8 20000
* 9 20000
* 10 20000
*
*/
public class ExponentialBackoffRetryPolicy extends BasicRetryPolicy
{
private final long maxRetryDelayMillis;
private final long maxAttemptsBeforeOverflow;
/**
* Constructs an exponential backoff retry policy unlimited number of retries and no delay between retries.
*/
public ExponentialBackoffRetryPolicy()
{
super();
this.maxRetryDelayMillis = 0;
this.maxAttemptsBeforeOverflow = computeMaxAttemptsBeforeOverflow();
}
/**
* Constructs an exponential backoff retry policy with {@code maxRetries} number of retries,
* {@code retryDelayMillis} delay between retries, and {@code maxRetryDelayMillis} maximum delay for the
* exponential backoff.
*
* @param maxRetries the maximum number of retries
* @param retryDelayMillis the delay between retries in milliseconds
* @param maxRetryDelayMillis the maximum retry delay in milliseconds
*/
public ExponentialBackoffRetryPolicy(int maxRetries, long retryDelayMillis, long maxRetryDelayMillis)
{
super(maxRetries, retryDelayMillis);
this.maxRetryDelayMillis = maxRetryDelayMillis;
this.maxAttemptsBeforeOverflow = computeMaxAttemptsBeforeOverflow();
}
/**
* Returns the number of milliseconds to wait before attempting the next request. This value is upper-bounded
* by {@code maxRetryDelayMillis} if configured. The delay increases exponentially based on the number of
* attempts already performed.
*
* @param attempts the number of attempts already performed for this request
* @return the number of milliseconds to wait before attempting the next request
*/
@Override
protected long retryDelayMillis(int attempts)
{
long retryDelay;
if (attempts >= maxAttemptsBeforeOverflow)
{
// the number of attempts in the method will overflow, so just use the Long.MAX_VALUE
retryDelay = Long.MAX_VALUE;
}
else
{
retryDelay = (long) Math.pow(2, attempts - 1) * retryDelayMillis;
}
if (maxRetryDelayMillis > 0)
{
return Math.min(maxRetryDelayMillis, retryDelay);
}
return retryDelay;
}
/**
* Computes the maximum number of attempts possible before overflowing. The value is computed from:
*
*
* ( Long.MAX_VALUE )
* max_attempts = 1 + log2 ( ----------------- )
* ( retryDelayMills )
*
*
* Which is deduced from the {@code retryDelay} calculation in the {@link #retryDelayMillis(int)} method:
*
*
* retryDelay = 2^(attempts - 1) * retryDelayMillis
*
*
* Where the {@code retryDelay} is the maximum allowed value before overflowing, {@code Long.MAX_VALUE}.
*
* @return the maximum number of attempts before overflowing
*/
private long computeMaxAttemptsBeforeOverflow()
{
return 1L + (long) (Math.log((double) Long.MAX_VALUE / (double) retryDelayMillis) / Math.log(2));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy