ExponentialRetryAlgorithm implements TimedRetryAlgorithm { @Override public TimedAttemptSettings createNextAttempt(TimedAttemptSettings prevSettings) { RetrySettings settings = prevSettings.getGlobalSettings(); long newRetryDelay = settings.getInitialRetryDelay().toMillis(); if (prevSettings.getAttemptCount() > 0) { newRetryDelay = (long) (settings.getRetryDelayMultiplier() * prevSettings.getRetryDelay().toMillis()); newRetryDelay = Math.min(newRetryDelay, settings.getMaxRetryDelay().toMillis()); } Duration randomDelay = Duration.ofMillis(nextRandomLong(newRetryDelay)); long newRpcTimeout = (long) (settings.getRpcTimeoutMultiplier() * prevSettings.getRpcTimeout().toMillis()); newRpcTimeout = Math.min(newRpcTimeout, settings.getMaxRpcTimeout().toMillis()); if (!settings.getTotalTimeout().isZero()) { Duration timeElapsed = Duration.ofNanos(clock.nanoTime()) .minus(Duration.ofNanos(prevSettings.getFirstAttemptStartTimeNanos())); Duration timeLeft = globalSettings.getTotalTimeout().minus(timeElapsed).minus(randomDelay); newRpcTimeout = Math.min(newRpcTimeout, timeLeft.toMillis()); } return TimedAttemptSettings.newBuilder() .setGlobalSettings(prevSettings.getGlobalSettings()) .setRetryDelay(Duration.ofMillis(newRetryDelay)) .setRpcTimeout(Duration.ofMillis(newRpcTimeout)) .setRandomizedRetryDelay(randomDelay) .setAttemptCount(prevSettings.getAttemptCount() + 1) .setOverallAttemptCount(prevSettings.getOverallAttemptCount() + 1) .setFirstAttemptStartTimeNanos(prevSettings.getFirstAttemptStartTimeNanos()) .build(); } ExponentialRetryAlgorithm(RetrySettings globalSettings, ApiClock clock); @Override TimedAttemptSettings createFirstAttempt(); @Override TimedAttemptSettings createNextAttempt(TimedAttemptSettings prevSettings); @Override boolean shouldRetry(TimedAttemptSettings nextAttemptSettings);  }
@Test public void testCreateNextAttempt() { TimedAttemptSettings firstAttempt = algorithm.createFirstAttempt(); TimedAttemptSettings secondAttempt = algorithm.createNextAttempt(firstAttempt); assertEquals(1, secondAttempt.getAttemptCount()); assertEquals(1, secondAttempt.getOverallAttemptCount()); assertEquals(Duration.ofMillis(1L), secondAttempt.getRetryDelay()); assertEquals(Duration.ofMillis(1L), secondAttempt.getRandomizedRetryDelay()); assertEquals(Duration.ofMillis(2L), secondAttempt.getRpcTimeout()); TimedAttemptSettings thirdAttempt = algorithm.createNextAttempt(secondAttempt); assertEquals(2, thirdAttempt.getAttemptCount()); assertEquals(Duration.ofMillis(2L), thirdAttempt.getRetryDelay()); assertEquals(Duration.ofMillis(2L), thirdAttempt.getRandomizedRetryDelay()); assertEquals(Duration.ofMillis(4L), thirdAttempt.getRpcTimeout()); }