backoff.go 1.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. package frankenphp
  2. import (
  3. "sync"
  4. "time"
  5. )
  6. type exponentialBackoff struct {
  7. backoff time.Duration
  8. failureCount int
  9. mu sync.RWMutex
  10. maxBackoff time.Duration
  11. minBackoff time.Duration
  12. maxConsecutiveFailures int
  13. }
  14. // recordSuccess resets the backoff and failureCount
  15. func (e *exponentialBackoff) recordSuccess() {
  16. e.mu.Lock()
  17. e.failureCount = 0
  18. e.backoff = e.minBackoff
  19. e.mu.Unlock()
  20. }
  21. // recordFailure increments the failure count and increases the backoff, it returns true if maxConsecutiveFailures has been reached
  22. func (e *exponentialBackoff) recordFailure() bool {
  23. e.mu.Lock()
  24. e.failureCount += 1
  25. if e.backoff < e.minBackoff {
  26. e.backoff = e.minBackoff
  27. }
  28. e.backoff = min(e.backoff*2, e.maxBackoff)
  29. e.mu.Unlock()
  30. return e.failureCount >= e.maxConsecutiveFailures
  31. }
  32. // wait sleeps for the backoff duration if failureCount is non-zero.
  33. // NOTE: this is not tested and should be kept 'obviously correct' (i.e., simple)
  34. func (e *exponentialBackoff) wait() {
  35. e.mu.RLock()
  36. if e.failureCount == 0 {
  37. e.mu.RUnlock()
  38. return
  39. }
  40. e.mu.RUnlock()
  41. time.Sleep(e.backoff)
  42. }