retry

package module
v0.1.9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 6, 2024 License: MIT Imports: 6 Imported by: 1

README

English | 中文

Retry

A simple, dependency-free module for effortless function retrying in various scenarios.

logo

Go Report Card Build Status Go Reference

Introduction

Retry is a lightweight module for retrying function calls. It is simple, easy to use, and has no third-party dependencies. It is designed for scenarios where you need to retry a function call.

Retry provides the following features:

  1. Retry a function call a specified number of times.
  2. Retry a function call a specified number of times for specific errors.
  3. Support action callback functions.
  4. Support jitter factor for delay.
  5. Support exponential backoff delay, random delay, and fixed delay.
  6. Support recording detailed errors for each failed retry.

Advantages

  • Simple and user-friendly
  • No external dependencies required
  • Efficient memory usage
  • Supports callback functions

Installation

go get github.com/shengyanli1982/retry

Quick Start

Using Retry is simple. Just one line of code is needed to retry a function call.

1. Normal Model

Config

Retry provides a config object to customize the retry behavior. The config object has the following fields:

  • ctx: The context.Context object. The default value is context.Background().
  • callback: The callback function. The default value is &emptyCallback{}.
  • attempts: The number of retry attempts. The default value is 3.
  • attemptsByErrors: The number of retry attempts for specific errors. The default value is map[error]uint64{}.
  • delay: The delay time between retries. The default value is 200ms.
  • factor: The retry times factor. The default value is 1.0.
  • retryIf: The function to determine whether to retry. The default value is defaultRetryIfFunc.
  • backoff: The backoff function. The default value is defaultBackoffFunc.
  • detail: Whether to record detailed errors. The default value is false.

You can use the following methods to set config values:

  • WithContext: Set the context.Context object.
  • WithCallback: Set the callback function.
  • WithAttempts: Set the number of retry attempts.
  • WithAttemptsByError: Set the number of retry attempts for specific errors.
  • WithDelay: Set the delay time for the first retry.
  • WithFactor: Set the retry times factor.
  • WithRetryIfFunc: Set the function to determine whether to retry.
  • WithBackOffFunc: Set the backoff function.
  • WithDetail: Set whether to record detailed errors.

[!NOTE] The backoff algorithm determines the delay time between retries. Retry supports three backoff algorithms: exponential backoff, random backoff, and fixed backoff. By default, Retry uses exponential backoff with random backoff values added to the delay time.

You can use the WithBackOffFunc method to set the backoff algorithm.

eg: backoff = backoffFunc(factor * count + jitter * rand.Float64()) * 100 * Millisecond + delay

Methods
  • Do: Retry a function call by specifying a config object and a function. It returns a Result object.
  • DoWithDefault: Retry a function call with default config values. It returns a Result object.

[!TIP] The Result object contains the result of the function call, the error of the last retry, the errors of all retries, and whether the retry was successful. If the function call fails, the default value will be returned.

Exec Result

After retrying, Retry returns a Result object. The Result object provides the following methods:

  • Data: Get the result of the successfully called function. The type is interface{}.
  • TryError: Get the error of the retry action. If the retry is successful, the value is nil.
  • ExecErrors: Get the errors of all retries.
  • IsSuccess: Check if the retry action was successful.
  • LastExecError: Get the last error of the retries.
  • FirstExecError: Get the first error of the retries.
  • ExecErrorByIndex: Get the error of a specific retry by index.
Example
package main

import (
	"fmt"

	"github.com/shengyanli1982/retry"
)

// 定义一个可重试的函数
// Define a retryable function
func testFunc() (any, error) {
	// 此函数返回一个字符串 "lee" 和一个 nil 错误
	// This function returns a string "lee" and a nil error
	return "lee", nil
}

func main() {
	// 使用默认的重试策略调用 testFunc 函数
	// Call the testFunc function using the default retry strategy
	result := retry.DoWithDefault(testFunc)

	// 打印执行结果
	// Print the execution result
	fmt.Println("result:", result.Data())

	// 打印尝试执行的错误
	// Print the error of the attempt to execute
	fmt.Println("tryError:", result.TryError())

	// 打印执行过程中的所有错误
	// Print all errors during execution
	fmt.Println("execErrors:", result.ExecErrors())

	// 打印是否成功执行
	// Print whether the execution was successful
	fmt.Println("isSuccess:", result.IsSuccess())
}

