github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/modelcache/manifold.go (about)

     1  // Copyright 2018 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package modelcache
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/prometheus/client_golang/prometheus"
     9  	"gopkg.in/juju/worker.v1"
    10  	"gopkg.in/juju/worker.v1/dependency"
    11  
    12  	"github.com/juju/juju/core/cache"
    13  	workerstate "github.com/juju/juju/worker/state"
    14  )
    15  
    16  // Logger describes the logging methods used in this package by the worker.
    17  type Logger interface {
    18  	IsTraceEnabled() bool
    19  	Tracef(string, ...interface{})
    20  	Errorf(string, ...interface{})
    21  }
    22  
    23  // ManifoldConfig holds the information necessary to run a model cache worker in
    24  // a dependency.Engine.
    25  type ManifoldConfig struct {
    26  	StateName string
    27  	Logger    Logger
    28  
    29  	PrometheusRegisterer prometheus.Registerer
    30  
    31  	NewWorker func(Config) (worker.Worker, error)
    32  }
    33  
    34  // Validate validates the manifold configuration.
    35  func (config ManifoldConfig) Validate() error {
    36  	if config.StateName == "" {
    37  		return errors.NotValidf("empty StateName")
    38  	}
    39  	if config.Logger == nil {
    40  		return errors.NotValidf("missing Logger")
    41  	}
    42  	if config.PrometheusRegisterer == nil {
    43  		return errors.NotValidf("missing PrometheusRegisterer")
    44  	}
    45  	if config.NewWorker == nil {
    46  		return errors.NotValidf("missing NewWorker func")
    47  	}
    48  	return nil
    49  }
    50  
    51  // Manifold returns a dependency.Manifold that will run a model cache
    52  // worker. The manifold outputs a *cache.Controller, primarily for
    53  // the apiserver to depend on and use.
    54  func Manifold(config ManifoldConfig) dependency.Manifold {
    55  	return dependency.Manifold{
    56  		Inputs: []string{
    57  			config.StateName,
    58  		},
    59  		Start:  config.start,
    60  		Output: ExtractCacheController,
    61  	}
    62  }
    63  
    64  // start is a method on ManifoldConfig because it's more readable than a closure.
    65  func (config ManifoldConfig) start(context dependency.Context) (worker.Worker, error) {
    66  	if err := config.Validate(); err != nil {
    67  		return nil, errors.Trace(err)
    68  	}
    69  
    70  	var stTracker workerstate.StateTracker
    71  	if err := context.Get(config.StateName, &stTracker); err != nil {
    72  		return nil, errors.Trace(err)
    73  	}
    74  
    75  	statePool, err := stTracker.Use()
    76  	if err != nil {
    77  		return nil, errors.Trace(err)
    78  	}
    79  
    80  	w, err := config.NewWorker(Config{
    81  		Logger:               config.Logger,
    82  		StatePool:            statePool,
    83  		PrometheusRegisterer: config.PrometheusRegisterer,
    84  		Cleanup: func() {
    85  			stTracker.Done()
    86  		},
    87  	})
    88  	if err != nil {
    89  		stTracker.Done()
    90  		return nil, errors.Trace(err)
    91  	}
    92  	return w, nil
    93  }
    94  
    95  // ExtractCacheController extracts a *cache.Controller from a *cacheWorker.
    96  func ExtractCacheController(in worker.Worker, out interface{}) error {
    97  	inWorker, _ := in.(*cacheWorker)
    98  	if inWorker == nil {
    99  		return errors.Errorf("in should be a %T; got %T", inWorker, in)
   100  	}
   101  
   102  	switch outPointer := out.(type) {
   103  	case **cache.Controller:
   104  		*outPointer = inWorker.controller
   105  	default:
   106  		return errors.Errorf("out should be *cache.Controller; got %T", out)
   107  	}
   108  	return nil
   109  }