v.io/jiri@v0.0.0-20160715023856-abfb8b131290/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 "v.io/jiri/tool" 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 = 10 * time.Second 31 ) 32 33 // Function retries the given function for the given number of 34 // attempts at the given interval. 35 func Function(ctx *tool.Context, fn func() error, 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 fmt.Fprintf(ctx.Stdout(), "Attempt %d/%d:\n", i, attempts) 50 } 51 if err = fn(); err == nil { 52 return nil 53 } 54 fmt.Fprintf(ctx.Stderr(), "%v\n", err) 55 if i < attempts { 56 fmt.Fprintf(ctx.Stdout(), "Wait for %v before next attempt...\n", interval) 57 time.Sleep(interval) 58 } 59 } 60 return fmt.Errorf("Failed %d times in a row. Last error:\n%v", attempts, err) 61 }