github.com/juju/juju@v0.0.0-20240327075706-a90865de2538/worker/caasunitsmanager/worker.go (about)

     1  // Copyright 2022 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package caasunitsmanager
     5  
     6  import (
     7  	"github.com/juju/clock"
     8  	"github.com/juju/errors"
     9  	"github.com/juju/worker/v3"
    10  	"github.com/juju/worker/v3/catacomb"
    11  
    12  	message "github.com/juju/juju/pubsub/agent"
    13  )
    14  
    15  // Hub is a pubsub hub used for internal messaging.
    16  type Hub interface {
    17  	Publish(topic string, data interface{}) func()
    18  	Subscribe(topic string, handler func(string, interface{})) func()
    19  }
    20  
    21  type manager struct {
    22  	catacomb catacomb.Catacomb
    23  
    24  	logger Logger
    25  	clock  clock.Clock
    26  
    27  	hub   Hub
    28  	unsub func()
    29  }
    30  
    31  type Config struct {
    32  	Logger
    33  	Clock clock.Clock
    34  
    35  	Hub
    36  }
    37  
    38  // NewWorker returns a worker that runs on CAAS agent and subscribes and handles unit topics.
    39  func NewWorker(config Config) (worker.Worker, error) {
    40  	w := manager{
    41  		logger: config.Logger,
    42  		clock:  config.Clock,
    43  		hub:    config.Hub,
    44  	}
    45  	unsubStop := w.hub.Subscribe(message.StopUnitTopic, w.stopUnitRequest)
    46  	unsubStart := w.hub.Subscribe(message.StartUnitTopic, w.startUnitRequest)
    47  	unsubStatus := w.hub.Subscribe(message.UnitStatusTopic, w.unitStatusRequest)
    48  	w.unsub = func() {
    49  		unsubStop()
    50  		unsubStart()
    51  		unsubStatus()
    52  	}
    53  	err := catacomb.Invoke(catacomb.Plan{
    54  		Site: &w.catacomb,
    55  		Work: w.loop,
    56  	})
    57  	if err != nil {
    58  		return nil, errors.Trace(err)
    59  	}
    60  	return &w, nil
    61  }
    62  
    63  func (w *manager) stopUnitRequest(topic string, data interface{}) {
    64  	units, ok := data.(message.Units)
    65  	if !ok {
    66  		w.logger.Errorf("data should be a Units structure")
    67  	}
    68  	response := message.StartStopResponse{
    69  		"error": errors.NotSupportedf("stop units for %v", units).Error(),
    70  	}
    71  	w.hub.Publish(message.StopUnitResponseTopic, response)
    72  }
    73  
    74  func (w *manager) startUnitRequest(topic string, data interface{}) {
    75  	units, ok := data.(message.Units)
    76  	if !ok {
    77  		w.logger.Errorf("data should be a Units structure")
    78  	}
    79  	response := message.StartStopResponse{
    80  		"error": errors.NotSupportedf("start units for %v", units).Error(),
    81  	}
    82  	w.hub.Publish(message.StartUnitResponseTopic, response)
    83  }
    84  
    85  func (w *manager) unitStatusRequest(topic string, _ interface{}) {
    86  	response := message.Status{
    87  		"error": errors.NotSupportedf("units status").Error(),
    88  	}
    89  	w.hub.Publish(message.UnitStatusResponseTopic, response)
    90  }
    91  
    92  func (w *manager) Kill() {
    93  	w.unsub()
    94  	w.catacomb.Kill(nil)
    95  }
    96  
    97  func (w *manager) Wait() error {
    98  	return w.catacomb.Wait()
    99  }
   100  
   101  func (w *manager) loop() error {
   102  	<-w.catacomb.Dying()
   103  	return w.catacomb.ErrDying()
   104  }