package main
import (
"fmt"
"github.com/sirupsen/logrus"
"proj_test/errlib"
)
func main() {
times := 0
retryErr := errlib.RetryOnErr(errlib.NewDefaultRetryConf(), func() error {
times++
return apply()
})
if retryErr != nil {
logrus.Errorf("catch error")
}
}
func apply() error {
logrus.Infof("apply")
// 编写业务逻辑
return fmt.Errorf("error")
}
package errlib
import (
"k8s.io/apimachinery/pkg/util/wait"
"time"
)
func NewDefaultRetryConf() wait.Backoff {
return wait.Backoff{
Steps: 5,
Duration: time.Duration(2) * time.Second,
Factor: 1.0,
Jitter: 0.1,
}
}
func RetryOnErr(bacoff wait.Backoff, fn func() error) error {
return OnErr(bacoff, IsError, fn)
}
func IsError(err error) bool {
return err != nil
}
func OnErr(backoff wait.Backoff, retriable func(error) bool, fn func() error) error {
var lastConflictErr error
err := wait.ExponentialBackoff(backoff, func() (bool, error) {
err := fn()
switch {
case err == nil:
return true, nil
case retriable(err):
lastConflictErr = err
return false, nil
default:
return false, err
}
})
if err == wait.ErrWaitTimeout {
err = lastConflictErr
}
return err
}
sync.WaitGroup实现一个goroutine等待一组goroutine任务结束,更好的实现了任务同步,但是waitGroup却无法返回错误。并且waitgroup会允许go先到GMP的g,g在p的队列进行等待而不分配m,从而实现waitgroup的等待,则不是直接不允许进入g
sync.ErrGroup在sync.WaitGroup功能的基础上,增加了错误传递,以及在发生不可恢复的错误时取消整个goroutine集合,或者等待超时。
RetryOnErr在sync.ErrGroup的基础上增加了出错重试功能。