Skip to content

Commit

Permalink
Add exponential backoff with jitter algorithm for retry package
Browse files Browse the repository at this point in the history
  • Loading branch information
ghosx committed Nov 25, 2023
1 parent b913549 commit 8503409
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 0 deletions.
20 changes: 20 additions & 0 deletions common/retry/retry.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package retry
//go:generate go run github.com/v2fly/v2ray-core/v5/common/errors/errorgen

import (
"math"
"math/rand"
"time"
)

Expand Down Expand Up @@ -60,3 +62,21 @@ func ExponentialBackoff(attempts int, delay uint32) Strategy {
},
}
}

// ExponentialBackoffWithJitter return a retry exponential backoff strategy with jitter
// http://www.awsarchitectureblog.com/2015/03/backoff.html
func ExponentialBackoffWithJitter(attempts int, delay uint32) Strategy {
rr := rand.New(rand.NewSource(time.Now().UnixNano()))
capLevel := delay * 5
epoch := 0
return &retryer{
totalAttempt: attempts,
nextDelay: func() uint32 {
temp := math.Min(float64(capLevel), float64(delay)*math.Exp2(float64(epoch)))
ri := int64(temp / 2)
epoch += 1
jitter := rr.Int63n(ri)
return uint32(ri + jitter)
},
}
}
17 changes: 17 additions & 0 deletions common/retry/retry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,20 @@ func TestExponentialBackoff(t *testing.T) {
t.Error("duration: ", v)
}
}

func TestExponentialBackoffWithJitter(t *testing.T) {
startTime := time.Now()
called := 0
err := ExponentialBackoffWithJitter(10, 100).On(func() error {
called++
return errorTestOnly
})
duration := time.Since(startTime)

if errors.Cause(err) != ErrRetryFailed {
t.Error("cause: ", err)
}
if v := int64(duration / time.Millisecond); v < 2000 {
t.Error("duration: ", v)
}
}

0 comments on commit 8503409

Please sign in to comment.