github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/api/allwatcher.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package api
     5  
     6  import (
     7  	"sort"
     8  
     9  	"github.com/juju/juju/api/base"
    10  	"github.com/juju/juju/rpc/params"
    11  )
    12  
    13  // AllWatch represents methods used on the AllWatcher
    14  // Primarily to facilitate mock tests.
    15  type AllWatch interface {
    16  	Next() ([]params.Delta, error)
    17  	Stop() error
    18  }
    19  
    20  // AllWatcher holds information allowing us to get Deltas describing
    21  // changes to the entire model or all models (depending on
    22  // the watcher type).
    23  type AllWatcher struct {
    24  	objType string
    25  	caller  base.APICaller
    26  	id      *string
    27  }
    28  
    29  // NewAllWatcher returns an AllWatcher instance which interacts with a
    30  // watcher created by the WatchAll API call.
    31  //
    32  // There should be no need to call this from outside of the api
    33  // package. It is only used by Client.WatchAll in this package.
    34  func NewAllWatcher(caller base.APICaller, id *string) *AllWatcher {
    35  	return newAllWatcher("AllWatcher", caller, id)
    36  }
    37  
    38  // NewAllModelWatcher returns an AllWatcher instance which interacts
    39  // with a watcher created by the WatchAllModels API call.
    40  //
    41  // There should be no need to call this from outside of the api
    42  // package. It is only used by Client.WatchAllModels in
    43  // api/controller.
    44  func NewAllModelWatcher(caller base.APICaller, id *string) *AllWatcher {
    45  	return newAllWatcher("AllModelWatcher", caller, id)
    46  }
    47  
    48  func newAllWatcher(objType string, caller base.APICaller, id *string) *AllWatcher {
    49  	return &AllWatcher{
    50  		objType: objType,
    51  		caller:  caller,
    52  		id:      id,
    53  	}
    54  }
    55  
    56  // Next returns a new set of deltas from a watcher previously created
    57  // by the WatchAll or WatchAllModels API calls. It will block until
    58  // there are deltas to return.
    59  func (watcher *AllWatcher) Next() ([]params.Delta, error) {
    60  	var info params.AllWatcherNextResults
    61  	err := watcher.caller.APICall(
    62  		watcher.objType,
    63  		watcher.caller.BestFacadeVersion(watcher.objType),
    64  		*watcher.id,
    65  		"Next",
    66  		nil, &info,
    67  	)
    68  	// We'll order the deltas so relation changes come last.
    69  	// This allows the callers like the Dashboard to process changes
    70  	// in the right order.
    71  	sort.Sort(orderedDeltas(info.Deltas))
    72  	return info.Deltas, err
    73  }
    74  
    75  type orderedDeltas []params.Delta
    76  
    77  func (o orderedDeltas) Len() int {
    78  	return len(o)
    79  }
    80  
    81  func (o orderedDeltas) kindPriority(kind string) int {
    82  	switch kind {
    83  	case "machine":
    84  		return 1
    85  	case "application":
    86  		return 2
    87  	case "relation":
    88  		return 3
    89  	}
    90  	return 0
    91  }
    92  
    93  func (o orderedDeltas) Less(i, j int) bool {
    94  	// All we care about is having relation deltas last.
    95  	// We'll add extra checks though to make the order more
    96  	// deterministic for tests.
    97  	pi, pj := o.kindPriority(o[i].Entity.EntityId().Kind), o.kindPriority(o[j].Entity.EntityId().Kind)
    98  	if pi == pj {
    99  		return o[i].Entity.EntityId().Id < o[j].Entity.EntityId().Id
   100  	}
   101  	return pi < pj
   102  }
   103  
   104  func (o orderedDeltas) Swap(i, j int) {
   105  	o[i], o[j] = o[j], o[i]
   106  }
   107  
   108  // Stop shutdowns down a watcher previously created by the WatchAll or
   109  // WatchAllModels API calls
   110  func (watcher *AllWatcher) Stop() error {
   111  	return watcher.caller.APICall(
   112  		watcher.objType,
   113  		watcher.caller.BestFacadeVersion(watcher.objType),
   114  		*watcher.id,
   115  		"Stop",
   116  		nil, nil,
   117  	)
   118  }