Switch all Guava Cache uses to Caffeine
This commit is contained in:
@@ -17,8 +17,8 @@
|
|||||||
|
|
||||||
package com.velocitypowered.proxy.network.netty;
|
package com.velocitypowered.proxy.network.netty;
|
||||||
|
|
||||||
import com.google.common.cache.Cache;
|
import com.github.benmanes.caffeine.cache.Cache;
|
||||||
import com.google.common.cache.CacheBuilder;
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||||
import io.netty.resolver.AddressResolver;
|
import io.netty.resolver.AddressResolver;
|
||||||
@@ -62,7 +62,7 @@ public final class SeparatePoolInetNameResolver extends InetNameResolver {
|
|||||||
.setDaemon(true)
|
.setDaemon(true)
|
||||||
.build());
|
.build());
|
||||||
this.delegate = new DefaultNameResolver(executor);
|
this.delegate = new DefaultNameResolver(executor);
|
||||||
this.cache = CacheBuilder.newBuilder()
|
this.cache = Caffeine.newBuilder()
|
||||||
.expireAfterWrite(30, TimeUnit.SECONDS)
|
.expireAfterWrite(30, TimeUnit.SECONDS)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
@@ -20,8 +20,8 @@ package com.velocitypowered.proxy.protocol.netty;
|
|||||||
import static com.velocitypowered.api.event.query.ProxyQueryEvent.QueryType.BASIC;
|
import static com.velocitypowered.api.event.query.ProxyQueryEvent.QueryType.BASIC;
|
||||||
import static com.velocitypowered.api.event.query.ProxyQueryEvent.QueryType.FULL;
|
import static com.velocitypowered.api.event.query.ProxyQueryEvent.QueryType.FULL;
|
||||||
|
|
||||||
import com.google.common.cache.Cache;
|
import com.github.benmanes.caffeine.cache.Cache;
|
||||||
import com.google.common.cache.CacheBuilder;
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.velocitypowered.api.event.query.ProxyQueryEvent;
|
import com.velocitypowered.api.event.query.ProxyQueryEvent;
|
||||||
import com.velocitypowered.api.network.ProtocolVersion;
|
import com.velocitypowered.api.network.ProtocolVersion;
|
||||||
@@ -73,7 +73,7 @@ public class GameSpyQueryHandler extends SimpleChannelInboundHandler<DatagramPac
|
|||||||
"hostip"
|
"hostip"
|
||||||
);
|
);
|
||||||
|
|
||||||
private final Cache<InetAddress, Integer> sessions = CacheBuilder.newBuilder()
|
private final Cache<InetAddress, Integer> sessions = Caffeine.newBuilder()
|
||||||
.expireAfterWrite(30, TimeUnit.SECONDS)
|
.expireAfterWrite(30, TimeUnit.SECONDS)
|
||||||
.build();
|
.build();
|
||||||
private final SecureRandom random;
|
private final SecureRandom random;
|
||||||
|
@@ -17,35 +17,33 @@
|
|||||||
|
|
||||||
package com.velocitypowered.proxy.util.ratelimit;
|
package com.velocitypowered.proxy.util.ratelimit;
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Cache;
|
||||||
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
|
import com.github.benmanes.caffeine.cache.Ticker;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.base.Ticker;
|
|
||||||
import com.google.common.cache.Cache;
|
|
||||||
import com.google.common.cache.CacheBuilder;
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple rate-limiter based on a Guava {@link Cache}.
|
* A simple rate-limiter based on a Caffeine {@link Cache}.
|
||||||
*/
|
*/
|
||||||
public class GuavaCacheRatelimiter implements Ratelimiter {
|
public class CaffeineCacheRatelimiter implements Ratelimiter {
|
||||||
|
|
||||||
private final Cache<InetAddress, Long> expiringCache;
|
private final Cache<InetAddress, Long> expiringCache;
|
||||||
private final long timeoutNanos;
|
private final long timeoutNanos;
|
||||||
|
|
||||||
GuavaCacheRatelimiter(long time, TimeUnit unit) {
|
CaffeineCacheRatelimiter(long time, TimeUnit unit) {
|
||||||
this(time, unit, Ticker.systemTicker());
|
this(time, unit, Ticker.systemTicker());
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
GuavaCacheRatelimiter(long time, TimeUnit unit, Ticker ticker) {
|
CaffeineCacheRatelimiter(long time, TimeUnit unit, Ticker ticker) {
|
||||||
Preconditions.checkNotNull(unit, "unit");
|
Preconditions.checkNotNull(unit, "unit");
|
||||||
Preconditions.checkNotNull(ticker, "ticker");
|
Preconditions.checkNotNull(ticker, "ticker");
|
||||||
this.timeoutNanos = unit.toNanos(time);
|
this.timeoutNanos = unit.toNanos(time);
|
||||||
this.expiringCache = CacheBuilder.newBuilder()
|
this.expiringCache = Caffeine.newBuilder()
|
||||||
.ticker(ticker)
|
.ticker(ticker)
|
||||||
.concurrencyLevel(Runtime.getRuntime().availableProcessors())
|
|
||||||
.expireAfterWrite(time, unit)
|
.expireAfterWrite(time, unit)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
@@ -60,13 +58,7 @@ public class GuavaCacheRatelimiter implements Ratelimiter {
|
|||||||
public boolean attempt(InetAddress address) {
|
public boolean attempt(InetAddress address) {
|
||||||
Preconditions.checkNotNull(address, "address");
|
Preconditions.checkNotNull(address, "address");
|
||||||
long expectedNewValue = System.nanoTime() + timeoutNanos;
|
long expectedNewValue = System.nanoTime() + timeoutNanos;
|
||||||
long last;
|
long last = expiringCache.get(address, (address1) -> expectedNewValue);
|
||||||
try {
|
|
||||||
last = expiringCache.get(address, () -> expectedNewValue);
|
|
||||||
} catch (ExecutionException e) {
|
|
||||||
// It should be impossible for this to fail.
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
return expectedNewValue == last;
|
return expectedNewValue == last;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -29,7 +29,7 @@ public final class Ratelimiters {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Ratelimiter createWithMilliseconds(long ms) {
|
public static Ratelimiter createWithMilliseconds(long ms) {
|
||||||
return ms <= 0 ? NoopCacheRatelimiter.INSTANCE : new GuavaCacheRatelimiter(ms,
|
return ms <= 0 ? NoopCacheRatelimiter.INSTANCE : new CaffeineCacheRatelimiter(ms,
|
||||||
TimeUnit.MILLISECONDS);
|
TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,17 +20,17 @@ package com.velocitypowered.proxy.util.ratelimit;
|
|||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
import com.google.common.base.Ticker;
|
import com.github.benmanes.caffeine.cache.Ticker;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
class GuavaCacheRatelimiterTest {
|
class CaffeineCacheRatelimiterTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void attemptZero() {
|
void attemptZero() {
|
||||||
Ratelimiter noRatelimiter = new GuavaCacheRatelimiter(0, TimeUnit.MILLISECONDS);
|
Ratelimiter noRatelimiter = new CaffeineCacheRatelimiter(0, TimeUnit.MILLISECONDS);
|
||||||
assertTrue(noRatelimiter.attempt(InetAddress.getLoopbackAddress()));
|
assertTrue(noRatelimiter.attempt(InetAddress.getLoopbackAddress()));
|
||||||
assertTrue(noRatelimiter.attempt(InetAddress.getLoopbackAddress()));
|
assertTrue(noRatelimiter.attempt(InetAddress.getLoopbackAddress()));
|
||||||
}
|
}
|
||||||
@@ -39,13 +39,8 @@ class GuavaCacheRatelimiterTest {
|
|||||||
void attemptOne() {
|
void attemptOne() {
|
||||||
long base = System.nanoTime();
|
long base = System.nanoTime();
|
||||||
AtomicLong extra = new AtomicLong();
|
AtomicLong extra = new AtomicLong();
|
||||||
Ticker testTicker = new Ticker() {
|
Ticker testTicker = () -> base + extra.get();
|
||||||
@Override
|
Ratelimiter ratelimiter = new CaffeineCacheRatelimiter(1000, TimeUnit.MILLISECONDS, testTicker);
|
||||||
public long read() {
|
|
||||||
return base + extra.get();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Ratelimiter ratelimiter = new GuavaCacheRatelimiter(1000, TimeUnit.MILLISECONDS, testTicker);
|
|
||||||
assertTrue(ratelimiter.attempt(InetAddress.getLoopbackAddress()));
|
assertTrue(ratelimiter.attempt(InetAddress.getLoopbackAddress()));
|
||||||
assertFalse(ratelimiter.attempt(InetAddress.getLoopbackAddress()));
|
assertFalse(ratelimiter.attempt(InetAddress.getLoopbackAddress()));
|
||||||
extra.addAndGet(TimeUnit.SECONDS.toNanos(2));
|
extra.addAndGet(TimeUnit.SECONDS.toNanos(2));
|
Reference in New Issue
Block a user