mirror of
https://gitclone.com/github.com/MetaCubeX/Clash.Meta
synced 2024-11-15 13:41:23 +08:00
50 lines
748 B
Go
50 lines
748 B
Go
|
package slowdown
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"sync/atomic"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
type SlowDown struct {
|
||
|
errTimes atomic.Int64
|
||
|
backoff Backoff
|
||
|
}
|
||
|
|
||
|
func (s *SlowDown) Wait(ctx context.Context) (err error) {
|
||
|
select {
|
||
|
case <-time.After(s.backoff.Duration()):
|
||
|
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
|
||
|
}
|