Skip to content

Commit bfaad39

Browse files
committed
Updated RateLimiter to user per-user checks.
1 parent 8c8d9b0 commit bfaad39

File tree

1 file changed

+34
-24
lines changed

1 file changed

+34
-24
lines changed

RateLimiter.java

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,64 @@
11
package com.cunningdj.grokJava;
22

3-
import java.time.LocalDateTime;
4-
import java.util.LinkedList;
53
import java.time.Duration;
4+
import java.time.LocalDateTime;
65
import java.time.Month;
6+
import java.util.HashMap;
7+
import java.util.LinkedList;
78

9+
/*
10+
* RATE LIMITER - *SLIDING WINDOW ALGORITHM*
11+
*/
812
class RateLimiter {
9-
private LinkedList<LocalDateTime> dtQueue;
13+
private HashMap<String, LinkedList<LocalDateTime>> dtQueue;
1014
private final int SECONDS_PER_MINUTE = 60;
1115
public final int MAX_REQS_PER_MINUTE;
1216
// FOR TESTING ONLY (otherwise null)
1317
private final LocalDateTime CURRENT_DT_OVERRIDE;
1418

1519
public RateLimiter(int maxReqsPerMinute) {
16-
this.dtQueue = new LinkedList<>();
20+
this.dtQueue = new HashMap<>();
1721
this.MAX_REQS_PER_MINUTE = maxReqsPerMinute;
1822
this.CURRENT_DT_OVERRIDE = null;
1923
}
2024

21-
private RateLimiter(int maxReqsPerMinute, LocalDateTime currentDtOverride) {
22-
// FOR TESTING ONLY
23-
this.dtQueue = new LinkedList<>();
24-
this.MAX_REQS_PER_MINUTE = maxReqsPerMinute;
25-
this.CURRENT_DT_OVERRIDE = currentDtOverride;
26-
}
27-
2825
// MAIN
2926
public static void main(String[] args) {
3027
Tester tester = new Tester();
3128
String testTitle="";
3229

3330
// TEST CLASS METHODS HERE USING TESTER CLASS
3431
testTitle = "RATE_LIMITER";
32+
String TEST_USER = "El Duderino";
33+
String OTHER_TEST_USER = "Mr. Lebowski";
3534
RateLimiter rl = new RateLimiter(3);
36-
tester.isTrue(rl.newRequest(new Request(RateLimiter.makeTestTime(10, 0))), testTitle);
37-
tester.isTrue(rl.newRequest(new Request(RateLimiter.makeTestTime(10, 20))), testTitle);
38-
tester.isTrue(rl.newRequest(new Request(RateLimiter.makeTestTime(10, 40))), testTitle);
35+
tester.isTrue(rl.newRequest(new Request(TEST_USER, RateLimiter.makeTestTime(10, 0))), testTitle);
36+
tester.isTrue(rl.newRequest(new Request(TEST_USER, RateLimiter.makeTestTime(10, 20))), testTitle);
37+
tester.isTrue(rl.newRequest(new Request(TEST_USER, RateLimiter.makeTestTime(10, 40))), testTitle);
3938
// False, and doesn't add it to the queue
40-
tester.isFalse(rl.newRequest(new Request(RateLimiter.makeTestTime(10, 59))), testTitle);
39+
tester.isFalse(rl.newRequest(new Request(TEST_USER, RateLimiter.makeTestTime(10, 59))), testTitle);
40+
// Different user; shouldn't fail
41+
tester.isFalse(rl.newRequest(new Request(OTHER_TEST_USER, RateLimiter.makeTestTime(10, 59))), testTitle);
4142
// True; Skipoed the 10:59 request, and 10:00 request is now > 60s old, leaving 2 within the window during check
42-
tester.isTrue(rl.newRequest(new Request(RateLimiter.makeTestTime(11, 01))), testTitle);
43+
tester.isTrue(rl.newRequest(new Request(TEST_USER, RateLimiter.makeTestTime(11, 01))), testTitle);
4344
}
4445

4546
// PUBLIC
4647
public boolean newRequest(Request req) {
47-
if (dtQueue.size() == MAX_REQS_PER_MINUTE) {
48-
while (dtQueue.size() > 0
49-
&& Duration.between(dtQueue.peek(), req.dt).getSeconds() > SECONDS_PER_MINUTE) {
50-
dtQueue.poll();
48+
if (dtQueue.containsKey(req.user)) {
49+
if (dtQueue.get(req.user).size() == MAX_REQS_PER_MINUTE) {
50+
while (dtQueue.get(req.user).size() > 0
51+
&& Duration.between(dtQueue.get(req.user).peek(), req.dt).getSeconds() > SECONDS_PER_MINUTE) {
52+
dtQueue.get(req.user).poll();
53+
}
5154
}
55+
} else {
56+
LinkedList<LocalDateTime> userRequestQ = new LinkedList<>();
57+
dtQueue.put(req.user, userRequestQ);
5258
}
53-
if (dtQueue.size() < MAX_REQS_PER_MINUTE) {
54-
dtQueue.add(req.dt);
59+
60+
if (dtQueue.get(req.user).size() < MAX_REQS_PER_MINUTE) {
61+
dtQueue.get(req.user).add(req.dt);
5562
return true;
5663
} else {
5764
return false;
@@ -67,12 +74,15 @@ private static LocalDateTime makeTestTime(int minutes, int seconds) {
6774
// Request
6875
static class Request {
6976
public LocalDateTime dt;
70-
public Request() {
77+
public String user;
78+
public Request(String user) {
79+
80+
this.user = user;
7181
this.dt = LocalDateTime.now();
7282
}
7383

7484
// TESTING ONLY
75-
private Request(LocalDateTime dt) {
85+
private Request(String user, LocalDateTime dt) {
7686
this.dt = dt;
7787
}
7888
}

0 commit comments

Comments
 (0)