Skip to content

Commit

Permalink
Fix ratelimiter not being updated properly
Browse files Browse the repository at this point in the history
  • Loading branch information
stelar7 committed Aug 9, 2017
1 parent a5c26b8 commit c2c7795
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 87 deletions.
143 changes: 73 additions & 70 deletions src/main/java/no/stelar7/api/l4j8/basic/calling/DataCallBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -63,90 +62,95 @@ 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());
System.err.println("Response Data:" + response.getResponseData());
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<Enum, RateLimiter> limits = DataCall.getLimiter().get(platform);
Expand Down Expand Up @@ -314,17 +318,16 @@ private void createRatelimiterIfMissing(String methodA, Enum platform, Enum endp
{
Map<Enum, RateLimiter> 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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
}
Expand Down

0 comments on commit c2c7795

Please sign in to comment.