// this function ensures that the job has the right worker before queuing it func prepareJobForQueue(j Job) { jobClaims.claimJob(j.JobHeader) ja := messages.JobAck{j.JobHeader} if line, ok := getLine(j.Conn); ok { line.Out <- ja.Message() } pr := GetProject(j.Project) // first, ensure that we've got the worker alreadyRequested := false waitforworker: for { w, ok := pr.GetWorker(j.Name) if ok && j.Version <= w.Version { // we've already got the right worker break } workerChan := make(chan Worker) workerSub := func(msg messages.Message, line messages.Line) (keepgoing bool) { if string(msg.Payload["type"]) != messages.WorkerType { return true } worker, err := messages.WorkerFromMessage(msg) if err != nil { return true } if worker.Project != j.Project || worker.Name != j.Name { return true } if worker.Version < j.Version { return true } // this is our worker w := Worker{worker, line.Conn} pr.AddWorker(w) workerChan <- w // stop this subscription return false } if !alreadyRequested { alreadyRequested = true log.Printf("requesting worker for %v", j) wr := messages.WorkerRequest{ Project: j.Project, Name: j.Name, Version: j.Version, } line, ok := getLine(j.Conn) if !ok { log.Printf("job came from lost source") } line.Out <- wr.Message() } go subscribe(workerSub) timeout := time.NewTimer(2e9) select { case w = <-workerChan: break waitforworker case <-timeout.C: /* this timeout is here because we might have received the worker between the first check and when the subscription went active */ } timeout.Stop() } log.Printf("enqueuing %v", j) jobQueue.Push <- j }
func handleMessages(mline messages.Line) { log.Println("connected to", mline.Conn.RemoteAddr()) defer log.Println("lost connection to", mline.Conn.RemoteAddr()) for msg := range mline.In { go func(msg messages.Message, conn *net.TCPConn) { if msg.Broadcast { broadcastMessage(msg) } // toss this to subscribers go func(msg messages.Message, line messages.Line) { subscriberLock.Lock() for _, ch := range subscriberChans { ch <- MsgSrc{msg, line} } subscriberLock.Unlock() }(msg, mline) typ, ok := msg.Payload["type"] if !ok { log.Println("received message with no type") return } switch string(typ) { case "load": l, err := LoadFromMessage(msg, conn) if err != nil { log.Println(err) return } recvLoad(l) case "ident": i, err := IdentFromMessage(msg) if err != nil { log.Println(err) return } recvIdent(i, conn) case messages.WorkerType: w, err := messages.WorkerFromMessage(msg) if err != nil { log.Println(err) return } recvWorker(Worker{w, conn}) case messages.WorkerRequestType: w, err := messages.WorkerRequestFromMessage(msg) if err != nil { log.Println(err) return } recvWorkerRequest(WorkerRequest{w, conn}) case messages.JobType: j, err := messages.JobFromMessage(msg) if err != nil { log.Println(err) return } recvJob(Job{j, conn}) case messages.JobAckType: ja, err := messages.JobAckFromMessage(msg) if err != nil { log.Println(err) return } recvJobAck(ja) case messages.JobStatusRequestType: jsr, err := messages.JobStatusRequestFromMessage(msg) if err != nil { log.Println(err) return } recvJobStatusRequest(jsr) case messages.JobStatusType: js, err := messages.JobStatusFromMessage(msg) if err != nil { log.Println(err) return } recvJobStatus(js) } }(msg, mline.Conn) } }