Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/main/java/org/sputnik/ratelimit/domain/CanDoResponse.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
package org.sputnik.ratelimit.domain;

public record CanDoResponse(boolean canDo, long waitMillis, Reason reason, long eventsIntents) {
public record CanDoResponse(boolean canDo, long waitMillis, Reason reason, long eventAttempts) {

public enum Reason {INVALID_REQUEST, TOO_MANY_EVENTS}

public static CanDoResponse success(long currentIntents) {
return new CanDoResponse(true, 0, null, currentIntents);
public static CanDoResponse success(long currentAttempts) {
return new CanDoResponse(true, 0, null, currentAttempts);
}

public static CanDoResponse invalidRequest() {
return new CanDoResponse(false, 0, Reason.INVALID_REQUEST, 0);
}

public static CanDoResponse tooMany(long waitMillis, long intents) {
return new CanDoResponse(false, waitMillis, Reason.TOO_MANY_EVENTS, intents);
public static CanDoResponse tooMany(long waitMillis, long attempts) {
return new CanDoResponse(false, waitMillis, Reason.TOO_MANY_EVENTS, attempts);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.sputnik.ratelimit.exeception;
package org.sputnik.ratelimit.exception;

public class DuplicatedEventKeyException extends RuntimeException {

Expand Down
18 changes: 9 additions & 9 deletions src/main/java/org/sputnik/ratelimit/service/RateLimiter.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import org.slf4j.LoggerFactory;
import org.sputnik.ratelimit.dao.EventsRedisRepository;
import org.sputnik.ratelimit.domain.CanDoResponse;
import org.sputnik.ratelimit.exeception.DuplicatedEventKeyException;
import org.sputnik.ratelimit.exception.DuplicatedEventKeyException;
import org.sputnik.ratelimit.util.EventConfig;
import org.sputnik.ratelimit.util.Hasher;
import redis.clients.jedis.JedisPool;
Expand Down Expand Up @@ -80,24 +80,24 @@ public CanDoResponse canDoEvent(String eventId, String key) {
String hashedKey = hashText(key);
EventConfig eventConfig = eventsConfig.get(eventId);
Duration eventTime = eventConfig.minTime();
long eventMaxIntents = eventConfig.maxIntents();
long eventMaxAttempts = eventConfig.maxAttempts();
Instant now = Instant.now();
eventsRedisRepository.removeEventsOlderThan(eventId, hashedKey, now.minus(eventTime));
long eventIntents = eventsRedisRepository.getEventsCount(eventId, hashedKey);
long eventAttempts = eventsRedisRepository.getEventsCount(eventId, hashedKey);

if (eventIntents >= eventMaxIntents) {
if (eventAttempts >= eventMaxAttempts) {
logger.debug("Checking dates");
Instant firstDate = eventsRedisRepository.getOldestEvent(eventId, hashedKey);
if (firstDate == null) {
logger.info("Event [{}] could be performed [{}/{}]", eventId, eventIntents, eventMaxIntents);
response = CanDoResponse.success(eventIntents);
logger.info("Event [{}] could be performed [{}/{}]", eventId, eventAttempts, eventMaxAttempts);
response = CanDoResponse.success(eventAttempts);
} else {
long millisDifference = ChronoUnit.MILLIS.between(firstDate, now);
response = CanDoResponse.tooMany(Math.max(0, eventTime.toMillis() - millisDifference), eventIntents);
response = CanDoResponse.tooMany(Math.max(0, eventTime.toMillis() - millisDifference), eventAttempts);
}
} else {
logger.info("Event [{}] could be performed [{}/{}]", eventId, eventIntents, eventMaxIntents);
response = CanDoResponse.success(eventIntents);
logger.info("Event [{}] could be performed [{}/{}]", eventId, eventAttempts, eventMaxAttempts);
response = CanDoResponse.success(eventAttempts);
}
} else {
response = CanDoResponse.invalidRequest();
Expand Down
10 changes: 5 additions & 5 deletions src/main/java/org/sputnik/ratelimit/util/EventConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@
import java.util.Objects;

/**
* Immutable event configuration. maxIntents: max events allowed inside minTime sliding window.
* Immutable event configuration. maxAttempts: max events allowed inside minTime sliding window.
*/
public record EventConfig(String eventId, long maxIntents, Duration minTime) {
public record EventConfig(String eventId, long maxAttempts, Duration minTime) {

public EventConfig {
if (eventId == null || eventId.isBlank()) {
throw new IllegalArgumentException("eventId must not be blank");
}
if (maxIntents <= 0) {
throw new IllegalArgumentException("maxIntents must be > 0");
if (maxAttempts <= 0) {
throw new IllegalArgumentException("maxAttempts must be > 0");
}
Objects.requireNonNull(minTime, "minTime");
if (minTime.isZero() || minTime.isNegative()) {
throw new IllegalArgumentException("minTime must be positive");
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import org.junit.jupiter.api.Test;
import org.sputnik.ratelimit.domain.CanDoResponse;
import org.sputnik.ratelimit.domain.CanDoResponse.Reason;
import org.sputnik.ratelimit.exeception.DuplicatedEventKeyException;
import org.sputnik.ratelimit.exception.DuplicatedEventKeyException;
import org.sputnik.ratelimit.util.EventConfig;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
Expand Down
Loading