Beispiel #1
0
func main() {
	raddr, err := net.ResolveTCPAddr("net", "localhost:1234")
	if err != nil {
		panic(err)
	}

	var line messages.Line
	for {
		line, err = messages.Connect(raddr)
		if err != nil {
			fmt.Println(err)
			time.Sleep(2e9)
		} else {
			break
		}
	}

	var j messages.Job
	j.Project = "john"
	j.Name = "py1"
	j.Version = 2

	w := messages.WorkerFromDirectory("john", "py1", "python", 2, "py1")

	msg := w.Message()
	line.Out <- msg
	for i := 0; i < 1; i++ {
		ji := j
		//ji.ID = fmt.Sprintf("%d", i)
		line.Out <- ji.Message()
	}

	for msg := range line.In {
		switch string(msg.Payload["type"]) {
		case messages.JobAckType:
			ja, _ := messages.JobAckFromMessage(msg)
			var jsr messages.JobStatusRequest
			jsr.JobHeader = ja.JobHeader
			msg = jsr.Message()
			msg.Broadcast = true
			line.Out <- msg
		case messages.JobStatusType:
			js, _ := messages.JobStatusFromMessage(msg)
			fmt.Println(js.JobHeader, js.Status)
		}
	}
}
Beispiel #2
0
/*
	this function runs in the background, ensuring the job completes

	basically, every so often it sends out a ping to make sure someone
	has claimed the job. if no one responds soon enough, the job is added
	back to the queue
*/
func watchOver(j Job) {
	jh := j.JobHeader

	var jsr messages.JobStatusRequest
	jsr.JobHeader = jh

	statusMessages := make(chan messages.JobStatus)
	statusSubscriber := func(msg messages.Message, src messages.Line) (keepgoing bool) {
		typ := string(msg.Payload["type"])
		if typ != messages.JobStatusType {
			keepgoing = true
			return
		}
		js, _ := messages.JobStatusFromMessage(msg)
		jsh := js.JobHeader
		if jsh == jh {
			statusMessages <- js
		}
		//resubscribe to get the next status
		keepgoing = false
		return
	}

	msg := jsr.Message()
	msg.Broadcast = true

	isMyJob := jobClaims.isMyJob(jh)

	broadcast := func() {
		statusWatcher.clearWatchStatus(jh)
		broadcastMessage(msg)
	}

	if true {
		// new hotness
		for {
			log.Printf("checking on %v", j)
			if !jobClaims.isMyJob(jh) {
				broadcast()

				go subscribe(statusSubscriber)

				timeout := time.NewTimer(1e9)
				defer timeout.Stop() // so if we don't pick it up, the goroutine attached to it can die

				//log.Printf("awaiting status")

				select {
				case js := <-statusMessages:
					log.Printf("%v is remote, %d", j, js.Status)
					if js.Status == messages.JobCompleted {
						return
					}
				case <-timeout.C:
					log.Printf("lost track of %v", j)
					// no status came back in time, so reclaim and requeue
					jobClaims.claimJob(jh)
					//purgatory.AddJob(j)
					go prepareJobForQueue(j)
				}
			} else {
				// it's my job
				status, ok := jobClaims.getJobStatus(jh)
				log.Printf("%v is here, %d", j, status)
				// it's my job and completed at the same time
				if ok && status == messages.JobCompleted {
					return
				}
			}
			time.Sleep(5e9)
		}
	} else {
		// old and busted
		if !isMyJob {
			broadcast()
		}

		for {
			// do this once every 5 seconds
			time.Sleep(5e9)

			log.Printf("checking on %v", j)

			// if it was my job and now isn't, send out a status request and go to sleep
			if isMyJob && !jobClaims.isMyJob(jh) {
				isMyJob = false
				broadcast()
				continue
			}

			isMyJob = jobClaims.isMyJob(jh)

			// if it's now my job, go back to sleep
			if isMyJob {
				status, ok := jobClaims.getJobStatus(jh)
				if ok && status == messages.JobCompleted {
					return
				}
				continue
			}

			// if it's not my job, check the last status report we got
			if status, set := statusWatcher.getWatchStatus(jh); set {
				if status == messages.JobCompleted {
					// job is done, stop watching
					return
				}
				// someone, in the last sleep cycle, broadcasted a status message about this job
				broadcast()
				continue
			}

			log.Printf("lost track of %v", j)

			// no one sent anything back, so let's send it to purgatory where it can await a worker
			jobClaims.claimJob(jh)
			isMyJob = true
			purgatory.AddJob(j)

		}
	}
}
Beispiel #3
0
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)
	}
}