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