// sleepWithInterrupt attempts to sleep for the specified duration, aborting // early if the application is shutdown, returning true. func (a *application) sleepWithInterrupt(ctx context.Context, amount time.Duration) bool { select { case <-clock.After(ctx, noMessageDelay): return false case <-a.shutdownC: return true } }
// Retry executes a function. If the function returns an error, it will // be re-executed according to a retry plan. // // If the supplied context is cancelled, retry will stop executing. Retry will // not execute the supplied function at all if the context is canelled when // Retry is invoked. // // If notify is not nil, it will be invoked if an error occurs (prior to // sleeping). func Retry(ctx context.Context, it Iterator, f func() error, callback Callback) (err error) { for { // If we've been cancelled, don't try/retry. select { case <-ctx.Done(): return ctx.Err() default: break } // Execute the function. err = f() if err == nil || it == nil { return } delay := it.Next(ctx, err) if delay == Stop { return } // Notify our observer that we are retrying. if callback != nil { callback(err, delay) } if delay > 0 { select { case <-ctx.Done(): return ctx.Err() case <-clock.After(ctx, delay): break } } } }