github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/cmd/jujud/agent/engine/valueworker.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package engine
     5  
     6  import (
     7  	"reflect"
     8  
     9  	"github.com/juju/errors"
    10  	"gopkg.in/tomb.v1"
    11  
    12  	"github.com/juju/juju/worker"
    13  )
    14  
    15  // NewValueWorker returns a degenerate worker that exposes the supplied value
    16  // when passed into ValueWorkerOutput. Please do not supply values that have
    17  // their own dependency or lifecycle considerations; such values will subvert
    18  // the operation of any containing dependency.Engine by insulating it from the
    19  // failures and dependency changes of the contained value.
    20  func NewValueWorker(value interface{}) (worker.Worker, error) {
    21  	if value == nil {
    22  		return nil, errors.New("NewValueWorker expects a value")
    23  	}
    24  	w := &valueWorker{
    25  		value: value,
    26  	}
    27  	go func() {
    28  		defer w.tomb.Done()
    29  		<-w.tomb.Dying()
    30  	}()
    31  	return w, nil
    32  }
    33  
    34  // ValueWorkerOutput sets the value wrapped by the supplied valueWorker into
    35  // the out pointer, if type-compatible, or fails.
    36  func ValueWorkerOutput(in worker.Worker, out interface{}) error {
    37  	inWorker, _ := in.(*valueWorker)
    38  	if inWorker == nil {
    39  		return errors.Errorf("in should be a *valueWorker; is %#v", in)
    40  	}
    41  	outV := reflect.ValueOf(out)
    42  	if outV.Kind() != reflect.Ptr {
    43  		return errors.Errorf("out should be a pointer; is %#v", out)
    44  	}
    45  	outValV := outV.Elem()
    46  	outValT := outValV.Type()
    47  	inValV := reflect.ValueOf(inWorker.value)
    48  	inValT := inValV.Type()
    49  	if !inValT.ConvertibleTo(outValT) {
    50  		return errors.Errorf("cannot output into %T", out)
    51  	}
    52  	outValV.Set(inValV.Convert(outValT))
    53  	return nil
    54  }
    55  
    56  // valueWorker implements a degenerate worker wrapping a single value.
    57  type valueWorker struct {
    58  	tomb  tomb.Tomb
    59  	value interface{}
    60  }
    61  
    62  // Kill is part of the worker.Worker interface.
    63  func (v *valueWorker) Kill() {
    64  	v.tomb.Kill(nil)
    65  }
    66  
    67  // Wait is part of the worker.Worker interface.
    68  func (v *valueWorker) Wait() error {
    69  	return v.tomb.Wait()
    70  }