Skip to content

Commit

Permalink
Merge pull request #3 from daroot/duration
Browse files Browse the repository at this point in the history
Switch to using time.Duration for better flexibility.
  • Loading branch information
flowchartsman authored Jun 11, 2018
2 parents 3dc1156 + 49c23d0 commit 627dbb4
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 27 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Retrier objects are intended to be re-used, which means you define them once and
```go
// create a new retrier that will try a maximum of five times, with
// an initial delay of 100 ms and a maximum delay of 1 second
retrier := retry.NewRetrier(5, 100, 1000)
retrier := retry.NewRetrier(5, 100 * time.Millisecond, time.Second)

err := retrier.Run(func() error {
resp, err := http.Get("http://golang.org")
Expand All @@ -41,7 +41,7 @@ if err != nil {
```go
// create a new retrier that will try a maximum of five times, with
// an initial delay of 100 ms and a maximum delay of 1 second
retrier := retry.NewRetrier(5, 100, 1000)
retrier := retry.NewRetrier(5, 100 * time.Millisecond, time.Second)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond)
defer cancel()

Expand Down
22 changes: 11 additions & 11 deletions retry.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,31 @@ import (

// Default backoff
const (
DefaultMaxTries = 5
DefaultInitialDelayMS = 200
DefaultMaxDelayMS = 1000
DefaultMaxTries = 5
DefaultInitialDelay = time.Millisecond * 200
DefaultMaxDelay = time.Millisecond * 1000
)

// Retrier retries code blocks with or without context using an exponential
// backoff algorithm with jitter. It is intended to be used as a retry policy,
// which means it is safe to create and use concurrently.
type Retrier struct {
maxTries int
initialDelay int
maxDelay int
initialDelay time.Duration
maxDelay time.Duration
}

// NewRetrier returns a retrier for retrying functions with expoential backoff.
// If any of the values are <= 0, they will be set to their respective defaults.
func NewRetrier(maxTries, initialDelay, maxDelay int) *Retrier {
func NewRetrier(maxTries int, initialDelay, maxDelay time.Duration) *Retrier {
if maxTries <= 0 {
maxTries = DefaultMaxTries
}
if initialDelay <= 0 {
initialDelay = DefaultInitialDelayMS
initialDelay = DefaultInitialDelay
}
if maxDelay <= 0 {
maxDelay = DefaultMaxDelayMS
maxDelay = DefaultMaxDelay
}
return &Retrier{maxTries, initialDelay, maxDelay}
}
Expand Down Expand Up @@ -122,10 +122,10 @@ func (t terminalError) Error() string {
return t.e.Error()
}

func getnextBackoff(attempts, initialDelay, maxDelay int) time.Duration {
func getnextBackoff(attempts int, initialDelay, maxDelay time.Duration) time.Duration {
return min(
time.Duration(maxDelay)*time.Millisecond,
time.Duration(randInt63n(int64(initialDelay)*(1<<uint(attempts))))*time.Millisecond,
maxDelay,
time.Duration(randInt63n(int64(initialDelay)*(1<<uint(attempts)))),
)
}

Expand Down
28 changes: 14 additions & 14 deletions retry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func TestBackoffBacksOff(t *testing.T) {
tries := 0
start := time.Now()
var last time.Time
retrier := NewRetrier(5, 50, 50)
retrier := NewRetrier(5, 50*time.Millisecond, 50*time.Millisecond)
err := retrier.Run(func() error {
tries++
last = time.Now()
Expand All @@ -41,7 +41,7 @@ func TestBackoffBacksOff(t *testing.T) {
tries := 0
start := time.Now()
var last time.Time
retrier := NewRetrier(5, 50, 50)
retrier := NewRetrier(5, 50*time.Millisecond, 50*time.Millisecond)
err := retrier.RunContext(context.Background(), func(ctx context.Context) error {
tries++
last = time.Now()
Expand All @@ -63,7 +63,7 @@ func TestBackoffBacksOff(t *testing.T) {
func TestEventualSuccessSucceedsTransparently(t *testing.T) {
t.Run("r.Run", func(t *testing.T) {
tries := 0
retrier := NewRetrier(5, 50, 50)
retrier := NewRetrier(5, 50*time.Millisecond, 50*time.Millisecond)
err := retrier.Run(func() error {
tries++
if tries == 2 {
Expand All @@ -80,7 +80,7 @@ func TestEventualSuccessSucceedsTransparently(t *testing.T) {
})
t.Run("r.RunContext", func(t *testing.T) {
tries := 0
retrier := NewRetrier(5, 50, 50)
retrier := NewRetrier(5, 50*time.Millisecond, 50*time.Millisecond)
err := retrier.RunContext(context.Background(), func(ctx context.Context) error {
tries++
if tries == 2 {
Expand All @@ -102,7 +102,7 @@ func TestRunContextExitsEarlyWhenContextCanceled(t *testing.T) {
var wg sync.WaitGroup
tries := 0
ctx, canceler := context.WithCancel(context.Background())
retrier := NewRetrier(5, 50, 50)
retrier := NewRetrier(5, 50*time.Millisecond, 50*time.Millisecond)

wg.Add(1)
go func() {
Expand Down Expand Up @@ -130,7 +130,7 @@ func TestRunContextExitsEarlyWhenContextCanceled(t *testing.T) {
func TestStopStopsImmediately(t *testing.T) {
t.Run("r.Run", func(t *testing.T) {
tries := 0
retrier := NewRetrier(5, 50, 50)
retrier := NewRetrier(5, 50*time.Millisecond, 50*time.Millisecond)
err := retrier.Run(func() error {
tries++
return Stop(errTest)
Expand All @@ -145,7 +145,7 @@ func TestStopStopsImmediately(t *testing.T) {
})
t.Run("r.RunContext", func(t *testing.T) {
tries := 0
retrier := NewRetrier(5, 50, 50)
retrier := NewRetrier(5, 50*time.Millisecond, 50*time.Millisecond)
err := retrier.RunContext(context.Background(), func(ctx context.Context) error {
tries++
return Stop(errTest)
Expand All @@ -165,11 +165,11 @@ func TestRetrierGetsDefaultsIfLessThanZero(t *testing.T) {
if r.maxTries != DefaultMaxTries {
t.Errorf("expected maxTries to be %d, got %d", DefaultMaxTries, r.maxTries)
}
if r.initialDelay != DefaultInitialDelayMS {
t.Errorf("expected initialDelay to be %d, got %d", DefaultInitialDelayMS, r.initialDelay)
if r.initialDelay != DefaultInitialDelay {
t.Errorf("expected initialDelay to be %d, got %d", DefaultInitialDelay, r.initialDelay)
}
if r.maxDelay != DefaultMaxDelayMS {
t.Errorf("expected maxDelay to be %d, got %d", DefaultMaxDelayMS, r.maxDelay)
if r.maxDelay != DefaultMaxDelay {
t.Errorf("expected maxDelay to be %d, got %d", DefaultMaxDelay, r.maxDelay)
}
}

Expand All @@ -186,7 +186,7 @@ type myErrorType struct{}
func (m myErrorType) Error() string { return "myErrorType" }

func TestTerminalErrorRetainsOriginalError(t *testing.T) {
retrier := NewRetrier(5, 50, 50)
retrier := NewRetrier(5, 50*time.Millisecond, 50*time.Millisecond)
tries := 0
err := retrier.Run(func() error {
tries++
Expand All @@ -203,7 +203,7 @@ func TestTerminalErrorRetainsOriginalError(t *testing.T) {
}

func ExampleRetrier_Run() {
retrier := NewRetrier(5, 50, 50)
retrier := NewRetrier(5, 50*time.Millisecond, 50*time.Millisecond)
err := retrier.Run(func() error {
resp, err := http.Get("http://golang.org")
switch {
Expand All @@ -220,7 +220,7 @@ func ExampleRetrier_Run() {
}

func ExampleRetrier_RunContext_output() {
retrier := NewRetrier(5, 50, 50)
retrier := NewRetrier(5, 50*time.Millisecond, 50*time.Millisecond)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond)
defer cancel()

Expand Down

0 comments on commit 627dbb4

Please sign in to comment.