mirror of
https://github.com/signalapp/Signal-Server
synced 2026-04-20 03:28:04 +01:00
Remove an unused rate limiter
This commit is contained in:
committed by
Chris Eager
parent
f3457502a6
commit
3a1c716c73
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.limits;
|
||||
|
||||
import java.time.Duration;
|
||||
import org.whispersystems.textsecuregcm.configuration.RateLimitsConfiguration.CardinalityRateLimitConfiguration;
|
||||
import org.whispersystems.textsecuregcm.controllers.RateLimitExceededException;
|
||||
import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster;
|
||||
|
||||
/**
|
||||
* A cardinality rate limiter prevents an actor from taking some action if that actor has attempted to take that action
|
||||
* on too many targets in a fixed period of time. Behind the scenes, we estimate the target count using a
|
||||
* hyper-log-log data structure; as a consequence, the number of targets is an approximation, and this rate limiter
|
||||
* should not be used in cases where precise time or target limits are required.
|
||||
*/
|
||||
public class CardinalityRateLimiter {
|
||||
|
||||
private final FaultTolerantRedisCluster cacheCluster;
|
||||
|
||||
private final String name;
|
||||
|
||||
private final Duration ttl;
|
||||
private final int defaultMaxCardinality;
|
||||
|
||||
public CardinalityRateLimiter(final FaultTolerantRedisCluster cacheCluster, final String name, final Duration ttl, final int defaultMaxCardinality) {
|
||||
this.cacheCluster = cacheCluster;
|
||||
|
||||
this.name = name;
|
||||
|
||||
this.ttl = ttl;
|
||||
this.defaultMaxCardinality = defaultMaxCardinality;
|
||||
}
|
||||
|
||||
public void validate(final String key, final String target, final int maxCardinality) throws RateLimitExceededException {
|
||||
|
||||
final boolean rateLimitExceeded = cacheCluster.withCluster(connection -> {
|
||||
final String hllKey = getHllKey(key);
|
||||
|
||||
final boolean changed = connection.sync().pfadd(hllKey, target) == 1;
|
||||
final long cardinality = connection.sync().pfcount(hllKey);
|
||||
|
||||
final boolean mayNeedExpiration = changed && cardinality == 1;
|
||||
|
||||
// If the set already existed, we can assume it already had an expiration time and can save a round trip by
|
||||
// skipping the ttl check.
|
||||
if (mayNeedExpiration && connection.sync().ttl(hllKey) == -1) {
|
||||
connection.sync().expire(hllKey, ttl.toSeconds());
|
||||
}
|
||||
|
||||
return cardinality > maxCardinality;
|
||||
});
|
||||
|
||||
if (rateLimitExceeded) {
|
||||
long remainingTtl = getRemainingTtl(key);
|
||||
throw new RateLimitExceededException(remainingTtl >= 0 ? Duration.ofSeconds(remainingTtl) : null);
|
||||
}
|
||||
}
|
||||
|
||||
private String getHllKey(final String key) {
|
||||
return "hll_rate_limit::" + name + "::" + key;
|
||||
}
|
||||
|
||||
public Duration getInitialTtl() {
|
||||
return ttl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the remaining ttl for the specified key
|
||||
*
|
||||
* @param key with timeout to check
|
||||
* @return the ttl, or negative in the case of error
|
||||
*/
|
||||
public long getRemainingTtl(final String key) {
|
||||
// ttl() returns -2 if key does not exist, -1 if key has no expiration
|
||||
return cacheCluster.withCluster(connection -> connection.sync().ttl(getHllKey(key)));
|
||||
}
|
||||
|
||||
public int getDefaultMaxCardinality() {
|
||||
return defaultMaxCardinality;
|
||||
}
|
||||
|
||||
public boolean hasConfiguration(final CardinalityRateLimitConfiguration configuration) {
|
||||
return defaultMaxCardinality == configuration.getMaxCardinality() && ttl.equals(configuration.getTtl());
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user