// return a few values that need to be refreshed func (zkc *ZkCache) refreshSomeValues(zconn zk.Conn, maxToRefresh int) { // build a list of a few values we want to refresh refreshThreshold := time.Now().Add(-10 * time.Minute) // range will randomize the traversal order, so we will not always try // the same entries in the same order dataEntries := make([]*zkCacheEntry, 0, maxToRefresh) childrenEntries := make([]*zkCacheEntry, 0, maxToRefresh) zkc.mutex.Lock() for _, entry := range zkc.Cache { shouldBeDataRefreshed, shouldBeChildrenRefreshed := entry.checkForRefresh(refreshThreshold) if shouldBeDataRefreshed { dataEntries = append(dataEntries, entry) } if shouldBeChildrenRefreshed { childrenEntries = append(childrenEntries, entry) } // check if we have enough work to do if len(dataEntries) == maxToRefresh || len(childrenEntries) == maxToRefresh { break } } zkc.mutex.Unlock() // now refresh the values for _, entry := range dataEntries { data, stat, watch, err := zconn.GetW(entry.node.Path) if err == nil { zkStat := &zk.ZkStat{} zkStat.FromZookeeperStat(stat) entry.updateData(data, zkStat, watch) } else if zookeeper.IsError(err, zookeeper.ZCLOSING) { // connection is closing, no point in asking for more log.Warningf("failed to refresh cache: %v (and stopping refresh)", err.Error()) return } else { // individual failure log.Warningf("failed to refresh cache: %v", err.Error()) } } for _, entry := range childrenEntries { children, stat, watch, err := zconn.ChildrenW(entry.node.Path) if err == nil { zkStat := &zk.ZkStat{} zkStat.FromZookeeperStat(stat) entry.updateChildren(children, zkStat, watch) } else if zookeeper.IsError(err, zookeeper.ZCLOSING) { // connection is closing, no point in asking for more log.Warningf("failed to refresh cache: %v (and stopping refresh)", err.Error()) return } else { // individual failure log.Warningf("failed to refresh cache: %v", err.Error()) } } }