@cryptotaxi247 / kubo / commits / e10289a93

fix: really cap the max backoff at 10 minutes

While preserving some randomness. And add a test.

Steven Allen committed May 25, 2020 at 21:18 UTC e10289a93d50e3cc80a5a3692b98391cc1aab62b
2 files changed +35 -2
peering/peering.go
+16 -2
@@ -14,10 +14,17 @@ import (
14 "github.com/multiformats/go-multiaddr"
15 )
16
17 +// Seed the random number generator.
18 +//
19 +// We don't need good randomness, but we do need randomness.
20 const (
21 // maxBackoff is the maximum time between reconnect attempts.
22 maxBackoff = 10 * time.Minute
20 - connmgrTag = "ipfs-peering"
23 + // The backoff will be cut off when we get within 10% of the actual max.
24 + // If we go over the max, we'll adjust the delay down to a random value
25 + // between 90-100% of the max backoff.
26 + maxBackoffJitter = 10 // %
27 + connmgrTag = "ipfs-peering"
28 // This needs to be sufficient to prevent two sides from simultaneously
29 // dialing.
30 initialDelay = 5 * time.Second
@@ -78,10 +85,17 @@ func (ph *peerHandler) stop() {
85 }
86
87 func (ph *peerHandler) nextBackoff() time.Duration {
81 - // calculate the timeout
88 if ph.nextDelay < maxBackoff {
89 ph.nextDelay += ph.nextDelay/2 + time.Duration(rand.Int63n(int64(ph.nextDelay)))
90 }
91 +
92 + // If we've gone over the max backoff, reduce it under the max.
93 + if ph.nextDelay > maxBackoff {
94 + ph.nextDelay = maxBackoff
95 + // randomize the backoff a bit (10%).
96 + ph.nextDelay -= time.Duration(rand.Int63n(int64(maxBackoff) * maxBackoffJitter / 100))
97 + }
98 +
99 return ph.nextDelay
100 }
101
peering/peering_test.go
+19
@@ -137,3 +137,22 @@ func TestPeeringService(t *testing.T) {
137 ps1.AddPeer(peer.AddrInfo{ID: h4.ID(), Addrs: h4.Addrs()})
138 ps1.RemovePeer(h2.ID())
139 }
140 +
141 +func TestNextBackoff(t *testing.T) {
142 + minMaxBackoff := (100 - maxBackoffJitter) / 100 * maxBackoff
143 + for x := 0; x < 1000; x++ {
144 + ph := peerHandler{nextDelay: time.Second}
145 + for min, max := time.Second*3/2, time.Second*5/2; min < minMaxBackoff; min, max = min*3/2, max*5/2 {
146 + b := ph.nextBackoff()
147 + if b > max || b < min {
148 + t.Errorf("expected backoff %s to be between %s and %s", b, min, max)
149 + }
150 + }
151 + for i := 0; i < 100; i++ {
152 + b := ph.nextBackoff()
153 + if b < minMaxBackoff || b > maxBackoff {
154 + t.Fatal("failed to stay within max bounds")
155 + }
156 + }
157 + }
158 +}