Skip to content

Commit

Permalink
Fix-Using Roundrobin tokens across multiple calls (#284)
Browse files Browse the repository at this point in the history
The GitHub tokens are picked from a list for each call using Roundrobin approach.
  • Loading branch information
naveensrinivasan committed Mar 17, 2021
1 parent 8333f1e commit 7ff09db
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 21 deletions.
35 changes: 17 additions & 18 deletions pkg/scorecard.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,30 +81,29 @@ func (r *RepoURL) Set(s string) error {

func RunScorecards(ctx context.Context, logger *zap.SugaredLogger,
repo RepoURL, checksToRun []checker.NamedCheck) <-chan Result {
// Use our custom roundtripper
rt := roundtripper.NewTransport(ctx, logger)

client := &http.Client{
Transport: rt,
}
ghClient := github.NewClient(client)
graphClient := githubv4.NewClient(client)

c := checker.Checker{
Ctx: ctx,
Client: ghClient,
HttpClient: client,
Owner: repo.Owner,
Repo: repo.Repo,
GraphClient: graphClient,
}

resultsCh := make(chan Result)
wg := sync.WaitGroup{}
for _, check := range checksToRun {
check := check
wg.Add(1)
go func() {
// Use our custom roundtripper
rt := roundtripper.NewTransport(ctx, logger)

client := &http.Client{
Transport: rt,
}
ghClient := github.NewClient(client)
graphClient := githubv4.NewClient(client)

c := checker.Checker{
Ctx: ctx,
Client: ghClient,
HttpClient: client,
Owner: repo.Owner,
Repo: repo.Repo,
GraphClient: graphClient,
}
defer wg.Done()
runner := checker.Runner{Checker: c}
r := runner.Run(check.Fn)
Expand Down
13 changes: 10 additions & 3 deletions roundtripper/roundtripper.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,25 @@ const (
BucketURL = "BLOB_URL"
)

var counter int64

// RateLimitRoundTripper is a rate-limit aware http.Transport for Github.
type RateLimitRoundTripper struct {
Logger *zap.SugaredLogger
InnerTransport http.RoundTripper
}

type RoundRobinTokenSource struct {
counter int64
AccessTokens []string
log *zap.SugaredLogger
}

func (r *RoundRobinTokenSource) Token() (*oauth2.Token, error) {
c := atomic.AddInt64(&r.counter, 1)
index := c % int64(len(r.AccessTokens))
c := atomic.AddInt64(&counter, 1)
// not locking it because it is never modified
l := len(r.AccessTokens)
index := c % int64(l)
r.log.Infof("using token %d of total %d.", index, l)
return &oauth2.Token{
AccessToken: r.AccessTokens[index],
}, nil
Expand All @@ -70,6 +75,7 @@ func NewTransport(ctx context.Context, logger *zap.SugaredLogger) http.RoundTrip
if token := os.Getenv(GithubAuthToken); token != "" {
ts := &RoundRobinTokenSource{
AccessTokens: strings.Split(token, ","),
log: logger,
}
transport = oauth2.NewClient(ctx, ts).Transport
} else if keyPath := os.Getenv(GithubAppKeyPath); keyPath != "" { // Also try a GITHUB_APP
Expand Down Expand Up @@ -171,5 +177,6 @@ func (gh *RateLimitRoundTripper) RoundTrip(r *http.Request) (*http.Response, err
gh.Logger.Warnf("Rate limit exceeded. Retrying...")
return gh.RoundTrip(r)
}

return resp, nil
}

0 comments on commit 7ff09db

Please sign in to comment.