Introduce a configuration to define time lapse for rate limiter
Before this change, rate limiter was executed every hour. Sometimes, a
sudden high memory demand on a short period of time happens caused by
high number of clones and fetches. Also, the user gets blocked from
fetching information due to reaching the limit per hour.
This change introduces an optional configurable field "timelapse". This
field defines a duration in minutes supported by the rate-limiter
plugin. This helps address the potential problem of sudden high memory
demand by configuring the number of uploaded packs over smaller amount
of time. If this field is not defined or is defined for a value higher
than or equal to 60, the default value of 60 minutes is established and
a warning message is logged.
This change also adapts the warnings provided by the rate limiter to
reflect the time lapse of the plugin.
Bug: Issue 10302
Change-Id: I5cdbb931d676c7630178d0b8ba0245e3c8b774a8
diff --git a/src/main/java/com/googlesource/gerrit/plugins/ratelimiter/Module.java b/src/main/java/com/googlesource/gerrit/plugins/ratelimiter/Module.java
index 191a86a..c59c2fe 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/ratelimiter/Module.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/ratelimiter/Module.java
@@ -32,6 +32,7 @@
import java.util.Optional;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
+import org.slf4j.Logger;
class Module extends AbstractModule {
static final String UPLOAD_PACK_PER_HOUR = "upload_pack_per_hour";
@@ -49,9 +50,9 @@
bind(LifecycleListener.class)
.annotatedWith(UniqueAnnotations.create())
.to(RateLimiterStatsLog.class);
- install(new FactoryModuleBuilder().build(HourlyRateLimiter.Factory.class));
- install(new FactoryModuleBuilder().build(WarningHourlyRateLimiter.Factory.class));
- install(new FactoryModuleBuilder().build(WarningHourlyUnlimitedRateLimiter.Factory.class));
+ install(new FactoryModuleBuilder().build(PeriodicRateLimiter.Factory.class));
+ install(new FactoryModuleBuilder().build(WarningRateLimiter.Factory.class));
+ install(new FactoryModuleBuilder().build(WarningUnlimitedRateLimiter.Factory.class));
}
@Provides
@@ -68,27 +69,29 @@
private static class RateLimiterLoader extends CacheLoader<String, RateLimiter> {
private final RateLimitFinder finder;
- private final HourlyRateLimiter.Factory hourlyRateLimiterFactory;
- private final WarningHourlyRateLimiter.Factory warningHourlyRateLimiterFactory;
- private final WarningHourlyUnlimitedRateLimiter.Factory
- warningHourlyUnlimitedRateLimiterFactory;
+ private final PeriodicRateLimiter.Factory periodicRateLimiterFactory;
+ private final WarningRateLimiter.Factory warningRateLimiterFactory;
+ private final WarningUnlimitedRateLimiter.Factory warningUnlimitedRateLimiterFactory;
+ private final Logger logger;
@Inject
RateLimiterLoader(
RateLimitFinder finder,
- HourlyRateLimiter.Factory hourlyRateLimiterFactory,
- WarningHourlyRateLimiter.Factory warningHourlyRateLimiterFactory,
- WarningHourlyUnlimitedRateLimiter.Factory warningUnlimitedRateLimiterFactory) {
+ PeriodicRateLimiter.Factory periodicRateLimiterFactory,
+ WarningRateLimiter.Factory warningRateLimiterFactory,
+ WarningUnlimitedRateLimiter.Factory warningUnlimitedRateLimiterFactory) {
this.finder = finder;
- this.hourlyRateLimiterFactory = hourlyRateLimiterFactory;
- this.warningHourlyRateLimiterFactory = warningHourlyRateLimiterFactory;
- this.warningHourlyUnlimitedRateLimiterFactory = warningUnlimitedRateLimiterFactory;
+ this.periodicRateLimiterFactory = periodicRateLimiterFactory;
+ this.warningRateLimiterFactory = warningRateLimiterFactory;
+ this.warningUnlimitedRateLimiterFactory = warningUnlimitedRateLimiterFactory;
+ this.logger = RateLimiterStatsLog.getLogger();
}
@Override
public RateLimiter load(String key) {
Optional<RateLimit> limit = finder.find(RateLimitType.UPLOAD_PACK_PER_HOUR, key);
Optional<RateLimit> warn = finder.find(RateLimitType.UPLOAD_PACK_PER_HOUR_WARN, key);
+ Optional<RateLimit> timeLapse = finder.find(RateLimitType.TIME_LAPSE_IN_MINUTES, key);
if (!limit.isPresent() && !warn.isPresent()) {
return UnlimitedRateLimiter.INSTANCE;
}
@@ -99,15 +102,26 @@
myLimit = limit.get().getRatePerHour();
}
- RateLimiter rateLimiter = hourlyRateLimiterFactory.create(myLimit);
+ long effectiveTimeLapse = PeriodicRateLimiter.DEFAULT_TIME_LAPSE_IN_MINUTES;
+ if (timeLapse.isPresent()) {
+ long providedTimeLapse = timeLapse.get().getRatePerHour();
+ if (providedTimeLapse > 0 && providedTimeLapse <= effectiveTimeLapse) {
+ effectiveTimeLapse = providedTimeLapse;
+ } else {
+ logger.warn(
+ "The time lapse is set to the default {} minutes, as the configured value is invalid.",
+ effectiveTimeLapse);
+ }
+ }
+ RateLimiter rateLimiter = periodicRateLimiterFactory.create(myLimit, effectiveTimeLapse);
if (warn.isPresent()) {
if (limit.isPresent()) {
- return warningHourlyRateLimiterFactory.create(
- rateLimiter, key, warn.get().getRatePerHour());
+ return warningRateLimiterFactory.create(
+ rateLimiter, key, warn.get().getRatePerHour(), effectiveTimeLapse);
}
- return warningHourlyUnlimitedRateLimiterFactory.create(
- rateLimiter, key, warn.get().getRatePerHour());
+ return warningUnlimitedRateLimiterFactory.create(
+ rateLimiter, key, warn.get().getRatePerHour(), effectiveTimeLapse);
}
return rateLimiter;
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/ratelimiter/HourlyRateLimiter.java b/src/main/java/com/googlesource/gerrit/plugins/ratelimiter/PeriodicRateLimiter.java
similarity index 82%
rename from src/main/java/com/googlesource/gerrit/plugins/ratelimiter/HourlyRateLimiter.java
rename to src/main/java/com/googlesource/gerrit/plugins/ratelimiter/PeriodicRateLimiter.java
index 4f9e44c..203645d 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/ratelimiter/HourlyRateLimiter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/ratelimiter/PeriodicRateLimiter.java
@@ -22,22 +22,28 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
-class HourlyRateLimiter implements RateLimiter {
+class PeriodicRateLimiter implements RateLimiter {
+ static final long DEFAULT_TIME_LAPSE_IN_MINUTES = 60L;
+
private final Semaphore semaphore;
private final int maxPermits;
private final AtomicInteger usedPermits;
private final ScheduledFuture<?> replenishTask;
interface Factory {
- HourlyRateLimiter create(int permits);
+ PeriodicRateLimiter create(int permits, long timeLapse);
}
@Inject
- HourlyRateLimiter(@RateLimitExecutor ScheduledExecutorService executor, @Assisted int permits) {
+ PeriodicRateLimiter(
+ @RateLimitExecutor ScheduledExecutorService executor,
+ @Assisted int permits,
+ @Assisted long timeLapse) {
this.semaphore = new Semaphore(permits);
this.maxPermits = permits;
this.usedPermits = new AtomicInteger();
- replenishTask = executor.scheduleAtFixedRate(this::replenishPermits, 1, 1, TimeUnit.HOURS);
+ this.replenishTask =
+ executor.scheduleAtFixedRate(this::replenishPermits, 1, timeLapse, TimeUnit.MINUTES);
}
@Override
diff --git a/src/main/java/com/googlesource/gerrit/plugins/ratelimiter/RateLimitType.java b/src/main/java/com/googlesource/gerrit/plugins/ratelimiter/RateLimitType.java
index 0d6e4e5..337508f 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/ratelimiter/RateLimitType.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/ratelimiter/RateLimitType.java
@@ -16,7 +16,8 @@
enum RateLimitType {
UPLOAD_PACK_PER_HOUR("uploadpackperhour"),
- UPLOAD_PACK_PER_HOUR_WARN("uploadpackperhourwarn");
+ UPLOAD_PACK_PER_HOUR_WARN("uploadpackperhourwarn"),
+ TIME_LAPSE_IN_MINUTES("timelapseinminutes");
private final String type;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/ratelimiter/WarningHourlyRateLimiter.java b/src/main/java/com/googlesource/gerrit/plugins/ratelimiter/WarningRateLimiter.java
similarity index 86%
rename from src/main/java/com/googlesource/gerrit/plugins/ratelimiter/WarningHourlyRateLimiter.java
rename to src/main/java/com/googlesource/gerrit/plugins/ratelimiter/WarningRateLimiter.java
index 497917e..5ce2200 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/ratelimiter/WarningHourlyRateLimiter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/ratelimiter/WarningRateLimiter.java
@@ -22,10 +22,10 @@
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
-class WarningHourlyRateLimiter implements RateLimiter {
+class WarningRateLimiter implements RateLimiter {
@FunctionalInterface
interface Factory {
- WarningHourlyRateLimiter create(RateLimiter delegate, String key, int warnLimit);
+ WarningRateLimiter create(RateLimiter delegate, String key, int warnLimit, long timeLapse);
}
private static final Logger rateLimitLog = RateLimiterStatsLog.getLogger();
@@ -35,20 +35,23 @@
private final RateLimiter delegate;
private final int warnLimit;
private final String key;
+ private final long timeLapse;
private volatile boolean wasLogged;
private volatile boolean warningWasLogged = false;
@Inject
- WarningHourlyRateLimiter(
+ WarningRateLimiter(
UserResolver userResolver,
@Assisted RateLimiter delegate,
@Assisted String key,
- @Assisted int warnLimit) {
+ @Assisted int warnLimit,
+ @Assisted long timeLapse) {
this.userResolver = userResolver;
this.delegate = delegate;
this.warnLimit = warnLimit;
this.key = key;
+ this.timeLapse = timeLapse;
}
@Override
@@ -61,18 +64,20 @@
boolean acquirePermit = delegate.acquirePermit();
if (usedPermits() == warnLimit) {
rateLimitLog.info(
- "{} reached the warning limit of {} uploadpacks per hour.",
+ "{} reached the warning limit of {} uploadpacks per {} minutes.",
userResolver.getUserName(key).orElse(key),
- warnLimit);
+ warnLimit,
+ timeLapse);
warningWasLogged = true;
}
if (!acquirePermit && !wasLogged) {
rateLimitLog.info(
- "{} was blocked due to exceeding the limit of {} uploadpacks per hour."
+ "{} was blocked due to exceeding the limit of {} uploadpacks per {} minutes."
+ " {} remaining to permits replenishing.",
userResolver.getUserName(key).orElse(key),
permitsPerHour(),
+ timeLapse,
secondsToMsSs(remainingTime(TimeUnit.SECONDS)));
wasLogged = true;
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/ratelimiter/WarningHourlyUnlimitedRateLimiter.java b/src/main/java/com/googlesource/gerrit/plugins/ratelimiter/WarningUnlimitedRateLimiter.java
similarity index 83%
rename from src/main/java/com/googlesource/gerrit/plugins/ratelimiter/WarningHourlyUnlimitedRateLimiter.java
rename to src/main/java/com/googlesource/gerrit/plugins/ratelimiter/WarningUnlimitedRateLimiter.java
index d2b8b09..f9e55b3 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/ratelimiter/WarningHourlyUnlimitedRateLimiter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/ratelimiter/WarningUnlimitedRateLimiter.java
@@ -20,10 +20,11 @@
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
-class WarningHourlyUnlimitedRateLimiter implements RateLimiter {
+class WarningUnlimitedRateLimiter implements RateLimiter {
@FunctionalInterface
interface Factory {
- WarningHourlyUnlimitedRateLimiter create(RateLimiter delegate, String key, int warnLimit);
+ WarningUnlimitedRateLimiter create(
+ RateLimiter delegate, String key, int warnLimit, long timeLapse);
}
private static final Logger rateLimitLog = RateLimiterStatsLog.getLogger();
@@ -32,18 +33,21 @@
private final RateLimiter delegate;
private final int warnLimit;
private final String key;
+ private final long timeLapse;
private volatile boolean warningWasLogged = false;
@Inject
- WarningHourlyUnlimitedRateLimiter(
+ WarningUnlimitedRateLimiter(
UserResolver userResolver,
@Assisted RateLimiter delegate,
@Assisted String key,
- @Assisted int warnLimit) {
+ @Assisted int warnLimit,
+ @Assisted long timeLapse) {
this.userResolver = userResolver;
this.delegate = delegate;
this.warnLimit = warnLimit;
this.key = key;
+ this.timeLapse = timeLapse;
}
@Override
@@ -57,9 +61,10 @@
if (acquirePermit && (usedPermits() == warnLimit)) {
rateLimitLog.info(
- "{} reached the warning limit of {} uploadpacks per hour.",
+ "{} reached the warning limit of {} uploadpacks per {} minutes.",
userResolver.getUserName(key).orElse(key),
- warnLimit);
+ warnLimit,
+ timeLapse);
warningWasLogged = true;
}
return acquirePermit;
diff --git a/src/main/resources/Documentation/about.md b/src/main/resources/Documentation/about.md
index 3313b71..e62f6f8 100644
--- a/src/main/resources/Documentation/about.md
+++ b/src/main/resources/Documentation/about.md
@@ -2,7 +2,9 @@
The @PLUGIN@ plugin supports the following rate limits:
-* `uploadpackperhour` requests per hour which are executed when a client runs a fetch command.
+* `uploadpackperhour` requests per period which are executed when a client runs a fetch command.
+* `timelapseinminutes` defines a period in minutes for the rate limiter. This value supports a
+ limit of 60.
Rate limits define the maximum request rate for users in a given group
for a given request type.
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index 098f1e2..ac07f24 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -14,6 +14,7 @@
[group "buildserver"]
uploadpackperhour = 10
uploadpackperhourwarn = 8
+ timelapseinminutes = 10
[group "Registered Users"]
uploadpackperhour = 1
@@ -25,6 +26,12 @@
uploadpackperhourwarn = 10
```
+In this example, the plugin will apply the uploadpackperhour and
+uploadpackperhourwarn properties every 10 minutes for the members of
+the group buildserver and every 1 hour for the other groups. Therefore,
+the members of the group buildserver will have a limit of 10 uploaded
+packs every 10 minutes.
+
For logged-in users, rate limits are associated to their accountId. For
anonymous users, rate limits are associated to their remote host address.
If multiple anonymous users are accessing Gerrit via the same host (e.g.,
@@ -104,3 +111,7 @@
message and will be replaced by the effective rate limit per hour.
Defaults to `Exceeded rate limit of ${rateLimit} fetch requests/hour`.
+
+`timelapseinminutes` defines a period of time in which the limit of
+uploadpack takes place. If it is not configured, a default value of 1 hour
+is established.
diff --git a/src/test/java/com/googlesource/gerrit/plugins/ratelimiter/HourlyRateLimiterTest.java b/src/test/java/com/googlesource/gerrit/plugins/ratelimiter/PeriodicRateLimiterTest.java
similarity index 79%
rename from src/test/java/com/googlesource/gerrit/plugins/ratelimiter/HourlyRateLimiterTest.java
rename to src/test/java/com/googlesource/gerrit/plugins/ratelimiter/PeriodicRateLimiterTest.java
index 7040682..0343d6b 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/ratelimiter/HourlyRateLimiterTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/ratelimiter/PeriodicRateLimiterTest.java
@@ -15,6 +15,7 @@
package com.googlesource.gerrit.plugins.ratelimiter;
import static com.google.common.truth.Truth.assertThat;
+import static com.googlesource.gerrit.plugins.ratelimiter.PeriodicRateLimiter.DEFAULT_TIME_LAPSE_IN_MINUTES;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
@@ -26,17 +27,17 @@
import org.junit.Test;
import org.mockito.ArgumentCaptor;
-public class HourlyRateLimiterTest {
+public class PeriodicRateLimiterTest {
private static final int RATE = 1000;
- private HourlyRateLimiter limiter;
+ private PeriodicRateLimiter limiter;
private ScheduledExecutorService scheduledExecutorMock;
@Before
public void setUp() {
scheduledExecutorMock = mock(ScheduledExecutorService.class);
- limiter = new HourlyRateLimiter(scheduledExecutorMock, RATE);
+ limiter = new PeriodicRateLimiter(scheduledExecutorMock, RATE, DEFAULT_TIME_LAPSE_IN_MINUTES);
}
@Test
@@ -65,14 +66,20 @@
@Test
public void testReplenishPermitsIsScheduled() {
- verify(scheduledExecutorMock).scheduleAtFixedRate(any(), eq(1L), eq(1L), eq(TimeUnit.HOURS));
+ verify(scheduledExecutorMock)
+ .scheduleAtFixedRate(
+ any(), eq(1L), eq(DEFAULT_TIME_LAPSE_IN_MINUTES), eq(TimeUnit.MINUTES));
}
@Test
public void testReplenishPermitsScheduledRunnableIsWorking() {
ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
verify(scheduledExecutorMock)
- .scheduleAtFixedRate(runnableCaptor.capture(), eq(1L), eq(1L), eq(TimeUnit.HOURS));
+ .scheduleAtFixedRate(
+ runnableCaptor.capture(),
+ eq(1L),
+ eq(DEFAULT_TIME_LAPSE_IN_MINUTES),
+ eq(TimeUnit.MINUTES));
// Use all permits
testAcquire();
diff --git a/src/test/java/com/googlesource/gerrit/plugins/ratelimiter/RateLimitUploadPackIT.java b/src/test/java/com/googlesource/gerrit/plugins/ratelimiter/RateLimitUploadPackIT.java
index f421748..7b32006 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/ratelimiter/RateLimitUploadPackIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/ratelimiter/RateLimitUploadPackIT.java
@@ -60,6 +60,32 @@
cloneProject(new Project.NameKey(projectB), user);
}
+ @Test
+ @UseLocalDisk
+ @GlobalPluginConfig(
+ pluginName = "rate-limiter",
+ name = "group.limitGroup.uploadpackperhour",
+ value = "1")
+ @GlobalPluginConfig(
+ pluginName = "rate-limiter",
+ name = "group.limitGroup.timelapseinminutes",
+ value = "1")
+ @GlobalPluginConfig(
+ pluginName = "rate-limiter",
+ name = "configuration.uploadpackLimitExceededMsg",
+ value = "Custom message: Limit exceeded ${rateLimit} requests/minute")
+ public void requestIsBlockedForGroupAfterRateLimitReachedAndGrantedAfterElapsed()
+ throws Exception {
+ String projectA = "projectA";
+ String projectB = "projectB";
+ createProjectWithChange(projectA);
+ createProjectWithChange(projectB);
+
+ cloneProject(new Project.NameKey(projectA), user);
+ Thread.sleep(PeriodicRateLimiter.DEFAULT_TIME_LAPSE_IN_MINUTES * 1000);
+ cloneProject(new Project.NameKey(projectB), user);
+ }
+
private void addUserToNewGroup() throws RestApiException {
GroupInput in = new GroupInput();
String groupName = "limitGroup";
diff --git a/src/test/java/com/googlesource/gerrit/plugins/ratelimiter/WarningHourlyRateLimiterTest.java b/src/test/java/com/googlesource/gerrit/plugins/ratelimiter/WarningRateLimiterTest.java
similarity index 77%
rename from src/test/java/com/googlesource/gerrit/plugins/ratelimiter/WarningHourlyRateLimiterTest.java
rename to src/test/java/com/googlesource/gerrit/plugins/ratelimiter/WarningRateLimiterTest.java
index 7541aa1..4a0162f 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/ratelimiter/WarningHourlyRateLimiterTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/ratelimiter/WarningRateLimiterTest.java
@@ -15,6 +15,7 @@
package com.googlesource.gerrit.plugins.ratelimiter;
import static com.google.common.truth.Truth.assertThat;
+import static com.googlesource.gerrit.plugins.ratelimiter.PeriodicRateLimiter.DEFAULT_TIME_LAPSE_IN_MINUTES;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
@@ -28,12 +29,12 @@
import org.junit.Test;
import org.mockito.ArgumentCaptor;
-public class WarningHourlyRateLimiterTest {
+public class WarningRateLimiterTest {
private static final int RATE = 1000;
private static final int WARN_RATE = 900;
- private WarningHourlyRateLimiter warningLimiter1;
- private WarningHourlyRateLimiter warningLimiter2;
+ private WarningRateLimiter warningLimiter1;
+ private WarningRateLimiter warningLimiter2;
private ScheduledExecutorService scheduledExecutorMock1;
private UserResolver userResolver = mock(UserResolver.class);
@@ -43,14 +44,20 @@
ScheduledExecutorService scheduledExecutorMock2 = mock(ScheduledExecutorService.class);
- HourlyRateLimiter limiter1 = spy(new HourlyRateLimiter(scheduledExecutorMock1, RATE));
+ PeriodicRateLimiter limiter1 =
+ spy(new PeriodicRateLimiter(scheduledExecutorMock1, RATE, DEFAULT_TIME_LAPSE_IN_MINUTES));
doReturn(1L).when(limiter1).remainingTime(any(TimeUnit.class));
- HourlyRateLimiter limiter2 = spy(new HourlyRateLimiter(scheduledExecutorMock2, RATE));
+ PeriodicRateLimiter limiter2 =
+ spy(new PeriodicRateLimiter(scheduledExecutorMock2, RATE, DEFAULT_TIME_LAPSE_IN_MINUTES));
doReturn(1L).when(limiter2).remainingTime(any(TimeUnit.class));
- warningLimiter1 = new WarningHourlyRateLimiter(userResolver, limiter1, "dummy", WARN_RATE);
- warningLimiter2 = new WarningHourlyRateLimiter(userResolver, limiter2, "dummy2", WARN_RATE);
+ warningLimiter1 =
+ new WarningRateLimiter(
+ userResolver, limiter1, "dummy", WARN_RATE, DEFAULT_TIME_LAPSE_IN_MINUTES);
+ warningLimiter2 =
+ new WarningRateLimiter(
+ userResolver, limiter2, "dummy2", WARN_RATE, DEFAULT_TIME_LAPSE_IN_MINUTES);
}
@Test
@@ -90,14 +97,20 @@
@Test
public void testReplenishPermitsIsScheduled() {
- verify(scheduledExecutorMock1).scheduleAtFixedRate(any(), eq(1L), eq(1L), eq(TimeUnit.HOURS));
+ verify(scheduledExecutorMock1)
+ .scheduleAtFixedRate(
+ any(), eq(1L), eq(DEFAULT_TIME_LAPSE_IN_MINUTES), eq(TimeUnit.MINUTES));
}
@Test
public void testReplenishPermitsScheduledRunnableIsWorking() {
ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
verify(scheduledExecutorMock1)
- .scheduleAtFixedRate(runnableCaptor.capture(), eq(1L), eq(1L), eq(TimeUnit.HOURS));
+ .scheduleAtFixedRate(
+ runnableCaptor.capture(),
+ eq(1L),
+ eq(DEFAULT_TIME_LAPSE_IN_MINUTES),
+ eq(TimeUnit.MINUTES));
replenishPermits(warningLimiter1, runnableCaptor);
testAcquireAll();
diff --git a/src/test/java/com/googlesource/gerrit/plugins/ratelimiter/WarningHourlyUnlimitedRateLimiterTest.java b/src/test/java/com/googlesource/gerrit/plugins/ratelimiter/WarningUnlimitedRateLimiterTest.java
similarity index 79%
rename from src/test/java/com/googlesource/gerrit/plugins/ratelimiter/WarningHourlyUnlimitedRateLimiterTest.java
rename to src/test/java/com/googlesource/gerrit/plugins/ratelimiter/WarningUnlimitedRateLimiterTest.java
index f2abebf..b402e77 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/ratelimiter/WarningHourlyUnlimitedRateLimiterTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/ratelimiter/WarningUnlimitedRateLimiterTest.java
@@ -15,6 +15,7 @@
package com.googlesource.gerrit.plugins.ratelimiter;
import static com.google.common.truth.Truth.assertThat;
+import static com.googlesource.gerrit.plugins.ratelimiter.PeriodicRateLimiter.DEFAULT_TIME_LAPSE_IN_MINUTES;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
@@ -26,20 +27,22 @@
import org.junit.Test;
import org.mockito.ArgumentCaptor;
-public class WarningHourlyUnlimitedRateLimiterTest {
+public class WarningUnlimitedRateLimiterTest {
private static final int RATE = 1000;
private static final int WARN_RATE = 900;
- private WarningHourlyUnlimitedRateLimiter warningUnlimitedLimiter;
+ private WarningUnlimitedRateLimiter warningUnlimitedLimiter;
private ScheduledExecutorService scheduledExecutorMock;
private UserResolver userResolver = mock(UserResolver.class);
@Before
public void setUp() {
scheduledExecutorMock = mock(ScheduledExecutorService.class);
- HourlyRateLimiter limiter = new HourlyRateLimiter(scheduledExecutorMock, RATE);
+ PeriodicRateLimiter limiter =
+ new PeriodicRateLimiter(scheduledExecutorMock, RATE, DEFAULT_TIME_LAPSE_IN_MINUTES);
warningUnlimitedLimiter =
- new WarningHourlyUnlimitedRateLimiter(userResolver, limiter, "dummy", WARN_RATE);
+ new WarningUnlimitedRateLimiter(
+ userResolver, limiter, "dummy", WARN_RATE, DEFAULT_TIME_LAPSE_IN_MINUTES);
}
@Test
@@ -68,14 +71,20 @@
@Test
public void testReplenishPermitsIsScheduled() {
- verify(scheduledExecutorMock).scheduleAtFixedRate(any(), eq(1L), eq(1L), eq(TimeUnit.HOURS));
+ verify(scheduledExecutorMock)
+ .scheduleAtFixedRate(
+ any(), eq(1L), eq(DEFAULT_TIME_LAPSE_IN_MINUTES), eq(TimeUnit.MINUTES));
}
@Test
public void testReplenishPermitsScheduledRunnableIsWorking() {
ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
verify(scheduledExecutorMock)
- .scheduleAtFixedRate(runnableCaptor.capture(), eq(1L), eq(1L), eq(TimeUnit.HOURS));
+ .scheduleAtFixedRate(
+ runnableCaptor.capture(),
+ eq(1L),
+ eq(DEFAULT_TIME_LAPSE_IN_MINUTES),
+ eq(TimeUnit.MINUTES));
testTriggerWarning();