1
1
package com .github .maven .plugins .core ;
2
2
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 ;
5
5
6
6
import java .io .IOException ;
7
7
import java .net .HttpURLConnection ;
8
8
9
+ import com .github .maven .plugins .core .egit .GitHubClientEgit ;
10
+ import com .google .common .util .concurrent .RateLimiter ;
11
+
9
12
public class RateLimitedGitHubClient extends GitHubClientEgit {
10
13
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 ;
16
15
17
16
public RateLimitedGitHubClient () {
18
17
super ();
@@ -28,25 +27,78 @@ public RateLimitedGitHubClient(String hostname, int port, String scheme) {
28
27
29
28
@ Override
30
29
protected HttpURLConnection createDelete (String uri ) throws IOException {
31
- //rateLimiter.acquire();
32
30
return super .createDelete (uri );
33
31
}
34
32
35
33
@ Override
36
34
protected HttpURLConnection createGet (String uri ) throws IOException {
37
- //rateLimiter.acquire();
38
35
return super .createGet (uri );
39
36
}
40
37
41
38
@ Override
42
39
protected HttpURLConnection createPost (String uri ) throws IOException {
43
- rateLimiter .acquire ();
40
+ rateLimiter () .acquire ();
44
41
return super .createPost (uri );
45
42
}
46
43
47
44
@ Override
48
45
protected HttpURLConnection createPut (String uri ) throws IOException {
49
- rateLimiter .acquire ();
46
+ rateLimiter () .acquire ();
50
47
return super .createPut (uri );
51
48
}
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