Skip to content

Commit bf2cd0d

Browse files
committed
add retry if
1 parent 2407e38 commit bf2cd0d

File tree

2 files changed

+68
-10
lines changed

2 files changed

+68
-10
lines changed

retry.go

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,13 @@ type retryableFuncResp struct {
2323
}
2424

2525
type Config struct {
26-
FastRetryTime time.Duration // 默认 2s,建议设置成当前 API 的 PCT99
27-
MaxRetryRate float64 // 最大重试百分比,0.05 代表 5%,默认 5%,超出返回 ErrRetryQuotaExceeded
28-
RetryCnt int // 最多发送的请求次数,默认 3 次,最少两次,其中一次是快速重试
29-
RetryWaitTime time.Duration // 重试间隔,默认是 FastRetryTime / 10
30-
Clock Clock // 模拟时钟,mock 用
31-
MaxRetryCapacity int // 平时没有超时的时候,允许积攒的重启请求最大数目,默认 1000 个
26+
FastRetryTime time.Duration // 默认 2s,建议设置成当前 API 的 PCT99
27+
MaxRetryRate float64 // 最大重试百分比,0.05 代表 5%,默认 5%,超出返回 ErrRetryQuotaExceeded
28+
RetryCnt int // 最多发送的请求次数,默认 3 次,最少两次,其中一次是快速重试
29+
RetryWaitTime time.Duration // 重试间隔,默认是 FastRetryTime / 10
30+
Clock Clock // 模拟时钟,mock 用
31+
MaxRetryCapacity int // 平时没有超时的时候,允许积攒的重启请求最大数目,默认 1000 个
32+
RetryIf func(err error) bool // 出错的时候调用,判断是否对 error 进行重试,默认值 err != nil
3233
}
3334

3435
type Retry struct {
@@ -65,6 +66,11 @@ func New(config Config) *Retry {
6566
if r.cfg.MaxRetryCapacity == 0 {
6667
r.cfg.MaxRetryCapacity = 1000
6768
}
69+
if r.cfg.RetryIf == nil {
70+
r.cfg.RetryIf = func(err error) bool {
71+
return err != nil
72+
}
73+
}
6874
r.maxScore = int64(r.cfg.MaxRetryCapacity) * r.oneRetryScore
6975
return r
7076
}
@@ -116,12 +122,12 @@ func (r *Retry) BackupRetry(ctx context.Context, retryableFunc func() (resp inte
116122
var firstResp retryableFuncResp
117123
for i := 0; i < r.cfg.RetryCnt; i++ {
118124
select {
119-
case r := <-result:
120-
if r.err == nil {
121-
return r.resp, r.err
125+
case re := <-result:
126+
if !r.cfg.RetryIf(re.err) {
127+
return re.resp, re.err
122128
}
123129
if i == 0 {
124-
firstResp = r
130+
firstResp = re
125131
}
126132
case <-ctx.Done():
127133
return nil, ctx.Err()

retry_test.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"errors"
66
"fmt"
7+
"io"
78
"log"
89
"math/rand"
910
"os"
@@ -338,3 +339,54 @@ type Line struct {
338339
UseTime float64
339340
Err bool
340341
}
342+
343+
func TestRetryIf(t *testing.T) {
344+
{
345+
// 设置了 RetryIf, 重试一次
346+
ctx := context.Background()
347+
var n atomic.Int32
348+
r := New(Config{RetryIf: func(err error) bool {
349+
if err == io.EOF {
350+
return false
351+
}
352+
return err != nil
353+
}})
354+
_, err := r.BackupRetry(ctx, func() (resp interface{}, err error) {
355+
n.Inc()
356+
return "ok", io.EOF
357+
})
358+
require.Error(t, err, io.EOF)
359+
require.Equal(t, int32(1), n.Load())
360+
}
361+
{
362+
// 设置了 RetryIf, 但是非预期错误,重试 3 次
363+
ctx := context.Background()
364+
var n atomic.Int32
365+
r := New(Config{RetryIf: func(err error) bool {
366+
if err == io.EOF {
367+
return false
368+
}
369+
return err != nil
370+
}})
371+
_, err := r.BackupRetry(ctx, func() (resp interface{}, err error) {
372+
n.Inc()
373+
return "ok", errors.New("ok")
374+
})
375+
require.Error(t, err, errors.New("ok"))
376+
require.Equal(t, int32(3), n.Load())
377+
}
378+
{
379+
// 没有设置了 RetryIf, 重试 3 次
380+
ctx := context.Background()
381+
var n atomic.Int32
382+
r := New(Config{RetryIf: func(err error) bool {
383+
return err != nil
384+
}})
385+
_, err := r.BackupRetry(ctx, func() (resp interface{}, err error) {
386+
n.Inc()
387+
return "ok", io.EOF
388+
})
389+
require.Error(t, err, io.EOF)
390+
require.Equal(t, int32(3), n.Load())
391+
}
392+
}

0 commit comments

Comments
 (0)