github.com/btwiuse/jiri@v0.0.0-20191125065820-53353bcfef54/retry/retry.go (about) 1 // Copyright 2015 The Vanadium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package retry provides a facility for retrying function 6 // invocations. 7 package retry 8 9 import ( 10 "fmt" 11 "time" 12 13 "github.com/btwiuse/jiri" 14 ) 15 16 type RetryOpt interface { 17 retryOpt() 18 } 19 20 type AttemptsOpt int 21 22 func (a AttemptsOpt) retryOpt() {} 23 24 type IntervalOpt time.Duration 25 26 func (i IntervalOpt) retryOpt() {} 27 28 const ( 29 defaultAttempts = 3 30 defaultInterval = 5 * time.Second 31 ) 32 33 // Function retries the given function for the given number of 34 // attempts at the given interval. 35 func Function(jirix *jiri.X, fn func() error, task string, opts ...RetryOpt) error { 36 attempts, interval := defaultAttempts, defaultInterval 37 for _, opt := range opts { 38 switch typedOpt := opt.(type) { 39 case AttemptsOpt: 40 attempts = int(typedOpt) 41 case IntervalOpt: 42 interval = time.Duration(typedOpt) 43 } 44 } 45 46 var err error 47 for i := 1; i <= attempts; i++ { 48 if i > 1 { 49 jirix.Logger.Infof("Attempt %d/%d: %s\n\n", i, attempts, task) 50 } 51 if err = fn(); err == nil { 52 return nil 53 } 54 if i < attempts { 55 jirix.Logger.Errorf("%s\n\n", err) 56 jirix.Logger.Infof("Wait for %s before next attempt...: %s\n\n", interval, task) 57 time.Sleep(interval) 58 } 59 } 60 if attempts > 1 { 61 return fmt.Errorf("%q failed %d times in a row, Last error: %s", task, attempts, err) 62 } 63 return err 64 }