55 lines
1.6 KiB
Go
55 lines
1.6 KiB
Go
|
|
package retryhelper
|
||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"math"
|
||
|
|
"time"
|
||
|
|
)
|
||
|
|
|
||
|
|
// RetryOptions 定义重试的配置项
|
||
|
|
type RetryOptions struct {
|
||
|
|
MaxRetries int // 最大重试次数
|
||
|
|
InitialInterval time.Duration // 初始重试间隔
|
||
|
|
MaxInterval time.Duration // 最大重试间隔
|
||
|
|
BackoffFactor float64 // 指数退避的增长因子
|
||
|
|
RetryableErrFn func(error) bool // 用于判断是否为可重试错误的函数(可选)
|
||
|
|
}
|
||
|
|
|
||
|
|
func DefaultRetryOptions() RetryOptions {
|
||
|
|
return RetryOptions{
|
||
|
|
MaxRetries: 3,
|
||
|
|
InitialInterval: 150 * time.Millisecond,
|
||
|
|
MaxInterval: 3 * time.Second,
|
||
|
|
BackoffFactor: 2.0,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Retry 重试通用函数(用于没有返回值的函数)
|
||
|
|
func Retry(op func() error, opts RetryOptions) error {
|
||
|
|
_, err := RetryWithResult(func() (struct{}, error) {
|
||
|
|
return struct{}{}, op()
|
||
|
|
}, opts)
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
|
||
|
|
// RetryWithResult 重试通用函数(用于带返回值的函数)
|
||
|
|
func RetryWithResult[T any](op func() (T, error), opts RetryOptions) (result T, err error) {
|
||
|
|
interval := opts.InitialInterval
|
||
|
|
for attempt := 0; attempt <= opts.MaxRetries; attempt++ {
|
||
|
|
result, err = op()
|
||
|
|
if err == nil {
|
||
|
|
return result, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
if opts.RetryableErrFn != nil && !opts.RetryableErrFn(err) {
|
||
|
|
return result, err
|
||
|
|
}
|
||
|
|
|
||
|
|
if attempt < opts.MaxRetries {
|
||
|
|
time.Sleep(interval)
|
||
|
|
interval = time.Duration(math.Min(float64(opts.MaxInterval), float64(interval)*opts.BackoffFactor))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return result, fmt.Errorf("retry failed after %d attempts, last error: %w", opts.MaxRetries+1, err)
|
||
|
|
}
|