diff --git a/src/main/java/io/vertx/circuitbreaker/impl/CircuitBreakerImpl.java b/src/main/java/io/vertx/circuitbreaker/impl/CircuitBreakerImpl.java index 27ac7cd..fe29689 100644 --- a/src/main/java/io/vertx/circuitbreaker/impl/CircuitBreakerImpl.java +++ b/src/main/java/io/vertx/circuitbreaker/impl/CircuitBreakerImpl.java @@ -30,7 +30,6 @@ import io.vertx.core.impl.ContextInternal; import io.vertx.core.json.JsonObject; -import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; @@ -466,14 +465,22 @@ public CircuitBreaker retryPolicy(RetryPolicy retryPolicy) { return this; } - public static class RollingCounter { + static class RollingCounter { + // all `RollingCounter` methods are called in a `synchronized (CircuitBreakerImpl.this)` block, + // which therefore guards access to these fields + private Map window; private long timeUnitsInWindow; private TimeUnit windowTimeUnit; public RollingCounter(long timeUnitsInWindow, TimeUnit windowTimeUnit) { this.windowTimeUnit = windowTimeUnit; - this.window = new LinkedHashMap<>((int) timeUnitsInWindow + 1); + this.window = new LinkedHashMap((int) timeUnitsInWindow + 1) { + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return size() > timeUnitsInWindow; + } + }; this.timeUnitsInWindow = timeUnitsInWindow; } @@ -481,18 +488,18 @@ public void increment() { long timeSlot = windowTimeUnit.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS); Long current = window.getOrDefault(timeSlot, 0L); window.put(timeSlot, ++current); - - if (window.size() > timeUnitsInWindow) { - Iterator iterator = window.keySet().iterator(); - if (iterator.hasNext()) { - window.remove(iterator.next()); - } - } } public long count() { long windowStartTime = windowTimeUnit.convert(System.currentTimeMillis() - windowTimeUnit.toMillis(timeUnitsInWindow), TimeUnit.MILLISECONDS); - return window.entrySet().stream().filter(entry -> entry.getKey() >= windowStartTime).mapToLong(entry -> entry.getValue()).sum(); + + long result = 0; + for (Map.Entry entry : window.entrySet()) { + if (entry.getKey() >= windowStartTime) { + result += entry.getValue(); + } + } + return result; } public void reset() {