github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/restorewatcher/worker.go (about) 1 // Copyright 2017 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package restorewatcher 5 6 import ( 7 "sync" 8 9 "github.com/juju/errors" 10 "gopkg.in/juju/worker.v1/catacomb" 11 12 "github.com/juju/juju/state" 13 ) 14 15 // Config holds the worker configuration. 16 type Config struct { 17 RestoreInfoWatcher RestoreInfoWatcher 18 } 19 20 // Validate validates the worker configuration. 21 func (config Config) Validate() error { 22 if config.RestoreInfoWatcher == nil { 23 return errors.NotValidf("nil RestoreInfoWatcher") 24 } 25 return nil 26 } 27 28 // RestoreInfoWatcher is an interface for watching and obtaining the 29 // restore info/status. 30 type RestoreInfoWatcher interface { 31 WatchRestoreInfoChanges() state.NotifyWatcher 32 RestoreStatus() (state.RestoreStatus, error) 33 } 34 35 // NewWorker returns a new worker that watches for changes to restore 36 // info, and reports the status to the provided function. 37 func NewWorker(config Config) (RestoreStatusWorker, error) { 38 if err := config.Validate(); err != nil { 39 return nil, errors.Trace(err) 40 } 41 restoreStatus, err := config.RestoreInfoWatcher.RestoreStatus() 42 if err != nil { 43 return nil, errors.Trace(err) 44 } 45 w := &restoreWorker{ 46 config: config, 47 status: restoreStatus, 48 } 49 if err := catacomb.Invoke(catacomb.Plan{ 50 Site: &w.catacomb, 51 Work: w.loop, 52 }); err != nil { 53 return nil, errors.Trace(err) 54 } 55 return w, nil 56 } 57 58 type restoreWorker struct { 59 catacomb catacomb.Catacomb 60 config Config 61 62 mu sync.Mutex 63 status state.RestoreStatus 64 } 65 66 func (w *restoreWorker) loop() error { 67 rw := w.config.RestoreInfoWatcher.WatchRestoreInfoChanges() 68 w.catacomb.Add(rw) 69 for { 70 select { 71 case <-w.catacomb.Dying(): 72 return w.catacomb.ErrDying() 73 case <-rw.Changes(): 74 status, err := w.config.RestoreInfoWatcher.RestoreStatus() 75 if err != nil { 76 return errors.Trace(err) 77 } 78 w.mu.Lock() 79 w.status = status 80 w.mu.Unlock() 81 } 82 } 83 } 84 85 // RestoreStatus returns the most recently observed restore status. 86 func (w *restoreWorker) RestoreStatus() state.RestoreStatus { 87 w.mu.Lock() 88 defer w.mu.Unlock() 89 return w.status 90 } 91 92 // Kill is part of the worker.Worker interface. 93 func (w *restoreWorker) Kill() { 94 w.catacomb.Kill(nil) 95 } 96 97 // Wait is part of the worker.Worker interface. 98 func (w *restoreWorker) Wait() error { 99 return w.catacomb.Wait() 100 }