Skip to content
Permalink
Browse files
446: Adhere to GitHub rate limits
Reviewed-by: ehelin
  • Loading branch information
rwestberg committed Jul 3, 2020
1 parent a5891a8 commit 4e845a5680af6571f7eb504e36b7f7b4acbd032d
Showing with 43 additions and 3 deletions.
  1. +43 −3 network/src/main/java/org/openjdk/skara/network/RestRequestCache.java
@@ -24,9 +24,10 @@

import java.io.IOException;
import java.net.http.*;
import java.time.Duration;
import java.time.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.*;
import java.util.logging.Logger;

enum RestRequestCache {
@@ -62,18 +63,36 @@ public int hashCode() {
private final Map<RequestContext, HttpResponse<String>> cachedResponses = new ConcurrentHashMap<>();
private final HttpClient client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(10)).build();
private final Logger log = Logger.getLogger("org.openjdk.skara.network");
private final Map<String, Lock> authLocks = new HashMap<>();
private final Map<String, Instant> lastUpdates = new ConcurrentHashMap<>();

HttpResponse<String> send(String authId, HttpRequest.Builder requestBuilder) throws IOException, InterruptedException {
if (authId == null) {
authId = "anonymous";
}
var unauthenticatedRequest = requestBuilder.build();
var requestContext = new RequestContext(authId, unauthenticatedRequest);
synchronized (authLocks) {
if (!authLocks.containsKey(authId)) {
authLocks.put(authId, new ReentrantLock());
}
}
var authLock = authLocks.get(authId);
if (unauthenticatedRequest.method().equals("GET")) {
var cached = cachedResponses.get(requestContext);
if (cached != null) {
var tag = cached.headers().firstValue("ETag");
tag.ifPresent(value -> requestBuilder.header("If-None-Match", value));
}
var finalRequest = requestBuilder.build();
var response = client.send(finalRequest, HttpResponse.BodyHandlers.ofString());
HttpResponse<String> response;
try {
// Perform requests using a certain account serially
authLock.lock();
response = client.send(finalRequest, HttpResponse.BodyHandlers.ofString());
} finally {
authLock.unlock();
}
if (response.statusCode() == 304) {
log.finer("Using cached response for " + finalRequest + " (" + authId + ")");
return cached;
@@ -85,7 +104,28 @@ public int hashCode() {
} else {
var finalRequest = requestBuilder.build();
log.finer("Not using response cache for " + finalRequest + " (" + authId + ")");
return client.send(finalRequest, HttpResponse.BodyHandlers.ofString());
Instant lastUpdate;
try {
authLock.lock();
lastUpdate = lastUpdates.getOrDefault(authId, Instant.now().minus(Duration.ofDays(1)));
lastUpdates.put(authId, Instant.now());
} finally {
authLock.unlock();
}
// Perform at most one update per second
var requiredDelay = Duration.between(Instant.now().minus(Duration.ofSeconds(1)), lastUpdate);
if (!requiredDelay.isNegative()) {
try {
Thread.sleep(requiredDelay.toMillis());
} catch (InterruptedException ignored) {
}
}
try {
authLock.lock();
return client.send(finalRequest, HttpResponse.BodyHandlers.ofString());
} finally {
authLock.unlock();
}
}
}
}

1 comment on commit 4e845a5

@bridgekeeper

This comment has been minimized.

Copy link

@bridgekeeper bridgekeeper bot commented on 4e845a5 Jul 3, 2020

Please sign in to comment.