<commit_before>package commands

import (
	"fmt"
	"github.com/centurylinkcloud/clc-go-cli/base"
	"github.com/centurylinkcloud/clc-go-cli/models"
	"github.com/centurylinkcloud/clc-go-cli/models/datacenter"
	"github.com/centurylinkcloud/clc-go-cli/models/group"
)

const (
	BaseURL = "https://api.ctl.io"
)

type GroupList struct {
	CommandBase
}

func NewGroupList(info CommandExcInfo) *GroupList {
	g := GroupList{}
	g.ExcInfo = info
	return &g
}

func (g *GroupList) Execute(cn base.Connection) error {
	var err error

	g.Output, err = GetGroups(cn)
	if err != nil {
		return err
	}
	return nil
}

func GetGroups(cn base.Connection) ([]group.Entity, error) {
	var err error
	var groups []group.Entity

	datacenters := []datacenter.GetRes{}
	dcURL := fmt.Sprintf("%s/v2/datacenters/{accountAlias}", BaseURL)
	err = cn.ExecuteRequest("GET", dcURL, nil, &datacenters)
	if err != nil {
		return nil, err
	}

	for _, ref := range datacenters {
		// Get detailed DC info.
		d := datacenter.GetRes{}
		dcURL = fmt.Sprintf("%s%s?groupLinks=true", BaseURL, GetLink(ref.Links, "self"))
		err = cn.ExecuteRequest("GET", dcURL, nil, &d)
		if err != nil {
			return nil, err
		}
		// Get the root group of the given DC.
		g := group.Entity{}
		gURL := fmt.Sprintf("%s%s", BaseURL, GetLink(d.Links, "group"))
		err = cn.ExecuteRequest("GET", gURL, nil, &g)
		if err != nil {
			return nil, err
		}
		groups = append(groups, g)
	}
	return groups, nil
}

func GetLink(links []models.LinkEntity, resource string) string {
	for _, link := range links {
		if link.Rel == resource {
			return link.Href
		}
	}
	panic(fmt.Sprintf("No %s link found", resource))
}
<commit_msg>Rewrite GetGroups using goroutines in order to achieve robust performance<commit_after>package commands

import (
	"fmt"
	"github.com/centurylinkcloud/clc-go-cli/base"
	"github.com/centurylinkcloud/clc-go-cli/models"
	"github.com/centurylinkcloud/clc-go-cli/models/datacenter"
	"github.com/centurylinkcloud/clc-go-cli/models/group"
	"time"
)

const (
	BaseURL          = "https://api.ctl.io"
	GroupListTimeout = 200
)

type GroupList struct {
	CommandBase
}

func NewGroupList(info CommandExcInfo) *GroupList {
	g := GroupList{}
	g.ExcInfo = info
	return &g
}

func (g *GroupList) Execute(cn base.Connection) error {
	var err error

	g.Output, err = GetGroups(cn)
	if err != nil {
		return err
	}
	return nil
}

func GetGroups(cn base.Connection) ([]group.Entity, error) {
	datacenters := []datacenter.GetRes{}
	dcURL := fmt.Sprintf("%s/v2/datacenters/{accountAlias}", BaseURL)
	err := cn.ExecuteRequest("GET", dcURL, nil, &datacenters)
	if err != nil {
		return nil, err
	}

	done := make(chan error)
	groups := make([]group.Entity, len(datacenters))
	for i, ref := range datacenters {
		go loadGroups(ref, groups, i, cn, done)
	}

	received := 0
	for {
		select {
		case err := <-done:
			if err != nil {
				return nil, err
			}
			received += 1
			if received == len(datacenters) {
				return groups, nil
			}
		case <-time.After(time.Second * GroupListTimeout):
			return nil, fmt.Errorf("Request timeout error.")
		}
	}
}

func GetLink(links []models.LinkEntity, resource string) string {
	for _, link := range links {
		if link.Rel == resource {
			return link.Href
		}
	}
	panic(fmt.Sprintf("No %s link found", resource))
}

func loadGroups(ref datacenter.GetRes, groups []group.Entity, dcnumber int, cn base.Connection, done chan<- error) {
	// Get detailed DC info.
	d := datacenter.GetRes{}
	dcURL := fmt.Sprintf("%s%s?groupLinks=true", BaseURL, GetLink(ref.Links, "self"))
	err := cn.ExecuteRequest("GET", dcURL, nil, &d)
	if err != nil {
		done <- err
		return
	}
	// Get the root group of the given DC.
	g := group.Entity{}
	gURL := fmt.Sprintf("%s%s", BaseURL, GetLink(d.Links, "group"))
	err = cn.ExecuteRequest("GET", gURL, nil, &g)
	if err != nil {
		done <- err
		return
	}
	groups[dcnumber] = g
	done <- nil
}

{'fraction_non_alphanumeric': 0.1498069498069498, 'fraction_numerical': 0.0018018018018018018, 'mean_word_length': 3.744810744810745, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7020583', 'n_tokens_mistral': 1501, 'n_tokens_neox': 1437, 'n_words': 356}