Skip to content

Instantly share code, notes, and snippets.

@rndstr
Created January 25, 2014 12:28
Show Gist options
  • Save rndstr/8615632 to your computer and use it in GitHub Desktop.
Save rndstr/8615632 to your computer and use it in GitHub Desktop.
import android.util.Log;
import java.util.Arrays;
/**
* Sample usage:
*
* class MyApp extends Application {
* private Api sApi;
* private RequestLimiter sRequestlimiter = new RequestLimiter(5, 1000);
*
* public static synchronized Api api() {
* if (sApi == null) {
* sApi = new Api();
* }
*
* sRequestLimiter.nextRequest();
* return sApi;
* }
*
* public static Api apiWithoutRequest() {
* return sApi;
* }
* }
*
* @author Roland Schilter <roli@schilter.me>
*/
public class RequestLimiter {
protected int mRateLimitCount;
protected int mRateLimitMillis;
protected long[] mRequestTimes;
/**
* Index of last recorded time
*/
protected int mRequestIndex = 0;
protected long mRequestCount = 0;
/**
* @param rateLimitCount How many requests
* @param rateLimitMillis In how much time
*/
public RequestLimiter(int rateLimitCount, int rateLimitMillis) {
mRateLimitCount = rateLimitCount;
mRateLimitMillis = rateLimitMillis;
mRequestTimes = new long[rateLimitCount];
Arrays.fill(mRequestTimes, 0);
}
/**
* In case of limit exceedance we wait the required time and then record this request
*/
public void nextRequest() {
waitRequest();
recordRequest();
}
protected void recordRequest() {
mRequestIndex = (mRequestIndex + 1) % mRateLimitCount;
mRequestTimes[mRequestIndex] = System.currentTimeMillis();
mRequestCount += 1;
}
protected void waitRequest() {
// verify that time since oldest request is more than rateLimitSeconds
int oldestIndex = (mRequestIndex + 1) % mRateLimitCount;
long sinceOldestRequest = System.currentTimeMillis() - mRequestTimes[oldestIndex];
// if time since oldest request (keeping only track of rate limited count times) is longer than
// the rate limit then we exceeded it
if (sinceOldestRequest < mRateLimitMillis) {
long pause = mRateLimitMillis - sinceOldestRequest;
Log.i(getClass().getName(), "Rate limit exceeded, pausing for " + pause + "ms");
if (pause > mRateLimitMillis) {
// somebody must have been screwing with the date/time on the phone
// just wait the max time and reset times
Arrays.fill(mRequestTimes, 0);
pause = mRateLimitMillis;
}
try {
Thread.sleep(pause);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment