Skip to content

Commit

Permalink
fix: fail if repo has too many star
Browse files Browse the repository at this point in the history
Signed-off-by: Carlos Alexandro Becker <caarlos0@gmail.com>
  • Loading branch information
caarlos0 committed Jul 30, 2021
1 parent 7f5f63b commit 11217af
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 8 deletions.
28 changes: 21 additions & 7 deletions controller/repositories.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package controller

import (
"errors"
"fmt"
"html/template"
"io/fs"
Expand Down Expand Up @@ -45,7 +46,7 @@ func IntValueFormatter(v interface{}) string {
//
// nolint: funlen
// TODO: refactor.
func GetRepoChart(github *github.GitHub, cache *cache.Redis) http.HandlerFunc {
func GetRepoChart(gh *github.GitHub, cache *cache.Redis) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
name := fmt.Sprintf(
"%s/%s",
Expand All @@ -54,13 +55,24 @@ func GetRepoChart(github *github.GitHub, cache *cache.Redis) http.HandlerFunc {
)
log := log.WithField("repo", name)
defer log.Trace("collect_stars").Stop(nil)
repo, err := github.RepoDetails(r.Context(), name)
repo, err := gh.RepoDetails(r.Context(), name)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
stargazers, err := github.Stargazers(r.Context(), repo)

w.Header().Add("content-type", "image/svg+xml;charset=utf-8")
w.Header().Add("cache-control", "public, max-age=86400")
w.Header().Add("date", time.Now().Format(time.RFC1123))
w.Header().Add("expires", time.Now().Format(time.RFC1123))

stargazers, err := gh.Stargazers(r.Context(), repo)
if errors.Is(err, github.ErrTooManyStars) {
w.Write([]byte(errSvg(err)))
return
}
if err != nil {
log.WithError(err).Error("failed to get stars")
http.Error(w, err.Error(), http.StatusServiceUnavailable)
return
}
Expand Down Expand Up @@ -119,12 +131,14 @@ func GetRepoChart(github *github.GitHub, cache *cache.Redis) http.HandlerFunc {
Series: []chart.Series{series},
}
defer log.Trace("chart").Stop(&err)
w.Header().Add("content-type", "image/svg+xml;charset=utf-8")
w.Header().Add("cache-control", "public, max-age=86400")
w.Header().Add("date", time.Now().Format(time.RFC1123))
w.Header().Add("expires", time.Now().Format(time.RFC1123))
if err := graph.Render(chart.SVG, w); err != nil {
log.WithError(err).Error("failed to render graph")
}
}
}

func errSvg(err error) string {
return fmt.Sprintf(`<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1024" height="50">
<text xmlns="http://www.w3.org/2000/svg" y="20" x="100" fill="red">%s</text>
</svg>`, err.Error())
}
13 changes: 12 additions & 1 deletion internal/github/stars.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
)

var errNoMorePages = errors.New("no more pages to get")
var ErrTooManyStars = errors.New("repo has too many stargazers, github won't allow us to list all stars")

// Stargazer is a star at a given time.
type Stargazer struct {
Expand All @@ -25,6 +26,11 @@ type Stargazer struct {
// Stargazers returns all the stargazers of a given repo.
func (gh *GitHub) Stargazers(ctx context.Context, repo Repository) (stars []Stargazer, err error) {
sem := make(chan bool, 4)

if gh.totalPages(repo) > 400 {
return stars, ErrTooManyStars
}

var g errgroup.Group
var lock sync.Mutex
for page := 1; page <= gh.lastPage(repo); page++ {
Expand Down Expand Up @@ -130,8 +136,13 @@ func (gh *GitHub) getStargazersPage(ctx context.Context, repo Repository, page i
}
}

func (gh *GitHub) totalPages(repo Repository) int {
return repo.StargazersCount / gh.pageSize
}


func (gh *GitHub) lastPage(repo Repository) int {
return (repo.StargazersCount / gh.pageSize) + 1
return gh.totalPages(repo) + 1
}

func (gh *GitHub) makeStarPageRequest(ctx context.Context, repo Repository, page int, etag string) (*http.Response, error) {
Expand Down

0 comments on commit 11217af

Please sign in to comment.