diff --git a/src/main/java/life/qbic/data/processing/AppConfig.java b/src/main/java/life/qbic/data/processing/AppConfig.java index 900dc9a..680597f 100644 --- a/src/main/java/life/qbic/data/processing/AppConfig.java +++ b/src/main/java/life/qbic/data/processing/AppConfig.java @@ -28,8 +28,8 @@ class AppConfig { @Bean ScannerConfiguration scannerConfiguration( @Value("${scanner.directory}") String scannerDirectory, - @Value("${scanner.interval}") int interval) { - return new ScannerConfiguration(scannerDirectory, interval); + @Value("${scanner.interval}") int interval, @Value("${scanner.ignore}") String[] ignore) { + return new ScannerConfiguration(scannerDirectory, interval, ignore); } @Bean diff --git a/src/main/java/life/qbic/data/processing/Application.java b/src/main/java/life/qbic/data/processing/Application.java index 268da61..1696c15 100644 --- a/src/main/java/life/qbic/data/processing/Application.java +++ b/src/main/java/life/qbic/data/processing/Application.java @@ -75,6 +75,8 @@ public static void main(String[] args) { registrationWorkers.forEach(Thread::interrupt); processingWorkers.forEach(Thread::interrupt); evaluationWorkers.forEach(Thread::interrupt); + // if every worker thread has shut down successfully, the application can exit with status code 0 + Runtime.getRuntime().halt(0); }, "Shutdown-thread")); } diff --git a/src/main/java/life/qbic/data/processing/evaluation/EvaluationRequest.java b/src/main/java/life/qbic/data/processing/evaluation/EvaluationRequest.java index 51cac39..59a3f80 100644 --- a/src/main/java/life/qbic/data/processing/evaluation/EvaluationRequest.java +++ b/src/main/java/life/qbic/data/processing/evaluation/EvaluationRequest.java @@ -218,7 +218,7 @@ private void moveBackToOrigin(File taskDir, Provenance provenance, String reason Paths.get(provenance.userWorkDirectoryPath).resolve(usersErrorDirectory) .resolve(taskDir.getName())); } catch (IOException e) { - LOG.error("Cannot move task to user intervention: %s".formatted(provenance.originPath), e); + LOG.error("Cannot move task to user intervention: %s".formatted(Paths.get(provenance.userWorkDirectoryPath).resolve(usersErrorDirectory)), e); moveToSystemIntervention(taskDir, e.getMessage()); } } diff --git a/src/main/java/life/qbic/data/processing/scanner/Scanner.java b/src/main/java/life/qbic/data/processing/scanner/Scanner.java index 8ef44cd..fa32692 100644 --- a/src/main/java/life/qbic/data/processing/scanner/Scanner.java +++ b/src/main/java/life/qbic/data/processing/scanner/Scanner.java @@ -14,6 +14,7 @@ import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.Set; import life.qbic.data.processing.ConcurrentRegistrationQueue; import life.qbic.data.processing.GlobalConfig; import life.qbic.data.processing.registration.RegistrationRequest; @@ -41,6 +42,7 @@ public class Scanner extends Thread { private final HashSet userProcessDirectories = new HashSet<>(); private final ConcurrentRegistrationQueue registrationQueue; private final HashSet submittedRequests = new HashSet<>(); + private final Set ignoredDirectories = new HashSet<>(); public Scanner(ScannerConfiguration scannerConfiguration, ConcurrentRegistrationQueue registrationQueue, GlobalConfig globalConfig) { @@ -53,6 +55,14 @@ public Scanner(ScannerConfiguration scannerConfiguration, this.scanInterval = scannerConfiguration.scanInterval(); this.registrationQueue = Objects.requireNonNull(registrationQueue, "registrationQueue must not be null"); + this.ignoredDirectories.addAll(scannerConfiguration.ignore()); + if (!this.ignoredDirectories.isEmpty()) { + log.info("Ignoring {} directories", ignoredDirectories.size()); + } + } + + private boolean notToIgnore(String filename) { + return !ignoredDirectories.contains(filename); } @Override @@ -62,6 +72,7 @@ public void run() { try { var userFolderIterator = Arrays.stream( Objects.requireNonNull(scannerPath.toFile().listFiles())).filter(File::isDirectory) + .filter(file -> notToIgnore(file.getName())) .toList().iterator(); while (userFolderIterator.hasNext()) { diff --git a/src/main/java/life/qbic/data/processing/scanner/ScannerConfiguration.java b/src/main/java/life/qbic/data/processing/scanner/ScannerConfiguration.java index 052ed75..ac558b1 100644 --- a/src/main/java/life/qbic/data/processing/scanner/ScannerConfiguration.java +++ b/src/main/java/life/qbic/data/processing/scanner/ScannerConfiguration.java @@ -1,16 +1,22 @@ package life.qbic.data.processing.scanner; +import java.util.Arrays; +import java.util.Collection; +import java.util.Objects; + public class ScannerConfiguration { private final String scannerDirectory; private final int scanInterval; + private final String[] ignore; - public ScannerConfiguration(String scannerDirectory, int interval) { + public ScannerConfiguration(String scannerDirectory, int interval, String[] ignore) { this.scannerDirectory = scannerDirectory; if (interval <= 0) { throw new IllegalArgumentException("Interval must be greater than 0"); } this.scanInterval = interval; + this.ignore = Arrays.copyOf(Objects.requireNonNull(ignore), ignore.length); } public String scannerDirectory() { @@ -20,4 +26,8 @@ public String scannerDirectory() { public int scanInterval() { return scanInterval; } + + public Collection ignore () { + return Arrays.stream(ignore).toList(); + } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 3900cde..10abf93 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -16,6 +16,9 @@ users.error.directory.name=error # Path to the directory that contains all user directories # e.g. /home in Linux or /Users in macOS scanner.directory=${SCANNER_DIR:/home} +# Ignored directories are skipped during scanning +# your can provide a list of comma-separated names if you want to ignore multiple directories +scanner.ignore=${SCANNER_IGNORE:} # The time interval (milliseconds) the scanner thread iterates through the scanner directory # Value must be an integer > 0 scanner.interval=1000