Improve cache load by a shitload
This commit is contained in:
parent
03e992bf6b
commit
415290de20
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-git/go-git/v5"
|
"github.com/go-git/go-git/v5"
|
||||||
@ -11,7 +12,14 @@ import (
|
|||||||
"github.com/xanzy/go-gitlab"
|
"github.com/xanzy/go-gitlab"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defProjectsPerPage = 30
|
// Will determine number of total projects,
|
||||||
|
// then based on projectsPerPage (request) and
|
||||||
|
// projectsPerGoroutine, will spin off goroutines
|
||||||
|
// with offsets
|
||||||
|
const (
|
||||||
|
projectsPerPage = 20
|
||||||
|
projectsPerGoroutine = 200
|
||||||
|
)
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
Ctx context.Context
|
Ctx context.Context
|
||||||
@ -154,38 +162,72 @@ func (c *Client) streamProjects(pi *ProgressInfo, ownerOnly bool) {
|
|||||||
|
|
||||||
listOpts := &gitlab.ListProjectsOptions{
|
listOpts := &gitlab.ListProjectsOptions{
|
||||||
ListOptions: gitlab.ListOptions{
|
ListOptions: gitlab.ListOptions{
|
||||||
PerPage: defProjectsPerPage,
|
PerPage: projectsPerPage,
|
||||||
Page: 1,
|
Page: 1,
|
||||||
},
|
},
|
||||||
Archived: gitlab.Ptr[bool](false),
|
Archived: gitlab.Ptr[bool](false),
|
||||||
Owned: gitlab.Ptr[bool](ownerOnly),
|
Owned: gitlab.Ptr[bool](ownerOnly),
|
||||||
}
|
}
|
||||||
|
|
||||||
var numProjects int
|
// Get total number of projects
|
||||||
|
projectsTotal := c.getTotalProjects(listOpts)
|
||||||
|
numGoroutines := projectsTotal / projectsPerGoroutine
|
||||||
|
|
||||||
|
wg := sync.WaitGroup{}
|
||||||
|
startPage := 1
|
||||||
|
for i := 1; i <= numGoroutines+1; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
endPage := startPage + (projectsPerGoroutine / projectsPerPage)
|
||||||
|
go func(startPage int, endPage int) {
|
||||||
|
defer wg.Done()
|
||||||
|
opts := *listOpts
|
||||||
|
opts.Page = startPage
|
||||||
for {
|
for {
|
||||||
projects, resp, err := c.ListProjects(listOpts)
|
projects, resp, err := c.ListProjects(&opts)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pi.ErrorChan <- err
|
pi.ErrorChan <- err
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
// We're done when we have it all or our context is done
|
|
||||||
if c.Ctx.Err() != nil || resp.NextPage == 0 {
|
|
||||||
pi.DoneChan <- nil
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
numProjects += len(projects)
|
|
||||||
pi.ProjectsChan <- projects
|
pi.ProjectsChan <- projects
|
||||||
pi.ProgressChan <- Progress{
|
pi.ProgressChan <- Progress{
|
||||||
Page: resp.CurrentPage,
|
Page: resp.CurrentPage,
|
||||||
Pages: resp.TotalPages,
|
Pages: resp.TotalPages,
|
||||||
Projects: numProjects,
|
Projects: len(projects),
|
||||||
TotalProjects: resp.TotalItems,
|
TotalProjects: resp.TotalItems,
|
||||||
}
|
}
|
||||||
listOpts.Page = resp.NextPage
|
|
||||||
|
// We're done when we have it all or our context is done
|
||||||
|
// or we've hit our total pages
|
||||||
|
if c.Ctx.Err() != nil || resp.NextPage == 0 {
|
||||||
|
break
|
||||||
|
} else if opts.Page == endPage {
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
opts.Page = resp.NextPage
|
||||||
|
}
|
||||||
|
}(startPage, endPage)
|
||||||
|
startPage = endPage + 1
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
pi.DoneChan <- nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) getTotalProjects(opts *gitlab.ListProjectsOptions) int {
|
||||||
|
reqOpts := *opts
|
||||||
|
reqOpts.ListOptions = gitlab.ListOptions{
|
||||||
|
Page: 1,
|
||||||
|
PerPage: 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
var projects int
|
||||||
|
if _, r, e := c.gitlab.Projects.ListProjects(opts, gitlab.WithContext(c.Ctx)); e == nil {
|
||||||
|
projects = r.TotalItems
|
||||||
|
}
|
||||||
|
|
||||||
|
return projects
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a list of projects along with the next page and an error
|
// Returns a list of projects along with the next page and an error
|
||||||
|
@ -146,7 +146,6 @@ func (c *Cache) LoadProjects() {
|
|||||||
|
|
||||||
defer pBar.Stop()
|
defer pBar.Stop()
|
||||||
|
|
||||||
var curProjects int
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case p := <-progressInfo.ProgressChan:
|
case p := <-progressInfo.ProgressChan:
|
||||||
@ -157,8 +156,7 @@ func (c *Cache) LoadProjects() {
|
|||||||
// This sucks, has to be a better way, and why is the logger incompatible
|
// This sucks, has to be a better way, and why is the logger incompatible
|
||||||
// with the progressbar?
|
// with the progressbar?
|
||||||
pterm.Debug.Println(fmt.Sprintf("Update received: %#v", p))
|
pterm.Debug.Println(fmt.Sprintf("Update received: %#v", p))
|
||||||
pBar.Add(p.Projects - curProjects)
|
pBar.Add(p.Projects)
|
||||||
curProjects = p.Projects
|
|
||||||
case p := <-progressInfo.ProjectsChan:
|
case p := <-progressInfo.ProjectsChan:
|
||||||
c.Projects = append(c.Projects, p...)
|
c.Projects = append(c.Projects, p...)
|
||||||
case e := <-progressInfo.ErrorChan:
|
case e := <-progressInfo.ErrorChan:
|
||||||
@ -167,7 +165,7 @@ func (c *Cache) LoadProjects() {
|
|||||||
c.log.Warn("LoadProjects cancelled", c.log.Args("reason", c.gitlab.Ctx.Err()))
|
c.log.Warn("LoadProjects cancelled", c.log.Args("reason", c.gitlab.Ctx.Err()))
|
||||||
return
|
return
|
||||||
case <-progressInfo.DoneChan:
|
case <-progressInfo.DoneChan:
|
||||||
pBar.Add(pBar.Total - curProjects)
|
// pBar.Add(pBar.Total - curProjects)
|
||||||
fmt.Println("")
|
fmt.Println("")
|
||||||
c.log.Info("Project load complete")
|
c.log.Info("Project load complete")
|
||||||
return
|
return
|
||||||
|
Loading…
Reference in New Issue
Block a user