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

     1  package scheduler
     2  
     3  import (
     4  	"github.com/evergreen-ci/evergreen"
     5  	"github.com/evergreen-ci/evergreen/model/task"
     6  	"github.com/pkg/errors"
     7  )
     8  
     9  // Comparator (-1 if second is more important, 1 if first is, 0 if equal)
    10  // takes in the task comparator because it may need access to additional info
    11  //  beyond just what's in the tasks
    12  type taskPriorityCmp func(task.Task, task.Task, *CmpBasedTaskComparator) (
    13  	int, error)
    14  
    15  // Importance comparison functions for tasks.  Used to prioritize tasks by the
    16  // CmpBasedTaskComparator.
    17  
    18  // byPriority compares the explicit Priority field of the Task documents for
    19  // each Task.  The Task whose Priority field is higher will be considered
    20  // more important.
    21  func byPriority(t1, t2 task.Task, comparator *CmpBasedTaskComparator) (int,
    22  	error) {
    23  	if t1.Priority > t2.Priority {
    24  		return 1, nil
    25  	}
    26  	if t1.Priority < t2.Priority {
    27  		return -1, nil
    28  	}
    29  
    30  	return 0, nil
    31  }
    32  
    33  // byNumDeps compares the NumDependents field of the Task documents for
    34  // each Task.  The Task whose NumDependents field is higher will be considered
    35  // more important.
    36  func byNumDeps(t1, t2 task.Task, comparator *CmpBasedTaskComparator) (int,
    37  	error) {
    38  	if t1.NumDependents > t2.NumDependents {
    39  		return 1, nil
    40  	}
    41  	if t1.NumDependents < t2.NumDependents {
    42  		return -1, nil
    43  	}
    44  
    45  	return 0, nil
    46  }
    47  
    48  // byRevisionOrderNumber compares the RevisionOrderNumber fields for the two Tasks,
    49  // and considers the one with the higher RevisionOrderNumber to be more important.
    50  // byRevisionOrderNumber short circuits if the two tasks are not of the same
    51  // project, since RevisionOrderNumber is meaningless across projects.
    52  func byRevisionOrderNumber(t1, t2 task.Task,
    53  	comparator *CmpBasedTaskComparator) (int, error) {
    54  
    55  	if t1.Project != t2.Project {
    56  		return 0, nil
    57  	}
    58  	if t1.RevisionOrderNumber > t2.RevisionOrderNumber {
    59  		return 1, nil
    60  	}
    61  	if t2.RevisionOrderNumber > t1.RevisionOrderNumber {
    62  		return -1, nil
    63  	}
    64  	return 0, nil
    65  }
    66  
    67  // byCreateTime compares the CreateTime fields of the two tasks, and considers
    68  // the task with the later CreateTime to be more important.  byCreateTime
    69  // short-circuits if the two tasks are from the same project, since
    70  // RevisionOrderNumber is a more reliable indicator on the same project.
    71  func byCreateTime(t1, t2 task.Task, comparator *CmpBasedTaskComparator) (int,
    72  	error) {
    73  
    74  	if t1.Project == t2.Project {
    75  		return 0, nil
    76  	}
    77  
    78  	if t1.CreateTime.After(t2.CreateTime) {
    79  		return 1, nil
    80  	}
    81  	if t2.CreateTime.After(t1.CreateTime) {
    82  		return -1, nil
    83  	}
    84  	return 0, nil
    85  }
    86  
    87  // byRecentlyFailing compares the results of the previous executions of each
    88  // Task, and considers one more important if its previous execution resulted in
    89  // failure.
    90  func byRecentlyFailing(t1, t2 task.Task,
    91  	comparator *CmpBasedTaskComparator) (int, error) {
    92  	firstPrev, present := comparator.previousTasksCache[t1.Id]
    93  	if !present {
    94  		return 0, errors.Errorf("No cached previous task available for task with"+
    95  			" id %v", t1.Id)
    96  	}
    97  	secondPrev, present := comparator.previousTasksCache[t2.Id]
    98  	if !present {
    99  		return 0, errors.Errorf("No cached previous task available for task with"+
   100  			" id %v", t2.Id)
   101  	}
   102  
   103  	if firstPrev.Status == evergreen.TaskFailed &&
   104  		secondPrev.Status != evergreen.TaskFailed {
   105  		return 1, nil
   106  	}
   107  	if secondPrev.Status == evergreen.TaskFailed &&
   108  		firstPrev.Status != evergreen.TaskFailed {
   109  		return -1, nil
   110  	}
   111  
   112  	return 0, nil
   113  }
   114  
   115  // bySimilarFailing takes two tasks with the same revision, and considers one
   116  // more important if it has a greater number of failed tasks with the same
   117  // revision, project, display name and requester (but in one or more
   118  // buildvariants) that failed.
   119  func bySimilarFailing(t1, t2 task.Task,
   120  	comparator *CmpBasedTaskComparator) (int, error) {
   121  	// this comparator only applies to tasks within the same revision
   122  	if t1.Revision != t2.Revision {
   123  		return 0, nil
   124  	}
   125  
   126  	numSimilarFailingOne, ok := comparator.similarFailingCount[t1.Id]
   127  	if !ok {
   128  		return 0, errors.Errorf("No similar failing count entry for task with "+
   129  			"id %v", t1.Id)
   130  	}
   131  
   132  	numSimilarFailingTwo, ok := comparator.similarFailingCount[t2.Id]
   133  	if !ok {
   134  		return 0, errors.Errorf("No similar failing count entry for task with "+
   135  			"id %v", t2.Id)
   136  	}
   137  
   138  	if numSimilarFailingOne > numSimilarFailingTwo {
   139  		return 1, nil
   140  	}
   141  
   142  	if numSimilarFailingOne < numSimilarFailingTwo {
   143  		return -1, nil
   144  	}
   145  	return 0, nil
   146  }