Finalize rate limit unit inversion

This commit is contained in:
Jon Chambers 2023-05-22 11:44:56 -04:00 committed by Jon Chambers
parent 48d39dccbd
commit 91805caa9a
6 changed files with 64 additions and 112 deletions

View File

@ -7,27 +7,15 @@ package org.whispersystems.textsecuregcm.limits;
import javax.validation.constraints.AssertTrue; import javax.validation.constraints.AssertTrue;
import java.time.Duration; import java.time.Duration;
import java.util.Optional;
import java.util.OptionalDouble;
public record RateLimiterConfig(int bucketSize, OptionalDouble leakRatePerMinute, Optional<Duration> permitRegenerationDuration) { public record RateLimiterConfig(int bucketSize, Duration permitRegenerationDuration) {
public double leakRatePerMillis() { public double leakRatePerMillis() {
if (leakRatePerMinute.isPresent()) { return 1.0 / permitRegenerationDuration.toMillis();
return leakRatePerMinute.getAsDouble() / (60.0 * 1000.0);
} else {
return permitRegenerationDuration.map(duration -> 1.0 / duration.toMillis())
.orElseThrow(() -> new AssertionError("Configuration must have leak rate per minute or permit regeneration duration"));
}
}
@AssertTrue
public boolean hasExactlyOneRegenerationRate() {
return leakRatePerMinute.isPresent() ^ permitRegenerationDuration().isPresent();
} }
@AssertTrue @AssertTrue
public boolean hasPositiveRegenerationRate() { public boolean hasPositiveRegenerationRate() {
return leakRatePerMillis() > 0; return permitRegenerationDuration.toMillis() > 0;
} }
} }

View File

