forked from tangled.org/core
this repo has no description

knotserver: calculate repoindex items in parallel

performing rev-list and filetree in sequential occupy a large amount of
the client budget. we can parallelize all these expensive operations.

Signed-off-by: oppiliappan <me@oppi.li>

Changed files
+71 -28
knotserver
+71 -28
knotserver/routes.go
···
"path/filepath"
"strconv"
"strings"
+
"sync"
securejoin "github.com/cyphar/filepath-securejoin"
"github.com/gliderlabs/ssh"
···
}
}
-
commits, err := gr.Commits(0, 60) // a good preview of commits in this repo
-
if err != nil {
-
writeError(w, err.Error(), http.StatusInternalServerError)
-
l.Error("fetching commits", "error", err.Error())
-
return
-
}
+
var (
+
commits []*object.Commit
+
total int
+
branches []types.Branch
+
files []types.NiceTree
+
tags []*git.TagReference
+
)
+
+
var wg sync.WaitGroup
+
errorsCh := make(chan error, 5)
+
+
wg.Add(1)
+
go func() {
+
defer wg.Done()
+
cs, err := gr.Commits(0, 60)
+
if err != nil {
+
errorsCh <- fmt.Errorf("commits: %w", err)
+
return
+
}
+
commits = cs
+
}()
+
+
wg.Add(1)
+
go func() {
+
defer wg.Done()
+
t, err := gr.TotalCommits()
+
if err != nil {
+
errorsCh <- fmt.Errorf("calculating total: %w", err)
+
return
+
}
+
total = t
+
}()
+
+
wg.Add(1)
+
go func() {
+
defer wg.Done()
+
bs, err := gr.Branches()
+
if err != nil {
+
errorsCh <- fmt.Errorf("fetching branches: %w", err)
+
return
+
}
+
branches = bs
+
}()
+
+
wg.Add(1)
+
go func() {
+
defer wg.Done()
+
ts, err := gr.Tags()
+
if err != nil {
+
errorsCh <- fmt.Errorf("fetching tags: %w", err)
+
return
+
}
+
tags = ts
+
}()
+
+
wg.Add(1)
+
go func() {
+
defer wg.Done()
+
fs, err := gr.FileTree(r.Context(), "")
+
if err != nil {
+
errorsCh <- fmt.Errorf("fetching filetree: %w", err)
+
return
+
}
+
files = fs
+
}()
-
total, err := gr.TotalCommits()
-
if err != nil {
-
writeError(w, err.Error(), http.StatusInternalServerError)
-
l.Error("fetching commits", "error", err.Error())
-
return
-
}
+
wg.Wait()
+
close(errorsCh)
-
branches, err := gr.Branches()
-
if err != nil {
-
l.Error("getting branches", "error", err.Error())
+
// show any errors
+
for err := range errorsCh {
+
l.Error("loading repo", "error", err.Error())
writeError(w, err.Error(), http.StatusInternalServerError)
return
-
}
-
-
tags, err := gr.Tags()
-
if err != nil {
-
// Non-fatal, we *should* have at least one branch to show.
-
l.Warn("getting tags", "error", err.Error())
}
rtags := []*types.TagReference{}
···
readmeContent = string(content)
readmeFile = readme
}
-
}
-
-
files, err := gr.FileTree(r.Context(), "")
-
if err != nil {
-
writeError(w, err.Error(), http.StatusInternalServerError)
-
l.Error("file tree", "error", err.Error())
-
return
}
if ref == "" {