clash/component/slowdown/slowdown.go

52 lines
789 B
Go
Raw Normal View History

2024-01-30 11:41:34 +00:00
package slowdown
import (
"context"
"sync/atomic"
"time"
)
type SlowDown struct {
errTimes atomic.Int64
backoff Backoff
}
func (s *SlowDown) Wait(ctx context.Context) (err error) {
2024-02-16 03:29:33 +00:00
timer := time.NewTimer(s.backoff.Duration())
defer timer.Stop()
2024-01-30 11:41:34 +00:00
select {
2024-02-16 03:29:33 +00:00
case <-timer.C:
2024-01-30 11:41:34 +00:00
case <-ctx.Done():
err = ctx.Err()
}
return
}
func New() *SlowDown {
return &SlowDown{
backoff: Backoff{
Min: 10 * time.Millisecond,
Max: 1 * time.Second,
Factor: 2,
Jitter: true,
},
}
}
func Do[T any](s *SlowDown, ctx context.Context, fn func() (T, error)) (t T, err error) {
if s.errTimes.Load() > 10 {
err = s.Wait(ctx)
if err != nil {
return
}
}
t, err = fn()
if err != nil {
s.errTimes.Add(1)
return
}
s.errTimes.Store(0)
s.backoff.Reset()
return
}