Allow custom restart pollInterval and quietPeriod

Allow the pollInterval and the quietPeriod of the filewatcher to be
configured.

Fixes gh-3139
pull/3096/merge
Phillip Webb 10 years ago
parent 7bcd6567ba
commit d0349879c3

@ -29,6 +29,10 @@ public class DevToolsProperties {
private static final String DEFAULT_RESTART_EXCLUDES = "META-INF/resources/**,resource/**,static/**,public/**,templates/**";
private static final long DEFAULT_RESTART_POLL_INTERVAL = 1000;
private static final long DEFAULT_RESTART_QUIET_PERIOD = 400;
private Restart restart = new Restart();
private Livereload livereload = new Livereload();
@ -62,6 +66,17 @@ public class DevToolsProperties {
*/
private String exclude = DEFAULT_RESTART_EXCLUDES;
/**
* Amount of time (in milliseconds) to wait between polling for classpath changes.
*/
private long pollInterval = DEFAULT_RESTART_POLL_INTERVAL;
/**
* Amount of quiet time (in milliseconds) requited without any classpath changes
* before a restart is triggered.
*/
private long quietPeriod = DEFAULT_RESTART_QUIET_PERIOD;
/**
* The name of specific that that when changed will will trigger the restart. If
* not specified any classpath file change will trigger the restart.
@ -84,6 +99,22 @@ public class DevToolsProperties {
this.exclude = exclude;
}
public long getPollInterval() {
return this.pollInterval;
}
public void setPollInterval(long pollInterval) {
this.pollInterval = pollInterval;
}
public long getQuietPeriod() {
return this.quietPeriod;
}
public void setQuietPeriod(long quietPeriod) {
this.quietPeriod = quietPeriod;
}
public String getTriggerFile() {
return this.triggerFile;
}

@ -23,6 +23,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.devtools.autoconfigure.DevToolsProperties.Restart;
import org.springframework.boot.devtools.classpath.ClassPathChangedEvent;
import org.springframework.boot.devtools.classpath.ClassPathFileSystemWatcher;
import org.springframework.boot.devtools.classpath.ClassPathRestartStrategy;
@ -130,8 +131,11 @@ public class LocalDevToolsAutoConfiguration {
@Bean
public FileSystemWatcher getFileSystemWatcher() {
FileSystemWatcher watcher = new FileSystemWatcher();
String triggerFile = this.properties.getRestart().getTriggerFile();
Restart restartProperties = this.properties.getRestart();
FileSystemWatcher watcher = new FileSystemWatcher(true,
restartProperties.getPollInterval(),
restartProperties.getQuietPeriod());
String triggerFile = restartProperties.getTriggerFile();
if (StringUtils.hasLength(triggerFile)) {
watcher.setTriggerFilter(new TriggerFileFilter(triggerFile));
}

@ -40,17 +40,17 @@ import org.springframework.util.Assert;
*/
public class FileSystemWatcher {
private static final long DEFAULT_IDLE_TIME = 400;
private static final long DEFAULT_POLL_INTERVAL = 1000;
private static final long DEFAULT_QUIET_TIME = 200;
private static final long DEFAULT_QUIET_PERIOD = 400;
private List<FileChangeListener> listeners = new ArrayList<FileChangeListener>();
private final boolean daemon;
private final long idleTime;
private final long pollInterval;
private final long quietTime;
private final long quietPeriod;
private Thread watchThread;
@ -64,20 +64,24 @@ public class FileSystemWatcher {
* Create a new {@link FileSystemWatcher} instance.
*/
public FileSystemWatcher() {
this(true, DEFAULT_IDLE_TIME, DEFAULT_QUIET_TIME);
this(true, DEFAULT_POLL_INTERVAL, DEFAULT_QUIET_PERIOD);
}
/**
* Create a new {@link FileSystemWatcher} instance.
* @param daemon if a daemon thread used to monitor changes
* @param idleTime the amount of time to wait between checking for changes
* @param quietTime the amount of time required after a change has been detected to
* @param pollInterval the amount of time to wait between checking for changes
* @param quietPeriod the amount of time required after a change has been detected to
* ensure that updates have completed
*/
public FileSystemWatcher(boolean daemon, long idleTime, long quietTime) {
public FileSystemWatcher(boolean daemon, long pollInterval, long quietPeriod) {
Assert.isTrue(pollInterval > 0, "PollInterval must be positive");
Assert.isTrue(quietPeriod > 0, "QuietPeriod must be positive");
Assert.isTrue(pollInterval > quietPeriod,
"PollInterval must be greater than QuietPeriod");
this.daemon = daemon;
this.idleTime = idleTime;
this.quietTime = quietTime;
this.pollInterval = pollInterval;
this.quietPeriod = quietPeriod;
}
/**
@ -131,10 +135,10 @@ public class FileSystemWatcher {
FileSystemWatcher.this.remainingScans.decrementAndGet();
}
scan();
remainingScans = FileSystemWatcher.this.remainingScans.get();
}
catch (InterruptedException ex) {
}
remainingScans = FileSystemWatcher.this.remainingScans.get();
}
};
};
@ -152,13 +156,13 @@ public class FileSystemWatcher {
}
private void scan() throws InterruptedException {
Thread.sleep(this.idleTime - this.quietTime);
Thread.sleep(this.pollInterval - this.quietPeriod);
Map<File, FolderSnapshot> previous;
Map<File, FolderSnapshot> current = this.folders;
do {
previous = current;
current = getCurrentSnapshots();
Thread.sleep(this.quietTime);
Thread.sleep(this.quietPeriod);
}
while (isDifferent(previous, current));
if (isDifferent(this.folders, current)) {
@ -228,6 +232,7 @@ public class FileSystemWatcher {
Thread thread = this.watchThread;
if (thread != null) {
this.remainingScans.set(remainingScans);
thread.interrupt();
if (Thread.currentThread() != thread) {
try {
thread.join();

@ -34,6 +34,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.devtools.autoconfigure.DevToolsProperties;
import org.springframework.boot.devtools.autoconfigure.DevToolsProperties.Restart;
import org.springframework.boot.devtools.autoconfigure.OptionalLiveReloadServer;
import org.springframework.boot.devtools.autoconfigure.RemoteDevToolsProperties;
import org.springframework.boot.devtools.autoconfigure.TriggerFileFilter;
@ -187,8 +188,11 @@ public class RemoteClientConfiguration {
@Bean
public FileSystemWatcher getFileSystemWather() {
FileSystemWatcher watcher = new FileSystemWatcher();
String triggerFile = this.properties.getRestart().getTriggerFile();
Restart restartProperties = this.properties.getRestart();
FileSystemWatcher watcher = new FileSystemWatcher(true,
restartProperties.getPollInterval(),
restartProperties.getQuietPeriod());
String triggerFile = restartProperties.getTriggerFile();
if (StringUtils.hasLength(triggerFile)) {
watcher.setTriggerFilter(new TriggerFileFilter(triggerFile));
}

@ -64,6 +64,27 @@ public class FileSystemWatcherTests {
setupWatcher(20, 10);
}
@Test
public void pollIntervalMustBePositive() throws Exception {
this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("PollInterval must be positive");
new FileSystemWatcher(true, 0, 1);
}
@Test
public void quietPeriodMustBePositive() throws Exception {
this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("QuietPeriod must be positive");
new FileSystemWatcher(true, 1, 0);
}
@Test
public void pollIntervalMustBeGreaterThanQuietPeriod() throws Exception {
this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("PollInterval must be greater than QuietPeriod");
new FileSystemWatcher(true, 1, 1);
}
@Test
public void listenerMustNotBeNull() throws Exception {
this.thrown.expect(IllegalArgumentException.class);
@ -117,7 +138,7 @@ public class FileSystemWatcherTests {
@Test
public void waitsForIdleTime() throws Exception {
this.changes.clear();
setupWatcher(100, 0);
setupWatcher(100, 1);
File folder = startWithNewFolder();
touch(new File(folder, "test1.txt"));
Thread.sleep(200);

@ -26,5 +26,4 @@ public class SampleDevToolsApplication extends WebMvcAutoConfigurationAdapter {
public static void main(String[] args) {
SpringApplication.run(SampleDevToolsApplication.class, args);
}
}

@ -1,2 +1,3 @@
spring.devtools.remote.secret=secret
# spring.devtools.restart.poll-interval=10000
# spring.devtools.restart.trigger-file=.reloadtrigger

Loading…
Cancel
Save