github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/worker/uniter/hook/sender.go (about) 1 // Copyright 2012-2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package hook 5 6 import ( 7 "github.com/juju/errors" 8 "gopkg.in/tomb.v1" 9 10 "github.com/juju/juju/state/watcher" 11 ) 12 13 // Sender maintains a Source and delivers its hooks via a channel. 14 type Sender interface { 15 Stop() error 16 } 17 18 // NewSender starts sending hooks from source onto the out channel, and will 19 // continue to do so until Stop()ped (or the source is exhausted). NewSender 20 // takes ownership of the supplied source, and responsibility for cleaning it up; 21 // but it will not close the out channel. 22 func NewSender(out chan<- Info, source Source) Sender { 23 sender := &hookSender{ 24 out: out, 25 } 26 go func() { 27 defer sender.tomb.Done() 28 defer watcher.Stop(source, &sender.tomb) 29 sender.tomb.Kill(sender.loop(source)) 30 }() 31 return sender 32 } 33 34 // hookSender implements Sender. 35 type hookSender struct { 36 tomb tomb.Tomb 37 out chan<- Info 38 } 39 40 // Stop stops the Sender and returns any errors encountered during 41 // operation or while shutting down. 42 func (sender *hookSender) Stop() error { 43 sender.tomb.Kill(nil) 44 return sender.tomb.Wait() 45 } 46 47 // loop synchronously delivers the source's change events to its update method, 48 // and, whenever the source is nonempty, repeatedly sends its first scheduled 49 // event on the out chan (and pops it from the source). 50 func (sender *hookSender) loop(source Source) error { 51 var next Info 52 var out chan<- Info 53 for { 54 if source.Empty() { 55 out = nil 56 } else { 57 out = sender.out 58 next = source.Next() 59 } 60 select { 61 case <-sender.tomb.Dying(): 62 return tomb.ErrDying 63 case out <- next: 64 source.Pop() 65 case change, ok := <-source.Changes(): 66 if !ok { 67 return errors.New("hook source stopped providing updates") 68 } 69 if err := change.Apply(); err != nil { 70 return errors.Trace(err) 71 } 72 } 73 } 74 }