blob: 686fe859cdc99d4443ae5cdd48a008445d8d672b [file] [log] [blame]
/*
* Copyright 2015 The gRPC Authors
*
* 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 io.grpc.internal;
import static com.google.common.base.Preconditions.checkArgument;
import com.google.common.annotations.VisibleForTesting;
import java.util.Random;
import java.util.concurrent.TimeUnit;
/**
* Retry Policy for Transport reconnection. Initial parameters from
* https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md
*
* <p>TODO(carl-mastrangelo): add unit tests for this class
*/
public final class ExponentialBackoffPolicy implements BackoffPolicy {
public static final class Provider implements BackoffPolicy.Provider {
@Override
public BackoffPolicy get() {
return new ExponentialBackoffPolicy();
}
}
private Random random = new Random();
private long initialBackoffNanos = TimeUnit.SECONDS.toNanos(1);
private long maxBackoffNanos = TimeUnit.MINUTES.toNanos(2);
private double multiplier = 1.6;
private double jitter = .2;
private long nextBackoffNanos = initialBackoffNanos;
@Override
public long nextBackoffNanos() {
long currentBackoffNanos = nextBackoffNanos;
nextBackoffNanos = Math.min((long) (currentBackoffNanos * multiplier), maxBackoffNanos);
return currentBackoffNanos
+ uniformRandom(-jitter * currentBackoffNanos, jitter * currentBackoffNanos);
}
private long uniformRandom(double low, double high) {
checkArgument(high >= low);
double mag = high - low;
return (long) (random.nextDouble() * mag + low);
}
/*
* No guice and no flags means we get to implement these setters for testing ourselves. Do not
* call these from non-test code.
*/
@VisibleForTesting
ExponentialBackoffPolicy setRandom(Random random) {
this.random = random;
return this;
}
@VisibleForTesting
ExponentialBackoffPolicy setInitialBackoffNanos(long initialBackoffNanos) {
this.initialBackoffNanos = initialBackoffNanos;
return this;
}
@VisibleForTesting
ExponentialBackoffPolicy setMaxBackoffNanos(long maxBackoffNanos) {
this.maxBackoffNanos = maxBackoffNanos;
return this;
}
@VisibleForTesting
ExponentialBackoffPolicy setMultiplier(double multiplier) {
this.multiplier = multiplier;
return this;
}
@VisibleForTesting
ExponentialBackoffPolicy setJitter(double jitter) {
this.jitter = jitter;
return this;
}
}