Skip to content

Commit 35255b9

Browse files
committed
Add builder for Backoff
1 parent 75d5af1 commit 35255b9

File tree

7 files changed

+184
-0
lines changed

7 files changed

+184
-0
lines changed

core/src/main/java/com/linecorp/armeria/client/retry/ExponentialBackoff.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,4 +95,33 @@ public String toString() {
9595
.add("multiplier", multiplier)
9696
.toString();
9797
}
98+
99+
public static Builder builder() {
100+
return new Builder();
101+
}
102+
103+
public static class Builder {
104+
private long initialDelayMillis;
105+
private long maxDelayMillis;
106+
private double multiplier;
107+
108+
ExponentialBackoff build() {
109+
return new ExponentialBackoff(initialDelayMillis, maxDelayMillis, multiplier);
110+
}
111+
112+
public Builder initialDelayMillis(long initialDelayMillis) {
113+
this.initialDelayMillis = initialDelayMillis;
114+
return this;
115+
}
116+
117+
public Builder maxDelayMillis(long maxDelayMillis) {
118+
this.maxDelayMillis = maxDelayMillis;
119+
return this;
120+
}
121+
122+
public Builder multiplier(double multiplier) {
123+
this.multiplier = multiplier;
124+
return this;
125+
}
126+
}
98127
}

core/src/main/java/com/linecorp/armeria/client/retry/FibonacciBackoff.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,27 @@ public String toString() {
8888
.add("initialDelayMillis", initialDelayMillis)
8989
.add("maxDelayMillis", maxDelayMillis).toString();
9090
}
91+
92+
public static Builder builder() {
93+
return new Builder();
94+
}
95+
96+
public static class Builder {
97+
private long initialDelayMillis;
98+
private long maxDelayMillis;
99+
100+
FibonacciBackoff build() {
101+
return new FibonacciBackoff(initialDelayMillis, maxDelayMillis);
102+
}
103+
104+
public Builder initialDelayMillis(long initialDelayMillis) {
105+
this.initialDelayMillis = initialDelayMillis;
106+
return this;
107+
}
108+
109+
public Builder maxDelayMillis(long maxDelayMillis) {
110+
this.maxDelayMillis = maxDelayMillis;
111+
return this;
112+
}
113+
}
91114
}

core/src/main/java/com/linecorp/armeria/client/retry/FixedBackoff.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,21 @@ public String toString() {
4040
.add("delayMillis", delayMillis)
4141
.toString();
4242
}
43+
44+
public static Builder builder() {
45+
return new Builder();
46+
}
47+
48+
public static class Builder {
49+
private long delayMillis;
50+
51+
FixedBackoff build() {
52+
return new FixedBackoff(delayMillis);
53+
}
54+
55+
public Builder delayMillis(long delayMillis) {
56+
this.delayMillis = delayMillis;
57+
return this;
58+
}
59+
}
4360
}

core/src/main/java/com/linecorp/armeria/client/retry/RandomBackoff.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,33 @@ public String toString() {
7575
.add("maxDelayMillis", maxDelayMillis)
7676
.toString();
7777
}
78+
79+
public static Builder builder() {
80+
return new Builder();
81+
}
82+
83+
public static class Builder {
84+
private long minDelayMillis;
85+
private long maxDelayMillis;
86+
private Supplier<Random> randomSupplier;
87+
88+
RandomBackoff build() {
89+
return new RandomBackoff(minDelayMillis, maxDelayMillis, randomSupplier);
90+
}
91+
92+
public Builder minDelayMillis(long minDelayMillis) {
93+
this.minDelayMillis = minDelayMillis;
94+
return this;
95+
}
96+
97+
public Builder maxDelayMillis(long maxDelayMillis) {
98+
this.maxDelayMillis = maxDelayMillis;
99+
return this;
100+
}
101+
102+
public Builder randomSupplier(Supplier<Random> randomSupplier) {
103+
this.randomSupplier = randomSupplier;
104+
return this;
105+
}
106+
}
78107
}

