retry.go 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. // Copyright 2012-present Oliver Eilhard. All rights reserved.
  2. // Use of this source code is governed by a MIT-license.
  3. // See http://olivere.mit-license.org/license.txt for details.
  4. // This file is based on code (c) 2014 Cenk Altı and governed by the MIT license.
  5. // See https://github.com/cenkalti/backoff for original source.
  6. package elastic
  7. import "time"
  8. // An Operation is executing by Retry() or RetryNotify().
  9. // The operation will be retried using a backoff policy if it returns an error.
  10. type Operation func() error
  11. // Notify is a notify-on-error function. It receives error returned
  12. // from an operation.
  13. //
  14. // Notice that if the backoff policy stated to stop retrying,
  15. // the notify function isn't called.
  16. type Notify func(error)
  17. // Retry the function f until it does not return error or BackOff stops.
  18. // f is guaranteed to be run at least once.
  19. // It is the caller's responsibility to reset b after Retry returns.
  20. //
  21. // Retry sleeps the goroutine for the duration returned by BackOff after a
  22. // failed operation returns.
  23. func Retry(o Operation, b Backoff) error { return RetryNotify(o, b, nil) }
  24. // RetryNotify calls notify function with the error and wait duration
  25. // for each failed attempt before sleep.
  26. func RetryNotify(operation Operation, b Backoff, notify Notify) error {
  27. var err error
  28. var wait time.Duration
  29. var retry bool
  30. var n int
  31. for {
  32. if err = operation(); err == nil {
  33. return nil
  34. }
  35. n++
  36. wait, retry = b.Next(n)
  37. if !retry {
  38. return err
  39. }
  40. if notify != nil {
  41. notify(err)
  42. }
  43. time.Sleep(wait)
  44. }
  45. }