github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/pruner/worker.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package pruner 5 6 import ( 7 "time" 8 9 "github.com/juju/clock" 10 "github.com/juju/errors" 11 "github.com/juju/loggo" 12 "gopkg.in/juju/worker.v1/catacomb" 13 14 "github.com/juju/juju/core/watcher" 15 "github.com/juju/juju/environs/config" 16 ) 17 18 var logger = loggo.GetLogger("juju.worker.pruner") 19 20 // Facade represents an API that implements status history pruning. 21 type Facade interface { 22 Prune(time.Duration, int) error 23 WatchForModelConfigChanges() (watcher.NotifyWatcher, error) 24 ModelConfig() (*config.Config, error) 25 } 26 27 // Worker prunes status history records at regular intervals. 28 type PrunerWorker struct { 29 catacomb catacomb.Catacomb 30 config Config 31 } 32 33 // Kill is defined on worker.Worker. 34 func (w *PrunerWorker) Kill() { 35 w.catacomb.Kill(nil) 36 } 37 38 // Wait is defined on worker.Worker. 39 func (w *PrunerWorker) Wait() error { 40 return w.catacomb.Wait() 41 } 42 43 // returns the prune worker's catacomb 44 func (w *PrunerWorker) Catacomb() *catacomb.Catacomb { 45 return &w.catacomb 46 } 47 48 // return the prune worker's config 49 func (w *PrunerWorker) Config() *Config { 50 return &w.config 51 } 52 53 // body of generic pruner loop 54 func (w *PrunerWorker) Work(getPrunerConfig func(*config.Config) (time.Duration, uint)) error { 55 modelConfigWatcher, err := w.config.Facade.WatchForModelConfigChanges() 56 if err != nil { 57 return errors.Trace(err) 58 } 59 err = w.catacomb.Add(modelConfigWatcher) 60 if err != nil { 61 return errors.Trace(err) 62 } 63 64 var ( 65 maxAge time.Duration 66 maxCollectionMB uint 67 modelConfigChanges = modelConfigWatcher.Changes() 68 // We will also get an initial event, but need to ensure that event is 69 // received before doing any pruning. 70 ) 71 72 var timer clock.Timer 73 var timerCh <-chan time.Time 74 for { 75 select { 76 case <-w.catacomb.Dying(): 77 return w.catacomb.ErrDying() 78 79 case _, ok := <-modelConfigChanges: 80 if !ok { 81 return errors.New("model configuration watcher closed") 82 } 83 modelConfig, err := w.config.Facade.ModelConfig() 84 if err != nil { 85 return errors.Annotate(err, "cannot load model configuration") 86 } 87 88 newMaxAge, newMaxCollectionMB := getPrunerConfig(modelConfig) 89 90 if newMaxAge != maxAge || newMaxCollectionMB != maxCollectionMB { 91 logger.Infof("status history config: max age: %v, max collection size %dM for %s (%s)", 92 newMaxAge, newMaxCollectionMB, modelConfig.Name(), modelConfig.UUID()) 93 maxAge = newMaxAge 94 maxCollectionMB = newMaxCollectionMB 95 } 96 if timer == nil { 97 timer = w.config.Clock.NewTimer(w.config.PruneInterval) 98 timerCh = timer.Chan() 99 } 100 101 case <-timerCh: 102 err := w.config.Facade.Prune(maxAge, int(maxCollectionMB)) 103 if err != nil { 104 return errors.Trace(err) 105 } 106 timer.Reset(w.config.PruneInterval) 107 } 108 } 109 }