All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.rt.storage.api.client.http.ExponentialBackOffPolicy Maven / Gradle / Ivy

package com.rt.storage.api.client.http;

import com.rt.storage.api.client.util.Beta;
import com.rt.storage.api.client.util.ExponentialBackOff;
import com.rt.storage.api.client.util.NanoClock;
import java.io.IOException;

/**
 * {@link Beta} 
* Implementation of {@link BackOffPolicy} that increases the back off period for each retry attempt * using a randomization function that grows exponentially. * *

{@link #getNextBackOffMillis()} is calculated using the following formula: * *

 * randomized_interval =
 *     retry_interval * (random value in range [1 - randomization_factor, 1 + randomization_factor])
 * 
* *

In other words {@link #getNextBackOffMillis()} will range between the randomization factor * percentage below and above the retry interval. For example, using 2 seconds as the base retry * interval and 0.5 as the randomization factor, the actual back off period used in the next retry * attempt will be between 1 and 3 seconds. * *

Note: max_interval caps the retry_interval and not the randomized_interval. * *

If the time elapsed since an {@link ExponentialBackOffPolicy} instance is created goes past * the max_elapsed_time then the method {@link #getNextBackOffMillis()} starts returning {@link * BackOffPolicy#STOP}. The elapsed time can be reset by calling {@link #reset()}. * *

Example: The default retry_interval is .5 seconds, default randomization_factor is 0.5, * default multiplier is 1.5 and the default max_interval is 1 minute. For 10 requests the sequence * will be (values in seconds) and assuming we go over the max_elapsed_time on the 10th request: * *

 * request#     retry_interval     randomized_interval
 *
 * 1             0.5                [0.25,   0.75]
 * 2             0.75               [0.375,  1.125]
 * 3             1.125              [0.562,  1.687]
 * 4             1.687              [0.8435, 2.53]
 * 5             2.53               [1.265,  3.795]
 * 6             3.795              [1.897,  5.692]
 * 7             5.692              [2.846,  8.538]
 * 8             8.538              [4.269, 12.807]
 * 9            12.807              [6.403, 19.210]
 * 10           19.210              {@link BackOffPolicy#STOP}
 * 
* *

Implementation is not thread-safe. * * @since 1.7 * @author Ravi Mistry * @deprecated (scheduled to be removed in 1.18). Use {@link HttpBackOffUnsuccessfulResponseHandler} * with {@link ExponentialBackOff} instead. */ @Beta @Deprecated public class ExponentialBackOffPolicy implements BackOffPolicy { /** The default initial interval value in milliseconds (0.5 seconds). */ public static final int DEFAULT_INITIAL_INTERVAL_MILLIS = ExponentialBackOff.DEFAULT_INITIAL_INTERVAL_MILLIS; /** * The default randomization factor (0.5 which results in a random period ranging between 50% * below and 50% above the retry interval). */ public static final double DEFAULT_RANDOMIZATION_FACTOR = ExponentialBackOff.DEFAULT_RANDOMIZATION_FACTOR; /** The default multiplier value (1.5 which is 50% increase per back off). */ public static final double DEFAULT_MULTIPLIER = ExponentialBackOff.DEFAULT_MULTIPLIER; /** The default maximum back off time in milliseconds (1 minute). */ public static final int DEFAULT_MAX_INTERVAL_MILLIS = ExponentialBackOff.DEFAULT_MAX_INTERVAL_MILLIS; /** The default maximum elapsed time in milliseconds (15 minutes). */ public static final int DEFAULT_MAX_ELAPSED_TIME_MILLIS = ExponentialBackOff.DEFAULT_MAX_ELAPSED_TIME_MILLIS; /** Exponential backoff. */ private final ExponentialBackOff exponentialBackOff; /** * Creates an instance of ExponentialBackOffPolicy using default values. To override the defaults * use {@link #builder}. * *

    *
  • {@code initialIntervalMillis} is defaulted to {@link #DEFAULT_INITIAL_INTERVAL_MILLIS} *
  • {@code randomizationFactor} is defaulted to {@link #DEFAULT_RANDOMIZATION_FACTOR} *
  • {@code multiplier} is defaulted to {@link #DEFAULT_MULTIPLIER} *
  • {@code maxIntervalMillis} is defaulted to {@link #DEFAULT_MAX_INTERVAL_MILLIS} *
  • {@code maxElapsedTimeMillis} is defaulted in {@link #DEFAULT_MAX_ELAPSED_TIME_MILLIS} *
*/ public ExponentialBackOffPolicy() { this(new Builder()); } /** * @param builder builder * @since 1.14 */ protected ExponentialBackOffPolicy(Builder builder) { exponentialBackOff = builder.exponentialBackOffBuilder.build(); } /** * Determines if back off is required based on the specified status code. * *

The idea is that the servers are only temporarily unavailable, and they should not be * overwhelmed when they are trying to get back up. * *

The default implementation requires back off for 500 and 503 status codes. Subclasses may * override if different status codes are required. */ public boolean isBackOffRequired(int statusCode) { switch (statusCode) { case HttpStatusCodes.STATUS_CODE_SERVER_ERROR: // 500 case HttpStatusCodes.STATUS_CODE_SERVICE_UNAVAILABLE: // 503 return true; default: return false; } } /** Sets the interval back to the initial retry interval and restarts the timer. */ public final void reset() { exponentialBackOff.reset(); } /** * Gets the number of milliseconds to wait before retrying an HTTP request. If {@link #STOP} is * returned, no retries should be made. * *

This method calculates the next back off interval using the formula: randomized_interval = * retry_interval +/- (randomization_factor * retry_interval) * *

Subclasses may override if a different algorithm is required. * * @return the number of milliseconds to wait when backing off requests, or {@link #STOP} if no * more retries should be made */ public long getNextBackOffMillis() throws IOException { return exponentialBackOff.nextBackOffMillis(); } /** Returns the initial retry interval in milliseconds. */ public final int getInitialIntervalMillis() { return exponentialBackOff.getInitialIntervalMillis(); } /** * Returns the randomization factor to use for creating a range around the retry interval. * *

A randomization factor of 0.5 results in a random period ranging between 50% below and 50% * above the retry interval. */ public final double getRandomizationFactor() { return exponentialBackOff.getRandomizationFactor(); } /** Returns the current retry interval in milliseconds. */ public final int getCurrentIntervalMillis() { return exponentialBackOff.getCurrentIntervalMillis(); } /** Returns the value to multiply the current interval with for each retry attempt. */ public final double getMultiplier() { return exponentialBackOff.getMultiplier(); } /** * Returns the maximum value of the back off period in milliseconds. Once the current interval * reaches this value it stops increasing. */ public final int getMaxIntervalMillis() { return exponentialBackOff.getMaxIntervalMillis(); } /** * Returns the maximum elapsed time in milliseconds. * *

If the time elapsed since an {@link ExponentialBackOffPolicy} instance is created goes past * the max_elapsed_time then the method {@link #getNextBackOffMillis()} starts returning {@link * BackOffPolicy#STOP}. The elapsed time can be reset by calling {@link #reset()}. */ public final int getMaxElapsedTimeMillis() { return exponentialBackOff.getMaxElapsedTimeMillis(); } /** * Returns the elapsed time in milliseconds since an {@link ExponentialBackOffPolicy} instance is * created and is reset when {@link #reset()} is called. * *

The elapsed time is computed using {@link System#nanoTime()}. */ public final long getElapsedTimeMillis() { return exponentialBackOff.getElapsedTimeMillis(); } /** Returns an instance of a new builder. */ public static Builder builder() { return new Builder(); } /** * {@link Beta}
* Builder for {@link ExponentialBackOffPolicy}. * *

Implementation is not thread-safe. * * @since 1.7 */ @Beta @Deprecated public static class Builder { /** Exponential back-off builder. */ final ExponentialBackOff.Builder exponentialBackOffBuilder = new ExponentialBackOff.Builder(); protected Builder() {} /** Builds a new instance of {@link ExponentialBackOffPolicy}. */ public ExponentialBackOffPolicy build() { return new ExponentialBackOffPolicy(this); } /** * Returns the initial retry interval in milliseconds. The default value is {@link * #DEFAULT_INITIAL_INTERVAL_MILLIS}. */ public final int getInitialIntervalMillis() { return exponentialBackOffBuilder.getInitialIntervalMillis(); } /** * Sets the initial retry interval in milliseconds. The default value is {@link * #DEFAULT_INITIAL_INTERVAL_MILLIS}. Must be {@code > 0}. * *

Overriding is only supported for the purpose of calling the super implementation and * changing the return type, but nothing else. */ public Builder setInitialIntervalMillis(int initialIntervalMillis) { exponentialBackOffBuilder.setInitialIntervalMillis(initialIntervalMillis); return this; } /** * Returns the randomization factor to use for creating a range around the retry interval. The * default value is {@link #DEFAULT_RANDOMIZATION_FACTOR}. * *

A randomization factor of 0.5 results in a random period ranging between 50% below and 50% * above the retry interval. * *

Overriding is only supported for the purpose of calling the super implementation and * changing the return type, but nothing else. */ public final double getRandomizationFactor() { return exponentialBackOffBuilder.getRandomizationFactor(); } /** * Sets the randomization factor to use for creating a range around the retry interval. The * default value is {@link #DEFAULT_RANDOMIZATION_FACTOR}. Must fall in the range {@code 0 <= * randomizationFactor < 1}. * *

A randomization factor of 0.5 results in a random period ranging between 50% below and 50% * above the retry interval. * *

Overriding is only supported for the purpose of calling the super implementation and * changing the return type, but nothing else. */ public Builder setRandomizationFactor(double randomizationFactor) { exponentialBackOffBuilder.setRandomizationFactor(randomizationFactor); return this; } /** * Returns the value to multiply the current interval with for each retry attempt. The default * value is {@link #DEFAULT_MULTIPLIER}. */ public final double getMultiplier() { return exponentialBackOffBuilder.getMultiplier(); } /** * Sets the value to multiply the current interval with for each retry attempt. The default * value is {@link #DEFAULT_MULTIPLIER}. Must be {@code >= 1}. * *

Overriding is only supported for the purpose of calling the super implementation and * changing the return type, but nothing else. */ public Builder setMultiplier(double multiplier) { exponentialBackOffBuilder.setMultiplier(multiplier); return this; } /** * Returns the maximum value of the back off period in milliseconds. Once the current interval * reaches this value it stops increasing. The default value is {@link * #DEFAULT_MAX_INTERVAL_MILLIS}. Must be {@code >= initialInterval}. */ public final int getMaxIntervalMillis() { return exponentialBackOffBuilder.getMaxIntervalMillis(); } /** * Sets the maximum value of the back off period in milliseconds. Once the current interval * reaches this value it stops increasing. The default value is {@link * #DEFAULT_MAX_INTERVAL_MILLIS}. * *

Overriding is only supported for the purpose of calling the super implementation and * changing the return type, but nothing else. */ public Builder setMaxIntervalMillis(int maxIntervalMillis) { exponentialBackOffBuilder.setMaxIntervalMillis(maxIntervalMillis); return this; } /** * Returns the maximum elapsed time in milliseconds. The default value is {@link * #DEFAULT_MAX_ELAPSED_TIME_MILLIS}. * *

If the time elapsed since an {@link ExponentialBackOffPolicy} instance is created goes * past the max_elapsed_time then the method {@link #getNextBackOffMillis()} starts returning * {@link BackOffPolicy#STOP}. The elapsed time can be reset by calling {@link #reset()}. */ public final int getMaxElapsedTimeMillis() { return exponentialBackOffBuilder.getMaxElapsedTimeMillis(); } /** * Sets the maximum elapsed time in milliseconds. The default value is {@link * #DEFAULT_MAX_ELAPSED_TIME_MILLIS}. Must be {@code > 0}. * *

If the time elapsed since an {@link ExponentialBackOffPolicy} instance is created goes * past the max_elapsed_time then the method {@link #getNextBackOffMillis()} starts returning * {@link BackOffPolicy#STOP}. The elapsed time can be reset by calling {@link #reset()}. * *

Overriding is only supported for the purpose of calling the super implementation and * changing the return type, but nothing else. */ public Builder setMaxElapsedTimeMillis(int maxElapsedTimeMillis) { exponentialBackOffBuilder.setMaxElapsedTimeMillis(maxElapsedTimeMillis); return this; } /** * Returns the nano clock. * * @since 1.14 */ public final NanoClock getNanoClock() { return exponentialBackOffBuilder.getNanoClock(); } /** * Sets the nano clock ({@link NanoClock#SYSTEM} by default). * *

Overriding is only supported for the purpose of calling the super implementation and * changing the return type, but nothing else. * * @since 1.14 */ public Builder setNanoClock(NanoClock nanoClock) { exponentialBackOffBuilder.setNanoClock(nanoClock); return this; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy