Delete src/main/java/net/viper/status/ratelimit/GlobalRateLimitFramework.java via Git Manager GUI

This commit is contained in:
2026-05-24 19:43:38 +00:00
parent e3301e70c2
commit df58149d7e

View File

@@ -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;
}
}