Result

$ go run demo.go
result: lee
tryError: <nil>
execErrors: []
isSuccess: true

2. Factory Model

The Factory Model provides all the same retry functions and features as the Normal Model. It uses the same Config, Methods, Result, and Callback.

The only difference is that the Retry object is created using the New method. Then you can use the TryOnConflict method to retry the function call with the same parameters.

Example
package main

import (
	"errors"
	"fmt"

	"github.com/shengyanli1982/retry"
)

// 定义一个可重试的函数 testFunc1
// Define a retryable function testFunc1
func testFunc1() (any, error) {
	// 此函数返回一个字符串 "testFunc1" 和一个 nil 错误
	// This function returns a string "testFunc1" and a nil error
	return "testFunc1", nil
}

// 定义一个可重试的函数 testFunc2
// Define a retryable function testFunc2
func testFunc2() (any, error) {
	// 此函数返回一个 nil 和一个新的错误 "testFunc2"
	// This function returns a nil and a new error "testFunc2"
	return nil, errors.New("testFunc2")
}

func main() {
	// 使用默认的配置创建一个新的重试实例
	// Create a new retry instance with the default configuration
	r := retry.New(nil)

	// 尝试执行 testFunc1 函数,如果遇到冲突则进行重试
	// Try to execute the testFunc1 function, retry if there is a conflict
	result := r.TryOnConflict(testFunc1)

	// 打印 testFunc1 执行结果
	// Print the testFunc1 execution result
	fmt.Println("========= testFunc1 =========")

	// 打印执行结果
	// Print the execution result
	fmt.Println("result:", result.Data())

	// 打印尝试执行的错误
	// Print the error of the attempt to execute
	fmt.Println("tryError:", result.TryError())

	// 打印执行过程中的所有错误
	// Print all errors during execution
	fmt.Println("execErrors:", result.ExecErrors())

	// 打印是否成功执行
	// Print whether the execution was successful
	fmt.Println("isSuccess:", result.IsSuccess())

	// 尝试执行 testFunc2 函数,如果遇到冲突则进行重试
	// Try to execute the testFunc2 function, retry if there is a conflict
	result = r.TryOnConflict(testFunc2)

	// 打印 testFunc2 执行结果
	// Print the testFunc2 execution result
	fmt.Println("========= testFunc2 =========")

	// 打印执行结果
	// Print the execution result
	fmt.Println("result:", result.Data())

	// 打印尝试执行的错误
	// Print the error of the attempt to execute
	fmt.Println("tryError:", result.TryError())

	// 打印执行过程中的所有错误
	// Print all errors during execution
	fmt.Println("execErrors:", result.ExecErrors())

	// 打印是否成功执行
	// Print whether the execution was successful
	fmt.Println("isSuccess:", result.IsSuccess())
}

Result

$ go run demo.go
========= testFunc1 =========
result: testFunc1
tryError: <nil>
execErrors: []
isSuccess: true
========= testFunc2 =========
result: <nil>
tryError: retry attempts exceeded
execErrors: []
isSuccess: false

Features

Retry provides a set of features that are sufficient for most services.

1. Callback

Retry supports callback functions. You can specify a callback function when creating a retry, and it will be called when the Retry performs certain actions.

[!TIP] Callback functions are optional. If you don't need a callback function, you can pass nil when creating a retry, and it won't be called.

You can use the WithCallback method to set a callback function.

The callback function has the following methods:

  • OnRetry: called when retrying. The count parameter represents the current retry count, the delay parameter represents the delay time for the next retry, and the err parameter represents the error from the last retry.

    // Callback 接口用于定义重试回调函数
    // The Callback interface is used to define the retry callback function.
    type Callback interface {
    	// OnRetry 方法在每次重试时调用,传入当前的重试次数、延迟时间和错误信息
    	// The OnRetry method is called on each retry, passing in the current retry count, delay time, and error information
    	OnRetry(count int64, delay time.Duration, err error)
    }
    
Example
package main

import (
	"errors"
	"fmt"
	"time"

	"github.com/shengyanli1982/retry"
)

