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)
 | |
| }
 |