@@ -68,14 +68,15 @@ func (f *GithubDownloaderV3Factory) GitServiceType() structs.GitServiceType {
6868// from github via APIv3
6969type GithubDownloaderV3 struct {
7070 base.NullDownloader
71- ctx context.Context
72- client * github.Client
73- repoOwner string
74- repoName string
75- userName string
76- password string
77- rate * github.Rate
78- maxPerPage int
71+ ctx context.Context
72+ clients []* github.Client
73+ repoOwner string
74+ repoName string
75+ userName string
76+ password string
77+ rates []* github.Rate
78+ curClientIdx int
79+ maxPerPage int
7980}
8081
8182// NewGithubDownloaderV3 creates a github Downloader via github v3 API
@@ -97,15 +98,31 @@ func NewGithubDownloaderV3(ctx context.Context, baseURL, userName, password, tok
9798 },
9899 },
99100 }
101+
100102 if token != "" {
101- ts := oauth2 .StaticTokenSource (
102- & oauth2.Token {AccessToken : token },
103- )
104- client = oauth2 .NewClient (downloader .ctx , ts )
105- }
106- downloader .client = github .NewClient (client )
107- if baseURL != "https://github.com" {
108- downloader .client , _ = github .NewEnterpriseClient (baseURL , baseURL , client )
103+ tokens := strings .Split (token , "," )
104+ for _ , token := range tokens {
105+ token = strings .TrimSpace (token )
106+
107+ ts := oauth2 .StaticTokenSource (
108+ & oauth2.Token {AccessToken : token },
109+ )
110+ client = oauth2 .NewClient (downloader .ctx , ts )
111+
112+ githubClient := github .NewClient (client )
113+ if baseURL != "https://github.com" {
114+ githubClient , _ = github .NewEnterpriseClient (baseURL , baseURL , client )
115+ }
116+ downloader .clients = append (downloader .clients , githubClient )
117+ downloader .rates = append (downloader .rates , nil )
118+ }
119+ } else {
120+ githubClient := github .NewClient (client )
121+ if baseURL != "https://github.com" {
122+ githubClient , _ = github .NewEnterpriseClient (baseURL , baseURL , client )
123+ }
124+ downloader .clients = append (downloader .clients , githubClient )
125+ downloader .rates = append (downloader .rates , nil )
109126 }
110127 return & downloader
111128}
@@ -116,8 +133,18 @@ func (g *GithubDownloaderV3) SetContext(ctx context.Context) {
116133}
117134
118135func (g * GithubDownloaderV3 ) sleep () {
119- for g .rate != nil && g .rate .Remaining <= GithubLimitRateRemaining {
120- timer := time .NewTimer (time .Until (g .rate .Reset .Time ))
136+ var recentIdx int
137+ var maxRemaining int
138+ for i := 0 ; i < len (g .clients ); i ++ {
139+ if g .rates [i ] != nil && g .rates [i ].Remaining > maxRemaining {
140+ maxRemaining = g .rates [i ].Remaining
141+ recentIdx = i
142+ }
143+ }
144+ g .curClientIdx = recentIdx
145+
146+ for g .rates [g .curClientIdx ] != nil && g .rates [g .curClientIdx ].Remaining <= GithubLimitRateRemaining {
147+ timer := time .NewTimer (time .Until (g .rates [g .curClientIdx ].Reset .Time ))
121148 select {
122149 case <- g .ctx .Done ():
123150 util .StopTimer (timer )
@@ -127,35 +154,43 @@ func (g *GithubDownloaderV3) sleep() {
127154
128155 err := g .RefreshRate ()
129156 if err != nil {
130- log .Error ("g.client .RateLimits: %s" , err )
157+ log .Error ("g.getClient() .RateLimits: %s" , err )
131158 }
132159 }
133160}
134161
135162// RefreshRate update the current rate (doesn't count in rate limit)
136163func (g * GithubDownloaderV3 ) RefreshRate () error {
137- rates , _ , err := g .client .RateLimits (g .ctx )
164+ rates , _ , err := g .getClient () .RateLimits (g .ctx )
138165 if err != nil {
139166 // if rate limit is not enabled, ignore it
140167 if strings .Contains (err .Error (), "404" ) {
141- g .rate = nil
168+ g .setRate ( nil )
142169 return nil
143170 }
144171 return err
145172 }
146173
147- g .rate = rates .GetCore ()
174+ g .setRate ( rates .GetCore () )
148175 return nil
149176}
150177
178+ func (g * GithubDownloaderV3 ) getClient () * github.Client {
179+ return g .clients [g .curClientIdx ]
180+ }
181+
182+ func (g * GithubDownloaderV3 ) setRate (rate * github.Rate ) {
183+ g .rates [g .curClientIdx ] = rate
184+ }
185+
151186// GetRepoInfo returns a repository information
152187func (g * GithubDownloaderV3 ) GetRepoInfo () (* base.Repository , error ) {
153188 g .sleep ()
154- gr , resp , err := g .client .Repositories .Get (g .ctx , g .repoOwner , g .repoName )
189+ gr , resp , err := g .getClient () .Repositories .Get (g .ctx , g .repoOwner , g .repoName )
155190 if err != nil {
156191 return nil , err
157192 }
158- g .rate = & resp .Rate
193+ g .setRate ( & resp .Rate )
159194
160195 // convert github repo to stand Repo
161196 return & base.Repository {
@@ -172,11 +207,11 @@ func (g *GithubDownloaderV3) GetRepoInfo() (*base.Repository, error) {
172207// GetTopics return github topics
173208func (g * GithubDownloaderV3 ) GetTopics () ([]string , error ) {
174209 g .sleep ()
175- r , resp , err := g .client .Repositories .Get (g .ctx , g .repoOwner , g .repoName )
210+ r , resp , err := g .getClient () .Repositories .Get (g .ctx , g .repoOwner , g .repoName )
176211 if err != nil {
177212 return nil , err
178213 }
179- g .rate = & resp .Rate
214+ g .setRate ( & resp .Rate )
180215 return r .Topics , nil
181216}
182217
@@ -186,7 +221,7 @@ func (g *GithubDownloaderV3) GetMilestones() ([]*base.Milestone, error) {
186221 var milestones = make ([]* base.Milestone , 0 , perPage )
187222 for i := 1 ; ; i ++ {
188223 g .sleep ()
189- ms , resp , err := g .client .Issues .ListMilestones (g .ctx , g .repoOwner , g .repoName ,
224+ ms , resp , err := g .getClient () .Issues .ListMilestones (g .ctx , g .repoOwner , g .repoName ,
190225 & github.MilestoneListOptions {
191226 State : "all" ,
192227 ListOptions : github.ListOptions {
@@ -196,7 +231,7 @@ func (g *GithubDownloaderV3) GetMilestones() ([]*base.Milestone, error) {
196231 if err != nil {
197232 return nil , err
198233 }
199- g .rate = & resp .Rate
234+ g .setRate ( & resp .Rate )
200235
201236 for _ , m := range ms {
202237 var state = "open"
@@ -234,15 +269,15 @@ func (g *GithubDownloaderV3) GetLabels() ([]*base.Label, error) {
234269 var labels = make ([]* base.Label , 0 , perPage )
235270 for i := 1 ; ; i ++ {
236271 g .sleep ()
237- ls , resp , err := g .client .Issues .ListLabels (g .ctx , g .repoOwner , g .repoName ,
272+ ls , resp , err := g .getClient () .Issues .ListLabels (g .ctx , g .repoOwner , g .repoName ,
238273 & github.ListOptions {
239274 Page : i ,
240275 PerPage : perPage ,
241276 })
242277 if err != nil {
243278 return nil , err
244279 }
245- g .rate = & resp .Rate
280+ g .setRate ( & resp .Rate )
246281
247282 for _ , label := range ls {
248283 labels = append (labels , convertGithubLabel (label ))
@@ -291,12 +326,12 @@ func (g *GithubDownloaderV3) convertGithubRelease(rel *github.RepositoryRelease)
291326 Updated : asset .UpdatedAt .Time ,
292327 DownloadFunc : func () (io.ReadCloser , error ) {
293328 g .sleep ()
294- asset , redirectURL , err := g .client .Repositories .DownloadReleaseAsset (g .ctx , g .repoOwner , g .repoName , assetID , nil )
329+ asset , redirectURL , err := g .getClient () .Repositories .DownloadReleaseAsset (g .ctx , g .repoOwner , g .repoName , assetID , nil )
295330 if err != nil {
296331 return nil , err
297332 }
298333 if err := g .RefreshRate (); err != nil {
299- log .Error ("g.client .RateLimits: %s" , err )
334+ log .Error ("g.getClient() .RateLimits: %s" , err )
300335 }
301336 if asset == nil {
302337 if redirectURL != "" {
@@ -308,7 +343,7 @@ func (g *GithubDownloaderV3) convertGithubRelease(rel *github.RepositoryRelease)
308343 resp , err := httpClient .Do (req )
309344 err1 := g .RefreshRate ()
310345 if err1 != nil {
311- log .Error ("g.client .RateLimits: %s" , err1 )
346+ log .Error ("g.getClient() .RateLimits: %s" , err1 )
312347 }
313348 if err != nil {
314349 return nil , err
@@ -330,15 +365,15 @@ func (g *GithubDownloaderV3) GetReleases() ([]*base.Release, error) {
330365 var releases = make ([]* base.Release , 0 , perPage )
331366 for i := 1 ; ; i ++ {
332367 g .sleep ()
333- ls , resp , err := g .client .Repositories .ListReleases (g .ctx , g .repoOwner , g .repoName ,
368+ ls , resp , err := g .getClient () .Repositories .ListReleases (g .ctx , g .repoOwner , g .repoName ,
334369 & github.ListOptions {
335370 Page : i ,
336371 PerPage : perPage ,
337372 })
338373 if err != nil {
339374 return nil , err
340375 }
341- g .rate = & resp .Rate
376+ g .setRate ( & resp .Rate )
342377
343378 for _ , release := range ls {
344379 releases = append (releases , g .convertGithubRelease (release ))
@@ -367,12 +402,12 @@ func (g *GithubDownloaderV3) GetIssues(page, perPage int) ([]*base.Issue, bool,
367402
368403 var allIssues = make ([]* base.Issue , 0 , perPage )
369404 g .sleep ()
370- issues , resp , err := g .client .Issues .ListByRepo (g .ctx , g .repoOwner , g .repoName , opt )
405+ issues , resp , err := g .getClient () .Issues .ListByRepo (g .ctx , g .repoOwner , g .repoName , opt )
371406 if err != nil {
372407 return nil , false , fmt .Errorf ("error while listing repos: %v" , err )
373408 }
374409 log .Trace ("Request get issues %d/%d, but in fact get %d" , perPage , page , len (issues ))
375- g .rate = & resp .Rate
410+ g .setRate ( & resp .Rate )
376411 for _ , issue := range issues {
377412 if issue .IsPullRequest () {
378413 continue
@@ -387,14 +422,14 @@ func (g *GithubDownloaderV3) GetIssues(page, perPage int) ([]*base.Issue, bool,
387422 var reactions []* base.Reaction
388423 for i := 1 ; ; i ++ {
389424 g .sleep ()
390- res , resp , err := g .client .Reactions .ListIssueReactions (g .ctx , g .repoOwner , g .repoName , issue .GetNumber (), & github.ListOptions {
425+ res , resp , err := g .getClient () .Reactions .ListIssueReactions (g .ctx , g .repoOwner , g .repoName , issue .GetNumber (), & github.ListOptions {
391426 Page : i ,
392427 PerPage : perPage ,
393428 })
394429 if err != nil {
395430 return nil , false , err
396431 }
397- g .rate = & resp .Rate
432+ g .setRate ( & resp .Rate )
398433 if len (res ) == 0 {
399434 break
400435 }
@@ -465,24 +500,24 @@ func (g *GithubDownloaderV3) getComments(issueContext base.IssueContext) ([]*bas
465500 }
466501 for {
467502 g .sleep ()
468- comments , resp , err := g .client .Issues .ListComments (g .ctx , g .repoOwner , g .repoName , int (issueContext .ForeignID ()), opt )
503+ comments , resp , err := g .getClient () .Issues .ListComments (g .ctx , g .repoOwner , g .repoName , int (issueContext .ForeignID ()), opt )
469504 if err != nil {
470505 return nil , fmt .Errorf ("error while listing repos: %v" , err )
471506 }
472- g .rate = & resp .Rate
507+ g .setRate ( & resp .Rate )
473508 for _ , comment := range comments {
474509 // get reactions
475510 var reactions []* base.Reaction
476511 for i := 1 ; ; i ++ {
477512 g .sleep ()
478- res , resp , err := g .client .Reactions .ListIssueCommentReactions (g .ctx , g .repoOwner , g .repoName , comment .GetID (), & github.ListOptions {
513+ res , resp , err := g .getClient () .Reactions .ListIssueCommentReactions (g .ctx , g .repoOwner , g .repoName , comment .GetID (), & github.ListOptions {
479514 Page : i ,
480515 PerPage : g .maxPerPage ,
481516 })
482517 if err != nil {
483518 return nil , err
484519 }
485- g .rate = & resp .Rate
520+ g .setRate ( & resp .Rate )
486521 if len (res ) == 0 {
487522 break
488523 }
@@ -534,27 +569,27 @@ func (g *GithubDownloaderV3) GetAllComments(page, perPage int) ([]*base.Comment,
534569 }
535570
536571 g .sleep ()
537- comments , resp , err := g .client .Issues .ListComments (g .ctx , g .repoOwner , g .repoName , 0 , opt )
572+ comments , resp , err := g .getClient () .Issues .ListComments (g .ctx , g .repoOwner , g .repoName , 0 , opt )
538573 if err != nil {
539574 return nil , false , fmt .Errorf ("error while listing repos: %v" , err )
540575 }
541576 var isEnd = resp .NextPage == 0
542577
543578 log .Trace ("Request get comments %d/%d, but in fact get %d, next page is %d" , perPage , page , len (comments ), resp .NextPage )
544- g .rate = & resp .Rate
579+ g .setRate ( & resp .Rate )
545580 for _ , comment := range comments {
546581 // get reactions
547582 var reactions []* base.Reaction
548583 for i := 1 ; ; i ++ {
549584 g .sleep ()
550- res , resp , err := g .client .Reactions .ListIssueCommentReactions (g .ctx , g .repoOwner , g .repoName , comment .GetID (), & github.ListOptions {
585+ res , resp , err := g .getClient () .Reactions .ListIssueCommentReactions (g .ctx , g .repoOwner , g .repoName , comment .GetID (), & github.ListOptions {
551586 Page : i ,
552587 PerPage : g .maxPerPage ,
553588 })
554589 if err != nil {
555590 return nil , false , err
556591 }
557- g .rate = & resp .Rate
592+ g .setRate ( & resp .Rate )
558593 if len (res ) == 0 {
559594 break
560595 }
@@ -599,12 +634,12 @@ func (g *GithubDownloaderV3) GetPullRequests(page, perPage int) ([]*base.PullReq
599634 }
600635 var allPRs = make ([]* base.PullRequest , 0 , perPage )
601636 g .sleep ()
602- prs , resp , err := g .client .PullRequests .List (g .ctx , g .repoOwner , g .repoName , opt )
637+ prs , resp , err := g .getClient () .PullRequests .List (g .ctx , g .repoOwner , g .repoName , opt )
603638 if err != nil {
604639 return nil , false , fmt .Errorf ("error while listing repos: %v" , err )
605640 }
606641 log .Trace ("Request get pull requests %d/%d, but in fact get %d" , perPage , page , len (prs ))
607- g .rate = & resp .Rate
642+ g .setRate ( & resp .Rate )
608643 for _ , pr := range prs {
609644 var labels = make ([]* base.Label , 0 , len (pr .Labels ))
610645 for _ , l := range pr .Labels {
@@ -615,14 +650,14 @@ func (g *GithubDownloaderV3) GetPullRequests(page, perPage int) ([]*base.PullReq
615650 var reactions []* base.Reaction
616651 for i := 1 ; ; i ++ {
617652 g .sleep ()
618- res , resp , err := g .client .Reactions .ListIssueReactions (g .ctx , g .repoOwner , g .repoName , pr .GetNumber (), & github.ListOptions {
653+ res , resp , err := g .getClient () .Reactions .ListIssueReactions (g .ctx , g .repoOwner , g .repoName , pr .GetNumber (), & github.ListOptions {
619654 Page : i ,
620655 PerPage : perPage ,
621656 })
622657 if err != nil {
623658 return nil , false , err
624659 }
625- g .rate = & resp .Rate
660+ g .setRate ( & resp .Rate )
626661 if len (res ) == 0 {
627662 break
628663 }
@@ -693,14 +728,14 @@ func (g *GithubDownloaderV3) convertGithubReviewComments(cs []*github.PullReques
693728 var reactions []* base.Reaction
694729 for i := 1 ; ; i ++ {
695730 g .sleep ()
696- res , resp , err := g .client .Reactions .ListPullRequestCommentReactions (g .ctx , g .repoOwner , g .repoName , c .GetID (), & github.ListOptions {
731+ res , resp , err := g .getClient () .Reactions .ListPullRequestCommentReactions (g .ctx , g .repoOwner , g .repoName , c .GetID (), & github.ListOptions {
697732 Page : i ,
698733 PerPage : g .maxPerPage ,
699734 })
700735 if err != nil {
701736 return nil , err
702737 }
703- g .rate = & resp .Rate
738+ g .setRate ( & resp .Rate )
704739 if len (res ) == 0 {
705740 break
706741 }
@@ -738,11 +773,11 @@ func (g *GithubDownloaderV3) GetReviews(context base.IssueContext) ([]*base.Revi
738773 }
739774 for {
740775 g .sleep ()
741- reviews , resp , err := g .client .PullRequests .ListReviews (g .ctx , g .repoOwner , g .repoName , int (context .ForeignID ()), opt )
776+ reviews , resp , err := g .getClient () .PullRequests .ListReviews (g .ctx , g .repoOwner , g .repoName , int (context .ForeignID ()), opt )
742777 if err != nil {
743778 return nil , fmt .Errorf ("error while listing repos: %v" , err )
744779 }
745- g .rate = & resp .Rate
780+ g .setRate ( & resp .Rate )
746781 for _ , review := range reviews {
747782 r := convertGithubReview (review )
748783 r .IssueIndex = context .LocalID ()
@@ -752,11 +787,11 @@ func (g *GithubDownloaderV3) GetReviews(context base.IssueContext) ([]*base.Revi
752787 }
753788 for {
754789 g .sleep ()
755- reviewComments , resp , err := g .client .PullRequests .ListReviewComments (g .ctx , g .repoOwner , g .repoName , int (context .ForeignID ()), review .GetID (), opt2 )
790+ reviewComments , resp , err := g .getClient () .PullRequests .ListReviewComments (g .ctx , g .repoOwner , g .repoName , int (context .ForeignID ()), review .GetID (), opt2 )
756791 if err != nil {
757792 return nil , fmt .Errorf ("error while listing repos: %v" , err )
758793 }
759- g .rate = & resp .Rate
794+ g .setRate ( & resp .Rate )
760795
761796 cs , err := g .convertGithubReviewComments (reviewComments )
762797 if err != nil {
0 commit comments