func retryWithExponentialBackOff(initialDuration time.Duration, fn wait.ConditionFunc) error { backoff := wait.Backoff{ Duration: initialDuration, Factor: 3, Jitter: 0, Steps: 4, } return wait.ExponentialBackoff(backoff, fn) }
// RetryConflict executes the provided function repeatedly, retrying if the server returns a conflicting // write. Callers should preserve previous executions if they wish to retry changes. It performs an // exponential backoff. // // var pod *api.Pod // err := RetryOnConflict(DefaultBackoff, func() (err error) { // pod, err = c.Pods("mynamespace").UpdateStatus(podStatus) // return // }) // if err != nil { // // may be conflict if max retries were hit // return err // } // ... // // TODO: Make Backoff an interface? func RetryOnConflict(backoff wait.Backoff, fn func() error) error { var lastConflictErr error err := wait.ExponentialBackoff(backoff, func() (bool, error) { err := fn() switch { case err == nil: return true, nil case errors.IsConflict(err): lastConflictErr = err return false, nil default: return false, err } }) if err == wait.ErrWaitTimeout { err = lastConflictErr } return err }
// waitTest waits until all tests, controllers and other goroutines do their // job and list of current volumes/claims is equal to list of expected // volumes/claims (with ~10 second timeout). func (r *volumeReactor) waitTest(test controllerTest) error { // start with 10 ms, multiply by 2 each step, 10 steps = 10.23 seconds backoff := wait.Backoff{ Duration: 10 * time.Millisecond, Jitter: 0, Factor: 2, Steps: 10, } err := wait.ExponentialBackoff(backoff, func() (done bool, err error) { // Finish all operations that are in progress r.ctrl.runningOperations.WaitForCompletion() // Return 'true' if the reactor reached the expected state err1 := r.checkClaims(test.expectedClaims) err2 := r.checkVolumes(test.expectedVolumes) if err1 == nil && err2 == nil { return true, nil } return false, nil }) return err }
// WithExponentialBackoff will retry webhookFn() up to 5 times with exponentially increasing backoff when // it returns an error for which apierrors.SuggestsClientDelay() or apierrors.IsInternalError() returns true. func WithExponentialBackoff(initialBackoff time.Duration, webhookFn func() error) error { backoff := wait.Backoff{ Duration: initialBackoff, Factor: 1.5, Jitter: 0.2, Steps: 5, } var err error wait.ExponentialBackoff(backoff, func() (bool, error) { err = webhookFn() if _, shouldRetry := apierrors.SuggestsClientDelay(err); shouldRetry { return false, nil } if apierrors.IsInternalError(err) { return false, nil } if err != nil { return false, err } return true, nil }) return err }