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  }