slowdown.go 789 B

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. package slowdown
  2. import (
  3. "context"
  4. "sync/atomic"
  5. "time"
  6. )
  7. type SlowDown struct {
  8. errTimes atomic.Int64
  9. backoff Backoff
  10. }
  11. func (s *SlowDown) Wait(ctx context.Context) (err error) {
  12. timer := time.NewTimer(s.backoff.Duration())
  13. defer timer.Stop()
  14. select {
  15. case <-timer.C:
  16. case <-ctx.Done():
  17. err = ctx.Err()
  18. }
  19. return
  20. }
  21. func New() *SlowDown {
  22. return &SlowDown{
  23. backoff: Backoff{
  24. Min: 10 * time.Millisecond,
  25. Max: 1 * time.Second,
  26. Factor: 2,
  27. Jitter: true,
  28. },
  29. }
  30. }
  31. func Do[T any](s *SlowDown, ctx context.Context, fn func() (T, error)) (t T, err error) {
  32. if s.errTimes.Load() > 10 {
  33. err = s.Wait(ctx)
  34. if err != nil {
  35. return
  36. }
  37. }
  38. t, err = fn()
  39. if err != nil {
  40. s.errTimes.Add(1)
  41. return
  42. }
  43. s.errTimes.Store(0)
  44. s.backoff.Reset()
  45. return
  46. }