github.com/billybanfield/evergreen@v0.0.0-20170525200750-eeee692790f7/db/globals.go (about)

     1  package db
     2  
     3  import (
     4  	"gopkg.in/mgo.v2"
     5  	"gopkg.in/mgo.v2/bson"
     6  )
     7  
     8  const (
     9  	GlobalsCollection = "globals"
    10  )
    11  
    12  // Global stores internal tracking information.
    13  type Global struct {
    14  	BuildVariant    string `bson:"_id"`
    15  	LastBuildNumber uint64 `bson:"last_build_number"`
    16  	LastTaskNumber  uint64 `bson:"last_task_number"`
    17  }
    18  
    19  // GetNewBuildVariantTaskNumber atomically gets a new number for a task,
    20  // given its variant name.
    21  func GetNewBuildVariantTaskNumber(buildVariant string) (uint64, error) {
    22  	session, db, err := GetGlobalSessionFactory().GetSession()
    23  	if err != nil {
    24  		return 0, err
    25  	}
    26  	defer session.Close()
    27  
    28  	// get the record for this build variant
    29  	global := Global{}
    30  	err = db.C(GlobalsCollection).Find(bson.M{"_id": buildVariant}).One(&global)
    31  
    32  	// if this is the first task for
    33  	// this build variant, insert it
    34  	if err != nil && err == mgo.ErrNotFound {
    35  		change := mgo.Change{
    36  			Update:    bson.M{"$inc": bson.M{"last_task_number": 1}},
    37  			Upsert:    true,
    38  			ReturnNew: true,
    39  		}
    40  
    41  		_, err = db.C(GlobalsCollection).Find(bson.M{"_id": buildVariant}).Apply(change, &global)
    42  		if err != nil {
    43  			return 0, err
    44  		}
    45  		return global.LastTaskNumber, nil
    46  	}
    47  
    48  	// use the current build number the first time
    49  	// any client requests the build variant's task number
    50  	var newBuildVariantTaskNumber uint64
    51  	if global.LastTaskNumber == uint64(0) {
    52  		newBuildVariantTaskNumber = global.LastBuildNumber
    53  	} else {
    54  		newBuildVariantTaskNumber = global.LastTaskNumber + 1
    55  	}
    56  	change := mgo.Change{
    57  		Update: bson.M{"$set": bson.M{
    58  			"last_task_number": newBuildVariantTaskNumber,
    59  		}},
    60  		ReturnNew: true,
    61  	}
    62  
    63  	_, err = db.C(GlobalsCollection).Find(bson.M{"_id": buildVariant}).Apply(change, &global)
    64  
    65  	if err != nil {
    66  		return 0, err
    67  	}
    68  
    69  	return global.LastTaskNumber, nil
    70  }
    71  
    72  // GetNewBuildVariantBuildNumber atomically gets a new number for a build,
    73  // given its variant name.
    74  func GetNewBuildVariantBuildNumber(buildVariant string) (uint64, error) {
    75  	session, db, err := GetGlobalSessionFactory().GetSession()
    76  	if err != nil {
    77  		return 0, err
    78  	}
    79  	defer session.Close()
    80  
    81  	// get the record for this build variant
    82  	global := Global{}
    83  	err = db.C(GlobalsCollection).Find(bson.M{"_id": buildVariant}).One(&global)
    84  
    85  	// if this is the first build for this
    86  	// this build variant, insert it
    87  	if err != nil && err == mgo.ErrNotFound {
    88  		change := mgo.Change{
    89  			Update:    bson.M{"$inc": bson.M{"last_build_number": 1}},
    90  			Upsert:    true,
    91  			ReturnNew: true,
    92  		}
    93  
    94  		_, err = db.C(GlobalsCollection).Find(bson.M{"_id": buildVariant}).Apply(change, &global)
    95  		if err != nil {
    96  			return 0, err
    97  		}
    98  		return global.LastBuildNumber, nil
    99  	}
   100  
   101  	// At this point, we know we've
   102  	// seen this build variant before
   103  	// find and modify last build variant number
   104  	change := mgo.Change{
   105  		Update:    bson.M{"$inc": bson.M{"last_build_number": 1}},
   106  		ReturnNew: true,
   107  	}
   108  
   109  	_, err = db.C(GlobalsCollection).Find(bson.M{"_id": buildVariant}).Apply(change, &global)
   110  
   111  	if err != nil {
   112  		return 0, err
   113  	}
   114  
   115  	return global.LastBuildNumber, nil
   116  }