volcano.sh/volcano@v1.9.0/pkg/scheduler/framework/job_updater.go (about) 1 package framework 2 3 import ( 4 "context" 5 "math/rand" 6 "reflect" 7 "time" 8 9 "k8s.io/client-go/util/workqueue" 10 "k8s.io/klog/v2" 11 12 "volcano.sh/apis/pkg/apis/scheduling" 13 "volcano.sh/volcano/pkg/scheduler/api" 14 ) 15 16 const ( 17 jobUpdaterWorker = 16 18 ) 19 20 // TimeJitterAfter means: new after old + duration + jitter 21 func TimeJitterAfter(new, old time.Time, duration, maxJitter time.Duration) bool { 22 var jitter int64 23 if maxJitter > 0 { 24 jitter = rand.Int63n(int64(maxJitter)) 25 } 26 return new.After(old.Add(duration + time.Duration(jitter))) 27 } 28 29 type jobUpdater struct { 30 ssn *Session 31 jobQueue []*api.JobInfo 32 } 33 34 func newJobUpdater(ssn *Session) *jobUpdater { 35 queue := make([]*api.JobInfo, 0, len(ssn.Jobs)) 36 for _, job := range ssn.Jobs { 37 queue = append(queue, job) 38 } 39 40 ju := &jobUpdater{ 41 ssn: ssn, 42 jobQueue: queue, 43 } 44 return ju 45 } 46 47 func (ju *jobUpdater) UpdateAll() { 48 workqueue.ParallelizeUntil(context.TODO(), jobUpdaterWorker, len(ju.jobQueue), ju.updateJob) 49 } 50 51 func isPodGroupConditionsUpdated(newCondition, oldCondition []scheduling.PodGroupCondition) bool { 52 if len(newCondition) != len(oldCondition) { 53 return true 54 } 55 56 for index, newCond := range newCondition { 57 oldCond := oldCondition[index] 58 59 newTime := newCond.LastTransitionTime 60 oldTime := oldCond.LastTransitionTime 61 62 // if newCond is not new enough, we treat it the same as the old one 63 newCond.LastTransitionTime = oldTime 64 65 // comparing should ignore the TransitionID 66 newTransitionID := newCond.TransitionID 67 newCond.TransitionID = oldCond.TransitionID 68 69 shouldUpdate := !reflect.DeepEqual(&newCond, &oldCond) 70 71 newCond.LastTransitionTime = newTime 72 newCond.TransitionID = newTransitionID 73 if shouldUpdate { 74 return true 75 } 76 } 77 78 return false 79 } 80 81 func isPodGroupStatusUpdated(newStatus, oldStatus scheduling.PodGroupStatus) bool { 82 newCondition := newStatus.Conditions 83 newStatus.Conditions = nil 84 oldCondition := oldStatus.Conditions 85 oldStatus.Conditions = nil 86 87 return !reflect.DeepEqual(newStatus, oldStatus) || isPodGroupConditionsUpdated(newCondition, oldCondition) 88 } 89 90 // updateJob update specified job 91 func (ju *jobUpdater) updateJob(index int) { 92 job := ju.jobQueue[index] 93 ssn := ju.ssn 94 95 job.PodGroup.Status = jobStatus(ssn, job) 96 oldStatus, found := ssn.podGroupStatus[job.UID] 97 updatePG := !found || isPodGroupStatusUpdated(job.PodGroup.Status, oldStatus) 98 if _, err := ssn.cache.UpdateJobStatus(job, updatePG); err != nil { 99 klog.Errorf("Failed to update job <%s/%s>: %v", 100 job.Namespace, job.Name, err) 101 } 102 }