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

     1  // Copyright 2016 Canonical Ltd.
     2  // Copyright 2016 Cloudbase Solutions
     3  // Licensed under the AGPLv3, see LICENCE file for details.
     4  
     5  package retrystrategy
     6  
     7  import (
     8  	"github.com/juju/errors"
     9  	"gopkg.in/juju/names.v2"
    10  	"gopkg.in/juju/worker.v1"
    11  
    12  	"github.com/juju/juju/apiserver/params"
    13  	"github.com/juju/juju/core/watcher"
    14  )
    15  
    16  // Facade defines the capabilities required by the worker from the API.
    17  type Facade interface {
    18  	RetryStrategy(names.Tag) (params.RetryStrategy, error)
    19  	WatchRetryStrategy(names.Tag) (watcher.NotifyWatcher, error)
    20  }
    21  
    22  // WorkerConfig defines the worker's dependencies.
    23  type WorkerConfig struct {
    24  	Facade        Facade
    25  	AgentTag      names.Tag
    26  	RetryStrategy params.RetryStrategy
    27  }
    28  
    29  // Validate returns an error if the configuration is not complete.
    30  func (c WorkerConfig) Validate() error {
    31  	if c.Facade == nil {
    32  		return errors.NotValidf("nil Facade")
    33  	}
    34  	if c.AgentTag == nil {
    35  		return errors.NotValidf("nil AgentTag")
    36  	}
    37  	empty := params.RetryStrategy{}
    38  	if c.RetryStrategy == empty {
    39  		return errors.NotValidf("empty RetryStrategy")
    40  	}
    41  	return nil
    42  }
    43  
    44  // RetryStrategyWorker is a NotifyWorker with one additional
    45  // method that returns the current retry strategy.
    46  type RetryStrategyWorker struct {
    47  	*watcher.NotifyWorker
    48  	retryStrategy params.RetryStrategy
    49  }
    50  
    51  // NewRetryStrategyWorker returns a worker.Worker that returns the current
    52  // retry strategy and bounces when it changes.
    53  func NewRetryStrategyWorker(config WorkerConfig) (worker.Worker, error) {
    54  	if err := config.Validate(); err != nil {
    55  		return nil, errors.Trace(err)
    56  	}
    57  	w, err := watcher.NewNotifyWorker(watcher.NotifyConfig{
    58  		Handler: retryStrategyHandler{config},
    59  	})
    60  	if err != nil {
    61  		return nil, errors.Trace(err)
    62  	}
    63  	return &RetryStrategyWorker{w, config.RetryStrategy}, nil
    64  }
    65  
    66  // GetRetryStrategy returns the current hook retry strategy
    67  func (w *RetryStrategyWorker) GetRetryStrategy() params.RetryStrategy {
    68  	return w.retryStrategy
    69  }
    70  
    71  // retryStrategyHandler implements watcher.NotifyHandler
    72  type retryStrategyHandler struct {
    73  	config WorkerConfig
    74  }
    75  
    76  // SetUp is part of the watcher.NotifyHandler interface.
    77  func (h retryStrategyHandler) SetUp() (watcher.NotifyWatcher, error) {
    78  	return h.config.Facade.WatchRetryStrategy(h.config.AgentTag)
    79  }
    80  
    81  // Handle is part of the watcher.NotifyHandler interface.
    82  // Whenever a valid change is encountered the worker bounces,
    83  // making the dependents bounce and get the new value
    84  func (h retryStrategyHandler) Handle(_ <-chan struct{}) error {
    85  	newRetryStrategy, err := h.config.Facade.RetryStrategy(h.config.AgentTag)
    86  	if err != nil {
    87  		return errors.Trace(err)
    88  	}
    89  	if newRetryStrategy != h.config.RetryStrategy {
    90  		return errors.Errorf("bouncing retrystrategy worker to get new values")
    91  	}
    92  	return nil
    93  }
    94  
    95  // TearDown is part of the watcher.NotifyHandler interface.
    96  func (h retryStrategyHandler) TearDown() error {
    97  	// Nothing to cleanup, only state is the watcher
    98  	return nil
    99  }