Skip to content

Commit 8c29b2e

Browse files
committed
fix backoff calucuration #245
1 parent fc30022 commit 8c29b2e

File tree

2 files changed

+30
-16
lines changed

2 files changed

+30
-16
lines changed

src/main/java/io/socket/backo/Backoff.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package io.socket.backo;
22

3+
import java.math.BigDecimal;
4+
import java.math.BigInteger;
5+
36
public class Backoff {
47

58
private long ms = 100;
@@ -11,17 +14,16 @@ public class Backoff {
1114
public Backoff() {}
1215

1316
public long duration() {
14-
long ms = this.ms * (long) Math.pow(this.factor, this.attempts++);
17+
BigInteger ms = BigInteger.valueOf(this.ms)
18+
.multiply(BigInteger.valueOf(this.factor).pow(this.attempts++));
1519
if (jitter != 0.0) {
1620
double rand = Math.random();
17-
int deviation = (int) Math.floor(rand * this.jitter * ms);
18-
ms = (((int) Math.floor(rand * 10)) & 1) == 0 ? ms - deviation : ms + deviation;
19-
}
20-
if (ms < this.ms) {
21-
// overflow happened
22-
ms = Long.MAX_VALUE;
21+
BigInteger deviation = BigDecimal.valueOf(rand)
22+
.multiply(BigDecimal.valueOf(jitter))
23+
.multiply(new BigDecimal(ms)).toBigInteger();
24+
ms = (((int) Math.floor(rand * 10)) & 1) == 0 ? ms.subtract(deviation) : ms.add(deviation);
2325
}
24-
return Math.min(ms, this.max);
26+
return ms.min(BigInteger.valueOf(this.max)).longValue();
2527
}
2628

2729
public void reset() {

src/test/java/io/socket/backo/BackoffTest.java

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
import org.junit.Test;
44

5+
import java.math.BigDecimal;
6+
import java.math.BigInteger;
7+
58
import static org.junit.Assert.assertTrue;
69

710
public class BackoffTest {
@@ -22,14 +25,23 @@ public void durationShouldIncreaseTheBackoff() {
2225

2326
@Test
2427
public void durationOverflow() {
25-
Backoff b = new Backoff();
26-
b.setMin(100);
27-
b.setMax(10000);
28-
b.setJitter(1.0);
29-
30-
for (int i = 0; i < 100; i++) {
31-
long duration = b.duration();
32-
assertTrue(100 <= duration && duration <= 10000);
28+
for (int i = 0; i < 10; i++) {
29+
Backoff b = new Backoff();
30+
b.setMin(100);
31+
b.setMax(10000);
32+
b.setJitter(0.5);
33+
34+
// repeats to make it overflow (a long can have 2 ** 63 - 1)
35+
for (int j = 0; j < 100; j++) {
36+
BigInteger ms = BigInteger.valueOf(100).multiply(BigInteger.valueOf(2).pow(j));
37+
BigInteger deviation = new BigDecimal(ms).multiply(BigDecimal.valueOf(0.5)).toBigInteger();
38+
BigInteger duration = BigInteger.valueOf(b.duration());
39+
40+
BigInteger min = ms.subtract(deviation).min(BigInteger.valueOf(10000));
41+
BigInteger max = ms.add(deviation).min(BigInteger.valueOf(10001));
42+
assertTrue(min + " <= " + duration + " < " + max,
43+
min.compareTo(duration) <= 0 && max.compareTo(duration) == 1);
44+
}
3345
}
3446
}
3547
}

0 commit comments

Comments
 (0)