func (a *HostAgent) processChildrenAndWait(conn *zk.Conn) bool { processing := make(map[string]chan int) ssDone := make(chan stateResult, 25) hostPath := zzk.HostPath(a.hostId) for { children, _, zkEvent, err := conn.ChildrenW(hostPath) if err != nil { glog.V(0).Infoln("Unable to read children, retrying.") time.Sleep(3 * time.Second) return true } a.startMissingChildren(conn, children, processing, ssDone) select { case errc := <-a.closing: glog.V(1).Info("Agent received interrupt") err = waitForSsNodes(processing, ssDone) errc <- err return false case ssResult := <-ssDone: glog.V(1).Infof("Goroutine finished %s", ssResult.id) delete(processing, ssResult.id) case evt := <-zkEvent: glog.V(1).Info("Agent event: ", evt) } } }
// main loop of the HostAgent func (a *HostAgent) start() { glog.V(1).Info("Starting HostAgent") for { // create a wrapping function so that client.Close() can be handled via defer keepGoing := func() bool { conn, zkEvt, err := zk.Connect(a.zookeepers, time.Second*10) if err != nil { glog.V(0).Info("Unable to connect, retrying.") return true } connectEvent := false for !connectEvent { select { case errc := <-a.closing: glog.V(0).Info("Received shutdown notice") errc <- errors.New("Unable to connect to zookeeper") return false case evt := <-zkEvt: glog.V(1).Infof("Got ZK connect event: %v", evt) if evt.State == zk.StateConnected { connectEvent = true } } } defer conn.Close() // Executed after lambda function finishes zzk.CreateNode(zzk.SCHEDULER_PATH, conn) node_path := zzk.HostPath(a.hostId) zzk.CreateNode(node_path, conn) glog.V(0).Infof("Connected to zookeeper node %s", node_path) return a.processChildrenAndWait(conn) }() if !keepGoing { break } } }