Switch from TimerTask to ScheduledExecutorService for more robustness

This commit is contained in:
Tom Morris 2013-08-18 11:31:03 -04:00
parent 25a3de410f
commit 4529310237
2 changed files with 27 additions and 30 deletions

View File

@ -41,8 +41,9 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@ -80,23 +81,19 @@ public class RefineServlet extends Butterfly {
static final private Map<String, Command> commands = new HashMap<String, Command>();
// timer for periodically saving projects
static private Timer _timer = new Timer("autosave");
static private ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
static final Logger logger = LoggerFactory.getLogger("refine");
static final protected long s_autoSavePeriod = 1000 * 60 * 5; // 5 minutes
static final protected long AUTOSAVE_PERIOD = 5; // 5 minutes
static protected class AutoSaveTimerTask extends TimerTask {
static protected class AutoSaveTimerTask implements Runnable {
@Override
public void run() {
try {
ProjectManager.singleton.save(false); // quick, potentially incomplete save
} finally {
if (_timer != null) {
_timer.schedule(new AutoSaveTimerTask(), s_autoSavePeriod);
// we don't use scheduleAtFixedRate because that might result in
// bunched up events when the computer is put in sleep mode
}
} catch (final Throwable e) {
// Not the best, but we REALLY want this to keep trying
}
}
}
@ -134,7 +131,8 @@ public class RefineServlet extends Butterfly {
FileProjectManager.initialize(s_dataDir);
ImportingManager.initialize(this);
_timer.schedule(new AutoSaveTimerTask(), s_autoSavePeriod);
service.scheduleWithFixedDelay(new AutoSaveTimerTask(), AUTOSAVE_PERIOD,
AUTOSAVE_PERIOD, TimeUnit.MINUTES);
logger.trace("< initialize");
}

View File

@ -35,6 +35,8 @@ package com.google.refine.importing;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@ -43,8 +45,9 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.FileUtils;
import org.json.JSONException;
@ -104,29 +107,25 @@ public class ImportingManager {
final static public Map<String, ImportingController> controllers = new HashMap<String, ImportingController>();
// timer for periodically deleting stale importing jobs
static private Timer _timer;
static private ScheduledExecutorService service;
final static private long s_timerPeriod = 1000 * 60 * 10; // 10 minutes
final static private long s_stalePeriod = 1000 * 60 * 60; // 60 minutes
final static private long TIMER_PERIOD = 10; // 10 minutes
final static private long STALE_PERIOD = 60; // 60 minutes
static private class CleaningTimerTask extends TimerTask {
static private class CleaningTimerTask implements Runnable {
@Override
public void run() {
try {
cleanUpStaleJobs();
} finally {
_timer.schedule(new CleaningTimerTask(), s_timerPeriod);
// we don't use scheduleAtFixedRate because that might result in
// bunched up events when the computer is put in sleep mode
}
// An exception here will keep future runs of this task from happening,
// but won't affect other timer tasks
cleanUpStaleJobs();
}
}
static public void initialize(RefineServlet servlet) {
ImportingManager.servlet = servlet;
_timer = new Timer("autosave");
_timer.schedule(new CleaningTimerTask(), s_timerPeriod);
service = Executors.newSingleThreadScheduledExecutor();
service.scheduleWithFixedDelay(new CleaningTimerTask(), TIMER_PERIOD, TIMER_PERIOD, TimeUnit.MINUTES);
}
static public void registerFormat(String format, String label) {
@ -289,13 +288,13 @@ public class ImportingManager {
static private void cleanUpStaleJobs() {
long now = System.currentTimeMillis();
HashSet<Long> keys;
Collection<Long> keys;
synchronized(jobs) {
keys = new HashSet<Long>(jobs.keySet());
keys = new ArrayList<Long>(jobs.keySet());
}
for (Long id : keys) {
ImportingJob job = jobs.get(id);
if (job != null && !job.updating && now - job.lastTouched > s_stalePeriod) {
if (job != null && !job.updating && now - job.lastTouched > STALE_PERIOD) {
job.dispose();
jobs.remove(id);
logger.info("Disposed " + id);