@ -9,8 +9,6 @@ import com.google.common.annotations.VisibleForTesting;
import java.time.Clock; import java.time.Clock;
import java.time.Duration; import java.time.Duration;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.OptionalDouble;
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration; import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration;
import org.whispersystems.textsecuregcm.redis.ClusterLuaScript; import org.whispersystems.textsecuregcm.redis.ClusterLuaScript;
import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster; import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster;
@ -19,36 +17,36 @@ import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager;
public class RateLimiters extends BaseRateLimiters<RateLimiters.For> { public class RateLimiters extends BaseRateLimiters<RateLimiters.For> {
public enum For implements RateLimiterDescriptor { public enum For implements RateLimiterDescriptor {
BACKUP_AUTH_CHECK("backupAuthCheck", false, new RateLimiterConfig(100, OptionalDouble.empty(), Optional.of(Duration.ofMinutes(15)))), BACKUP_AUTH_CHECK("backupAuthCheck", false, new RateLimiterConfig(100, Duration.ofSeconds(15))),
SMS_DESTINATION("smsDestination", false, new RateLimiterConfig(2, OptionalDouble.empty(), Optional.of(Duration.ofSeconds(30)))), SMS_DESTINATION("smsDestination", false, new RateLimiterConfig(2, Duration.ofMillis(500))),
VOICE_DESTINATION("voxDestination", false, new RateLimiterConfig(2, OptionalDouble.empty(), Optional.of(Duration.ofMinutes(2)))), VOICE_DESTINATION("voxDestination", false, new RateLimiterConfig(2, Duration.ofSeconds(2))),
VOICE_DESTINATION_DAILY("voxDestinationDaily", false, new RateLimiterConfig(10, OptionalDouble.empty(), Optional.of(Duration.ofMinutes(144)))), VOICE_DESTINATION_DAILY("voxDestinationDaily", false, new RateLimiterConfig(10, Duration.ofSeconds(144))),
SMS_VOICE_IP("smsVoiceIp", false, new RateLimiterConfig(1000, OptionalDouble.empty(), Optional.of(Duration.ofMillis(60)))), SMS_VOICE_IP("smsVoiceIp", false, new RateLimiterConfig(1000, Duration.ofMillis(1))),
SMS_VOICE_PREFIX("smsVoicePrefix", false, new RateLimiterConfig(1000, OptionalDouble.empty(), Optional.of(Duration.ofMillis(60)))), SMS_VOICE_PREFIX("smsVoicePrefix", false, new RateLimiterConfig(1000, Duration.ofMillis(1))),
VERIFY("verify", false, new RateLimiterConfig(6, OptionalDouble.empty(), Optional.of(Duration.ofSeconds(30)))), VERIFY("verify", false, new RateLimiterConfig(6, Duration.ofMillis(500))),
PIN("pin", false, new RateLimiterConfig(10, OptionalDouble.empty(), Optional.of(Duration.ofDays(1)))), PIN("pin", false, new RateLimiterConfig(10, Duration.ofMinutes(24))),
ATTACHMENT("attachmentCreate", false, new RateLimiterConfig(50, OptionalDouble.empty(), Optional.of(Duration.ofSeconds(1)))), ATTACHMENT("attachmentCreate", false, new RateLimiterConfig(50, Duration.ofMillis(20))),
PRE_KEYS("prekeys", false, new RateLimiterConfig(6, OptionalDouble.empty(), Optional.of(Duration.ofMinutes(10)))), PRE_KEYS("prekeys", false, new RateLimiterConfig(6, Duration.ofSeconds(10))),
MESSAGES("messages", false, new RateLimiterConfig(60, OptionalDouble.empty(), Optional.of(Duration.ofSeconds(1)))), MESSAGES("messages", false, new RateLimiterConfig(60, Duration.ofMillis(17))),
ALLOCATE_DEVICE("allocateDevice", false, new RateLimiterConfig(2, OptionalDouble.empty(), Optional.of(Duration.ofMinutes(2)))), ALLOCATE_DEVICE("allocateDevice", false, new RateLimiterConfig(2, Duration.ofSeconds(2))),
VERIFY_DEVICE("verifyDevice", false, new RateLimiterConfig(6, OptionalDouble.empty(), Optional.of(Duration.ofMinutes(10)))), VERIFY_DEVICE("verifyDevice", false, new RateLimiterConfig(6, Duration.ofSeconds(10))),
TURN("turnAllocate", false, new RateLimiterConfig(60, OptionalDouble.empty(), Optional.of(Duration.ofSeconds(1)))), TURN("turnAllocate", false, new RateLimiterConfig(60, Duration.ofMillis(17))),
PROFILE("profile", false, new RateLimiterConfig(4320, OptionalDouble.empty(), Optional.of(Duration.ofSeconds(20)))), PROFILE("profile", false, new RateLimiterConfig(4320, Duration.ofMillis(333))),
STICKER_PACK("stickerPack", false, new RateLimiterConfig(50, OptionalDouble.empty(), Optional.of(Duration.ofMinutes(72)))), STICKER_PACK("stickerPack", false, new RateLimiterConfig(50, Duration.ofSeconds(72))),
ART_PACK("artPack", false, new RateLimiterConfig(50, OptionalDouble.empty(), Optional.of(Duration.ofMinutes(72)))), ART_PACK("artPack", false, new RateLimiterConfig(50, Duration.ofSeconds(72))),
USERNAME_LOOKUP("usernameLookup", false, new RateLimiterConfig(100, OptionalDouble.empty(), Optional.of(Duration.ofMinutes(15)))), USERNAME_LOOKUP("usernameLookup", false, new RateLimiterConfig(100, Duration.ofSeconds(15))),
USERNAME_SET("usernameSet", false, new RateLimiterConfig(100, OptionalDouble.empty(), Optional.of(Duration.ofMinutes(15)))), USERNAME_SET("usernameSet", false, new RateLimiterConfig(100, Duration.ofSeconds(15))),
USERNAME_RESERVE("usernameReserve", false, new RateLimiterConfig(100, OptionalDouble.empty(), Optional.of(Duration.ofMinutes(15)))), USERNAME_RESERVE("usernameReserve", false, new RateLimiterConfig(100, Duration.ofSeconds(15))),
CHECK_ACCOUNT_EXISTENCE("checkAccountExistence", false, new RateLimiterConfig(1000, OptionalDouble.empty(), Optional.of(Duration.ofSeconds(3)))), CHECK_ACCOUNT_EXISTENCE("checkAccountExistence", false, new RateLimiterConfig(1000, Duration.ofMillis(60))),
REGISTRATION("registration", false, new RateLimiterConfig(6, OptionalDouble.empty(), Optional.of(Duration.ofSeconds(30)))), REGISTRATION("registration", false, new RateLimiterConfig(6, Duration.ofMillis(500))),
VERIFICATION_PUSH_CHALLENGE("verificationPushChallenge", false, new RateLimiterConfig(5, OptionalDouble.empty(), Optional.of(Duration.ofSeconds(30)))), VERIFICATION_PUSH_CHALLENGE("verificationPushChallenge", false, new RateLimiterConfig(5, Duration.ofMillis(500))),
VERIFICATION_CAPTCHA("verificationCaptcha", false, new RateLimiterConfig(10, OptionalDouble.empty(), Optional.of(Duration.ofSeconds(30)))), VERIFICATION_CAPTCHA("verificationCaptcha", false, new RateLimiterConfig(10, Duration.ofMillis(500))),
RATE_LIMIT_RESET("rateLimitReset", true, new RateLimiterConfig(2, OptionalDouble.empty(), Optional.of(Duration.ofHours(12)))), RATE_LIMIT_RESET("rateLimitReset", true, new RateLimiterConfig(2, Duration.ofMinutes(12))),
RECAPTCHA_CHALLENGE_ATTEMPT("recaptchaChallengeAttempt", true, new RateLimiterConfig(10, OptionalDouble.empty(), Optional.of(Duration.ofMinutes(144)))), RECAPTCHA_CHALLENGE_ATTEMPT("recaptchaChallengeAttempt", true, new RateLimiterConfig(10, Duration.ofSeconds(144))),
RECAPTCHA_CHALLENGE_SUCCESS("recaptchaChallengeSuccess", true, new RateLimiterConfig(2, OptionalDouble.empty(), Optional.of(Duration.ofHours(12)))), RECAPTCHA_CHALLENGE_SUCCESS("recaptchaChallengeSuccess", true, new RateLimiterConfig(2, Duration.ofMinutes(12))),
PUSH_CHALLENGE_ATTEMPT("pushChallengeAttempt", true, new RateLimiterConfig(10, OptionalDouble.empty(), Optional.of(Duration.ofMinutes(144)))), PUSH_CHALLENGE_ATTEMPT("pushChallengeAttempt", true, new RateLimiterConfig(10, Duration.ofSeconds(144))),
PUSH_CHALLENGE_SUCCESS("pushChallengeSuccess", true, new RateLimiterConfig(2, OptionalDouble.empty(), Optional.of(Duration.ofHours(12)))), PUSH_CHALLENGE_SUCCESS("pushChallengeSuccess", true, new RateLimiterConfig(2, Duration.ofMinutes(12))),
CREATE_CALL_LINK("createCallLink", false, new RateLimiterConfig(100, OptionalDouble.empty(), Optional.of(Duration.ofMinutes(15)))); CREATE_CALL_LINK("createCallLink", false, new RateLimiterConfig(100, Duration.ofSeconds(15)));
private final String id; private final String id;

View File

@ -18,7 +18,6 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.OptionalDouble;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -299,39 +298,19 @@ class DynamicConfigurationTest {
@Test @Test
void testParseLimits() throws JsonProcessingException { void testParseLimits() throws JsonProcessingException {
{ final String limitsConfig = REQUIRED_CONFIG.concat("""
final String limitsConfig = REQUIRED_CONFIG.concat(""" limits:
limits: rateLimitReset:
rateLimitReset: bucketSize: 17
bucketSize: 17 permitRegenerationDuration: PT4S
leakRatePerMinute: 44 """);
""");
final RateLimiterConfig resetRateLimiterConfig = final RateLimiterConfig resetRateLimiterConfig =
DynamicConfigurationManager.parseConfiguration(limitsConfig, DynamicConfiguration.class).orElseThrow() DynamicConfigurationManager.parseConfiguration(limitsConfig, DynamicConfiguration.class).orElseThrow()
.getLimits().get(RateLimiters.For.RATE_LIMIT_RESET.id()); .getLimits().get(RateLimiters.For.RATE_LIMIT_RESET.id());
assertThat(resetRateLimiterConfig.bucketSize()).isEqualTo(17); assertThat(resetRateLimiterConfig.bucketSize()).isEqualTo(17);
assertThat(resetRateLimiterConfig.leakRatePerMinute()).isEqualTo(OptionalDouble.of(44)); assertThat(resetRateLimiterConfig.permitRegenerationDuration()).isEqualTo(Duration.ofSeconds(4));
assertThat(resetRateLimiterConfig.permitRegenerationDuration()).isEmpty();
}
{
final String limitsConfig = REQUIRED_CONFIG.concat("""
limits:
rateLimitReset:
bucketSize: 17
permitRegenerationDuration: PT4S
""");
final RateLimiterConfig resetRateLimiterConfig =
DynamicConfigurationManager.parseConfiguration(limitsConfig, DynamicConfiguration.class).orElseThrow()
.getLimits().get(RateLimiters.For.RATE_LIMIT_RESET.id());
assertThat(resetRateLimiterConfig.bucketSize()).isEqualTo(17);
assertThat(resetRateLimiterConfig.leakRatePerMinute()).isEmpty();
assertThat(resetRateLimiterConfig.permitRegenerationDuration()).isEqualTo(Optional.of(Duration.ofSeconds(4)));
}
} }
@Test @Test

View File

@ -9,7 +9,6 @@ import org.junit.jupiter.api.Test;
import java.time.Duration; import java.time.Duration;
import java.util.Optional; import java.util.Optional;
import java.util.OptionalDouble;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
@ -17,24 +16,13 @@ class RateLimiterConfigTest {
@Test @Test
void leakRatePerMillis() { void leakRatePerMillis() {
assertEquals(0.001, new RateLimiterConfig(1, OptionalDouble.of(60), Optional.empty()).leakRatePerMillis()); assertEquals(0.001, new RateLimiterConfig(1, Duration.ofSeconds(1)).leakRatePerMillis());
assertEquals(0.001, new RateLimiterConfig(1, OptionalDouble.empty(), Optional.of(Duration.ofSeconds(1))).leakRatePerMillis());
}
@Test
void hasExactlyOneRegenerationRate() {
assertTrue(new RateLimiterConfig(1, OptionalDouble.of(1), Optional.empty()).hasExactlyOneRegenerationRate());
assertTrue(new RateLimiterConfig(1, OptionalDouble.empty(), Optional.of(Duration.ofSeconds(1))).hasExactlyOneRegenerationRate());
assertFalse(new RateLimiterConfig(1, OptionalDouble.of(1), Optional.of(Duration.ofSeconds(1))).hasExactlyOneRegenerationRate());
assertFalse(new RateLimiterConfig(1, OptionalDouble.empty(), Optional.empty()).hasExactlyOneRegenerationRate());
} }
@Test @Test
void isRegenerationRatePositive() { void isRegenerationRatePositive() {
assertTrue(new RateLimiterConfig(1, OptionalDouble.of(1), Optional.empty()).hasPositiveRegenerationRate()); assertTrue(new RateLimiterConfig(1, Duration.ofSeconds(1)).hasPositiveRegenerationRate());
assertTrue(new RateLimiterConfig(1, OptionalDouble.empty(), Optional.of(Duration.ofSeconds(1))).hasPositiveRegenerationRate()); assertFalse(new RateLimiterConfig(1, Duration.ZERO).hasPositiveRegenerationRate());
assertFalse(new RateLimiterConfig(1, OptionalDouble.of(-1), Optional.empty()).hasPositiveRegenerationRate()); assertFalse(new RateLimiterConfig(1, Duration.ofSeconds(-1)).hasPositiveRegenerationRate());
assertFalse(new RateLimiterConfig(1, OptionalDouble.empty(), Optional.of(Duration.ofSeconds(-1))).hasPositiveRegenerationRate());
assertFalse(new RateLimiterConfig(1, OptionalDouble.of(1 / 10), Optional.empty()).hasPositiveRegenerationRate());
} }
} }

View File

@ -16,10 +16,10 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import io.lettuce.core.RedisException; import io.lettuce.core.RedisException;
import io.lettuce.core.ScriptOutputType; import io.lettuce.core.ScriptOutputType;
import java.time.Clock; import java.time.Clock;
import java.time.Duration;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.OptionalDouble;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.extension.RegisterExtension;
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration; import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration;
@ -57,7 +57,7 @@ public class RateLimitersLuaScriptTest {
final RateLimiters.For descriptor = RateLimiters.For.REGISTRATION; final RateLimiters.For descriptor = RateLimiters.For.REGISTRATION;
final FaultTolerantRedisCluster redisCluster = REDIS_CLUSTER_EXTENSION.getRedisCluster(); final FaultTolerantRedisCluster redisCluster = REDIS_CLUSTER_EXTENSION.getRedisCluster();
final RateLimiters limiters = new RateLimiters( final RateLimiters limiters = new RateLimiters(
Map.of(descriptor.id(), new RateLimiterConfig(60, OptionalDouble.of(60), Optional.empty())), Map.of(descriptor.id(), new RateLimiterConfig(60, Duration.ofSeconds(1))),
dynamicConfig, dynamicConfig,
RateLimiters.defaultScript(redisCluster), RateLimiters.defaultScript(redisCluster),
redisCluster, redisCluster,
@ -74,7 +74,7 @@ public class RateLimitersLuaScriptTest {
final RateLimiters.For descriptor = RateLimiters.For.REGISTRATION; final RateLimiters.For descriptor = RateLimiters.For.REGISTRATION;
final FaultTolerantRedisCluster redisCluster = REDIS_CLUSTER_EXTENSION.getRedisCluster(); final FaultTolerantRedisCluster redisCluster = REDIS_CLUSTER_EXTENSION.getRedisCluster();
final RateLimiters limiters = new RateLimiters( final RateLimiters limiters = new RateLimiters(
Map.of(descriptor.id(), new RateLimiterConfig(60, OptionalDouble.of(60), Optional.empty())), Map.of(descriptor.id(), new RateLimiterConfig(60, Duration.ofSeconds(1))),
dynamicConfig, dynamicConfig,
RateLimiters.defaultScript(redisCluster), RateLimiters.defaultScript(redisCluster),
redisCluster, redisCluster,
@ -118,7 +118,7 @@ public class RateLimitersLuaScriptTest {
final RateLimiters.For descriptor = RateLimiters.For.REGISTRATION; final RateLimiters.For descriptor = RateLimiters.For.REGISTRATION;
final FaultTolerantRedisCluster redisCluster = REDIS_CLUSTER_EXTENSION.getRedisCluster(); final FaultTolerantRedisCluster redisCluster = REDIS_CLUSTER_EXTENSION.getRedisCluster();
final RateLimiters limiters = new RateLimiters( final RateLimiters limiters = new RateLimiters(
Map.of(descriptor.id(), new RateLimiterConfig(1000, OptionalDouble.of(60), Optional.empty())), Map.of(descriptor.id(), new RateLimiterConfig(1000, Duration.ofSeconds(1))),
dynamicConfig, dynamicConfig,
RateLimiters.defaultScript(redisCluster), RateLimiters.defaultScript(redisCluster),
redisCluster, redisCluster,
@ -169,7 +169,7 @@ public class RateLimitersLuaScriptTest {
final RateLimiters.For descriptor = RateLimiters.For.REGISTRATION; final RateLimiters.For descriptor = RateLimiters.For.REGISTRATION;
final FaultTolerantRedisCluster redisCluster = mock(FaultTolerantRedisCluster.class); final FaultTolerantRedisCluster redisCluster = mock(FaultTolerantRedisCluster.class);
final RateLimiters limiters = new RateLimiters( final RateLimiters limiters = new RateLimiters(
Map.of(descriptor.id(), new RateLimiterConfig(1000, OptionalDouble.of(60), Optional.empty())), Map.of(descriptor.id(), new RateLimiterConfig(1000, Duration.ofSeconds(1))),
dynamicConfig, dynamicConfig,
RateLimiters.defaultScript(redisCluster), RateLimiters.defaultScript(redisCluster),
redisCluster, redisCluster,

View File

@ -12,11 +12,10 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import java.time.Duration;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.OptionalDouble;
import javax.validation.Valid; import javax.validation.Valid;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -46,20 +45,20 @@ public class RateLimitersTest {
limits: limits:
smsVoicePrefix: smsVoicePrefix:
bucketSize: 150 bucketSize: 150
leakRatePerMinute: 10 permitRegenerationDuration: PT6S
unexpected: unexpected:
bucketSize: 4 bucketSize: 4
leakRatePerMinute: 2 permitRegenerationDuration: PT30S
"""; """;
private static final String GOOD_YAML = """ private static final String GOOD_YAML = """
limits: limits:
smsVoicePrefix: smsVoicePrefix:
bucketSize: 150 bucketSize: 150
leakRatePerMinute: 10 permitRegenerationDuration: PT6S
attachmentCreate: attachmentCreate:
bucketSize: 4 bucketSize: 4
leakRatePerMinute: 2 permitRegenerationDuration: PT30S
rateLimitPolicy: rateLimitPolicy:
failOpen: true failOpen: true
"""; """;
@ -117,9 +116,9 @@ public class RateLimitersTest {
@Test @Test
void testChangingConfiguration() { void testChangingConfiguration() {
final RateLimiterConfig initialRateLimiterConfig = new RateLimiterConfig(4, OptionalDouble.of(1), Optional.empty()); final RateLimiterConfig initialRateLimiterConfig = new RateLimiterConfig(4, Duration.ofMinutes(1));
final RateLimiterConfig updatedRateLimiterCongig = new RateLimiterConfig(17, OptionalDouble.of(19), Optional.empty()); final RateLimiterConfig updatedRateLimiterCongig = new RateLimiterConfig(17, Duration.ofSeconds(3));
final RateLimiterConfig baseConfig = new RateLimiterConfig(1, OptionalDouble.of(1), Optional.empty()); final RateLimiterConfig baseConfig = new RateLimiterConfig(1, Duration.ofMinutes(1));
final Map<String, RateLimiterConfig> limitsConfigMap = new HashMap<>(); final Map<String, RateLimiterConfig> limitsConfigMap = new HashMap<>();
@ -147,8 +146,8 @@ public class RateLimitersTest {
@Test @Test
public void testRateLimiterHasItsPrioritiesStraight() throws Exception { public void testRateLimiterHasItsPrioritiesStraight() throws Exception {
final RateLimiters.For descriptor = RateLimiters.For.RECAPTCHA_CHALLENGE_ATTEMPT; final RateLimiters.For descriptor = RateLimiters.For.RECAPTCHA_CHALLENGE_ATTEMPT;
final RateLimiterConfig configForDynamic = new RateLimiterConfig(1, OptionalDouble.of(1), Optional.empty()); final RateLimiterConfig configForDynamic = new RateLimiterConfig(1, Duration.ofMinutes(1));
final RateLimiterConfig configForStatic = new RateLimiterConfig(2, OptionalDouble.of(2), Optional.empty()); final RateLimiterConfig configForStatic = new RateLimiterConfig(2, Duration.ofSeconds(30));
final RateLimiterConfig defaultConfig = descriptor.defaultConfig(); final RateLimiterConfig defaultConfig = descriptor.defaultConfig();
final Map<String, RateLimiterConfig> mapForDynamic = new HashMap<>(); final Map<String, RateLimiterConfig> mapForDynamic = new HashMap<>();
@ -189,7 +188,7 @@ public class RateLimitersTest {
@Override @Override
public RateLimiterConfig defaultConfig() { public RateLimiterConfig defaultConfig() {
return new RateLimiterConfig(1, OptionalDouble.of(1), Optional.empty()); return new RateLimiterConfig(1, Duration.ofMinutes(1));
} }
} }
} }