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

com.google.firebase.internal.RetryConfig Maven / Gradle / Ivy

/*
 * Copyright 2019 Google Inc.
 *
 * Licensed 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 com.google.firebase.internal;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

import com.google.api.client.util.BackOff;
import com.google.api.client.util.ExponentialBackOff;
import com.google.api.client.util.Sleeper;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * Configures when and how HTTP requests should be retried.
 */
public final class RetryConfig {

  private static final int INITIAL_INTERVAL_MILLIS = 500;

  private final List retryStatusCodes;
  private final boolean retryOnIOExceptions;
  private final int maxRetries;
  private final Sleeper sleeper;
  private final ExponentialBackOff.Builder backOffBuilder;

  private RetryConfig(Builder builder) {
    if (builder.retryStatusCodes != null) {
      this.retryStatusCodes = ImmutableList.copyOf(builder.retryStatusCodes);
    } else {
      this.retryStatusCodes = ImmutableList.of();
    }

    this.retryOnIOExceptions = builder.retryOnIOExceptions;
    checkArgument(builder.maxRetries >= 0, "maxRetries must not be negative");
    this.maxRetries = builder.maxRetries;
    this.sleeper = checkNotNull(builder.sleeper);
    this.backOffBuilder = new ExponentialBackOff.Builder()
        .setInitialIntervalMillis(INITIAL_INTERVAL_MILLIS)
        .setMaxIntervalMillis(builder.maxIntervalMillis)
        .setMultiplier(builder.backOffMultiplier)
        .setRandomizationFactor(0);

    // Force validation of arguments by building the BackOff object
    this.backOffBuilder.build();
  }

  List getRetryStatusCodes() {
    return retryStatusCodes;
  }

  boolean isRetryOnIOExceptions() {
    return retryOnIOExceptions;
  }

  int getMaxRetries() {
    return maxRetries;
  }

  int getMaxIntervalMillis() {
    return backOffBuilder.getMaxIntervalMillis();
  }

  double getBackOffMultiplier() {
    return backOffBuilder.getMultiplier();
  }

  Sleeper getSleeper() {
    return sleeper;
  }

  BackOff newBackOff() {
    return backOffBuilder.build();
  }

  public static Builder builder() {
    return new Builder();
  }

  public static final class Builder {

    private List retryStatusCodes;
    private boolean retryOnIOExceptions;
    private int maxRetries;
    private int maxIntervalMillis = (int) TimeUnit.MINUTES.toMillis(2);
    private double backOffMultiplier = 2.0;
    private Sleeper sleeper = Sleeper.DEFAULT;

    private Builder() { }

    /**
     * Sets a list of HTTP status codes that should be retried. If null or empty, HTTP requests
     * will not be retried as long as they result in some HTTP response message.
     *
     * @param retryStatusCodes A list of status codes.
     * @return This builder.
     */
    public Builder setRetryStatusCodes(List retryStatusCodes) {
      this.retryStatusCodes = retryStatusCodes;
      return this;
    }

    /**
     * Sets whether requests should be retried on IOExceptions.
     *
     * @param retryOnIOExceptions A boolean indicating whether to retry on IOExceptions.
     * @return This builder.
     */
    public Builder setRetryOnIOExceptions(boolean retryOnIOExceptions) {
      this.retryOnIOExceptions = retryOnIOExceptions;
      return this;
    }

    /**
     * Maximum number of retry attempts for a request. This is the cumulative total for all retries
     * regardless of their cause (I/O errors and HTTP error responses).
     *
     * @param maxRetries A non-negative integer.
     * @return This builder.
     */
    public Builder setMaxRetries(int maxRetries) {
      this.maxRetries = maxRetries;
      return this;
    }

    /**
     * Maximum interval to wait before a request should be retried. Must be at least 500
     * milliseconds. Defaults to 2 minutes.
     *
     * @param maxIntervalMillis Interval in milliseconds.
     * @return This builder.
     */
    public Builder setMaxIntervalMillis(int maxIntervalMillis) {
      this.maxIntervalMillis = maxIntervalMillis;
      return this;
    }

    /**
     * Factor by which the retry interval is multiplied when employing exponential back
     * off to delay consecutive retries of the same request. Must be at least 1. Defaults
     * to 2.
     *
     * @param backOffMultiplier Multiplication factor for exponential back off.
     * @return This builder.
     */
    public Builder setBackOffMultiplier(double backOffMultiplier) {
      this.backOffMultiplier = backOffMultiplier;
      return this;
    }

    @VisibleForTesting
    Builder setSleeper(Sleeper sleeper) {
      this.sleeper = sleeper;
      return this;
    }

    public RetryConfig build() {
      return new RetryConfig(this);
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy