github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/agent/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.v2"
    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  	w.tomb.Go(func() error {
    26  		defer close(w.out)
    27  		return w.loop()
    28  	})
    29  	return w
    30  }
    31  
    32  // Stop stops the watcher, and returns any error encountered while running
    33  // or shutting down.
    34  func (w *machineErrorRetry) Stop() error {
    35  	w.Kill()
    36  	return w.Wait()
    37  }
    38  
    39  // Kill kills the watcher without waiting for it to shut down.
    40  func (w *machineErrorRetry) Kill() {
    41  	w.tomb.Kill(nil)
    42  }
    43  
    44  // Wait waits for the watcher to die and returns any
    45  // error encountered when it was running.
    46  func (w *machineErrorRetry) Wait() error {
    47  	return w.tomb.Wait()
    48  }
    49  
    50  // Err returns any error encountered while running or shutting down, or
    51  // tomb.ErrStillAlive if the watcher is still running.
    52  func (w *machineErrorRetry) Err() error {
    53  	return w.tomb.Err()
    54  }
    55  
    56  // Changes returns the event channel for the machineErrorRetry watcher.
    57  func (w *machineErrorRetry) Changes() <-chan struct{} {
    58  	return w.out
    59  }
    60  
    61  // ErrorRetryWaitDelay is the poll time currently used to trigger the watcher.
    62  var ErrorRetryWaitDelay = 1 * time.Minute
    63  
    64  // The initial implementation of this watcher simply acts as a poller,
    65  // triggering every ErrorRetryWaitDelay minutes.
    66  func (w *machineErrorRetry) loop() error {
    67  	out := w.out
    68  	for {
    69  		select {
    70  		case <-w.tomb.Dying():
    71  			return tomb.ErrDying
    72  		// TODO(fwereade): 2016-03-17 lp:1558657
    73  		case <-time.After(ErrorRetryWaitDelay):
    74  			out = w.out
    75  		case out <- struct{}{}:
    76  			out = nil
    77  		}
    78  	}
    79  }