package com.zendesk.maxwell.util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.concurrent.TimeoutException; public class TaskManager { private static final Logger LOGGER = LoggerFactory.getLogger(TaskManager.class); private final ArrayList<StoppableTask> tasks; private volatile RunState state; public TaskManager() { this.tasks = new ArrayList<>(); this.state = RunState.RUNNING; } // Can be invoked multiple times, will only return `true` // for the first invocation. public synchronized boolean requestStop() { if (state == RunState.RUNNING) { state = RunState.REQUEST_STOP; return true; } else { return false; } } public synchronized void stop(Exception error) { if (this.state == RunState.STOPPED) { LOGGER.debug("stop() called multiple times"); return; } this.state = RunState.REQUEST_STOP; LOGGER.info("stopping " + tasks.size() + " tasks"); if (error != null) { LOGGER.error("cause: ", error); } // tell everything to stop for (StoppableTask task: this.tasks) { task.requestStop(); } // then wait for everything to stop Long timeout = 500L; for (StoppableTask task: this.tasks) { try { task.awaitStop(timeout); } catch (TimeoutException e) { LOGGER.error(e.getMessage()); } } this.state = RunState.STOPPED; LOGGER.info("stopped all tasks"); } public synchronized void add(StoppableTask task) { synchronized (tasks) { tasks.add(task); } } }