github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/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.time.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  }