From 5a8241726b3f43198e6c0b59030b99fcf054ff15 Mon Sep 17 00:00:00 2001 From: "htfv (Aliaksei Lahachou)" Date: Tue, 30 Jun 2015 17:36:27 +0200 Subject: [PATCH] #27: Query rate limit using GitHub API instead of using small hardcoded value. --- .../plugins/core/RateLimitedGitHubClient.java | 76 ++++++++++++++++--- 1 file changed, 64 insertions(+), 12 deletions(-) diff --git a/github-core/src/main/java/com/github/maven/plugins/core/RateLimitedGitHubClient.java b/github-core/src/main/java/com/github/maven/plugins/core/RateLimitedGitHubClient.java index 5a3ff445..f27e56d3 100644 --- a/github-core/src/main/java/com/github/maven/plugins/core/RateLimitedGitHubClient.java +++ b/github-core/src/main/java/com/github/maven/plugins/core/RateLimitedGitHubClient.java @@ -1,18 +1,17 @@ package com.github.maven.plugins.core; -import com.github.maven.plugins.core.egit.GitHubClientEgit; -import com.google.common.util.concurrent.RateLimiter; +import static java.lang.Math.max; +import static java.lang.System.currentTimeMillis; import java.io.IOException; import java.net.HttpURLConnection; +import com.github.maven.plugins.core.egit.GitHubClientEgit; +import com.google.common.util.concurrent.RateLimiter; + public class RateLimitedGitHubClient extends GitHubClientEgit { - /** - * AS per https://github.com/octokit/octokit.net/issues/638#issuecomment-67795998, - * it seems that GitHub only allow 20 API calls per 1-minute period - */ - private RateLimiter rateLimiter = RateLimiter.create(20.0/60.0); + private volatile RateLimiter rateLimiter; public RateLimitedGitHubClient() { super(); @@ -28,25 +27,78 @@ public RateLimitedGitHubClient(String hostname, int port, String scheme) { @Override protected HttpURLConnection createDelete(String uri) throws IOException { - //rateLimiter.acquire(); return super.createDelete(uri); } @Override protected HttpURLConnection createGet(String uri) throws IOException { - //rateLimiter.acquire(); return super.createGet(uri); } @Override protected HttpURLConnection createPost(String uri) throws IOException { - rateLimiter.acquire(); + rateLimiter().acquire(); return super.createPost(uri); } @Override protected HttpURLConnection createPut(String uri) throws IOException { - rateLimiter.acquire(); + rateLimiter().acquire(); return super.createPut(uri); } -} \ No newline at end of file + + private RateLimiter rateLimiter() { + final RateLimiter rateLimiter = this.rateLimiter; + + if (rateLimiter != null) { + return rateLimiter; + } + + return initializeRateLimiter(); + } + + private synchronized RateLimiter initializeRateLimiter() { + + if (rateLimiter != null) { + return rateLimiter; + } + + HttpURLConnection connection = null; + + try { + + // + // Query rate limit. + // + + connection = createGet("/rate_limit"); + + final int remaining = connection.getHeaderFieldInt("X-RateLimit-Remaining", -1); + final int reset = connection.getHeaderFieldInt("X-RateLimit-Reset", -1); + final int now = (int) (currentTimeMillis() / 1000); + + // + // Calculate the sustained request rate until the limits are reset. + // + + return rateLimiter = RateLimiter.create((double) remaining / max(reset - now, 1)); + + } catch (Exception e) { + + // + // Fall back to 20 requests per minute. + // + // As per https://github.com/octokit/octokit.net/issues/638#issuecomment-67795998, + // it seems that GitHub only allow 20 API calls per 1-minute period + // + + return rateLimiter = RateLimiter.create(20. / 60.); + + } finally { + + if (connection != null) { + connection.disconnect(); + } + } + } +}