Delete src/main/java/net/viper/status/ratelimit/GlobalRateLimitFramework.java via Git Manager GUI
This commit is contained in:
@@ -1,119 +0,0 @@
|
|||||||
package net.viper.status.ratelimit;
|
|
||||||
|
|
||||||
import java.util.ArrayDeque;
|
|
||||||
import java.util.Deque;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gemeinsames Rate-Limit-Framework fuer mehrere Module.
|
|
||||||
*/
|
|
||||||
public final class GlobalRateLimitFramework {
|
|
||||||
|
|
||||||
private static final GlobalRateLimitFramework INSTANCE = new GlobalRateLimitFramework();
|
|
||||||
|
|
||||||
private final Map<String, Bucket> buckets = new ConcurrentHashMap<String, Bucket>();
|
|
||||||
|
|
||||||
private GlobalRateLimitFramework() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public static GlobalRateLimitFramework getInstance() {
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Result check(String scope, String actorId, Rule rule) {
|
|
||||||
return check(scope, actorId, rule, System.currentTimeMillis());
|
|
||||||
}
|
|
||||||
|
|
||||||
public Result check(String scope, String actorId, Rule rule, long now) {
|
|
||||||
if (rule == null || !rule.enabled || scope == null || scope.isEmpty() || actorId == null || actorId.isEmpty()) {
|
|
||||||
return Result.allowed(0, 0L);
|
|
||||||
}
|
|
||||||
|
|
||||||
String key = scope + ":" + actorId;
|
|
||||||
Bucket bucket = buckets.computeIfAbsent(key, k -> new Bucket());
|
|
||||||
|
|
||||||
synchronized (bucket) {
|
|
||||||
if (bucket.blockedUntil > now) {
|
|
||||||
return Result.blocked(Math.max(0L, bucket.blockedUntil - now), bucket.hits.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
long minTs = now - Math.max(1L, rule.windowMs);
|
|
||||||
while (!bucket.hits.isEmpty() && bucket.hits.peekFirst() < minTs) {
|
|
||||||
bucket.hits.pollFirst();
|
|
||||||
}
|
|
||||||
|
|
||||||
bucket.hits.addLast(now);
|
|
||||||
|
|
||||||
if (bucket.hits.size() > Math.max(1, rule.maxActions)) {
|
|
||||||
long blockMs = Math.max(1L, rule.blockMs);
|
|
||||||
bucket.blockedUntil = now + blockMs;
|
|
||||||
return Result.blocked(blockMs, bucket.hits.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result.allowed(bucket.hits.size(), 0L);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearActor(String actorId) {
|
|
||||||
if (actorId == null || actorId.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (String key : buckets.keySet()) {
|
|
||||||
if (key.endsWith(":" + actorId)) {
|
|
||||||
buckets.remove(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class Rule {
|
|
||||||
public final boolean enabled;
|
|
||||||
public final long windowMs;
|
|
||||||
public final int maxActions;
|
|
||||||
public final long blockMs;
|
|
||||||
|
|
||||||
public Rule(boolean enabled, long windowMs, int maxActions, long blockMs) {
|
|
||||||
this.enabled = enabled;
|
|
||||||
this.windowMs = Math.max(1L, windowMs);
|
|
||||||
this.maxActions = Math.max(1, maxActions);
|
|
||||||
this.blockMs = Math.max(1L, blockMs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class Result {
|
|
||||||
private final boolean blocked;
|
|
||||||
private final int currentHits;
|
|
||||||
private final long remainingBlockMs;
|
|
||||||
|
|
||||||
private Result(boolean blocked, int currentHits, long remainingBlockMs) {
|
|
||||||
this.blocked = blocked;
|
|
||||||
this.currentHits = Math.max(0, currentHits);
|
|
||||||
this.remainingBlockMs = Math.max(0L, remainingBlockMs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Result blocked(long remainingBlockMs, int currentHits) {
|
|
||||||
return new Result(true, currentHits, remainingBlockMs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Result allowed(int currentHits, long remainingBlockMs) {
|
|
||||||
return new Result(false, currentHits, remainingBlockMs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isBlocked() {
|
|
||||||
return blocked;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getCurrentHits() {
|
|
||||||
return currentHits;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getRemainingBlockMs() {
|
|
||||||
return remainingBlockMs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class Bucket {
|
|
||||||
final Deque<Long> hits = new ArrayDeque<Long>();
|
|
||||||
long blockedUntil = 0L;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user