core/src/test/java/com/linecorp/armeria/client/retry/ExponentialBackoffTest.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,19 @@ void normal() {
3131
assertThat(backoff.nextDelayMillis(5)).isEqualTo(120);
3232
assertThat(backoff.nextDelayMillis(6)).isEqualTo(120);
3333
assertThat(backoff.nextDelayMillis(7)).isEqualTo(120);
34+
35+
final Backoff backoff2 = ExponentialBackoff.builder()
36+
.initialDelayMillis(10)
37+
.maxDelayMillis(120)
38+
.multiplier(3.0)
39+
.build();
40+
assertThat(backoff2.nextDelayMillis(1)).isEqualTo(10);
41+
assertThat(backoff2.nextDelayMillis(2)).isEqualTo(30);
42+
assertThat(backoff2.nextDelayMillis(3)).isEqualTo(90);
43+
assertThat(backoff2.nextDelayMillis(4)).isEqualTo(120);
44+
assertThat(backoff2.nextDelayMillis(5)).isEqualTo(120);
45+
assertThat(backoff2.nextDelayMillis(6)).isEqualTo(120);
46+
assertThat(backoff2.nextDelayMillis(7)).isEqualTo(120);
3447
}
3548

3649
@Test
@@ -42,6 +55,17 @@ void nonPrecomputed() {
4255
assertThat(backoff.nextDelayMillis(30)).isEqualTo(5368709120L);
4356
// Not precomputed, should fallback to computation and return a correct value.
4457
assertThat(backoff.nextDelayMillis(31)).isEqualTo(10737418240L);
58+
59+
ExponentialBackoff backoff2 = ExponentialBackoff.builder()
60+
.initialDelayMillis(10)
61+
.maxDelayMillis(Long.MAX_VALUE)
62+
.multiplier(2.0)
63+
.build();
64+
assertThat(backoff2.nextDelayMillis(1)).isEqualTo(10);
65+
assertThat(backoff2.nextDelayMillis(2)).isEqualTo(20);
66+
assertThat(backoff2.nextDelayMillis(3)).isEqualTo(40);
67+
assertThat(backoff2.nextDelayMillis(30)).isEqualTo(5368709120L);
68+
assertThat(backoff2.nextDelayMillis(31)).isEqualTo(10737418240L);
4569
}
4670

4771
@Test
@@ -51,5 +75,15 @@ void overflow() {
5175
assertThat(backoff.nextDelayMillis(2)).isEqualTo((long) (Long.MAX_VALUE / 3 * 2.0));
5276
assertThat(backoff.nextDelayMillis(3)).isEqualTo(Long.MAX_VALUE);
5377
assertThat(backoff.nextDelayMillis(4)).isEqualTo(Long.MAX_VALUE);
78+
79+
ExponentialBackoff backoff2 = ExponentialBackoff.builder()
80+
.initialDelayMillis(Long.MAX_VALUE / 3)
81+
.maxDelayMillis(Long.MAX_VALUE)
82+
.multiplier(2.0)
83+
.build();
84+
assertThat(backoff2.nextDelayMillis(1)).isEqualTo(Long.MAX_VALUE / 3);
85+
assertThat(backoff2.nextDelayMillis(2)).isEqualTo((long) (Long.MAX_VALUE / 3 * 2.0));
86+
assertThat(backoff2.nextDelayMillis(3)).isEqualTo(Long.MAX_VALUE);
87+
assertThat(backoff2.nextDelayMillis(4)).isEqualTo(Long.MAX_VALUE);
5488
}
5589
}

core/src/test/java/com/linecorp/armeria/client/retry/FibonacciBackoffTest.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,16 @@ void testNextDelay() {
3030
assertThat(backoff.nextDelayMillis(3)).isEqualTo(20);
3131
assertThat(backoff.nextDelayMillis(4)).isEqualTo(30);
3232
assertThat(backoff.nextDelayMillis(7)).isEqualTo(120);
33+
34+
final Backoff backoff2 = FibonacciBackoff.builder()
35+
.initialDelayMillis(10)
36+
.maxDelayMillis(120)
37+
.build();
38+
assertThat(backoff2.nextDelayMillis(1)).isEqualTo(10);
39+
assertThat(backoff2.nextDelayMillis(2)).isEqualTo(10);
40+
assertThat(backoff2.nextDelayMillis(3)).isEqualTo(20);
41+
assertThat(backoff2.nextDelayMillis(4)).isEqualTo(30);
42+
assertThat(backoff2.nextDelayMillis(7)).isEqualTo(120);
3343
}
3444

