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

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package state
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/mgo/v3/bson"
     9  
    10  	"github.com/juju/juju/core/life"
    11  	"github.com/juju/juju/mongo"
    12  )
    13  
    14  // Life represents the lifecycle state of the entities
    15  // Relation, Unit, Application and Machine.
    16  type Life int8
    17  
    18  const (
    19  	Alive Life = iota
    20  	Dying
    21  	Dead
    22  )
    23  
    24  // String is deprecated, use Value.
    25  func (l Life) String() string {
    26  	switch l {
    27  	case Alive:
    28  		return "alive"
    29  	case Dying:
    30  		return "dying"
    31  	case Dead:
    32  		return "dead"
    33  	default:
    34  		return "unknown"
    35  	}
    36  }
    37  
    38  // Value returns the core.life.Value type.
    39  func (l Life) Value() life.Value {
    40  	switch l {
    41  	case Alive:
    42  		return life.Alive
    43  	case Dying:
    44  		return life.Dying
    45  	case Dead:
    46  		return life.Dead
    47  	default:
    48  		return life.Value("unknown")
    49  	}
    50  }
    51  
    52  // LifeFromValue converts a life.Value into it's corresponding
    53  // state.Life
    54  func LifeFromValue(value life.Value) Life {
    55  	return valueMap[value]
    56  }
    57  
    58  var (
    59  	isAliveDoc = bson.D{{"life", Alive}}
    60  	isDyingDoc = bson.D{{"life", Dying}}
    61  	isDeadDoc  = bson.D{{"life", Dead}}
    62  	notDeadDoc = bson.D{{"life", bson.D{{"$ne", Dead}}}}
    63  
    64  	errDeadOrGone     = errors.New("neither alive nor dying")
    65  	errAlreadyDying   = errors.New("already dying")
    66  	errAlreadyRemoved = errors.New("already removed")
    67  )
    68  
    69  var valueMap = map[life.Value]Life{
    70  	life.Alive: Alive,
    71  	life.Dying: Dying,
    72  	life.Dead:  Dead,
    73  }
    74  
    75  // Living describes state entities with a lifecycle.
    76  type Living interface {
    77  	Life() Life
    78  	Destroy() error
    79  	Refresh() error
    80  }
    81  
    82  // AgentLiving describes state entities with a lifecycle and an agent that
    83  // manages it.
    84  type AgentLiving interface {
    85  	Living
    86  	EnsureDead() error
    87  	Remove() error
    88  }
    89  
    90  func isAlive(mb modelBackend, collName string, id interface{}) (bool, error) {
    91  	coll, closer := mb.db().GetCollection(collName)
    92  	defer closer()
    93  	return isAliveWithSession(coll, id)
    94  }
    95  
    96  func isAliveWithSession(coll mongo.Collection, id interface{}) (bool, error) {
    97  	return checkLifeWithSession(coll, id, bson.DocElem{"life", Alive})
    98  }
    99  
   100  func isNotDead(mb modelBackend, collName string, id interface{}) (bool, error) {
   101  	coll, closer := mb.db().GetCollection(collName)
   102  	defer closer()
   103  	return isNotDeadWithSession(coll, id)
   104  }
   105  
   106  func isNotDeadWithSession(coll mongo.Collection, id interface{}) (bool, error) {
   107  	return checkLifeWithSession(coll, id, bson.DocElem{"life", bson.D{{"$ne", Dead}}})
   108  }
   109  
   110  func isDying(mb modelBackend, collName string, id interface{}) (bool, error) {
   111  	coll, closer := mb.db().GetCollection(collName)
   112  	defer closer()
   113  	return isDyingWithSession(coll, id)
   114  }
   115  
   116  func isDyingWithSession(coll mongo.Collection, id interface{}) (bool, error) {
   117  	return checkLifeWithSession(coll, id, bson.DocElem{"life", Dying})
   118  }
   119  
   120  func checkLifeWithSession(coll mongo.Collection, id interface{}, sel bson.DocElem) (bool, error) {
   121  	n, err := coll.Find(bson.D{{"_id", id}, sel}).Count()
   122  	return n == 1, err
   123  }