You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

75 lines
1.7 KiB

  1. package aws
  2. import (
  3. "time"
  4. )
  5. // AttemptStrategy represents a strategy for waiting for an action
  6. // to complete successfully. This is an internal type used by the
  7. // implementation of other goamz packages.
  8. type AttemptStrategy struct {
  9. Total time.Duration // total duration of attempt.
  10. Delay time.Duration // interval between each try in the burst.
  11. Min int // minimum number of retries; overrides Total
  12. }
  13. type Attempt struct {
  14. strategy AttemptStrategy
  15. last time.Time
  16. end time.Time
  17. force bool
  18. count int
  19. }
  20. // Start begins a new sequence of attempts for the given strategy.
  21. func (s AttemptStrategy) Start() *Attempt {
  22. now := time.Now()
  23. return &Attempt{
  24. strategy: s,
  25. last: now,
  26. end: now.Add(s.Total),
  27. force: true,
  28. }
  29. }
  30. // Next waits until it is time to perform the next attempt or returns
  31. // false if it is time to stop trying.
  32. func (a *Attempt) Next() bool {
  33. now := time.Now()
  34. sleep := a.nextSleep(now)
  35. if !a.force && !now.Add(sleep).Before(a.end) && a.strategy.Min <= a.count {
  36. return false
  37. }
  38. a.force = false
  39. if sleep > 0 && a.count > 0 {
  40. time.Sleep(sleep)
  41. now = time.Now()
  42. }
  43. a.count++
  44. a.last = now
  45. return true
  46. }
  47. func (a *Attempt) nextSleep(now time.Time) time.Duration {
  48. sleep := a.strategy.Delay - now.Sub(a.last)
  49. if sleep < 0 {
  50. return 0
  51. }
  52. return sleep
  53. }
  54. // HasNext returns whether another attempt will be made if the current
  55. // one fails. If it returns true, the following call to Next is
  56. // guaranteed to return true.
  57. func (a *Attempt) HasNext() bool {
  58. if a.force || a.strategy.Min > a.count {
  59. return true
  60. }
  61. now := time.Now()
  62. if now.Add(a.nextSleep(now)).Before(a.end) {
  63. a.force = true
  64. return true
  65. }
  66. return false
  67. }