// 定义一个错误变量
// Define an error variable
var err = errors.New("test") // error

// 定义一个回调结构体
// Define a callback structure
type callback struct{}

// OnRetry 方法在每次重试时被调用,接收重试次数、延迟时间和错误作为参数
// The OnRetry method is called each time a retry is performed, receiving the number of retries, delay time, and error as parameters
func (cb *callback) OnRetry(count int64, delay time.Duration, err error) {
	fmt.Println("OnRetry", count, delay.String(), err)
}

// 定义一个可重试的函数,返回一个 nil 和一个错误
// Define a retryable function that returns a nil and an error
func testFunc() (any, error) {
	return nil, err
}

func main() {
	// 创建一个新的重试配置,并设置回调函数
	// Create a new retry configuration and set the callback function
	cfg := retry.NewConfig().WithCallback(&callback{})

	// 使用重试配置调用可重试的函数
	// Call the retryable function using the retry configuration
	result := retry.Do(testFunc, cfg)

	// 打印执行结果
	// Print the execution result
	fmt.Println("result:", result.Data())

	// 打印尝试执行的错误
	// Print the error of the attempt to execute
	fmt.Println("tryError:", result.TryError())

	// 打印执行过程中的所有错误
	// Print all errors during execution
	fmt.Println("execErrors:", result.ExecErrors())

	// 打印是否成功执行
	// Print whether the execution was successful
	fmt.Println("isSuccess:", result.IsSuccess())
}

Result

$ go run demo.go
OnRetry 1 1s test
OnRetry 2 1.5s test
OnRetry 3 2.4s test
result: <nil>
tryError: retry attempts exceeded
execErrors: []
isSuccess: false

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrorRetryIf 表示重试检查函数的结果为FALSE的错误
	// ErrorRetryIf represents an error when the retry check function result is FALSE
	ErrorRetryIf = errors.New("retry check func result is FALSE")

	// ErrorRetryAttemptsExceeded 表示重试次数超过限制的错误
	// ErrorRetryAttemptsExceeded represents an error when the retry attempts exceeded the limit
	ErrorRetryAttemptsExceeded = errors.New("retry attempts exceeded")

	// ErrorRetryAttemptsByErrorExceeded 表示由于特定错误导致的重试次数超过限制的错误
	// ErrorRetryAttemptsByErrorExceeded represents an error when the retry attempts exceeded the limit due to a specific error
	ErrorRetryAttemptsByErrorExceeded = errors.New("retry attempts by spec error exceeded")

	// ErrorExecErrByIndexOutOfBound 表示由于索引越界导致的执行错误
	// ErrorExecErrByIndexOutOfBound represents an execution error caused by index out of bound
	ErrorExecErrByIndexOutOfBound = errors.New("exec error by index out of bound")

	// ErrorExecErrNotFound 表示未找到执行错误
	// ErrorExecErrNotFound represents an error when the execution error is not found
	ErrorExecErrNotFound = errors.New("exec error not found")
)

Functions

func ExponentialBackoff added in v0.1.9

func ExponentialBackoff(power int64) time.Duration

ExponentialBackoff 返回指数增长的退避策略 ExponentialBackoff returns an exponential backoff strategy

func FixedBackoff added in v0.1.9

func FixedBackoff(interval int64) time.Duration

FixedBackoff 返回固定时间间隔的退避策略 FixedBackoff returns a fixed-interval backoff strategy

func RandomBackoff added in v0.1.9

func RandomBackoff(maxInterval int64) time.Duration

RandomBackoff 返回随机时间间隔的退避策略 RandomBackoff returns a random-interval backoff strategy

Types

type BackoffFunc

type BackoffFunc = func(int64) time.Duration

BackoffFunc 定义了退避策略函数的类型 BackoffFunc defines the type for backoff strategy functions

func CombineBackoffs added in v0.1.9

func CombineBackoffs(backoffs ...BackoffFunc) BackoffFunc

CombineBackoffs 将多个退避策略组合成一个 CombineBackoffs combines multiple backoff strategies into one

type Callback

type Callback interface {
	// OnRetry 方法在每次重试时调用,传入当前的重试次数、延迟时间和错误信息
	// The OnRetry method is called on each retry, passing in the current retry count, delay time, and error information
	OnRetry(count int64, delay time.Duration, err error)
}

