github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/apiserver/provisioner/machineerror.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package provisioner
     5  
     6  import (
     7  	"time"
     8  
     9  	"gopkg.in/tomb.v1"
    10  
    11  	"github.com/juju/juju/state"
    12  )
    13  
    14  // machineErrorRetry is a notify watcher that fires when it is
    15  // appropriate to retry provisioning machines with transient errors.
    16  type machineErrorRetry struct {
    17  	tomb tomb.Tomb
    18  	out  chan struct{}
    19  }
    20  
    21  func newWatchMachineErrorRetry() state.NotifyWatcher {
    22  	w := &machineErrorRetry{
    23  		out: make(chan struct{}),
    24  	}
    25  	go func() {
    26  		defer w.tomb.Done()
    27  		defer close(w.out)
    28  		w.tomb.Kill(w.loop())
    29  	}()
    30  	return w
    31  }
    32  
    33  // Stop stops the watcher, and returns any error encountered while running
    34  // or shutting down.
    35  func (w *machineErrorRetry) Stop() error {
    36  	w.Kill()
    37  	return w.Wait()
    38  }
    39  
    40  // Kill kills the watcher without waiting for it to shut down.
    41  func (w *machineErrorRetry) Kill() {
    42  	w.tomb.Kill(nil)
    43  }
    44  
    45  // Wait waits for the watcher to die and returns any
    46  // error encountered when it was running.
    47  func (w *machineErrorRetry) Wait() error {
    48  	return w.tomb.Wait()
    49  }
    50  
    51  // Err returns any error encountered while running or shutting down, or
    52  // tomb.ErrStillAlive if the watcher is still running.
    53  func (w *machineErrorRetry) Err() error {
    54  	return w.tomb.Err()
    55  }
    56  
    57  // Changes returns the event channel for the machineErrorRetry watcher.
    58  func (w *machineErrorRetry) Changes() <-chan struct{} {
    59  	return w.out
    60  }
    61  
    62  // ErrorRetryWaitDelay is the poll time currently used to trigger the watcher.
    63  var ErrorRetryWaitDelay = 1 * time.Minute
    64  
    65  // The initial implementation of this watcher simply acts as a poller,
    66  // triggering every ErrorRetryWaitDelay minutes.
    67  func (w *machineErrorRetry) loop() error {
    68  	out := w.out
    69  	for {
    70  		select {
    71  		case <-w.tomb.Dying():
    72  			return tomb.ErrDying
    73  		// TODO(fwereade): 2016-03-17 lp:1558657
    74  		case <-time.After(ErrorRetryWaitDelay):
    75  			out = w.out
    76  		case out <- struct{}{}:
    77  			out = nil
    78  		}
    79  	}
    80  }