github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/watcher/legacy/stringsworker.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package legacy 5 6 import ( 7 "gopkg.in/juju/worker.v1" 8 "gopkg.in/tomb.v2" 9 10 "github.com/juju/juju/state" 11 "github.com/juju/juju/state/watcher" 12 ) 13 14 // stringsWorker is the internal implementation of the Worker 15 // interface, using a StringsWatcher for handling changes. 16 type stringsWorker struct { 17 tomb tomb.Tomb 18 handler StringsWatchHandler 19 } 20 21 // StringsWatchHandler implements the business logic triggered as part 22 // of watching a StringsWatcher. 23 type StringsWatchHandler interface { 24 // SetUp will be called once, and should return the watcher that will 25 // be used to trigger subsequent Handle()s. SetUp can return a watcher 26 // even if there is an error, and the notify worker will make sure 27 // to stop the watcher. 28 SetUp() (state.StringsWatcher, error) 29 30 // TearDown should cleanup any resources that are left around. 31 TearDown() error 32 33 // Handle is called whenever the watcher returned from SetUp sends a value 34 // on its Changes() channel. 35 Handle(changes []string) error 36 } 37 38 // NewStringsWorker starts a new worker running the business logic 39 // from the handler. The worker loop is started in another goroutine 40 // as a side effect of calling this. 41 func NewStringsWorker(handler StringsWatchHandler) worker.Worker { 42 sw := &stringsWorker{ 43 handler: handler, 44 } 45 sw.tomb.Go(sw.loop) 46 return sw 47 } 48 49 // Kill is part of the worker.Worker interface. 50 func (sw *stringsWorker) Kill() { 51 sw.tomb.Kill(nil) 52 } 53 54 // Wait is part of the worker.Worker interface. 55 func (sw *stringsWorker) Wait() error { 56 return sw.tomb.Wait() 57 } 58 59 func (sw *stringsWorker) loop() error { 60 w, err := sw.handler.SetUp() 61 if err != nil { 62 if w != nil { 63 // We don't bother to propagate an error, because we 64 // already have an error. 65 w.Stop() 66 } 67 return err 68 } 69 defer propagateTearDown(sw.handler, &sw.tomb) 70 defer watcher.Stop(w, &sw.tomb) 71 for { 72 select { 73 case <-sw.tomb.Dying(): 74 return tomb.ErrDying 75 case changes, ok := <-w.Changes(): 76 if !ok { 77 return ensureErr(w) 78 } 79 if err := sw.handler.Handle(changes); err != nil { 80 return err 81 } 82 } 83 } 84 }