Created
December 15, 2018 21:27
-
-
Save JakubGraczyk/6d178a61bb81b9a98b95ce2d3d28cd33 to your computer and use it in GitHub Desktop.
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
package main; | |
import java.util.Date; | |
import java.util.concurrent.ConcurrentHashMap; | |
import java.util.concurrent.Semaphore; | |
import java.util.concurrent.TimeUnit; | |
public class RequestsLimiter { | |
private int maxNumberOFRequestsFromSingleUser; | |
private long waitTimeInMillis; | |
private Semaphore usersLimiter; | |
private Semaphore requestsLimiter; | |
private ConcurrentHashMap<String, Semaphore> requestsPerUserLimiter = new ConcurrentHashMap<>(); | |
public RequestsLimiter(int maxNumberOfUsers, int maxNumberOFRequestsPerUser, int maxNumberOfRequests, long waitTimeInMillis) { | |
usersLimiter = new Semaphore(maxNumberOfUsers); | |
this.maxNumberOFRequestsFromSingleUser = maxNumberOFRequestsPerUser; | |
requestsLimiter = new Semaphore(maxNumberOfRequests); | |
this.waitTimeInMillis = waitTimeInMillis; | |
} | |
public boolean work(String user) throws InterruptedException { | |
long startTime = new Date().getTime(); | |
if (tryLogin(user) && tryPassRequestFromUser(user, startTime) && trySendRequest(user, startTime)) { | |
TimeUnit.MILLISECONDS.sleep((int) (Math.random() * 2000)); | |
return true; | |
} else { | |
return false; | |
} | |
} | |
private boolean trySendRequest(String user, long startTime) throws InterruptedException { | |
try { | |
return checkIfRequestCanBeSend(startTime); | |
} finally { | |
requestsLimiter.release(); | |
} | |
} | |
private boolean tryPassRequestFromUser(String user, long startTime) throws InterruptedException { | |
try { | |
return checkIfUserCanGenerateRequest(user, startTime); | |
} finally { | |
releaseSlotForGivenUser(user); | |
} | |
} | |
private boolean tryLogin(String user) throws InterruptedException { | |
if (requestsPerUserLimiter.containsKey(user)) { | |
return true; | |
} else { | |
return usersLimiter.tryAcquire(waitTimeInMillis, TimeUnit.MILLISECONDS); | |
} | |
} | |
private boolean checkIfUserCanGenerateRequest(String user, long startTime) throws InterruptedException { | |
if (!requestsPerUserLimiter.containsKey(user)) | |
requestsPerUserLimiter.put(user, new Semaphore(maxNumberOFRequestsFromSingleUser)); | |
return requestsPerUserLimiter.get(user).tryAcquire(waitTimeInMillis - (new Date().getTime() - startTime), TimeUnit.MILLISECONDS); | |
} | |
private boolean checkIfRequestCanBeSend(long startTime) throws InterruptedException { | |
return requestsLimiter.tryAcquire(waitTimeInMillis - (new Date().getTime() - startTime), TimeUnit.MILLISECONDS); | |
} | |
private void releaseSlotForGivenUser(String user) { | |
requestsPerUserLimiter.get(user).release(); | |
if (requestsPerUserLimiter.get(user).availablePermits() == maxNumberOFRequestsFromSingleUser) { | |
requestsPerUserLimiter.remove(user); | |
usersLimiter.release(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment