Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added wait and retries for rate limit response code from Bitbucket server #433

Closed
wants to merge 6 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ public class BitbucketServerAPIClient implements BitbucketApi {
private static final String API_COMMIT_STATUS_PATH = "/rest/build-status/1.0/commits{/hash}";
private static final Integer DEFAULT_PAGE_LIMIT = 200;

private static final int API_RATE_LIMIT_CODE = 429;
private static final int API_RATE_LIMIT_WAIT_TIME_DEFAULT = 5000;

/**
* Repository owner.
*/
Expand Down Expand Up @@ -529,6 +532,15 @@ public boolean checkPathExists(@NonNull String branchOrHash, @NonNull String pat
// https://support.atlassian.com/bitbucket-cloud/docs/use-bitbucket-rest-api-version-1/
} else if (HttpStatus.SC_NOT_FOUND == status || HttpStatus.SC_UNAUTHORIZED == status) {
return false;
} else if (API_RATE_LIMIT_CODE == status) {
LOGGER.fine("Bitbucket API rate limit reached, sleeping for 5 sec then retry...");
try {
Thread.sleep(API_RATE_LIMIT_WAIT_TIME_DEFAULT);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just waiting for 5 seconds will cause a lot of polling and spamming of the server. Please shift to some kind of progressive back off where each of retry waits longer (up to some reasonable limit.

Alternative: see if they the headers of the 429 provide information about when to the limit will reset and sleep for something like that long.

} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return checkPathExists(branchOrHash, path);
} else {
throw new IOException("Communication error for url: " + path + " status code: " + status);
}
Expand Down Expand Up @@ -871,9 +883,23 @@ protected String getRequest(String path) throws IOException {
throw new FileNotFoundException("URL: " + path);
}
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
throw new BitbucketRequestException(response.getStatusLine().getStatusCode(),
"HTTP request error. Status: " + response.getStatusLine().getStatusCode()
+ ": " + response.getStatusLine().getReasonPhrase() + ".\n" + response);

if(response.getStatusLine().getStatusCode() == API_RATE_LIMIT_CODE) {
response.close();
httpget.releaseConnection();
LOGGER.fine("Bitbucket API rate limit reached, sleeping for 5 sec then retry...");
try {
Thread.sleep(API_RATE_LIMIT_WAIT_TIME_DEFAULT);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Comment on lines +890 to +896
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two blocks are identical, convert to a method.

return getRequest(path);
} else {
throw new BitbucketRequestException(response.getStatusLine().getStatusCode(),
"HTTP request error. Status: " + response.getStatusLine().getStatusCode()
+ ": " + response.getStatusLine().getReasonPhrase() + ".\n" + response);
}
}
return content;
} catch (BitbucketRequestException | FileNotFoundException e) {
Expand Down Expand Up @@ -911,6 +937,11 @@ private BufferedImage getImageRequest(String path) throws IOException, Interrupt
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_FOUND) {
throw new FileNotFoundException("URL: " + path);
}
if(response.getStatusLine().getStatusCode() == API_RATE_LIMIT_CODE) {
httpget.releaseConnection();
Thread.sleep(API_RATE_LIMIT_WAIT_TIME_DEFAULT);
return getImageRequest(path);
}
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
throw new BitbucketRequestException(response.getStatusLine().getStatusCode(),
"HTTP request error. Status: " + response.getStatusLine().getStatusCode() + ": "
Expand Down Expand Up @@ -1084,6 +1115,17 @@ private String doRequest(HttpRequestBase request) throws IOException {
content = new String(buf.toByteArray(), StandardCharsets.UTF_8);
}
EntityUtils.consume(response.getEntity());

if(response.getStatusLine().getStatusCode() == API_RATE_LIMIT_CODE) {
request.releaseConnection();
try {
Thread.sleep(API_RATE_LIMIT_WAIT_TIME_DEFAULT);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return doRequest(request);
}
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK && response.getStatusLine().getStatusCode() != HttpStatus.SC_CREATED) {
throw new BitbucketRequestException(response.getStatusLine().getStatusCode(), "HTTP request error. Status: " + response.getStatusLine().getStatusCode() + ": " + response.getStatusLine().getReasonPhrase() + ".\n" + response);
}
Expand Down