Callback 接口用于定义重试回调函数 The Callback interface is used to define the retry callback function.

func NewEmptyCallback added in v0.1.4

func NewEmptyCallback() Callback

NewEmptyCallback 函数返回一个新的空回调实例 The NewEmptyCallback function returns a new empty callback instance

type Config

type Config struct {
	// contains filtered or unexported fields
}

Config 结构体定义了重试的配置 The Config structure defines the configuration for retries

func DefaultConfig added in v0.1.1

func DefaultConfig() *Config

DefaultConfig 函数返回一个新的默认配置的 Config 实例 The DefaultConfig function returns a new Config instance with the default configuration

func FixConfig added in v0.1.1

func FixConfig() *Config

FixConfig 函数返回一个新的固定退避时间的 Config 实例 The FixConfig function returns a new Config instance with a fixed backoff time

func NewConfig

func NewConfig() *Config

NewConfig 函数返回一个新的 Config 实例,使用默认的配置 The NewConfig function returns a new Config instance with the default configuration

func (*Config) WithAttempts

func (c *Config) WithAttempts(attempts uint64) *Config

WithAttempts 方法设置 Config 的重试次数并返回 Config 实例 The WithAttempts method sets the number of retries of the Config and returns the Config instance

func (*Config) WithAttemptsByError

func (c *Config) WithAttemptsByError(attemptsByError map[error]uint64) *Config

WithAttemptsByError 方法设置 Config 的错误重试次数并返回 Config 实例 The WithAttemptsByError method sets the number of error retries of the Config and returns the Config instance

func (*Config) WithBackOffFunc added in v0.1.4

func (c *Config) WithBackOffFunc(backoff BackoffFunc) *Config

WithBackOffFunc 方法设置 Config 的退避函数并返回 Config 实例 The WithBackOffFunc method sets the backoff function of the Config and returns the Config instance

func (*Config) WithCallback

func (c *Config) WithCallback(cb Callback) *Config

WithCallback 方法设置 Config 的回调函数并返回 Config 实例 The WithCallback method sets the callback function of the Config and returns the Config instance

func (*Config) WithContext

func (c *Config) WithContext(ctx context.Context) *Config

WithContext 方法设置 Config 的上下文并返回 Config 实例 The WithContext method sets the context of the Config and returns the Config instance

func (*Config) WithDetail

func (c *Config) WithDetail(detail bool) *Config

WithDetail 方法设置 Config 的详细错误信息显示选项并返回 Config 实例 The WithDetail method sets the detailed error information display option of the Config and returns the Config instance

func (*Config) WithFactor

func (c *Config) WithFactor(factor float64) *Config

WithFactor 方法设置 Config 的因子并返回 Config 实例 The WithFactor method sets the factor of the Config and returns the Config instance

func (*Config) WithInitDelay added in v0.1.4

func (c *Config) WithInitDelay(delay time.Duration) *Config

WithInitDelay 方法设置 Config 的初始延迟时间并返回 Config 实例 The WithInitDelay method sets the initial delay time of the Config and returns the Config instance

func (*Config) WithJitter

func (c *Config) WithJitter(jitter float64) *Config

WithJitter 方法设置 Config 的抖动并返回 Config 实例 The WithJitter method sets the jitter of the Config and returns the Config instance

func (*Config) WithRetryIfFunc added in v0.1.4

func (c *Config) WithRetryIfFunc(retryIf RetryIfFunc) *Config

WithRetryIfFunc 方法设置 Config 的重试条件函数并返回 Config 实例 The WithRetryIfFunc method sets the retry condition function of the Config and returns the Config instance

type Result

type Result struct {
	// contains filtered or unexported fields
}

Result 结构体用于存储执行结果 The Result struct is used to store the execution result

func NewResult

func NewResult() *Result

NewResult 函数用于创建一个新的 Result 实例 The NewResult function is used to create a new Result instance

func (*Result) Count

func (r *Result) Count() int64

Count 方法返回执行的次数 The Count method returns the number of executions

func (*Result) Data

func (r *Result) Data() any

Data 方法返回执行结果的数据 The Data method returns the data of the execution result

func (*Result) ExecErrorByIndex

func (r *Result) ExecErrorByIndex(idx int) error

