package com.griddynamics.jagger.engine.e1.process;
import com.google.common.util.concurrent.Service;
import com.griddynamics.jagger.coordinator.NodeContext;
import com.griddynamics.jagger.engine.e1.scenario.WorkloadConfiguration;
import com.griddynamics.jagger.util.Futures;
import com.griddynamics.jagger.util.TimeoutsConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* Workload process that perform invocation with given period.
*/
public class PeriodWorkloadProcess extends AbstractWorkloadProcess {
private PeriodSingleTaskScheduler loopExecutor = new PeriodSingleTaskScheduler();
Logger log = LoggerFactory.getLogger(PeriodWorkloadProcess.class);
public PeriodWorkloadProcess(String sessionId, StartWorkloadProcess command, NodeContext context, ThreadPoolExecutor executor, TimeoutsConfiguration timeoutsConfiguration) {
super(executor, sessionId, command, context, timeoutsConfiguration);
}
@Override
protected Collection<WorkloadService> getRunningWorkloadServiceCollection() {
return new LinkedBlockingQueue<WorkloadService>();
}
@Override
protected void doStart() {
long period = command.getScenarioContext().getWorkloadConfiguration().getPeriod();
long delay = command.getScenarioContext().getWorkloadConfiguration().getDelay();
// start scheduling task with given period.
loopExecutor.scheduleAtFixedRate(() -> startNewThread(0), delay, period, TimeUnit.MILLISECONDS);
}
@Override
protected void startNewThread(int delay) {
for (WorkloadService thread : threads) {
Future<Service.State> future = thread.start();
if (future != null) {
Service.State state = Futures.get(future, timeoutsConfiguration.getWorkloadStartTimeout());
log.debug("Workload thread is started with state {}. Total threads number - {}", state, executor.getActiveCount());
return;
}
}
if (executor.getActiveCount() >= executor.getMaximumPoolSize()) {
log.warn("Thread pool(size={}) is full. Skip adding new thread.", executor.getPoolSize());
return;
}
super.startNewThread(delay);
}
@Override
protected WorkloadService getService(AbstractWorkloadService.WorkloadServiceBuilder serviceBuilder) {
// return workload service that should execute 1 sample on demand
return serviceBuilder.buildInvokeOnDemandWorkloadService();
}
@Override
public void stop() {
// do not stat new workload service
loopExecutor.clear();
loopExecutor.shutdown();
super.stop();
}
@Override
public void changeConfiguration(WorkloadConfiguration configuration) {
loopExecutor.scheduleAtFixedRate(() -> startNewThread(0), configuration.getDelay(), configuration.getPeriod(), TimeUnit.MILLISECONDS);
}
}