// GetVersion returns a semver.Version object by querying /info func GetVersion(addr string) (*semver.Version, error) { endpoint := fmt.Sprintf("http://%s/info", addr) log.Printf("version negotiation %s", endpoint) info, err := util.APIRequestNegotiateV1("GET", endpoint, nil) if err != nil { log.Printf("ERROR: %s - %s", endpoint, err) return nil, err } version := info.Get("version").MustString("unknown") return semver.Parse(version) }
// GetLookupdProducers returns a slice of pointers to Producer structs // containing metadata for each node connected to given lookupds func GetLookupdProducers(lookupdHTTPAddrs []string) ([]*Producer, error) { success := false allProducers := make(map[string]*Producer, 0) output := make([]*Producer, 0) maxVersion, _ := semver.Parse("0.0.0") var lock sync.Mutex var wg sync.WaitGroup for _, addr := range lookupdHTTPAddrs { wg.Add(1) endpoint := fmt.Sprintf("http://%s/nodes", addr) log.Printf("LOOKUPD: querying %s", endpoint) go func(addr string, endpoint string) { data, err := util.ApiRequest(endpoint) lock.Lock() defer lock.Unlock() defer wg.Done() if err != nil { log.Printf("ERROR: lookupd %s - %s", endpoint, err.Error()) return } success = true producers := data.Get("producers") producersArray, _ := producers.Array() for i := range producersArray { producer := producers.GetIndex(i) remoteAddress := producer.Get("remote_address").MustString() if remoteAddress == "" { remoteAddress = "NA" } hostname := producer.Get("hostname").MustString() broadcastAddress := producer.Get("broadcast_address").MustString() httpPort := producer.Get("http_port").MustInt() tcpPort := producer.Get("tcp_port").MustInt() key := fmt.Sprintf("%s:%d:%d", broadcastAddress, httpPort, tcpPort) p, ok := allProducers[key] if !ok { var tombstones []bool var topics ProducerTopics topicList, _ := producer.Get("topics").Array() tombstoneList, err := producer.Get("tombstones").Array() if err != nil { // backwards compatibility with nsqlookupd < v0.2.22 tombstones = make([]bool, len(topicList)) } else { for _, t := range tombstoneList { tombstones = append(tombstones, t.(bool)) } } for i, t := range topicList { topics = append(topics, ProducerTopic{ Topic: t.(string), Tombstoned: tombstones[i], }) } sort.Sort(topics) version := producer.Get("version").MustString("unknown") versionObj, err := semver.Parse(version) if err != nil { versionObj = maxVersion } if maxVersion.Less(versionObj) { maxVersion = versionObj } p = &Producer{ Hostname: hostname, BroadcastAddress: broadcastAddress, TcpPort: tcpPort, HttpPort: httpPort, Version: version, VersionObj: versionObj, Topics: topics, } allProducers[key] = p output = append(output, p) } p.RemoteAddresses = append(p.RemoteAddresses, fmt.Sprintf("%s/%s", addr, remoteAddress)) } }(addr, endpoint) } wg.Wait() for _, producer := range allProducers { if producer.VersionObj.Less(maxVersion) { producer.OutOfDate = true } } sort.Sort(ProducersByHost{output}) if success == false { return nil, errors.New("unable to query any lookupd") } return output, nil }
func init() { v1EndpointVersion, _ = semver.Parse("0.2.29-alpha") }
func getLookupdProducers(lookupdHTTPAddrs []string) ([]*Producer, error) { success := false allProducers := make(map[string]*Producer, 0) output := make([]*Producer, 0) maxVersion, _ := semver.Parse("0.0.0") var lock sync.Mutex var wg sync.WaitGroup for _, addr := range lookupdHTTPAddrs { wg.Add(1) endpoint := fmt.Sprintf("http://%s/nodes", addr) log.Printf("LOOKUPD: querying %s", endpoint) go func(endpoint string) { data, err := nsq.ApiRequest(endpoint) lock.Lock() defer lock.Unlock() defer wg.Done() if err != nil { log.Printf("ERROR: lookupd %s - %s", endpoint, err.Error()) return } success = true producers := data.Get("producers") producersArray, _ := producers.Array() for i := range producersArray { producer := producers.GetIndex(i) address := producer.Get("address").MustString() //TODO: remove for 1.0 hostname := producer.Get("hostname").MustString() broadcastAddress := producer.Get("broadcast_address").MustString() if broadcastAddress == "" { broadcastAddress = address } httpPort := producer.Get("http_port").MustInt() tcpPort := producer.Get("tcp_port").MustInt() key := fmt.Sprintf("%s:%d:%d", broadcastAddress, httpPort, tcpPort) _, ok := allProducers[key] if !ok { topicList, _ := producer.Get("topics").Array() var topics []string for _, t := range topicList { topics = append(topics, t.(string)) } sort.Strings(topics) version := producer.Get("version").MustString("unknown") versionObj, err := semver.Parse(version) if err != nil { versionObj = maxVersion } if maxVersion.Less(versionObj) { maxVersion = versionObj } p := &Producer{ Address: address, //TODO: remove for 1.0 Hostname: hostname, BroadcastAddress: broadcastAddress, TcpPort: tcpPort, HttpPort: httpPort, Version: version, VersionObj: versionObj, Topics: topics, } allProducers[key] = p output = append(output, p) } } }(endpoint) } wg.Wait() for _, producer := range allProducers { if producer.VersionObj.Less(maxVersion) { producer.OutOfDate = true } } sort.Sort(ProducersByHost{output}) if success == false { return nil, errors.New("unable to query any lookupd") } return output, nil }