io.hyperfoil.core.steps.PollStep Maven / Gradle / Ivy
package io.hyperfoil.core.steps;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import io.hyperfoil.api.session.Access;
import io.hyperfoil.api.session.Session;
import io.hyperfoil.api.config.Step;
import io.hyperfoil.api.session.ResourceUtilizer;
import io.hyperfoil.core.builders.BaseStepBuilder;
import io.hyperfoil.core.session.SessionFactory;
import io.vertx.core.logging.Logger;
import io.vertx.core.logging.LoggerFactory;
public class PollStep implements Step, ResourceUtilizer {
private static final Logger log = LoggerFactory.getLogger(PollStep.class);
private final Function provider;
private final Access toVar;
private final BiPredicate filter;
private final BiConsumer recycler;
private final long periodMs;
private final int maxRetries;
public PollStep(Function provider, String toVar, BiPredicate filter, BiConsumer recycler, long periodMs, int maxRetries) {
this.provider = provider;
this.filter = filter;
this.toVar = SessionFactory.access(toVar);
this.recycler = recycler;
this.periodMs = periodMs;
this.maxRetries = maxRetries;
}
@Override
public boolean invoke(Session session) {
for (int i = 0; i < maxRetries; ++i) {
T object = provider.apply(session);
if (object == null) {
// Note: it's possible that we'll try to poll earlier
log.trace("Did not fetch object, scheduling #{} in {}", session.uniqueId(), periodMs);
session.executor().schedule((Runnable) session, periodMs, TimeUnit.MILLISECONDS);
return false;
} else if (filter.test(session, object)) {
toVar.setObject(session, object);
return true;
} else {
recycler.accept(session, object);
}
}
// We did not have an accepting match
log.trace("Not accepted, scheduling #{} in {}", session.uniqueId(), periodMs);
session.executor().schedule((Runnable) session, periodMs, TimeUnit.MILLISECONDS);
return false;
}
@Override
public void reserve(Session session) {
toVar.declareObject(session);
}
/**
* Periodically tries to insert object into session variable.
*/
public static class Builder extends BaseStepBuilder> {
private final Function provider;
private final String var;
private BiPredicate filter = (s, o) -> true;
private BiConsumer recycler;
private long periodMs = 50;
private int maxRetries = 16;
public Builder(Function provider, String var) {
this.provider = provider;
this.var = var;
}
public Builder filter(BiPredicate filter, BiConsumer recycler) {
this.filter = Objects.requireNonNull(filter);
this.recycler = Objects.requireNonNull(recycler);
return this;
}
public Builder filter(Predicate filter, Consumer recycler) {
Objects.requireNonNull(filter);
Objects.requireNonNull(recycler);
this.filter = (s, ship) -> filter.test(ship);
this.recycler = (s, ship) -> recycler.accept(ship);
return this;
}
/**
* Polling period.
*
* @param periodMs Period in milliseconds.
* @return Self.
*/
public Builder periodMs(long periodMs) {
this.periodMs = periodMs;
return this;
}
/**
* Maximum number of retries before giving up (and waiting for next period).
*
* @param maxRetries Number of retries.
* @return Self.
*/
public Builder maxRetries(int maxRetries) {
this.maxRetries = maxRetries;
return this;
}
@Override
public List build() {
return Collections.singletonList(new PollStep<>(provider, var, filter, recycler, periodMs, maxRetries));
}
}
}