Skip to content

Commit

Permalink
4119 Initialize with a buffer to prevent pre-mature backoff calculation
Browse files Browse the repository at this point in the history
Signed-off-by: Tomas Longo <[email protected]>
  • Loading branch information
Tomas Longo authored and KarstenSchnitter committed Oct 11, 2024
1 parent 1232498 commit b29246a
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ class GrpcRetryInfoCalculator {
GrpcRetryInfoCalculator(Duration minimumDelay, Duration maximumDelay) {
this.minimumDelay = minimumDelay;
this.maximumDelay = maximumDelay;
this.lastTimeCalled = new AtomicReference<>(Instant.now());
// Create a cushion so that the calculator treats a first quick exception (after prepper startup) as normal request (e.g. does not calculate a backoff)
this.lastTimeCalled = new AtomicReference<>(Instant.now().minus(maximumDelay));
this.nextDelay = new AtomicReference<>(minimumDelay);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@ public void testExponentialBackoff() {
RetryInfo retryInfo1 = calculator.createRetryInfo();
RetryInfo retryInfo2 = calculator.createRetryInfo();
RetryInfo retryInfo3 = calculator.createRetryInfo();
RetryInfo retryInfo4 = calculator.createRetryInfo();

assertThat(retryInfo1.getRetryDelay().getSeconds(), equalTo(1L));
assertThat(retryInfo2.getRetryDelay().getSeconds(), equalTo(2L));
assertThat(retryInfo3.getRetryDelay().getSeconds(), equalTo(4L));
assertThat(retryInfo2.getRetryDelay().getSeconds(), equalTo(1L));
assertThat(retryInfo3.getRetryDelay().getSeconds(), equalTo(2L));
assertThat(retryInfo4.getRetryDelay().getSeconds(), equalTo(4L));
}

@Test
Expand All @@ -40,21 +42,42 @@ public void testUsesMaximumAsLongestDelay() {
RetryInfo retryInfo3 = calculator.createRetryInfo();

assertThat(retryInfo1.getRetryDelay().getSeconds(), equalTo(1L));
assertThat(retryInfo2.getRetryDelay().getSeconds(), equalTo(2L));
assertThat(retryInfo2.getRetryDelay().getSeconds(), equalTo(1L));
assertThat(retryInfo3.getRetryDelay().getSeconds(), equalTo(2L));
}

@Test
public void testResetAfterDelayWearsOff() throws InterruptedException {
int minDelayNanos = 1_000_000;
GrpcRetryInfoCalculator calculator =
new GrpcRetryInfoCalculator(Duration.ofNanos(1_000_000), Duration.ofSeconds(1));
new GrpcRetryInfoCalculator(Duration.ofNanos(minDelayNanos), Duration.ofSeconds(1));

RetryInfo retryInfo1 = calculator.createRetryInfo();
RetryInfo retryInfo2 = calculator.createRetryInfo();
Thread.sleep(5);
RetryInfo retryInfo3 = calculator.createRetryInfo();
sleep(retryInfo3);
RetryInfo retryInfo4 = calculator.createRetryInfo();

assertThat(retryInfo1.getRetryDelay().getNanos(), equalTo(minDelayNanos));
assertThat(retryInfo2.getRetryDelay().getNanos(), equalTo(minDelayNanos));
assertThat(retryInfo3.getRetryDelay().getNanos(), equalTo(minDelayNanos * 2));
assertThat(retryInfo4.getRetryDelay().getNanos(), equalTo(minDelayNanos));
}

@Test
public void testQuickFirstExceptionDoesNotTriggerBackoffCalculationEvenWithLongMinDelay() throws InterruptedException {
GrpcRetryInfoCalculator calculator =
new GrpcRetryInfoCalculator(Duration.ofSeconds(10), Duration.ofSeconds(20));

RetryInfo retryInfo1 = calculator.createRetryInfo();
RetryInfo retryInfo2 = calculator.createRetryInfo();

assertThat(retryInfo1.getRetryDelay().getSeconds(), equalTo(10L));
assertThat(retryInfo2.getRetryDelay().getSeconds(), equalTo(10L));
}

assertThat(retryInfo1.getRetryDelay().getNanos(), equalTo(1_000_000));
assertThat(retryInfo2.getRetryDelay().getNanos(), equalTo(2_000_000));
assertThat(retryInfo3.getRetryDelay().getNanos(), equalTo(1_000_000));
private void sleep(RetryInfo retryInfo) throws InterruptedException {
// make sure we let enough time pass by adding a few milliseconds on top
Thread.sleep((retryInfo.getRetryDelay().getNanos() / 1_000_000) + 200 );
}
}

0 comments on commit b29246a

Please sign in to comment.