5 // An Operation is executing by Retry() or RetryNotify().
6 // The operation will be retried using a backoff policy if it returns an error.
7 type Operation func() error
9 // Notify is a notify-on-error function. It receives an operation error and
10 // backoff delay if the operation failed (with an error).
12 // NOTE that if the backoff policy stated to stop retrying,
13 // the notify function isn't called.
14 type Notify func(error, time.Duration)
16 // Retry the operation o until it does not return error or BackOff stops.
17 // o is guaranteed to be run at least once.
19 // If o returns a *PermanentError, the operation is not retried, and the
20 // wrapped error is returned.
22 // Retry sleeps the goroutine for the duration returned by BackOff after a
23 // failed operation returns.
24 func Retry(o Operation, b BackOff) error { return RetryNotify(o, b, nil) }
26 // RetryNotify calls notify function with the error and wait duration
27 // for each failed attempt before sleep.
28 func RetryNotify(operation Operation, b BackOff, notify Notify) error {
30 var next time.Duration
33 cb := ensureContext(b)
37 if err = operation(); err == nil {
41 if permanent, ok := err.(*PermanentError); ok {
45 if next = cb.NextBackOff(); next == Stop {
54 t = time.NewTimer(next)
61 case <-cb.Context().Done():
68 // PermanentError signals that the operation should not be retried.
69 type PermanentError struct {
73 func (e *PermanentError) Error() string {
77 // Permanent wraps the given err in a *PermanentError.
78 func Permanent(err error) *PermanentError {
79 return &PermanentError{