11package com .github .maven .plugins .core ;
22
3- import com . github . maven . plugins . core . egit . GitHubClientEgit ;
4- import com . google . common . util . concurrent . RateLimiter ;
3+ import static java . lang . Math . max ;
4+ import static java . lang . System . currentTimeMillis ;
55
66import java .io .IOException ;
77import java .net .HttpURLConnection ;
88
9+ import com .github .maven .plugins .core .egit .GitHubClientEgit ;
10+ import com .google .common .util .concurrent .RateLimiter ;
11+
912public class RateLimitedGitHubClient extends GitHubClientEgit {
1013
11- /**
12- * AS per https://github.com/octokit/octokit.net/issues/638#issuecomment-67795998,
13- * it seems that GitHub only allow 20 API calls per 1-minute period
14- */
15- private RateLimiter rateLimiter = RateLimiter .create (20.0 /60.0 );
14+ private volatile RateLimiter rateLimiter ;
1615
1716 public RateLimitedGitHubClient () {
1817 super ();
@@ -28,25 +27,78 @@ public RateLimitedGitHubClient(String hostname, int port, String scheme) {
2827
2928 @ Override
3029 protected HttpURLConnection createDelete (String uri ) throws IOException {
31- //rateLimiter.acquire();
3230 return super .createDelete (uri );
3331 }
3432
3533 @ Override
3634 protected HttpURLConnection createGet (String uri ) throws IOException {
37- //rateLimiter.acquire();
3835 return super .createGet (uri );
3936 }
4037
4138 @ Override
4239 protected HttpURLConnection createPost (String uri ) throws IOException {
43- rateLimiter .acquire ();
40+ rateLimiter () .acquire ();
4441 return super .createPost (uri );
4542 }
4643
4744 @ Override
4845 protected HttpURLConnection createPut (String uri ) throws IOException {
49- rateLimiter .acquire ();
46+ rateLimiter () .acquire ();
5047 return super .createPut (uri );
5148 }
52- }
49+
50+ private RateLimiter rateLimiter () {
51+ final RateLimiter rateLimiter = this .rateLimiter ;
52+
53+ if (rateLimiter != null ) {
54+ return rateLimiter ;
55+ }
56+
57+ return initializeRateLimiter ();
58+ }
59+
60+ private synchronized RateLimiter initializeRateLimiter () {
61+
62+ if (rateLimiter != null ) {
63+ return rateLimiter ;
64+ }
65+
66+ HttpURLConnection connection = null ;
67+
68+ try {
69+
70+ //
71+ // Query rate limit.
72+ //
73+
74+ connection = createGet ("/rate_limit" );
75+
76+ final int remaining = connection .getHeaderFieldInt ("X-RateLimit-Remaining" , -1 );
77+ final int reset = connection .getHeaderFieldInt ("X-RateLimit-Reset" , -1 );
78+ final int now = (int ) (currentTimeMillis () / 1000 );
79+
80+ //
81+ // Calculate the sustained request rate until the limits are reset.
82+ //
83+
84+ return rateLimiter = RateLimiter .create ((double ) remaining / max (reset - now , 1 ));
85+
86+ } catch (Exception e ) {
87+
88+ //
89+ // Fall back to 20 requests per minute.
90+ //
91+ // As per https://github.com/octokit/octokit.net/issues/638#issuecomment-67795998,
92+ // it seems that GitHub only allow 20 API calls per 1-minute period
93+ //
94+
95+ return rateLimiter = RateLimiter .create (20. / 60. );
96+
97+ } finally {
98+
99+ if (connection != null ) {
100+ connection .disconnect ();
101+ }
102+ }
103+ }
104+ }
0 commit comments