retry.go 1.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. package retry
  2. import (
  3. "time"
  4. "v2ray.com/core/common/errors"
  5. )
  6. var (
  7. ErrRetryFailed = errors.New("All retry attempts failed.")
  8. )
  9. // Strategy is a way to retry on a specific function.
  10. type Strategy interface {
  11. // On performs a retry on a specific function, until it doesn't return any error.
  12. On(func() error) error
  13. }
  14. type retryer struct {
  15. totalAttempt int
  16. nextDelay func() uint32
  17. }
  18. // On implements Strategy.On.
  19. func (r *retryer) On(method func() error) error {
  20. attempt := 0
  21. for attempt < r.totalAttempt {
  22. err := method()
  23. if err == nil {
  24. return nil
  25. }
  26. delay := r.nextDelay()
  27. <-time.After(time.Duration(delay) * time.Millisecond)
  28. attempt++
  29. }
  30. return ErrRetryFailed
  31. }
  32. // Timed returns a retry strategy with fixed interval.
  33. func Timed(attempts int, delay uint32) Strategy {
  34. return &retryer{
  35. totalAttempt: attempts,
  36. nextDelay: func() uint32 {
  37. return delay
  38. },
  39. }
  40. }
  41. func ExponentialBackoff(attempts int, delay uint32) Strategy {
  42. nextDelay := uint32(0)
  43. return &retryer{
  44. totalAttempt: attempts,
  45. nextDelay: func() uint32 {
  46. r := nextDelay
  47. nextDelay += delay
  48. return r
  49. },
  50. }
  51. }