github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/worker/storageprovisioner/schedule.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package storageprovisioner 5 6 import "time" 7 8 // minRetryDelay is the minimum delay to apply 9 // to operation retries; this does not apply to 10 // the first attempt for operations. 11 const minRetryDelay = 30 * time.Second 12 13 // maxRetryDelay is the maximum delay to apply 14 // to operation retries. Retry delays will backoff 15 // up to this ceiling. 16 const maxRetryDelay = 30 * time.Minute 17 18 // scheduleOperations schedules the given operations 19 // by calculating the current time once, and then 20 // adding each operation's delay to that time. By 21 // calculating the current time once, we guarantee 22 // that operations with the same delay will be 23 // batched together. 24 func scheduleOperations(ctx *context, ops ...scheduleOp) { 25 if len(ops) == 0 { 26 return 27 } 28 now := ctx.config.Clock.Now() 29 for _, op := range ops { 30 k := op.key() 31 d := op.delay() 32 ctx.schedule.Add(k, op, now.Add(d)) 33 } 34 } 35 36 // scheduleOp is an interface implemented by schedule 37 // operations. 38 type scheduleOp interface { 39 // key is the key for the operation; this 40 // must be unique among all operations. 41 key() interface{} 42 43 // delay is the amount of time to delay 44 // before next executing the operation. 45 delay() time.Duration 46 } 47 48 // exponentialBackoff is a type that can be embedded to implement the 49 // delay() method of scheduleOp, providing truncated binary exponential 50 // backoff for operations that may be rescheduled. 51 type exponentialBackoff struct { 52 d time.Duration 53 } 54 55 func (s *exponentialBackoff) delay() time.Duration { 56 current := s.d 57 if s.d < minRetryDelay { 58 s.d = minRetryDelay 59 } else { 60 s.d *= 2 61 if s.d > maxRetryDelay { 62 s.d = maxRetryDelay 63 } 64 } 65 return current 66 }