package com.griddynamics.jagger.user.test.configurations.loadbalancer;
import com.griddynamics.jagger.invoker.CircularExclusiveAccessLoadBalancer;
import com.griddynamics.jagger.invoker.ExclusiveAccessLoadBalancer;
import com.griddynamics.jagger.invoker.NonCircularExclusiveAccessLoadBalancer;
import com.griddynamics.jagger.invoker.OneByOneLoadBalancer;
import com.griddynamics.jagger.invoker.OneByOnePairSupplierFactory;
import com.griddynamics.jagger.invoker.PairSupplierFactory;
import com.griddynamics.jagger.invoker.PairSupplierFactoryLoadBalancer;
import com.griddynamics.jagger.invoker.QueryPoolLoadBalancer;
import com.griddynamics.jagger.invoker.RandomLoadBalancer;
import com.griddynamics.jagger.invoker.RoundRobinLoadBalancer;
import com.griddynamics.jagger.invoker.RoundRobinPairSupplierFactory;
import com.griddynamics.jagger.invoker.SimpleCircularLoadBalancer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Serializable;
import java.util.Objects;
import java.util.Random;
/**
* Provides load balancer aka distributor (how to pair endpoints and queries) (subtypes of {@link QueryPoolLoadBalancer}).
*
* @ingroup Main_Distributors_group
*/
public class JLoadBalancer implements Serializable {
private final static Logger log = LoggerFactory.getLogger(JLoadBalancer.class);
/**
* Creates {@link Builder} of load balancer
*
* @param loadBalancer load balancer to use (look at {@link DefaultLoadBalancer})
*/
public static Builder builder(DefaultLoadBalancer loadBalancer) {
return new Builder(loadBalancer);
}
/**
* Default load balancers.
*
* @see RoundRobinLoadBalancer
* @see OneByOneLoadBalancer
*/
public enum DefaultLoadBalancer {
ROUND_ROBIN, ONE_BY_ONE
}
public static class Builder {
private final DefaultLoadBalancer loadBalancer;
private Long seed;
private boolean exclusiveAccess;
private boolean oneIterationOnly;
/**
* Creates {@link Builder} of load balancer
*
* @param loadBalancer load balancer to use (look at {@link DefaultLoadBalancer})
*/
public Builder(DefaultLoadBalancer loadBalancer) {
this.loadBalancer = loadBalancer;
}
/**
* Optional: Calling this setter will produce a load balancer
* which randomly picks an endpoint & query pair to provide
* with random seed specified by parameter <b>seed</b>.
*
* @param seed the initial seed of {@link Random} (look at {@link Random#Random(long)})
* @return {@link Builder} this
* @n
*/
public Builder withRandomSeed(long seed) {
this.seed = seed;
return this;
}
/**
* Optional: If this flag is true the builder will produce a load balancer with an exclusive access
* to each endpoint & query pair. That means once a virtual user acquires a pair
* any other virtual user won't get the same pair until that user comes for the next pair.
*
* @return {@link Builder} this
* @see ExclusiveAccessLoadBalancer
*/
public Builder withExclusiveAccess() {
this.exclusiveAccess = true;
return this;
}
/**
* Optional: If this flag is true the builder will produce a load balancer
* which provides each pair only once (does only one iteration over a sequence of those pairs)
* @return {@link Builder} this
* @see NonCircularExclusiveAccessLoadBalancer
*/
public Builder withUniqueAccess() {
this.oneIterationOnly = true;
this.exclusiveAccess = true;
return this;
}
/**
* @return Load balancer (subtype of {@link QueryPoolLoadBalancer})
*/
public QueryPoolLoadBalancer build() {
PairSupplierFactory pairSupplierFactory = null;
switch (loadBalancer) {
case ONE_BY_ONE:
pairSupplierFactory = new OneByOnePairSupplierFactory();
break;
case ROUND_ROBIN:
default:
pairSupplierFactory = new RoundRobinPairSupplierFactory();
break;
}
PairSupplierFactoryLoadBalancer loadBalancer = null;
if (exclusiveAccess) {
if (oneIterationOnly) {
loadBalancer = new NonCircularExclusiveAccessLoadBalancer(pairSupplierFactory);
} else {
loadBalancer = new CircularExclusiveAccessLoadBalancer(pairSupplierFactory);
}
((ExclusiveAccessLoadBalancer)loadBalancer).setRandomnessSeed(seed);
} else {
if (Objects.nonNull(seed)) {
loadBalancer = new RandomLoadBalancer(seed, pairSupplierFactory);
} else {
loadBalancer = new SimpleCircularLoadBalancer(pairSupplierFactory);
}
}
log.info("Built a {} load balancer", loadBalancer);
return loadBalancer;
}
}
}