ExecErrorByIndex 方法返回指定索引处的执行错误 The ExecErrorByIndex method returns the execution error at the specified index

func (*Result) ExecErrors

func (r *Result) ExecErrors() []error

ExecErrors 方法返回所有执行错误的列表 The ExecErrors method returns a list of all execution errors

func (*Result) FirstExecError

func (r *Result) FirstExecError() error

FirstExecError 方法返回第一次执行的错误 The FirstExecError method returns the error of the first execution

func (*Result) IsSuccess

func (r *Result) IsSuccess() bool

IsSuccess 方法返回执行是否成功 The IsSuccess method returns whether the execution was successful

func (*Result) LastExecError

func (r *Result) LastExecError() error

LastExecError 方法返回最后一次执行的错误 The LastExecError method returns the error of the last execution

func (*Result) TryError

func (r *Result) TryError() error

TryError 方法返回尝试执行时的错误 The TryError method returns the error when trying to execute

type Retry added in v0.1.2

type Retry struct {
	// contains filtered or unexported fields
}

Retry 结构体用于定义重试的配置 The Retry struct is used to define the retry configuration

func New added in v0.1.2

func New(conf *Config) *Retry

New 函数用于创建一个新的 Retry 实例。它接受一个 Config 结构体作为参数,该结构体包含了重试的配置信息。 The New function is used to create a new Retry instance. It accepts a Config structure as a parameter, which contains the configuration information for retrying.

func (*Retry) TryOnConflict added in v0.1.2

func (r *Retry) TryOnConflict(fn RetryableFunc) *Result

TryOnConflict 方法尝试执行 fn 函数,如果遇到冲突则进行重试 The TryOnConflict method attempts to execute the fn function, and retries if a conflict is encountered

func (*Retry) TryOnConflictVal added in v0.1.5

func (r *Retry) TryOnConflictVal(fn RetryableFunc) RetryResult

TryOnConflict 方法尝试执行 RetryableFunc 函数,如果发生冲突,则进行重试 The TryOnConflict method tries to execute the RetryableFunc function, and retries if a conflict occurs

type RetryIfFunc

type RetryIfFunc = func(error) bool

RetryIfFunc 类型定义了一个接受错误并返回布尔值的函数类型 The RetryIfFunc type defines a function type that accepts an error and returns a boolean value

type RetryResult added in v0.1.5

type RetryResult = interface {
	// Data 方法返回执行结果的数据
	// The Data method returns the data of the execution result
	Data() any

	// TryError 方法返回尝试执行时的错误
	// The TryError method returns the error when trying to execute
	TryError() error

	// ExecErrors 方法返回所有执行错误的列表
	// The ExecErrors method returns a list of all execution errors
	ExecErrors() []error

	// IsSuccess 方法返回执行是否成功
	// The IsSuccess method returns whether the execution was successful
	IsSuccess() bool

	// LastExecError 方法返回最后一次执行的错误
	// The LastExecError method returns the error of the last execution
	LastExecError() error

	// FirstExecError 方法返回第一次执行的错误
	// The FirstExecError method returns the error of the first execution
	FirstExecError() error

	// ExecErrorByIndex 方法返回指定索引处的执行错误
	// The ExecErrorByIndex method returns the execution error at the specified index
	ExecErrorByIndex(idx int) error

	// Count 方法返回执行的次数
	// The Count method returns the number of executions
	Count() int64
}

RetryResult 接口定义了执行结果的相关方法 The RetryResult interface defines methods related to execution results

func Do

func Do(fn RetryableFunc, conf *Config) RetryResult

Do 函数尝试执行 fn 函数,如果遇到冲突则根据 conf 配置进行重试 The Do function attempts to execute the fn function, and retries according to the conf configuration if a conflict is encountered

func DoWithDefault

func DoWithDefault(fn RetryableFunc) RetryResult

DoWithDefault 函数尝试执行 fn 函数,如果遇到冲突则使用默认配置进行重试 The DoWithDefault function attempts to execute the fn function, and retries with the default configuration if a conflict is encountered

type RetryableFunc

type RetryableFunc = func() (any, error)

RetryableFunc 类型定义了一个可重试的函数 The RetryableFunc type defines a retryable function

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL