Files
goodBaby/internal/retry/retry.go
T

57 lines
1.5 KiB
Go
Raw Normal View History

2026-07-26 22:19:41 +08:00
// Package retry 封装规则执行使用的指数退避重试
package retry
import (
"context"
"time"
"github.com/cenkalti/backoff/v5"
"github.com/ssdomei232/goodBaby/configs"
)
// 手动测试时使用的超时,避免用户在 WebUI 上等待数小时
const TestTimeout = 30 * time.Second
// Do 在 ctx 允许的时间内按指数退避执行 op
//
// 超时后返回最后一次真实的业务错误,而不是干巴巴的 context deadline exceeded。
func Do(ctx context.Context, op func() error) error {
var lastErr error
_, err := backoff.Retry(ctx, func() (struct{}, error) {
e := op()
if e != nil {
lastErr = e
}
return struct{}{}, e
}, backoff.WithBackOff(backoff.NewExponentialBackOff()))
if err != nil && lastErr != nil {
return lastErr
}
return err
}
2026-09-12 15:32:27 +08:00
// Permanent 标记一个重试没有意义的错误(例如凭据无效、配置错误)
//
// driver 里凡是重试也救不回来的失败都包一层,避免白白退避几个小时。
func Permanent(err error) error {
if err == nil {
return nil
}
return backoff.Permanent(err)
}
2026-07-26 22:19:41 +08:00
// ExecutionTimeout 返回配置中的规则执行超时时间
func ExecutionTimeout() time.Duration {
config, err := configs.GetConfig()
if err != nil || config.TimeoutDurationHours <= 0 {
return 6 * time.Hour
}
return time.Duration(config.TimeoutDurationHours) * time.Hour
}
// ExecutionContext 返回一个带规则执行超时的 context
func ExecutionContext() (context.Context, context.CancelFunc) {
return context.WithTimeout(context.Background(), ExecutionTimeout())
}