3545
@Test
@@ -38,6 +48,14 @@ void testLargeNumberOfRetries() {
3848
assertThat(backoff.nextDelayMillis(30)).isEqualTo(832040);
3949
assertThat(backoff.nextDelayMillis(31)).isEqualTo(1346269);
4050
assertThat(backoff.nextDelayMillis(32)).isEqualTo(2178309);
51+
52+
final Backoff backoff2 = FibonacciBackoff.builder()
53+
.initialDelayMillis(1)
54+
.maxDelayMillis(Long.MAX_VALUE)
55+
.build();
56+
assertThat(backoff2.nextDelayMillis(30)).isEqualTo(832040);
57+
assertThat(backoff2.nextDelayMillis(31)).isEqualTo(1346269);
58+
assertThat(backoff2.nextDelayMillis(32)).isEqualTo(2178309);
4159
}
4260

4361
@Test
@@ -48,17 +66,37 @@ void testOverflow() {
4866
assertThat(backoff.nextDelayMillis(3)).isEqualTo(Long.MAX_VALUE / 3 * 2);
4967
assertThat(backoff.nextDelayMillis(4)).isEqualTo(Long.MAX_VALUE / 3 * 3);
5068
assertThat(backoff.nextDelayMillis(5)).isEqualTo(Long.MAX_VALUE);
69+
70+
final Backoff backoff2 = FibonacciBackoff.builder()
71+
.initialDelayMillis(Long.MAX_VALUE / 3)
72+
.maxDelayMillis(Long.MAX_VALUE)
73+
.build();
74+
assertThat(backoff.nextDelayMillis(1)).isEqualTo(Long.MAX_VALUE / 3);
75+
assertThat(backoff.nextDelayMillis(2)).isEqualTo(Long.MAX_VALUE / 3);
76+
assertThat(backoff.nextDelayMillis(3)).isEqualTo(Long.MAX_VALUE / 3 * 2);
77+
assertThat(backoff.nextDelayMillis(4)).isEqualTo(Long.MAX_VALUE / 3 * 3);
78+
assertThat(backoff.nextDelayMillis(5)).isEqualTo(Long.MAX_VALUE);
5179
}
5280

5381
@Test
5482
void testConstraintInitialDelay() {
5583
assertThatThrownBy(() -> new FibonacciBackoff(-5, 120))
5684
.isInstanceOf(IllegalArgumentException.class);
85+
assertThatThrownBy(() -> FibonacciBackoff.builder()
86+
.initialDelayMillis(-5)
87+
.maxDelayMillis(120)
88+
.build())
89+
.isInstanceOf(IllegalArgumentException.class);
5790
}
5891

5992
@Test
6093
void testConstraintMaxDelay() {
6194
assertThatThrownBy(() -> new FibonacciBackoff(10, 0))
6295
.isInstanceOf(IllegalArgumentException.class);
96+
assertThatThrownBy(() -> FibonacciBackoff.builder()
97+
.initialDelayMillis(10)
98+
.maxDelayMillis(0)
99+
.build())
100+
.isInstanceOf(IllegalArgumentException.class);
63101
}
64102
}

core/src/test/java/com/linecorp/armeria/client/retry/RandomBackoffTest.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,20 @@ public void nextDelayMillis() throws Exception {
3333
assertThat(backoff.nextDelayMillis(1)).isEqualTo(95);
3434
}
3535

36+
@Test
37+
public void nextDelayMillisWithBuilder() throws Exception {
38+
final Random r = new Random(1);
39+
final Backoff backoff2 = RandomBackoff.builder()
40+
.minDelayMillis(10)
41+
.maxDelayMillis(100)
42+
.randomSupplier(() -> r)
43+
.build();
44+
assertThat(backoff2.nextDelayMillis(1)).isEqualTo(18);
45+
assertThat(backoff2.nextDelayMillis(1)).isEqualTo(93);
46+
assertThat(backoff2.nextDelayMillis(1)).isEqualTo(12);
47+
assertThat(backoff2.nextDelayMillis(1)).isEqualTo(95);
48+
}
49+
3650
@Test
3751
public void validation() {
3852
// Negative minDelayMillis

0 commit comments

Comments
 (0)