-
-
Notifications
You must be signed in to change notification settings - Fork 181
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #475 from Bastian/improve-global-ratelimits
Add ratelimiter to allow custom hard-coded global ratelimits
- Loading branch information
Showing
9 changed files
with
206 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
85 changes: 85 additions & 0 deletions
85
javacord-api/src/main/java/org/javacord/api/util/ratelimit/LocalRatelimiter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
package org.javacord.api.util.ratelimit; | ||
|
||
/** | ||
* An implementation of {@code Ratelimiter} that allows simple local ratelimits. | ||
*/ | ||
public class LocalRatelimiter implements Ratelimiter { | ||
|
||
private volatile long nextResetNanos; | ||
private volatile int remainingQuota; | ||
|
||
private final int amount; | ||
private final int seconds; | ||
|
||
/** | ||
* Creates a new local ratelimiter. | ||
* | ||
* @param amount The amount available per reset interval. | ||
* @param seconds The time to wait until the available quota resets. | ||
*/ | ||
public LocalRatelimiter(int amount, int seconds) { | ||
this.amount = amount; | ||
this.seconds = seconds; | ||
} | ||
|
||
/** | ||
* Gets the amount available per reset interval. | ||
* | ||
* @return The amount. | ||
*/ | ||
public int getAmount() { | ||
return amount; | ||
} | ||
|
||
/** | ||
* Gets the time to wait until the available quota resets in seconds. | ||
* | ||
* @return The time to wait until the available quota resets. | ||
*/ | ||
public int getSeconds() { | ||
return seconds; | ||
} | ||
|
||
/** | ||
* Gets the next time the quota resets. | ||
* | ||
* <p>Use {@link System#nanoTime()} to calculate the absolute difference. | ||
* | ||
* @return The next time the quota resets. Can be in the past. | ||
*/ | ||
public long getNextResetNanos() { | ||
return nextResetNanos; | ||
} | ||
|
||
/** | ||
* Gets the remaining quota in the current reset interval. | ||
* | ||
* @return The remaining quota. | ||
*/ | ||
public int getRemainingQuota() { | ||
return remainingQuota; | ||
} | ||
|
||
@Override | ||
public synchronized void requestQuota() throws InterruptedException { | ||
if (remainingQuota <= 0) { | ||
// Wait until a new quota becomes available | ||
long sleepTime; | ||
while ((sleepTime = calculateSleepTime()) > 0) { // Sleep is unreliable, so we have to loop | ||
Thread.sleep(sleepTime); | ||
} | ||
} | ||
|
||
// Reset the limit when the last reset timestamp is past | ||
if (System.nanoTime() > nextResetNanos) { | ||
remainingQuota = amount; | ||
nextResetNanos = System.nanoTime() + seconds * 1_000_000_000L; | ||
} | ||
|
||
remainingQuota--; | ||
} | ||
|
||
private long calculateSleepTime() { | ||
return (nextResetNanos - System.nanoTime()) / 1_000_000; | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
javacord-api/src/main/java/org/javacord/api/util/ratelimit/Ratelimiter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package org.javacord.api.util.ratelimit; | ||
|
||
/** | ||
* Can be used to implement ratelimits. | ||
*/ | ||
public interface Ratelimiter { | ||
|
||
/** | ||
* Blocks the requesting thread until a quota becomes available. | ||
* | ||
* @throws InterruptedException if any thread has interrupted the current thread. | ||
* The interrupted status of the current thread is cleared when this exception is | ||
* thrown. | ||
*/ | ||
void requestQuota() throws InterruptedException; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.