wait.go 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. /*
  2. Copyright 2014 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package wait
  14. import (
  15. "errors"
  16. "math/rand"
  17. "time"
  18. )
  19. // For any test of the style:
  20. // ...
  21. // <- time.After(timeout):
  22. // t.Errorf("Timed out")
  23. // The value for timeout should effectively be "forever." Obviously we don't want our tests to truly lock up forever, but 30s
  24. // is long enough that it is effectively forever for the things that can slow down a run on a heavily contended machine
  25. // (GC, seeks, etc), but not so long as to make a developer ctrl-c a test run if they do happen to break that test.
  26. var ForeverTestTimeout = time.Second * 30
  27. // NeverStop may be passed to Until to make it never stop.
  28. var NeverStop <-chan struct{} = make(chan struct{})
  29. // Forever is syntactic sugar on top of Until
  30. func Forever(f func(), period time.Duration) {
  31. Until(f, period, NeverStop)
  32. }
  33. // Until loops until stop channel is closed, running f every period.
  34. // Until is syntactic sugar on top of JitterUntil with zero jitter
  35. // factor, with sliding = true (which means the timer for period
  36. // starts after the f completes).
  37. func Until(f func(), period time.Duration, stopCh <-chan struct{}) {
  38. JitterUntil(f, period, 0.0, true, stopCh)
  39. }
  40. // NonSlidingUntil loops until stop channel is closed, running f every
  41. // period. NonSlidingUntil is syntactic sugar on top of JitterUntil
  42. // with zero jitter factor, with sliding = false (meaning the timer for
  43. // period starts at the same time as the function starts).
  44. func NonSlidingUntil(f func(), period time.Duration, stopCh <-chan struct{}) {
  45. JitterUntil(f, period, 0.0, false, stopCh)
  46. }
  47. // JitterUntil loops until stop channel is closed, running f every period.
  48. // If jitterFactor is positive, the period is jittered before every run of f.
  49. // If jitterFactor is not positive, the period is unchanged.
  50. // Catches any panics, and keeps going. f may not be invoked if
  51. // stop channel is already closed. Pass NeverStop to Until if you
  52. // don't want it stop.
  53. func JitterUntil(f func(), period time.Duration, jitterFactor float64, sliding bool, stopCh <-chan struct{}) {
  54. for {
  55. select {
  56. case <-stopCh:
  57. return
  58. default:
  59. }
  60. jitteredPeriod := period
  61. if jitterFactor > 0.0 {
  62. jitteredPeriod = Jitter(period, jitterFactor)
  63. }
  64. var t *time.Timer
  65. if !sliding {
  66. t = time.NewTimer(jitteredPeriod)
  67. }
  68. func() {
  69. f()
  70. }()
  71. if sliding {
  72. t = time.NewTimer(jitteredPeriod)
  73. }
  74. // NOTE: b/c there is no priority selection in golang
  75. // it is possible for this to race, meaning we could
  76. // trigger t.C and stopCh, and t.C select falls through.
  77. // In order to mitigate we re-check stopCh at the beginning
  78. // of every loop to prevent extra executions of f().
  79. select {
  80. case <-stopCh:
  81. return
  82. case <-t.C:
  83. }
  84. }
  85. }
  86. // Jitter returns a time.Duration between duration and duration + maxFactor * duration,
  87. // to allow clients to avoid converging on periodic behavior. If maxFactor is 0.0, a
  88. // suggested default value will be chosen.
  89. func Jitter(duration time.Duration, maxFactor float64) time.Duration {
  90. if maxFactor <= 0.0 {
  91. maxFactor = 1.0
  92. }
  93. wait := duration + time.Duration(rand.Float64()*maxFactor*float64(duration))
  94. return wait
  95. }
  96. // ErrWaitTimeout is returned when the condition exited without success
  97. var ErrWaitTimeout = errors.New("timed out waiting for the condition")
  98. // ConditionFunc returns true if the condition is satisfied, or an error
  99. // if the loop should be aborted.
  100. type ConditionFunc func() (done bool, err error)
  101. // Backoff is parameters applied to a Backoff function.
  102. type Backoff struct {
  103. Duration time.Duration
  104. Factor float64
  105. Jitter float64
  106. Steps int
  107. }
  108. // ExponentialBackoff repeats a condition check up to steps times, increasing the wait
  109. // by multipling the previous duration by factor. If jitter is greater than zero,
  110. // a random amount of each duration is added (between duration and duration*(1+jitter)).
  111. // If the condition never returns true, ErrWaitTimeout is returned. All other errors
  112. // terminate immediately.
  113. func ExponentialBackoff(backoff Backoff, condition ConditionFunc) error {
  114. duration := backoff.Duration
  115. for i := 0; i < backoff.Steps; i++ {
  116. if i != 0 {
  117. adjusted := duration
  118. if backoff.Jitter > 0.0 {
  119. adjusted = Jitter(duration, backoff.Jitter)
  120. }
  121. time.Sleep(adjusted)
  122. duration = time.Duration(float64(duration) * backoff.Factor)
  123. }
  124. if ok, err := condition(); err != nil || ok {
  125. return err
  126. }
  127. }
  128. return ErrWaitTimeout
  129. }
  130. // Poll tries a condition func until it returns true, an error, or the timeout
  131. // is reached. condition will always be invoked at least once but some intervals
  132. // may be missed if the condition takes too long or the time window is too short.
  133. // If you want to Poll something forever, see PollInfinite.
  134. // Poll always waits the interval before the first check of the condition.
  135. func Poll(interval, timeout time.Duration, condition ConditionFunc) error {
  136. return pollInternal(poller(interval, timeout), condition)
  137. }
  138. func pollInternal(wait WaitFunc, condition ConditionFunc) error {
  139. done := make(chan struct{})
  140. defer close(done)
  141. return WaitFor(wait, condition, done)
  142. }
  143. // PollImmediate is identical to Poll, except that it performs the first check
  144. // immediately, not waiting interval beforehand.
  145. func PollImmediate(interval, timeout time.Duration, condition ConditionFunc) error {
  146. return pollImmediateInternal(poller(interval, timeout), condition)
  147. }
  148. func pollImmediateInternal(wait WaitFunc, condition ConditionFunc) error {
  149. done, err := condition()
  150. if err != nil {
  151. return err
  152. }
  153. if done {
  154. return nil
  155. }
  156. return pollInternal(wait, condition)
  157. }
  158. // PollInfinite polls forever.
  159. func PollInfinite(interval time.Duration, condition ConditionFunc) error {
  160. done := make(chan struct{})
  161. defer close(done)
  162. return WaitFor(poller(interval, 0), condition, done)
  163. }
  164. // WaitFunc creates a channel that receives an item every time a test
  165. // should be executed and is closed when the last test should be invoked.
  166. type WaitFunc func(done <-chan struct{}) <-chan struct{}
  167. // WaitFor gets a channel from wait(), and then invokes fn once for every value
  168. // placed on the channel and once more when the channel is closed. If fn
  169. // returns an error the loop ends and that error is returned, and if fn returns
  170. // true the loop ends and nil is returned. ErrWaitTimeout will be returned if
  171. // the channel is closed without fn ever returning true.
  172. func WaitFor(wait WaitFunc, fn ConditionFunc, done <-chan struct{}) error {
  173. c := wait(done)
  174. for {
  175. _, open := <-c
  176. ok, err := fn()
  177. if err != nil {
  178. return err
  179. }
  180. if ok {
  181. return nil
  182. }
  183. if !open {
  184. break
  185. }
  186. }
  187. return ErrWaitTimeout
  188. }
  189. // poller returns a WaitFunc that will send to the channel every
  190. // interval until timeout has elapsed and then close the channel.
  191. // Over very short intervals you may receive no ticks before
  192. // the channel is closed. If timeout is 0, the channel
  193. // will never be closed.
  194. func poller(interval, timeout time.Duration) WaitFunc {
  195. return WaitFunc(func(done <-chan struct{}) <-chan struct{} {
  196. ch := make(chan struct{})
  197. go func() {
  198. defer close(ch)
  199. tick := time.NewTicker(interval)
  200. defer tick.Stop()
  201. var after <-chan time.Time
  202. if timeout != 0 {
  203. // time.After is more convenient, but it
  204. // potentially leaves timers around much longer
  205. // than necessary if we exit early.
  206. timer := time.NewTimer(timeout)
  207. after = timer.C
  208. defer timer.Stop()
  209. }
  210. for {
  211. select {
  212. case <-tick.C:
  213. // If the consumer isn't ready for this signal drop it and
  214. // check the other channels.
  215. select {
  216. case ch <- struct{}{}:
  217. default:
  218. }
  219. case <-after:
  220. return
  221. case <-done:
  222. return
  223. }
  224. }
  225. }()
  226. return ch
  227. })
  228. }