github.com/rahart/packer@v0.12.2-0.20161229105310-282bb6ad370f/common/retry.go (about) 1 package common 2 3 import ( 4 "fmt" 5 "math" 6 "time" 7 ) 8 9 var RetryExhaustedError error = fmt.Errorf("Function never succeeded in Retry") 10 11 // Retry retries a function up to numTries times with exponential backoff. 12 // If numTries == 0, retry indefinitely. If interval == 0, Retry will not delay retrying and there will be 13 // no exponential backoff. If maxInterval == 0, maxInterval is set to +Infinity. 14 // Intervals are in seconds. 15 // Returns an error if initial > max intervals, if retries are exhausted, or if the passed function returns 16 // an error. 17 func Retry(initialInterval float64, maxInterval float64, numTries uint, function func() (bool, error)) error { 18 if maxInterval == 0 { 19 maxInterval = math.Inf(1) 20 } else if initialInterval < 0 || initialInterval > maxInterval { 21 return fmt.Errorf("Invalid retry intervals (negative or initial < max). Initial: %f, Max: %f.", initialInterval, maxInterval) 22 } 23 24 var err error 25 done := false 26 interval := initialInterval 27 for i := uint(0); !done && (numTries == 0 || i < numTries); i++ { 28 done, err = function() 29 if err != nil { 30 return err 31 } 32 33 if !done { 34 // Retry after delay. Calculate next delay. 35 time.Sleep(time.Duration(interval) * time.Second) 36 interval = math.Min(interval*2, maxInterval) 37 } 38 } 39 40 if !done { 41 return RetryExhaustedError 42 } 43 return nil 44 }