feat: File watching service

This commit is contained in:
Piotr Dec 2024-07-16 23:39:47 +02:00
parent 8d03c86c8f
commit 12ca1369f3
Signed by: stawros
GPG key ID: F89F27AD8F881A91
2 changed files with 81 additions and 0 deletions

View file

@ -0,0 +1,5 @@
package eu.ztsh.lfr.files;
public record FileModifiedEvent(long timestamp) {
}

View file

@ -0,0 +1,76 @@
package eu.ztsh.lfr.files;
import eu.ztsh.lfr.config.DataProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
@Service
public class WatcherService {
private static final Logger log = LoggerFactory.getLogger(WatcherService.class);
private final WatchService watchService;
private final ApplicationEventPublisher eventPublisher;
private final String fileName;
@Autowired
public WatcherService(DataProperties dataProperties, ApplicationEventPublisher eventPublisher) throws IOException {
this.eventPublisher = eventPublisher;
this.watchService = FileSystems.getDefault().newWatchService();
var filePath = Paths.get(dataProperties.fileUrl());
fileName = filePath.getFileName().toString();
filePath.getParent().register(
watchService,
// register file creation as some editors modify files in temp, and then replaces original file.
StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_MODIFY
);
}
@SuppressWarnings("BusyWait")
@EventListener(ApplicationReadyEvent.class)
public void watch() throws InterruptedException {
WatchKey key;
while ((key = watchService.take()) != null) {
/*
When modifying in IntelliJ, one line edit ends with:
ENTRY_CREATE: temperatures.csv~
ENTRY_MODIFY: temperatures.csv~
ENTRY_MODIFY: temperatures.csv~
ENTRY_MODIFY: temperatures.csv
ENTRY_MODIFY: temperatures.csv
ENTRY_MODIFY: temperatures.csv
Thread.sleep is used to filter out duplicated events.
origin: https://stackoverflow.com/a/25221600
*/
Thread.sleep(50);
var maybeLastEvent = key.pollEvents().stream()
.filter(event -> event.context() != null)
.filter(event -> event.context().toString().endsWith(fileName))
.reduce((o1, o2) -> o2);
if (maybeLastEvent.isPresent()) {
var lastEvent = maybeLastEvent.get();
log.info("Got event of kind:{}", lastEvent.kind());
eventPublisher.publishEvent(new FileModifiedEvent(System.currentTimeMillis()));
} else {
log.trace("Got event for not watched file");
}
key.reset();
}
}
}