github.com/metux/go-metabuild@v0.0.0-20240118143255-d9ed5ab697f9/util/jobs/runner.go (about) 1 package jobs 2 3 import ( 4 "fmt" 5 "log" 6 // "sync" 7 ) 8 9 type Runner struct { 10 Jobs map[JobId]*RunnerJob 11 } 12 13 func NewRunner() Runner { 14 r := Runner{} 15 r.Jobs = make(map[JobId]*RunnerJob) 16 return r 17 } 18 19 func (r Runner) AddJob(id JobId, job Job) error { 20 j, err := NewJob(id, job) 21 if err != nil { 22 log.Println("AddJob: error creating job runner: ", err) 23 return err 24 } 25 26 r.Jobs[id] = j 27 28 for _, walk := range j.Sub { 29 r.AddJob(walk.JobId(), walk) 30 } 31 32 return err 33 } 34 35 // resolve dependencies 36 func (r Runner) Resolve() error { 37 for id, walk := range r.Jobs { 38 for _, dwalk := range walk.Job.JobDepends() { 39 if d1, ok := r.Jobs[dwalk]; ok { 40 walk.Depends = append(walk.Depends, d1) 41 } else { 42 err := fmt.Errorf("missing dep %s for %s", dwalk, id) 43 return err 44 } 45 } 46 for _, subWalk := range walk.Sub { 47 subId := subWalk.JobId() 48 if d1, ok := r.Jobs[subId]; ok { 49 walk.Depends = append(walk.Depends, d1) 50 } else { 51 err := fmt.Errorf("missing sub dep %s for %s", subId, id) 52 return err 53 } 54 } 55 } 56 return nil 57 } 58 59 func (r Runner) Scan() (RunnerJobList, RunnerJobList, RunnerJobList) { 60 doneList := RunnerJobList{} 61 runnableList := RunnerJobList{} 62 waitList := RunnerJobList{} 63 64 for _, walk := range r.Jobs { 65 if walk.Done { 66 doneList = append(doneList, walk) 67 } else if walk.Runnable() { 68 runnableList = append(runnableList, walk) 69 } else { 70 waitList = append(waitList, walk) 71 } 72 } 73 return doneList, runnableList, waitList 74 } 75 76 // FIXME: parallel runs 77 func (r Runner) Run() error { 78 if err := r.Resolve(); err != nil { 79 return err 80 } 81 82 for true { 83 done, runnable, waiting := r.Scan() 84 log.Printf("done: %d runnable: %d waiting: %d\n", len(done), len(runnable), len(waiting)) 85 86 if len(runnable) == 0 { 87 log.Println("no more waiting. finished") 88 if len(waiting) != 0 { 89 return fmt.Errorf("some jobs cant run: %d", len(waiting)) 90 } 91 return nil 92 } 93 94 for _, b := range runnable { 95 log.Println("Running job", b.Id) 96 if err := b.Job.JobRun(); err != nil { 97 return err 98 } 99 b.Done = true 100 log.Println("Done job", b.Id) 101 } 102 } 103 return nil 104 }