Documentation
¶
Index ¶
Examples ¶
Constants ¶
View Source
const ( ExpInitial = 500 * time.Millisecond ExpMultiplier = 1.5 )
Default values for ExpDelayer.
Variables ¶
View Source
var DefaultDelayer = ExpDelayer{Rand: 50}
DefaultDelayer is an ExpDelayer with Rand 50.
Functions ¶
Types ¶
type BreakError ¶
type BreakError struct {
Err error
}
BreakError indicates that the operation should not be retried.
func (*BreakError) Error ¶
func (e *BreakError) Error() string
func (*BreakError) Is ¶
func (e *BreakError) Is(target error) bool
func (*BreakError) Unwrap ¶
func (e *BreakError) Unwrap() error
type ConstantDelayer ¶
ConstantDelayer provides constant delay between attempts.
Example ¶
package main
import (
"fmt"
"time"
"github.com/go-camp/retry"
)
func main() {
delayer := retry.ConstantDelayer{Duration: time.Second}
for attempt := 1; attempt <= 3; attempt++ {
delay := delayer.Delay(attempt)
fmt.Println(delay)
}
}
Output: 1s 1s 1s
type Delayer ¶
Delayer calculates the delay before the next attempt after this attempt.
The delay before the first attempt(<=0) is always 0.
type ExpDelayer ¶
type ExpDelayer struct {
// Initial is the delay after first attempt.
// If Initial less than or equals to 0, the ExpInitial will be used.
Initial time.Duration
// Multiplier is a multiplicator used to calculate the delay after the last attempt.
// If Multiplier less than 1, the ExpMultiplier will be used.
Multiplier float64
// Max is max day between attempts.
// If Max less than or equals to 0, the math.MaxInt64 will be used.
Max time.Duration
// Rand gives delay a variation of ±(Rand%).
// The range of Rand is [0,100].
// If Rand greater than 100, 100 will be used.
// If Rand greater than 0, the delay may greater than Max.
Rand uint8
}
ExpDelayer provides exponential and random growth delay between attempts.
Example ¶
package main
import (
"fmt"
"time"
"github.com/go-camp/retry"
)
func main() {
delayer := retry.ExpDelayer{
Initial: 1 * time.Second,
Multiplier: 2,
Max: 20 * time.Second,
}
for attempt := 1; attempt <= 10; attempt++ {
delay := delayer.Delay(attempt)
fmt.Println(delay)
}
}
Output: 1s 2s 4s 8s 16s 20s 20s 20s 20s 20s
Example (Rand) ¶
package main
import (
"fmt"
"time"
"github.com/go-camp/retry"
)
func main() {
delayer := retry.ExpDelayer{
Initial: time.Second,
Multiplier: 2,
Max: 20 * time.Second,
Rand: 50,
}
delayRanges := [][2]time.Duration{
{500 * time.Millisecond, 1500 * time.Millisecond},
{1 * time.Second, 3 * time.Second},
{2 * time.Second, 6 * time.Second},
{4 * time.Second, 12 * time.Second},
{8 * time.Second, 24 * time.Second},
{10 * time.Second, 30 * time.Second},
{10 * time.Second, 30 * time.Second},
{10 * time.Second, 30 * time.Second},
{10 * time.Second, 30 * time.Second},
{10 * time.Second, 30 * time.Second},
}
for i, delayRange := range delayRanges {
attempt := i + 1
delay := delayer.Delay(attempt)
if delay >= delayRange[0] && delay <= delayRange[1] {
fmt.Println(delayRange)
} else {
fmt.Println(delay, "out range of", delayRange)
}
}
}
Output: [500ms 1.5s] [1s 3s] [2s 6s] [4s 12s] [8s 24s] [10s 30s] [10s 30s] [10s 30s] [10s 30s] [10s 30s]
type RetryResult ¶
func (RetryResult) FinalAttemptError ¶
func (rr RetryResult) FinalAttemptError() error
func (RetryResult) FinalOperationError ¶
func (rr RetryResult) FinalOperationError() error
type Retryer ¶
type Retryer struct {
// If Delayer is nil, the DefaultDelayer will be used.
Delayer Delayer
// MaxAttempts is the maximum number of calls to op.
// MaxAttempts is 0 means there is no constraint on the number of attempts.
MaxAttempts int
}
Retryer contains basic retry logic using Delayer.
Example (MaxAttempts) ¶
package main
import (
"context"
"fmt"
"github.com/go-camp/retry"
)
func printRetryResult(result retry.RetryResult) {
fmt.Printf("%+v\n", result)
fmt.Println("result.FinalOperationError:", result.FinalOperationError())
fmt.Println("result.FinalAttemptError:", result.FinalAttemptError())
}
func main() {
retryer := retry.Retryer{
Delayer: retry.NopDelayer{},
MaxAttempts: 3,
}
attempt := 0
result := retryer.Retry(
context.Background(),
func(context.Context) error {
attempt++
return fmt.Errorf("err%d", attempt)
},
)
printRetryResult(result)
}
Output: {MaxAttempts:3 Attempts:[{Delay:0s ContextError:<nil> OperationError:err1} {Delay:0s ContextError:<nil> OperationError:err2} {Delay:0s ContextError:<nil> OperationError:err3}]} result.FinalOperationError: err3 result.FinalAttemptError: err3
func (Retryer) Retry ¶
Retry retries to call function operation at least once.
Example (Break) ¶
package main
import (
"context"
"fmt"
"github.com/go-camp/retry"
)
func printRetryResult(result retry.RetryResult) {
fmt.Printf("%+v\n", result)
fmt.Println("result.FinalOperationError:", result.FinalOperationError())
fmt.Println("result.FinalAttemptError:", result.FinalAttemptError())
}
func main() {
retryer := retry.Retryer{
Delayer: retry.NopDelayer{},
MaxAttempts: 3,
}
attempt := 0
result := retryer.Retry(
context.Background(),
func(context.Context) error {
attempt++
return retry.Break(fmt.Errorf("err%d", attempt))
},
)
printRetryResult(result)
}
Output: {MaxAttempts:3 Attempts:[{Delay:0s ContextError:<nil> OperationError:err1}]} result.FinalOperationError: err1 result.FinalAttemptError: err1
Example (CtxCanceled) ¶
package main
import (
"context"
"fmt"
"github.com/go-camp/retry"
)
func printRetryResult(result retry.RetryResult) {
fmt.Printf("%+v\n", result)
fmt.Println("result.FinalOperationError:", result.FinalOperationError())
fmt.Println("result.FinalAttemptError:", result.FinalAttemptError())
}
func main() {
ctx, cancel := context.WithCancel(context.Background())
cancel()
retryer := retry.Retryer{
Delayer: retry.NopDelayer{},
MaxAttempts: 3,
}
attempt := 0
result := retryer.Retry(
ctx,
func(context.Context) error {
attempt++
return fmt.Errorf("err%d", attempt)
},
)
printRetryResult(result)
}
Output: {MaxAttempts:3 Attempts:[{Delay:0s ContextError:<nil> OperationError:err1} {Delay:0s ContextError:context canceled OperationError:<nil>}]} result.FinalOperationError: err1 result.FinalAttemptError: context canceled
Example (CtxCanceled2) ¶
package main
import (
"context"
"fmt"
"time"
"github.com/go-camp/retry"
)
func printRetryResult(result retry.RetryResult) {
fmt.Printf("%+v\n", result)
fmt.Println("result.FinalOperationError:", result.FinalOperationError())
fmt.Println("result.FinalAttemptError:", result.FinalAttemptError())
}
func main() {
ctx, cancel := context.WithCancel(context.Background())
go func() {
time.Sleep(time.Millisecond)
cancel()
}()
retryer := retry.Retryer{
Delayer: retry.ConstantDelayer{Duration: 2 * time.Millisecond},
MaxAttempts: 3,
}
attempt := 0
result := retryer.Retry(
ctx,
func(context.Context) error {
attempt++
return fmt.Errorf("err%d", attempt)
},
)
printRetryResult(result)
}
Output: {MaxAttempts:3 Attempts:[{Delay:0s ContextError:<nil> OperationError:err1} {Delay:2ms ContextError:context canceled OperationError:<nil>}]} result.FinalOperationError: err1 result.FinalAttemptError: context canceled
Example (CtxTimeout) ¶
package main
import (
"context"
"fmt"
"time"
"github.com/go-camp/retry"
)
func printRetryResult(result retry.RetryResult) {
fmt.Printf("%+v\n", result)
fmt.Println("result.FinalOperationError:", result.FinalOperationError())
fmt.Println("result.FinalAttemptError:", result.FinalAttemptError())
}
func main() {
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond)
defer cancel()
retryer := retry.Retryer{
Delayer: retry.ConstantDelayer{Duration: 2 * time.Millisecond},
MaxAttempts: 3,
}
attempt := 0
result := retryer.Retry(
ctx,
func(context.Context) error {
attempt++
return fmt.Errorf("err%d", attempt)
},
)
printRetryResult(result)
}
Output: {MaxAttempts:3 Attempts:[{Delay:0s ContextError:<nil> OperationError:err1} {Delay:2ms ContextError:context deadline exceeded OperationError:<nil>}]} result.FinalOperationError: err1 result.FinalAttemptError: context deadline exceeded
Example (Success) ¶
package main
import (
"context"
"fmt"
"github.com/go-camp/retry"
)
func printRetryResult(result retry.RetryResult) {
fmt.Printf("%+v\n", result)
fmt.Println("result.FinalOperationError:", result.FinalOperationError())
fmt.Println("result.FinalAttemptError:", result.FinalAttemptError())
}
func main() {
retryer := retry.Retryer{
Delayer: retry.NopDelayer{},
MaxAttempts: 3,
}
attempt := 0
result := retryer.Retry(
context.Background(),
func(context.Context) error {
attempt++
if attempt > 1 {
return nil
}
return fmt.Errorf("err%d", attempt)
},
)
printRetryResult(result)
}
Output: {MaxAttempts:3 Attempts:[{Delay:0s ContextError:<nil> OperationError:err1} {Delay:0s ContextError:<nil> OperationError:<nil>}]} result.FinalOperationError: <nil> result.FinalAttemptError: <nil>
Click to show internal directories.
Click to hide internal directories.