Bläddra i källkod

Protect rand prng with a mutex. Add test against regressions.

Gabriel Glachant 7 år sedan
förälder
incheckning
2c68be121c
2 ändrade filer med 17 tillägg och 0 borttagningar
  1. 5 0
      retrier/retrier.go
  2. 12 0
      retrier/retrier_test.go

+ 5 - 0
retrier/retrier.go

@@ -3,6 +3,7 @@ package retrier
 
 import (
 	"math/rand"
+	"sync"
 	"time"
 )
 
@@ -13,6 +14,7 @@ type Retrier struct {
 	class   Classifier
 	jitter  float64
 	rand    *rand.Rand
+	randMu  sync.Mutex
 }
 
 // New constructs a Retrier with the given backoff pattern and classifier. The length of the backoff pattern
@@ -55,6 +57,9 @@ func (r *Retrier) Run(work func() error) error {
 }
 
 func (r *Retrier) calcSleep(i int) time.Duration {
+	// lock unsafe rand prng
+	r.randMu.Lock()
+	defer r.randMu.Unlock()
 	// take a random float in the range (-r.jitter, +r.jitter) and multiply it by the base amount
 	return r.backoff[i] + time.Duration(((r.rand.Float64()*2)-1)*r.jitter*float64(r.backoff[i]))
 }

+ 12 - 0
retrier/retrier_test.go

@@ -1,6 +1,7 @@
 package retrier
 
 import (
+	"errors"
 	"testing"
 	"time"
 )
@@ -115,6 +116,17 @@ func TestRetrierJitter(t *testing.T) {
 	}
 }
 
+func TestRetrierThreadSafety(t *testing.T) {
+	r := New([]time.Duration{0}, nil)
+	for i := 0; i < 2; i++ {
+		go func() {
+			r.Run(func() error {
+				return errors.New("error")
+			})
+		}()
+	}
+}
+
 func ExampleRetrier() {
 	r := New(ConstantBackoff(3, 100*time.Millisecond), nil)