
com.remondis.limbus.tasks.TaskSchedulerImpl Maven / Gradle / Ivy
package com.remondis.limbus.tasks;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.remondis.limbus.api.Initializable;
import com.remondis.limbus.files.LimbusFileService;
import com.remondis.limbus.properties.LimbusProperties;
import com.remondis.limbus.system.api.LimbusComponent;
import com.remondis.limbus.utils.Lang;
public class TaskSchedulerImpl extends Initializable implements TaskScheduler, ThreadFactory {
private static final String PERIODIC_TASKS_THREAD_POOL_SIZE = "periodic-tasks.thread-pool.size";
private static final String SHUTDOWN_TIMEOUT = "periodic-tasks.shutdown-timeout.value";
private static final String SHUTDOWN_TIMEOUT_UNIT = "periodic-tasks.shutdown-timeout.timeUnit";
private static final Logger log = LoggerFactory.getLogger(TaskSchedulerImpl.class);
private static final AtomicInteger threadCount = new AtomicInteger();
@LimbusComponent
protected LimbusFileService filesystem;
protected long shutdownTimeout;
protected TimeUnit shutdownTimeoutUnit;
protected ScheduledExecutorService scheduler;
protected ConcurrentHashMap tasks;
@Override
protected void performInitialize() throws Exception {
LimbusProperties properties = new LimbusProperties(filesystem, TaskSchedulerImpl.class, true, false);
int threadCount = properties.getInt(PERIODIC_TASKS_THREAD_POOL_SIZE);
this.shutdownTimeout = properties.getLong(SHUTDOWN_TIMEOUT);
this.shutdownTimeoutUnit = properties.getEnum(SHUTDOWN_TIMEOUT_UNIT, TimeUnit.class);
// extra scheduler for cyclical call of commands so that the scheduler can be stopped separately
scheduler = Executors.newScheduledThreadPool(threadCount, this);
this.tasks = new ConcurrentHashMap();
}
@Override
protected void performFinish() {
// Cancel all tasks
if (tasks != null) {
Iterator it = tasks.values()
.iterator();
while (it.hasNext()) {
TaskExecution exec = it.next();
exec.cancel();
}
tasks.clear();
}
if (scheduler != null) {
log.info("Shutting down task scheduler.");
scheduler.shutdown();
try {
scheduler.awaitTermination(shutdownTimeout, shutdownTimeoutUnit);
scheduler.shutdownNow();
} catch (InterruptedException e) {
log.info("Shutting down task scheduler failed.", e);
}
}
}
@Override
public void schedulePeriodicTask(Task task, Function scheduleRateFunction) {
Lang.denyNull("task", task);
Lang.denyNull("scheduleRateFunction", scheduleRateFunction);
checkState();
TaskExecution execution = new TaskExecution(this, task, scheduleRateFunction);
Long initialRate = getInitialRate(scheduleRateFunction);
execution.setCurrentRate(initialRate);
ScheduledFuture> future = scheduler.scheduleAtFixedRate(execution, 0, initialRate, TimeUnit.MILLISECONDS);
execution.setFuture(future);
tasks.put(task, execution);
}
@Override
public void unschedulePeriodicTask(Task task) {
Lang.denyNull("task", task);
if (tasks.containsKey(task)) {
TaskExecution taskExecution = tasks.get(task);
tasks.remove(task);
taskExecution.cancel();
} else {
throw new NoSuchElementException("Attempt to unschedule an unknown task.");
}
}
public void reschedule(TaskExecution execution, Long newRate) {
try {
ScheduledFuture> future = scheduler.scheduleAtFixedRate(execution, newRate, normalizeRate(newRate),
TimeUnit.MILLISECONDS);
execution.setFuture(future);
} catch (RejectedExecutionException e) {
execution.wasRejected();
}
}
protected static long normalizeRate(long rate) {
return Math.max(500l, rate);
}
private Long getInitialRate(Function scheduleRateFunction) {
return normalizeRate(scheduleRateFunction.apply(true));
}
@Override
public List getSchedulerInfo() {
checkState();
List info = new LinkedList<>();
Iterator it = tasks.values()
.iterator();
while (it.hasNext()) {
TaskExecution e = it.next();
info.add(e.getTaskInfo());
}
return info;
}
@Override
public Thread newThread(Runnable r) {
Thread newThread = new Thread(r, "Limbus Task Scheduler - Thread " + threadCount.incrementAndGet());
return newThread;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy