github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/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 }