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

com.twitter.hbc.BasicReconnectionManager Maven / Gradle / Ivy

The newest version!
/**
 * Copyright 2013 Twitter, 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.twitter.hbc;

import com.google.common.annotations.VisibleForTesting;
import com.twitter.hbc.core.Constants;

/**
 * This manages all of the reconnection logic. Mostly just keeps a bunch of information about whether we should
 * reconnect at all, how much we should backfill, and how much to back off from connection failures.
 */
public class BasicReconnectionManager implements ReconnectionManager {

  public static final int INITIAL_EXPONENTIAL_BACKOFF_MILLIS = 5000;
  public static final int INITIAL_LINEAR_BACKOFF_MILLIS = 250;

  public static final int MAX_LINEAR_BACKOFF_MILLIS = 16000;
  public static final int MAX_EXPONENTIAL_BACKOFF_MILLIS = 320000;

  private final int maxRetries;

  private int currentRetryCount;
  private int exponentialBackoffCount;
  private int linearBackoffCount;
  private int backoffMillis;

  public BasicReconnectionManager(int maxRetries) {
    this.maxRetries = maxRetries;
    this.backoffMillis = Constants.MIN_BACKOFF_MILLIS;
  }

  @Override
  public void handleExponentialBackoff() {
    handleBackoff(incrAndGetExponentialBackoff());
  }

  @Override
  public void handleLinearBackoff() {
    handleBackoff(incrAndGetLinearBackoff());
  }

  @Override
  public boolean shouldReconnectOn400s() {
    currentRetryCount++;
    return currentRetryCount <= maxRetries;
  }

  @Override
  public int estimateBackfill(double tps) {
    int upperBound = Math.min(Constants.MAX_BACKOFF_COUNT, (int) tps * (backoffMillis));
    return Math.max(upperBound, Constants.MIN_BACKOFF_MILLIS);
  }

  @Override
  public void resetCounts() {
    linearBackoffCount = 0;
    exponentialBackoffCount = 0;
    currentRetryCount = 0;
    backoffMillis = 0;
  }

  private void handleBackoff(int millis) {
    backoffMillis += millis;
    try {
      Thread.sleep(millis);
    } catch (InterruptedException e) {
      // TODO: log an error
    }
  }

  @VisibleForTesting
  int incrAndGetExponentialBackoff() {
    linearBackoffCount = 0;
    exponentialBackoffCount += 1;
    return calculateExponentialBackoffMillis();
  }

  @VisibleForTesting
  int incrAndGetLinearBackoff() {
    exponentialBackoffCount = 0;
    linearBackoffCount += 1;
    return calculateLinearBackoffMillis();
  }

  private int calculateExponentialBackoffMillis() {
    assert(exponentialBackoffCount > 0);
    return Math.min(MAX_EXPONENTIAL_BACKOFF_MILLIS, INITIAL_EXPONENTIAL_BACKOFF_MILLIS << (exponentialBackoffCount - 1));
  }

  private int calculateLinearBackoffMillis() {
    return Math.min(MAX_LINEAR_BACKOFF_MILLIS, INITIAL_LINEAR_BACKOFF_MILLIS * linearBackoffCount);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy