package uk.co.acuminous.julez.scenario.limiter;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import uk.co.acuminous.julez.event.Event;
import uk.co.acuminous.julez.event.handler.EventHandler;
import uk.co.acuminous.julez.scenario.Scenario;
import uk.co.acuminous.julez.scenario.ScenarioEvent;
import uk.co.acuminous.julez.scenario.ScenarioSource;
import uk.co.acuminous.julez.util.ConcurrencyUtils;
import uk.co.acuminous.julez.util.JulezSugar;
public class InLimboLimiter implements ScenarioSource, EventHandler {
private ScenarioSource scenarios;
private Integer upperLimit = Integer.MAX_VALUE;
private Integer lowerLimit;
private AtomicInteger counter = new AtomicInteger();
private long pause = 100;
public InLimboLimiter() {
}
public InLimboLimiter(ScenarioSource scenarios, int limit) {
this(scenarios, limit, limit);
}
public InLimboLimiter(ScenarioSource scenarios, int upperLimit, int lowerLimit) {
this.scenarios = scenarios;
this.upperLimit = upperLimit;
this.lowerLimit = lowerLimit;
}
public InLimboLimiter block(ScenarioSource scenarios) {
this.scenarios = scenarios;
return this;
}
public InLimboLimiter when(int limit, JulezSugar units) {
this.upperLimit = limit;
this.lowerLimit = lowerLimit == null ? limit : lowerLimit;
return this;
}
public InLimboLimiter unblockWhen(int limit, JulezSugar units) {
this.lowerLimit = limit;
return this;
}
@Override
public Scenario next() {
if (counter.get() > upperLimit) {
while (counter.get() > lowerLimit) {
ConcurrencyUtils.sleep(pause, MILLISECONDS);
}
}
counter.incrementAndGet();
return scenarios.next();
}
@Override
public void onEvent(Event event) {
if (ScenarioEvent.END.equals(event.getType())) {
counter.decrementAndGet();
}
}
public void setPause(long value, TimeUnit units) {
pause = MILLISECONDS.convert(value, units);
}
}