Commit 30a1519d authored by Adin Schmahmann's avatar Adin Schmahmann

backoff strategy factory constructors take sources instead of seeds for randomness

parent c3c44c90
...@@ -91,8 +91,8 @@ func (b *fixedBackoff) Reset() {} ...@@ -91,8 +91,8 @@ func (b *fixedBackoff) Reset() {}
// timeUnits are the units of time the polynomial is evaluated in // timeUnits are the units of time the polynomial is evaluated in
// polyCoefs is the array of polynomial coefficients from [c0, c1, ... cn] // polyCoefs is the array of polynomial coefficients from [c0, c1, ... cn]
func NewPolynomialBackoff(min, max time.Duration, jitter Jitter, func NewPolynomialBackoff(min, max time.Duration, jitter Jitter,
timeUnits time.Duration, polyCoefs []float64, rngSeed int64) BackoffFactory { timeUnits time.Duration, polyCoefs []float64, rngSrc rand.Source) BackoffFactory {
rng := rand.New(&lockedSource{src: rand.NewSource(rngSeed)}) rng := rand.New(&lockedSource{src: rngSrc})
return func() BackoffStrategy { return func() BackoffStrategy {
return &polynomialBackoff{ return &polynomialBackoff{
attemptBackoff: attemptBackoff{ attemptBackoff: attemptBackoff{
...@@ -140,8 +140,8 @@ func (b *polynomialBackoff) Delay() time.Duration { ...@@ -140,8 +140,8 @@ func (b *polynomialBackoff) Delay() time.Duration {
// jitter is the function for adding randomness around the backoff // jitter is the function for adding randomness around the backoff
// timeUnits are the units of time the base^x is evaluated in // timeUnits are the units of time the base^x is evaluated in
func NewExponentialBackoff(min, max time.Duration, jitter Jitter, func NewExponentialBackoff(min, max time.Duration, jitter Jitter,
timeUnits time.Duration, base float64, offset time.Duration, rngSeed int64) BackoffFactory { timeUnits time.Duration, base float64, offset time.Duration, rngSrc rand.Source) BackoffFactory {
rng := rand.New(&lockedSource{src: rand.NewSource(rngSeed)}) rng := rand.New(&lockedSource{src: rngSrc})
return func() BackoffStrategy { return func() BackoffStrategy {
return &exponentialBackoff{ return &exponentialBackoff{
attemptBackoff: attemptBackoff{ attemptBackoff: attemptBackoff{
...@@ -176,8 +176,8 @@ func (b *exponentialBackoff) Delay() time.Duration { ...@@ -176,8 +176,8 @@ func (b *exponentialBackoff) Delay() time.Duration {
// NewExponentialDecorrelatedJitter creates a BackoffFactory with backoff of the roughly of the form base^x where x is the attempt number. // NewExponentialDecorrelatedJitter creates a BackoffFactory with backoff of the roughly of the form base^x where x is the attempt number.
// Delays start at the minimum duration and after each attempt delay = rand(min, delay * base), bounded by the max // Delays start at the minimum duration and after each attempt delay = rand(min, delay * base), bounded by the max
// See https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/ for more information // See https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/ for more information
func NewExponentialDecorrelatedJitter(min, max time.Duration, base float64, rngSeed int64) BackoffFactory { func NewExponentialDecorrelatedJitter(min, max time.Duration, base float64, rngSrc rand.Source) BackoffFactory {
rng := rand.New(&lockedSource{src: rand.NewSource(rngSeed)}) rng := rand.New(&lockedSource{src: rngSrc})
return func() BackoffStrategy { return func() BackoffStrategy {
return &exponentialDecorrelatedJitter{ return &exponentialDecorrelatedJitter{
randomizedBackoff: randomizedBackoff{ randomizedBackoff: randomizedBackoff{
......
...@@ -39,7 +39,7 @@ func TestFixedBackoff(t *testing.T) { ...@@ -39,7 +39,7 @@ func TestFixedBackoff(t *testing.T) {
} }
func TestPolynomialBackoff(t *testing.T) { func TestPolynomialBackoff(t *testing.T) {
bkf := NewPolynomialBackoff(time.Second, time.Second*33, NoJitter, time.Second, []float64{0.5, 2, 3}, 0) bkf := NewPolynomialBackoff(time.Second, time.Second*33, NoJitter, time.Second, []float64{0.5, 2, 3}, rand.NewSource(0))
b1 := bkf() b1 := bkf()
b2 := bkf() b2 := bkf()
...@@ -58,7 +58,7 @@ func TestPolynomialBackoff(t *testing.T) { ...@@ -58,7 +58,7 @@ func TestPolynomialBackoff(t *testing.T) {
} }
func TestExponentialBackoff(t *testing.T) { func TestExponentialBackoff(t *testing.T) {
bkf := NewExponentialBackoff(time.Millisecond*650, time.Second*7, NoJitter, time.Second, 1.5, -time.Millisecond*400, 0) bkf := NewExponentialBackoff(time.Millisecond*650, time.Second*7, NoJitter, time.Second, 1.5, -time.Millisecond*400, rand.NewSource(0))
b1 := bkf() b1 := bkf()
b2 := bkf() b2 := bkf()
...@@ -125,17 +125,17 @@ func TestFullJitter(t *testing.T) { ...@@ -125,17 +125,17 @@ func TestFullJitter(t *testing.T) {
} }
func TestManyBackoffFactory(t *testing.T) { func TestManyBackoffFactory(t *testing.T) {
rng := rand.New(rand.NewSource(0)) rngSource := rand.NewSource(0)
concurrent := 10 concurrent := 10
t.Run("Exponential", func(t *testing.T) { t.Run("Exponential", func(t *testing.T) {
testManyBackoffFactoryHelper(concurrent, testManyBackoffFactoryHelper(concurrent,
NewExponentialBackoff(time.Millisecond*650, time.Second*7, FullJitter, time.Second, 1.5, -time.Millisecond*400, rng), NewExponentialBackoff(time.Millisecond*650, time.Second*7, FullJitter, time.Second, 1.5, -time.Millisecond*400, rngSource),
) )
}) })
t.Run("Polynomial", func(t *testing.T) { t.Run("Polynomial", func(t *testing.T) {
testManyBackoffFactoryHelper(concurrent, testManyBackoffFactoryHelper(concurrent,
NewPolynomialBackoff(time.Second, time.Second*33, NoJitter, time.Second, []float64{0.5, 2, 3}, rng), NewPolynomialBackoff(time.Second, time.Second*33, NoJitter, time.Second, []float64{0.5, 2, 3}, rngSource),
) )
}) })
t.Run("Fixed", func(t *testing.T) { t.Run("Fixed", func(t *testing.T) {
...@@ -175,7 +175,7 @@ func testManyBackoffFactoryHelper(concurrent int, bkf BackoffFactory) { ...@@ -175,7 +175,7 @@ func testManyBackoffFactoryHelper(concurrent int, bkf BackoffFactory) {
} }
}() }()
for i := 0; i < 5 ; i++ { for i := 0; i < 5; i++ {
for j := 0; j < 10; j++ { for j := 0; j < 10; j++ {
backoff.Delay() backoff.Delay()
} }
...@@ -188,4 +188,4 @@ func testManyBackoffFactoryHelper(concurrent int, bkf BackoffFactory) { ...@@ -188,4 +188,4 @@ func testManyBackoffFactoryHelper(concurrent int, bkf BackoffFactory) {
if err := errGrp.Wait(); err != nil { if err := errGrp.Wait(); err != nil {
panic(err) panic(err)
} }
} }
\ No newline at end of file
...@@ -2,6 +2,7 @@ package discovery ...@@ -2,6 +2,7 @@ package discovery
import ( import (
"context" "context"
"math/rand"
"testing" "testing"
"time" "time"
...@@ -67,7 +68,7 @@ func TestBackoffDiscoverySingleBackoff(t *testing.T) { ...@@ -67,7 +68,7 @@ func TestBackoffDiscoverySingleBackoff(t *testing.T) {
d2 := &mockDiscoveryClient{h2, discServer} d2 := &mockDiscoveryClient{h2, discServer}
bkf := NewExponentialBackoff(time.Millisecond*100, time.Second*10, NoJitter, bkf := NewExponentialBackoff(time.Millisecond*100, time.Second*10, NoJitter,
time.Millisecond*100, 2.5, 0, 0) time.Millisecond*100, 2.5, 0, rand.NewSource(0))
dCache, err := NewBackoffDiscovery(d1, bkf) dCache, err := NewBackoffDiscovery(d1, bkf)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
...@@ -101,7 +102,7 @@ func TestBackoffDiscoveryMultipleBackoff(t *testing.T) { ...@@ -101,7 +102,7 @@ func TestBackoffDiscoveryMultipleBackoff(t *testing.T) {
// Startup delay is 0ms. First backoff after finding data is 100ms, second backoff is 250ms. // Startup delay is 0ms. First backoff after finding data is 100ms, second backoff is 250ms.
bkf := NewExponentialBackoff(time.Millisecond*100, time.Second*10, NoJitter, bkf := NewExponentialBackoff(time.Millisecond*100, time.Second*10, NoJitter,
time.Millisecond*100, 2.5, 0, 0) time.Millisecond*100, 2.5, 0, rand.NewSource(0))
dCache, err := NewBackoffDiscovery(d1, bkf) dCache, err := NewBackoffDiscovery(d1, bkf)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
......
...@@ -371,6 +371,7 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6Zh ...@@ -371,6 +371,7 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6Zh
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment