add backoff module tests
diff --git a/apigee_sync.go b/apigee_sync.go index 612e891..d6b3a19 100644 --- a/apigee_sync.go +++ b/apigee_sync.go
@@ -46,7 +46,7 @@ */ func pollWithBackoff(quit chan bool, toExecute func(chan bool) error, handleError func(error)) { - backoff := NewExponentialBackoff(200*time.Millisecond, config.GetDuration(configPollInterval), 2) + backoff := NewExponentialBackoff(200*time.Millisecond, config.GetDuration(configPollInterval), 2, true) //inintialize the retry channel to start first attempt immediately retry := time.After(0 * time.Millisecond)
diff --git a/backoff.go b/backoff.go index 291a037..e3a7403 100644 --- a/backoff.go +++ b/backoff.go
@@ -2,8 +2,8 @@ import ( "math" - "math/rand" "time" + "math/rand" ) const defaultInitial time.Duration = 200 * time.Millisecond @@ -13,6 +13,7 @@ type Backoff struct { attempt int initial, max time.Duration + jitter bool backoffStrategy func() time.Duration } @@ -21,7 +22,7 @@ factor float64 } -func NewExponentialBackoff(initial, max time.Duration, factor float64) *Backoff { +func NewExponentialBackoff(initial, max time.Duration, factor float64, jitter bool) *ExponentialBackoff { backoff := &ExponentialBackoff{} if initial <= 0 { @@ -39,9 +40,10 @@ backoff.max = max backoff.attempt = 0 backoff.factor = factor + backoff.jitter = jitter backoff.backoffStrategy = backoff.exponentialBackoffStrategy - return &backoff.Backoff + return backoff } func (b *Backoff) Duration() time.Duration { @@ -56,14 +58,15 @@ attempt := float64(b.Backoff.attempt) duration := initial * math.Pow(b.factor, attempt) - //introduce some jitter - duration = (rand.Float64()*(duration-initial) + initial) - if duration > math.MaxInt64 { return b.max } dur := time.Duration(duration) + if b.jitter { + duration = (rand.Float64()*(duration-initial) + initial) + } + if dur > b.max { return b.max }
diff --git a/backoff_test.go b/backoff_test.go new file mode 100644 index 0000000..dbf956c --- /dev/null +++ b/backoff_test.go
@@ -0,0 +1,56 @@ +package apidApigeeSync + +import ( + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "time" +) + +var _ = FDescribe("backoff", func() { + + Context("Backoff timeout calculations", func() { + + It("Should properly apply defaults", func() { + log.Info("Starting backoff tests...") + b := NewExponentialBackoff(0, 0, 0, true) + Expect(defaultInitial).To(Equal(b.initial)) + Expect(defaultMax).To(Equal(b.max)) + Expect(defaultFactor).To(Equal(b.factor)) + + b = NewExponentialBackoff(-1, -1, -1, true) + Expect(defaultInitial).To(Equal(b.initial)) + Expect(defaultMax).To(Equal(b.max)) + Expect(defaultFactor).To(Equal(b.factor)) + }) + + It("should properly apply exponential backoff strategy", func() { + b := NewExponentialBackoff(200 * time.Millisecond, 2 * time.Second, 2, false) + Expect(200 * time.Millisecond).To(Equal(b.Duration())) + Expect(1).To(Equal(b.Attempt())) + Expect(400 * time.Millisecond).To(Equal(b.Duration())) + Expect(2).To(Equal(b.Attempt())) + Expect(800 * time.Millisecond).To(Equal(b.Duration())) + Expect(3).To(Equal(b.Attempt())) + Expect(1600 * time.Millisecond).To(Equal(b.Duration())) + Expect(4).To(Equal(b.Attempt())) + }) + + It("should reset properly", func() { + b := NewExponentialBackoff(200 * time.Millisecond, 2 * time.Second, 2, false) + Expect(200 * time.Millisecond).To(Equal(b.Duration())) + Expect(1).To(Equal(b.Attempt())) + Expect(400 * time.Millisecond).To(Equal(b.Duration())) + Expect(2).To(Equal(b.Attempt())) + Expect(800 * time.Millisecond).To(Equal(b.Duration())) + Expect(3).To(Equal(b.Attempt())) + b.Reset() + Expect(200 * time.Millisecond).To(Equal(b.Duration())) + Expect(1).To(Equal(b.Attempt())) + Expect(400 * time.Millisecond).To(Equal(b.Duration())) + Expect(2).To(Equal(b.Attempt())) + Expect(800 * time.Millisecond).To(Equal(b.Duration())) + Expect(3).To(Equal(b.Attempt())) + }) + }) + +})