Skip to content

Commit

Permalink
Add exponential backoff retry policy
Browse files Browse the repository at this point in the history
  • Loading branch information
rkuris committed May 30, 2017
1 parent 00a4bbc commit 31287b6
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 0 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,4 @@ Vincent Rischmann <me@vrischmann.me>
Jesse Claven <jesse.claven@gmail.com>
Derrick Wippler <thrawn01@gmail.com>
Leigh McCulloch <leigh@leighmcculloch.com>
Ron Kuris <swcafe@gmail.com>
31 changes: 31 additions & 0 deletions policies.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ package gocql

import (
"fmt"
"math"
"math/rand"
"net"
"sync"
"sync/atomic"
"time"

"github.com/hailocab/go-hostpool"
)
Expand Down Expand Up @@ -159,6 +162,34 @@ func (s *SimpleRetryPolicy) Attempt(q RetryableQuery) bool {
return q.Attempts() <= s.NumRetries
}

// ExponentialBackoffRetryPolicy sleeps between attempts
type ExponentialBackoffRetryPolicy struct {
NumRetries int
Min, Max time.Duration
}

func (e *ExponentialBackoffRetryPolicy) Attempt(q RetryableQuery) bool {
if q.Attempts() > e.NumRetries {
return false
}
time.Sleep(e.napTime(q.Attempts()))
return true
}

func (e *ExponentialBackoffRetryPolicy) napTime(attempts int) time.Duration {
if e.Min <= 0 {
e.Min = 100 * time.Millisecond
}
if e.Max <= 0 {
e.Max = 10 * time.Second
}
minFloat := float64(e.Min)
napDuration := minFloat * math.Pow(2, float64(attempts-1))
// add some jitter
napDuration += rand.Float64()*minFloat - (minFloat / 2)
return time.Duration(napDuration)
}

type HostStateNotifier interface {
AddHost(host *HostInfo)
RemoveHost(host *HostInfo)
Expand Down
29 changes: 29 additions & 0 deletions policies_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"fmt"
"net"
"testing"
"time"

"github.com/hailocab/go-hostpool"
)
Expand Down Expand Up @@ -272,3 +273,31 @@ func TestSimpleRetryPolicy(t *testing.T) {
}
}
}

func TestExponentialBackoffPolicy(t *testing.T) {
// test with defaults
sut := &ExponentialBackoffRetryPolicy{NumRetries: 2}

cases := []struct {
attempts int
delay time.Duration
}{

{1, 100 * time.Millisecond},
{2, (2) * 100 * time.Millisecond},
{3, (2 * 2) * 100 * time.Millisecond},
{4, (2 * 2 * 2) * 100 * time.Millisecond},
}
for _, c := range cases {
// test 100 times for each case
for i := 0; i < 100; i++ {
d := sut.napTime(c.attempts)
if d < c.delay-(100*time.Millisecond)/2 {
t.Fatalf("Delay %d less than jitter min of %d", d, c.delay-100*time.Millisecond/2)
}
if d > c.delay+(100*time.Millisecond)/2 {
t.Fatalf("Delay %d greater than jitter max of %d", d, c.delay+100*time.Millisecond/2)
}
}
}
}

0 comments on commit 31287b6

Please sign in to comment.