diff --git a/src/main/java/no/stelar7/api/l4j8/basic/calling/DataCallBuilder.java b/src/main/java/no/stelar7/api/l4j8/basic/calling/DataCallBuilder.java index 01bb7e70..82ede47e 100644 --- a/src/main/java/no/stelar7/api/l4j8/basic/calling/DataCallBuilder.java +++ b/src/main/java/no/stelar7/api/l4j8/basic/calling/DataCallBuilder.java @@ -35,7 +35,6 @@ private static void updateRatelimiter(Enum server, Enum endpoint) * * @param retrys the amount of retries already done (should not be passed in!) * @return an object generated from the requested JSON - * @throws APINoValidResponseException if the request failed in some fashion */ public Object build(int... retrys) { @@ -63,81 +62,55 @@ public Object build(int... retrys) System.err.println(response); } - try + switch (response.getResponseCode()) { - switch (response.getResponseCode()) + case 200: + case 204: { - case 200: - case 204: - { - final Object returnType = this.dc.getEndpoint().getType(); - Object dtoobj = Utils.getGson().fromJson(response.getResponseData(), (returnType instanceof Class) ? (Class) returnType : (Type) returnType); - - return process(dtoobj); - } - - case 403: - { - String reasonText = "Your Api key is invalid!\n"; - reasonText += "You may be trying to call a endpoint you dont have access to\n"; - reasonText += "or if you just regenerated it; wait a few seconds, then try again\n"; - throw new APIResponseException(APIHTTPErrorReason.ERROR_403, reasonText + response.getResponseData()); - } + final Object returnType = this.dc.getEndpoint().getType(); + Object dtoobj = Utils.getGson().fromJson(response.getResponseData(), (returnType instanceof Class) ? (Class) returnType : (Type) returnType); - case 404: + return process(dtoobj); + } + + case 403: + { + String reasonText = "Your Api key is invalid!\n"; + reasonText += "You may be trying to call a endpoint you dont have access to\n"; + reasonText += "or if you just regenerated it; wait a few seconds, then try again\n"; + throw new APIResponseException(APIHTTPErrorReason.ERROR_403, reasonText + response.getResponseData()); + } + + case 404: + { + return null; + } + + case 429: + if (response.getResponseData().startsWith(RateLimitType.LIMIT_UNDERLYING.getReason()) || response.getResponseData().startsWith(RateLimitType.LIMIT_SERVICE.getReason())) { - return null; - } - - case 429: - if (response.getResponseData().startsWith(RateLimitType.LIMIT_UNDERLYING.getReason()) || response.getResponseData().startsWith(RateLimitType.LIMIT_SERVICE.getReason())) - { - int attempts = (retrys != null && retrys.length == 1) ? ++retrys[0] : 1; - if (attempts > 2) - { - System.err.println("Service ratelimit reached too many times, waiting 10 second and retrying"); - Thread.sleep(10000); - return this.build(attempts); - } - - System.err.format("Service ratelimit reached (%s / 3 times), waiting 1 second and retrying%n", attempts); - Thread.sleep(1000); - return this.build(attempts); - } else - { - System.err.println(response.getResponseData()); - System.err.println("429 ratelimit hit! Please do not restart your application to refresh the timer!"); - System.err.println("This isnt supposed to happen unless you restarted your app before the last limit was hit!"); - } - - return this.build(); - - case 500: - case 502: - case 503: - case 504: + return sleepAndRetry(retrys, "Ratelimit reached too many times, waiting 10 second and retrying", "Ratelimit reached (%s / 3 times), waiting 1 second and retrying%n"); + } else { - int attempts = (retrys != null && retrys.length == 1) ? ++retrys[0] : 1; - System.err.format("Server error, waiting 1 second and retrying%n"); - Thread.sleep(1000); - - if (attempts > 3) - { - throw new APIResponseException(APIHTTPErrorReason.ERROR_500, response.getResponseData()); - } - - return this.build(attempts); + System.err.println(response.getResponseData()); + System.err.println("429 ratelimit hit! Please do not restart your application to refresh the timer!"); + System.err.println("This isnt supposed to happen unless you restarted your app before the last limit was hit!"); } - default: - { - break; - } + return this.build(); + + case 500: + case 502: + case 503: + case 504: + { + return sleepAndRetry(retrys, "Server error, waiting 10 second and retrying", "Server error (%s / 3 times), waiting 1 second and retrying%n"); } - } catch (InterruptedException e) - { - e.printStackTrace(); + default: + { + break; + } } System.err.println("Response Code:" + response.getResponseCode()); @@ -145,8 +118,39 @@ public Object build(int... retrys) throw new APINoValidResponseException(response.getResponseData()); } + private Object sleepAndRetry(int[] retrys, String shortMessage, String longMessage) + { + try + { + int attempts = (retrys != null && retrys.length == 1) ? ++retrys[0] : 1; + + if (attempts > 5) + { + System.err.println("Error! too many times!"); + return null; + } + + + if (attempts > 2) + { + System.err.println(shortMessage); + Thread.sleep(10000); + return this.build(attempts); + } + + System.err.format(longMessage, attempts); + Thread.sleep(1000); + return this.build(attempts); + } catch (InterruptedException e) + { + e.printStackTrace(); + return null; + } + } + // TODO + private void applyLimit(Enum platform, Enum endpoint) { Map limits = DataCall.getLimiter().get(platform); @@ -314,17 +318,16 @@ private void createRatelimiterIfMissing(String methodA, Enum platform, Enum endp { Map child = DataCall.getLimiter().getOrDefault(platform, new HashMap<>()); - RateLimiter oldLimit = child.getOrDefault(endpoint, createLimiter(endpoint, methodA)); + RateLimiter oldLimit = child.get(endpoint); RateLimiter newerLimit = createLimiter(endpoint, methodA); - if (!oldLimit.equals(newerLimit)) + if (!newerLimit.equals(oldLimit)) { newerLimit.mergeFrom(oldLimit); child.put(endpoint, newerLimit); } DataCall.getLimiter().put(platform, child); - } private void saveHeaderRateLimit(String limitCount, Enum platform, Enum endpoint) diff --git a/src/main/java/no/stelar7/api/l4j8/basic/ratelimiting/RateLimit.java b/src/main/java/no/stelar7/api/l4j8/basic/ratelimiting/RateLimit.java index dd217d5e..847cd538 100644 --- a/src/main/java/no/stelar7/api/l4j8/basic/ratelimiting/RateLimit.java +++ b/src/main/java/no/stelar7/api/l4j8/basic/ratelimiting/RateLimit.java @@ -23,6 +23,35 @@ public long getTimeframeInMS() return delayInMs; } + @Override + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + if (o == null || getClass() != o.getClass()) + { + return false; + } + + RateLimit rateLimit = (RateLimit) o; + + if (permits != rateLimit.permits) + { + return false; + } + + return delayInMs == rateLimit.delayInMs; + } + + @Override + public int hashCode() + { + int result = permits; + result = 31 * result + (int) (delayInMs ^ (delayInMs >>> 32)); + return result; + } @Override public String toString() diff --git a/src/main/java/no/stelar7/api/l4j8/basic/ratelimiting/RateLimiter.java b/src/main/java/no/stelar7/api/l4j8/basic/ratelimiting/RateLimiter.java index 98c4381f..810811c2 100644 --- a/src/main/java/no/stelar7/api/l4j8/basic/ratelimiting/RateLimiter.java +++ b/src/main/java/no/stelar7/api/l4j8/basic/ratelimiting/RateLimiter.java @@ -118,8 +118,11 @@ public void resetCalls() public void mergeFrom(RateLimiter oldLimit) { - this.callCountInTime = oldLimit.getCallCountInTime(); - this.firstCallInTime = oldLimit.getFirstCallInTime(); - this.overloadTimer = oldLimit.overloadTimer; + if (oldLimit != null) + { + this.callCountInTime = oldLimit.getCallCountInTime(); + this.firstCallInTime = oldLimit.getFirstCallInTime(); + this.overloadTimer = oldLimit.overloadTimer; + } } } diff --git a/src/test/java/no/stelar7/api/l4j8/tests/ratelimit/RatelimitTest.java b/src/test/java/no/stelar7/api/l4j8/tests/ratelimit/RatelimitTest.java index 80052584..d2d7e99d 100644 --- a/src/test/java/no/stelar7/api/l4j8/tests/ratelimit/RatelimitTest.java +++ b/src/test/java/no/stelar7/api/l4j8/tests/ratelimit/RatelimitTest.java @@ -50,27 +50,29 @@ protected void finished(long nanos, Description description) final L4J8 l4j8 = new L4J8(SecretFile.CREDS); @Test - public void testRateLimit() throws InterruptedException + public void testRateLimitThreaded() { - ExecutorService pool = Executors.newFixedThreadPool(8); - pool.submit(() -> - { - for (int i2 = 0; i2 < 30; i2++) - { - Summoner ignore = l4j8.getSummonerAPI().getSummonerByAccount(Platform.EUW1, Constants.TEST_ACCOUNT_IDS[0]); - } - }); - - pool.shutdown(); - pool.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); + try + { + ExecutorService pool = Executors.newFixedThreadPool(8); + for (int i2 = 0; i2 < 130; i2++) + { + pool.execute(() -> l4j8.getSummonerAPI().getSummonerByAccount(Platform.EUW1, Constants.TEST_ACCOUNT_IDS[0])); + } + pool.shutdown(); + pool.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); + } catch (InterruptedException e) + { + e.printStackTrace(); + } } @Test - public void testRatelimit() + public void testRateLimit() { final L4J8 test = new L4J8(SecretFile.CREDS); - for (int i2 = 0; i2 < 120; i2++) + for (int i2 = 0; i2 < 130; i2++) { Summoner ignore = l4j8.getSummonerAPI().getSummonerByAccount(Platform.EUW1, Constants.TEST_ACCOUNT_IDS[0]); }