Github user afine commented on a diff in the pull request: https://github.com/apache/zookeeper/pull/419#discussion_r151812103 --- Diff: src/java/main/org/apache/zookeeper/server/quorum/ExponentialBackoffStrategy.java --- @@ -0,0 +1,192 @@ +package org.apache.zookeeper.server.quorum; + +/** + * A {@link BackoffStrategy} that increases the wait time between each + * interval up to the configured maximum wait time. + */ +public class ExponentialBackoffStrategy implements BackoffStrategy { + + // Sensible default values to use if not set by the user + private static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 500L; // 0.5s + private static final long DEFAULT_MAX_BACKOFF_MILLIS = 30_000L; // 30s + private static final long DEFAULT_MAX_ELAPSED_MILLIS = 5 * 60_000L; // 10m + private static final double DEFAULT_BACKOFF_MULTIPLE = 1.5; + + // internal values per instance + private final long initialBackoffMillis; + private final long maxBackoffMillis; + private final long maxElapsedMillis; + private final double backoffMultiple; + + // internal state + private long nextWait; + private long totalElapsed; + private final boolean limitBackoffMillis; + private final boolean checkElapsedTime; + + /** + * Construct a new instance. + * @param builder the Builder to use for configuring this BackoffStrategy + */ + private ExponentialBackoffStrategy(Builder builder) { + this.initialBackoffMillis = builder.initialBackoffMillis; + this.maxBackoffMillis = builder.maxBackoffMillis; + this.maxElapsedMillis = builder.maxElapsedMillis; + this.backoffMultiple = builder.backoffMultiple; + + if(maxBackoffMillis == -1) { + limitBackoffMillis = false; + } else { + limitBackoffMillis = true; + } + + if(maxElapsedMillis == -1) { + checkElapsedTime = false; + } else { + checkElapsedTime = true; + } + + reset(); + } + + + @Override + public long nextWaitMillis() throws IllegalStateException { + // check if we have exceeded the allowed maximum elapsed time + if(checkElapsedTime && totalElapsed > maxElapsedMillis) { + return BackoffStrategy.STOP; + } + + long waitMillis = nextWait; + + // calculate the next wait milliseconds + nextWait = Math.round(nextWait * backoffMultiple); + + // don't exceed the allowed maximum wait milliseconds + // if a maximum was configured + if(limitBackoffMillis && nextWait > maxBackoffMillis) { + nextWait = maxBackoffMillis; + } + + // track total elapsed time, even if we don't wait we have to assume + // that some amount of time passed outside of the wait or we'll never + // hit the elapsed time limit + totalElapsed += waitMillis != 0 ? waitMillis : 1L; + return waitMillis; + } + + @Override + public void reset() { + nextWait = this.initialBackoffMillis; + totalElapsed = 0; + } + + /** + * + * @return a new {@link Builder} instance. + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Builder for instances of {@link ExponentialBackoffStrategy}. + */ + public static final class Builder { --- End diff -- So I probably wasn't clear here. It would be great if it was also possible, since backoff strategy is such a nicely defined interface, if the user could include jar with their own backoff strategy in the classpath and tell zookeeper to use that. What do you think?
---