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