Add test and comments for RetryUtils.nextSleep (#17556)

This commit is contained in:
Kashif Faraz 2024-12-16 23:40:13 -08:00 committed by GitHub
parent cd6083fb94
commit e80a05c38e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 45 additions and 0 deletions

View File

@ -206,9 +206,29 @@ public class RetryUtils
Thread.sleep(sleepMillis); Thread.sleep(sleepMillis);
} }
/**
* Calculates the duration in milliseconds to sleep before the next attempt of
* a retryable operation. The duration is calculated in an exponential back-off
* manner with a fuzzy multiplier to introduce some variance.
* <p>
* Sleep duration in milliseconds for subsequent retries:
* <ul>
* <li>Retry 1: [0, 2000]</li>
* <li>Retry 2: [0, 4000]</li>
* <li>Retry 3: [0, 8000]</li>
* <li>...</li>
* <li>Retry 7 and later: [0, 120,000]</li>
* </ul>
*
* @param nTry Index of the next retry, starting with 1
* @return Next sleep duration in the range [0, 120,000] millis
*/
public static long nextRetrySleepMillis(final int nTry) public static long nextRetrySleepMillis(final int nTry)
{ {
// fuzzyMultiplier in [0, 2]
final double fuzzyMultiplier = Math.min(Math.max(1 + 0.2 * ThreadLocalRandom.current().nextGaussian(), 0), 2); final double fuzzyMultiplier = Math.min(Math.max(1 + 0.2 * ThreadLocalRandom.current().nextGaussian(), 0), 2);
// sleepMillis in [1 x 2^(nTry-1), 60] * [0, 2] seconds
final long sleepMillis = (long) (Math.min(MAX_SLEEP_MILLIS, BASE_SLEEP_MILLIS * Math.pow(2, nTry - 1)) final long sleepMillis = (long) (Math.min(MAX_SLEEP_MILLIS, BASE_SLEEP_MILLIS * Math.pow(2, nTry - 1))
* fuzzyMultiplier); * fuzzyMultiplier);
return sleepMillis; return sleepMillis;

View File

@ -186,4 +186,29 @@ public class RetryUtilsTest
Assert.assertEquals(result, "hey"); Assert.assertEquals(result, "hey");
Assert.assertEquals("count", 2, count.get()); Assert.assertEquals("count", 2, count.get());
} }
@Test
public void testNextRetrySleepMillis()
{
long totalSleepTimeMillis = 0;
for (int i = 1; i < 7; ++i) {
final long nextSleepMillis = RetryUtils.nextRetrySleepMillis(i);
Assert.assertTrue(nextSleepMillis >= 0);
Assert.assertTrue(nextSleepMillis <= (2_000 * Math.pow(2, i - 1)));
totalSleepTimeMillis += nextSleepMillis;
}
for (int i = 7; i < 11; ++i) {
final long nextSleepMillis = RetryUtils.nextRetrySleepMillis(i);
Assert.assertTrue(nextSleepMillis >= 0);
Assert.assertTrue(nextSleepMillis <= 120_000);
totalSleepTimeMillis += nextSleepMillis;
}
Assert.assertTrue(totalSleepTimeMillis > 3 * 60_000);
Assert.assertTrue(totalSleepTimeMillis < 8 * 60_000);
}
} }