diff --git a/app/common/src/main/java/stirling/software/common/service/TempFileCleanupService.java b/app/common/src/main/java/stirling/software/common/service/TempFileCleanupService.java index 81b45aed09..438481c212 100644 --- a/app/common/src/main/java/stirling/software/common/service/TempFileCleanupService.java +++ b/app/common/src/main/java/stirling/software/common/service/TempFileCleanupService.java @@ -144,8 +144,10 @@ public class TempFileCleanupService { int directoriesDeletedCount = 0; for (Path directory : registry.getTempDirectories()) { try { - if (Files.exists(directory)) { + if (Files.exists(directory) + && shouldDeleteRegisteredDirectory(directory, maxAgeMillis)) { GeneralUtils.deleteDirectory(directory); + registry.unregisterDirectory(directory); directoriesDeletedCount++; log.debug("Cleaned up temporary directory: {}", directory); } @@ -275,6 +277,21 @@ public class TempFileCleanupService { return totalDeletedCount.get(); } + private boolean shouldDeleteRegisteredDirectory(Path directory, long maxAgeMillis) { + if (maxAgeMillis <= 0) { + return true; + } + + try { + long currentTime = System.currentTimeMillis(); + long lastModified = Files.getLastModifiedTime(directory).toMillis(); + return (currentTime - lastModified) > maxAgeMillis; + } catch (IOException e) { + log.debug("Could not check directory age, skipping cleanup: {}", directory, e); + return false; + } + } + /** Get the system temp directory path based on configuration or system property. */ private Path getSystemTempPath() { String systemTempDir = diff --git a/app/common/src/main/java/stirling/software/common/util/TempFileManager.java b/app/common/src/main/java/stirling/software/common/util/TempFileManager.java index ff31975837..0d977e7d06 100644 --- a/app/common/src/main/java/stirling/software/common/util/TempFileManager.java +++ b/app/common/src/main/java/stirling/software/common/util/TempFileManager.java @@ -155,6 +155,7 @@ public class TempFileManager { if (directory != null && Files.isDirectory(directory)) { try { GeneralUtils.deleteDirectory(directory); + registry.unregisterDirectory(directory); log.debug("Deleted temp directory: {}", directory.toString()); } catch (IOException e) { log.warn("Failed to delete temp directory: {}", directory.toString(), e); diff --git a/app/common/src/main/java/stirling/software/common/util/TempFileRegistry.java b/app/common/src/main/java/stirling/software/common/util/TempFileRegistry.java index ab1304f5e4..84a3c12272 100644 --- a/app/common/src/main/java/stirling/software/common/util/TempFileRegistry.java +++ b/app/common/src/main/java/stirling/software/common/util/TempFileRegistry.java @@ -85,6 +85,18 @@ public class TempFileRegistry { return directory; } + /** + * Unregister a temporary directory from the registry. + * + * @param directory The directory to unregister + */ + public void unregisterDirectory(Path directory) { + if (directory != null) { + tempDirectories.remove(directory); + log.debug("Unregistered temp directory: {}", directory.toString()); + } + } + /** * Register a third-party temporary file that requires special handling. * diff --git a/app/common/src/test/java/stirling/software/common/service/TempFileCleanupServiceMoreTest.java b/app/common/src/test/java/stirling/software/common/service/TempFileCleanupServiceMoreTest.java index 802dc2eace..cfbe950574 100644 --- a/app/common/src/test/java/stirling/software/common/service/TempFileCleanupServiceMoreTest.java +++ b/app/common/src/test/java/stirling/software/common/service/TempFileCleanupServiceMoreTest.java @@ -176,11 +176,13 @@ class TempFileCleanupServiceMoreTest { class ScheduledCleanup { @Test - @DisplayName("deletes registered temp directories and reports counts") + @DisplayName("deletes stale registered temp directories and reports counts") void deletesRegisteredDirectories() throws IOException { when(tempFileManager.cleanupOldTempFiles(anyLong())).thenReturn(2); Path regDir = Files.createDirectories(tempDir.resolve("registeredDir")); Files.createFile(regDir.resolve("inside.txt")); + Files.setLastModifiedTime( + regDir, FileTime.fromMillis(System.currentTimeMillis() - 2L * 60 * 60 * 1000)); Set dirs = new HashSet<>(); dirs.add(regDir); when(registry.getTempDirectories()).thenReturn(dirs); @@ -193,6 +195,22 @@ class TempFileCleanupServiceMoreTest { verify(tempFileManager).cleanupOldTempFiles(anyLong()); } + @Test + @DisplayName("keeps a fresh registered temp directory") + void keepsFreshRegisteredDirectory() throws IOException { + when(tempFileManager.cleanupOldTempFiles(anyLong())).thenReturn(0); + Path regDir = Files.createDirectories(tempDir.resolve("freshRegisteredDir")); + Files.createFile(regDir.resolve("inside.txt")); + Set dirs = new HashSet<>(); + dirs.add(regDir); + when(registry.getTempDirectories()).thenReturn(dirs); + lenient().when(registry.contains(any(File.class))).thenReturn(false); + + withIsolatedUserHome(cleanupService::scheduledCleanup); + + assertThat(Files.exists(regDir)).isTrue(); + } + @Test @DisplayName("skips a registered directory that no longer exists") void skipsMissingRegisteredDirectory() {