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  }