Skip to content

Commit 6fc9ba6

Browse files
committed
add method to retry as many time for a duration
1 parent e3d6204 commit 6fc9ba6

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

core/src/main/java/org/apache/accumulo/core/util/Retry.java

+28
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,12 @@ public interface NeedsRetries {
268268
* @return this builder with the maximum number of retries set to the provided value
269269
*/
270270
NeedsRetryDelay maxRetries(long max);
271+
272+
/**
273+
* @return this builder with the maximum number of retries set to the number of retries that can
274+
* occur within the given duration
275+
*/
276+
NeedsRetryDelay retriesForDuration(long duration, TimeUnit unit);
271277
}
272278

273279
public interface NeedsRetryDelay {
@@ -380,6 +386,28 @@ public NeedsRetryDelay maxRetries(long max) {
380386
return this;
381387
}
382388

389+
@Override
390+
public NeedsRetryDelay retriesForDuration(long duration, TimeUnit unit) {
391+
checkState();
392+
long durationInMillis = unit.toMillis(duration);
393+
long totalWait = 0;
394+
long retries = 0;
395+
long currentWait = initialWait;
396+
while (totalWait < durationInMillis && (maxRetries == -1 || retries < maxRetries)) {
397+
totalWait += currentWait;
398+
if (totalWait < durationInMillis) {
399+
retries++;
400+
if (backOffFactor > 1) {
401+
currentWait = Math.min(maxWait, (long) (currentWait * backOffFactor));
402+
} else {
403+
currentWait = Math.min(maxWait, currentWait + waitIncrement);
404+
}
405+
}
406+
}
407+
this.maxRetries = retries;
408+
return this;
409+
}
410+
383411
@Override
384412
public NeedsTimeIncrement retryAfter(long duration, TimeUnit unit) {
385413
checkState();

core/src/test/java/org/apache/accumulo/core/util/RetryTest.java

+33
Original file line numberDiff line numberDiff line change
@@ -344,4 +344,37 @@ public void testInfiniteRetryWithBackoff() throws InterruptedException {
344344
}
345345
}
346346
}
347+
348+
@Test
349+
public void testRetriesForDuration() throws InterruptedException {
350+
final TimeUnit unit = MILLISECONDS;
351+
final long duration = 10_000;
352+
353+
Retry retry = Retry.builder().retriesForDuration(duration, unit).retryAfter(100, unit)
354+
.incrementBy(100, unit).maxWait(500, unit).backOffFactor(1.5).logInterval(3, MINUTES)
355+
.createRetry();
356+
357+
long totalTime = 0;
358+
long expectedRetries = 0;
359+
360+
// While the total wait time is less than the duration and there are retries left
361+
while (totalTime <= duration && retry.canRetry()) {
362+
totalTime += retry.getCurrentWait();
363+
if (totalTime <= duration) {
364+
retry.useRetry();
365+
expectedRetries++;
366+
if (retry.canRetry()) {
367+
try {
368+
retry.waitForNextAttempt(log, "Iteration " + expectedRetries);
369+
} catch (IllegalArgumentException | InterruptedException e) {
370+
log.error("Failed on iteration: {}", expectedRetries, e);
371+
throw e;
372+
}
373+
}
374+
}
375+
}
376+
377+
assertEquals(expectedRetries, retry.retriesCompleted());
378+
}
379+
347380
}

0 commit comments

Comments
 (0)