Improve cache load by a shitload

This commit is contained in:
Ryan McGuire 2023-12-29 15:02:17 -05:00
parent 03e992bf6b
commit 415290de20
2 changed files with 67 additions and 27 deletions

View File

@ -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
for { projectsTotal := c.getTotalProjects(listOpts)
projects, resp, err := c.ListProjects(listOpts) numGoroutines := projectsTotal / projectsPerGoroutine
if err != nil { wg := sync.WaitGroup{}
pi.ErrorChan <- err startPage := 1
break 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 {
projects, resp, err := c.ListProjects(&opts)
// We're done when we have it all or our context is done if err != nil {
if c.Ctx.Err() != nil || resp.NextPage == 0 { pi.ErrorChan <- err
pi.DoneChan <- nil break
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: len(projects),
Projects: numProjects, 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

View File

@ -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