github.com/billybanfield/evergreen@v0.0.0-20170525200750-eeee692790f7/taskrunner/task_runner.go (about) 1 package taskrunner 2 3 import ( 4 "path/filepath" 5 "runtime" 6 "sync" 7 "time" 8 9 "github.com/evergreen-ci/evergreen" 10 "github.com/evergreen-ci/evergreen/model/host" 11 "github.com/mongodb/grip" 12 "github.com/pkg/errors" 13 ) 14 15 // TODO: take out task queue finder and host finder once transition is complete 16 type TaskRunner struct { 17 *evergreen.Settings 18 HostGateway 19 } 20 21 func NewTaskRunner(settings *evergreen.Settings) *TaskRunner { 22 // get mci home, and set the source and destination for the agent 23 // executables 24 evgHome := evergreen.FindEvergreenHome() 25 26 return &TaskRunner{ 27 settings, 28 &AgentHostGateway{ 29 ExecutablesDir: filepath.Join(evgHome, settings.AgentExecutablesDir), 30 }, 31 } 32 } 33 34 // agentStartData is the information needed to start an agent on a host 35 type agentStartData struct { 36 Host host.Host 37 Settings *evergreen.Settings 38 } 39 40 func (tr *TaskRunner) Run() error { 41 // Find all hosts that are running and have a LCT (last communication time) 42 // of 0 or ones that haven't been communicated in MaxLCT time. 43 // These are the hosts that need to have agents dispatched 44 freeHosts, err := host.Find(host.ByRunningWithTimedOutLCT(time.Now())) 45 if err != nil { 46 return err 47 } 48 49 grip.Infof("Found %d hosts that need agents dispatched", len(freeHosts)) 50 51 freeHostChan := make(chan agentStartData, len(freeHosts)) 52 53 // put all of the information needed about the host in a channel 54 for _, h := range freeHosts { 55 freeHostChan <- agentStartData{ 56 Host: h, 57 Settings: tr.Settings, 58 } 59 } 60 // close the free hosts channel 61 close(freeHostChan) 62 wg := sync.WaitGroup{} 63 workers := runtime.NumCPU() 64 wg.Add(workers) 65 66 catcher := grip.NewCatcher() 67 // for each worker create a new goroutine 68 for i := 0; i < workers; i++ { 69 go func() { 70 defer wg.Done() 71 for input := range freeHostChan { 72 catcher.Add(errors.Wrapf(tr.StartAgentOnHost(input.Settings, input.Host), 73 "problem starting agent on host %s", input.Host.Id)) 74 } 75 }() 76 } 77 wg.Wait() 78 return catcher.Resolve() 79 }