package com.griddynamics.jagger.invoker; import com.griddynamics.jagger.util.Pair; import com.griddynamics.jagger.util.Timeout; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.concurrent.TimeUnit; /** * Subclass of {@link ExclusiveAccessLoadBalancer} that circularly selects pairs of Q and E. * As a result it simulates infinite iteration over the limited sequence of pairs. * @n * Also as a subclass of {@link ExclusiveAccessLoadBalancer} provides guarantees * that each query and endpoint pair will be in exclusive access, i.e. once it is acquired by one thread * it won't be acquired by any other thread (virtual user) in multi threaded environment. * @n * If {@link #randomnessSeed} is not {@code null} randomly shuffles the sequence of pairs from {@link #pairSupplierFactory} using it. * @n * Created by Andrey Badaev * Date: 07/02/17 * * @ingroup Main_Distributors_group */ public class CircularExclusiveAccessLoadBalancer<Q, E> extends ExclusiveAccessLoadBalancer<Q, E> { private final static Logger log = LoggerFactory.getLogger(CircularExclusiveAccessLoadBalancer.class); public CircularExclusiveAccessLoadBalancer(PairSupplierFactory<Q, E> pairSupplierFactory) { super(pairSupplierFactory); } private final static String POLL_TIMEOUT_NAME = "load balancer poll next timeout"; private Timeout pollTimeout = new Timeout(10 * 60 * 1000, POLL_TIMEOUT_NAME); // 10 minutes by default @Override protected boolean isToCircleAnIteration() { return true; } protected Pair<Q, E> pollNext() { Pair<Q, E> next = null; long startMillis = System.currentTimeMillis(); try { next = getPairQueue().poll(pollTimeout.getValue(), TimeUnit.MILLISECONDS); } catch (InterruptedException ignored) { } if (next == null) { throw new IllegalStateException(String.format("Didn't manage to poll the next pair. Timeout %s", pollTimeout)); } long endMillis = System.currentTimeMillis(); if (endMillis - startMillis > 1000) { log.warn( "It took {} ms to poll the next pair for the load balancer. Possible reason: not enough test data for selected load", endMillis - startMillis); } return next; } public void setPollTimeout(long pollTimeout) { this.pollTimeout = new Timeout(pollTimeout, POLL_TIMEOUT_NAME); } }