github.com/vmg/backoff@v1.0.0/retry.go (about)

     1  package backoff
     2  
     3  import "time"
     4  
     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
     8  
     9  // Notify is a notify-on-error function. It receives an operation error and
    10  // backoff delay if the operation failed (with an error).
    11  //
    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)
    15  
    16  // Retry the function f until it does not return error or BackOff stops.
    17  // f is guaranteed to be run at least once.
    18  // It is the caller's responsibility to reset b after Retry returns.
    19  //
    20  // Retry sleeps the goroutine for the duration returned by BackOff after a
    21  // failed operation returns.
    22  func Retry(o Operation, b BackOff) error { return RetryNotify(o, b, nil) }
    23  
    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 next time.Duration
    29  
    30  	b.Reset()
    31  	for {
    32  		if err = operation(); err == nil {
    33  			return nil
    34  		}
    35  
    36  		if next = b.NextBackOff(); next == Stop {
    37  			return err
    38  		}
    39  
    40  		if notify != nil {
    41  			notify(err, next)
    42  		}
    43  
    44  		time.Sleep(next)
    45  	}
    46  }