diff --git a/docs/input-folder-scheduler-plan.md b/docs/input-folder-scheduler-plan.md index 4e58564..32b34c8 100644 --- a/docs/input-folder-scheduler-plan.md +++ b/docs/input-folder-scheduler-plan.md @@ -26,7 +26,7 @@ Note: the local machine's filesystem root is read-only in this workspace, so abs 6. [x] Add valid-video detection using extension filtering and `ffprobe`. 7. [x] Add invalid-file handling that logs the reason and moves files to rejected storage. 8. [x] Add FFmpeg clipping into `/output/clips//` using 8-second MP4/H.264/AAC segments. -9. [ ] Add success handling that moves processed source files to processed storage. +9. [x] Add success handling that moves processed source files to processed storage. 10. [ ] Add failure handling for FFmpeg or filesystem errors. 11. [ ] Add unit tests for ordering, invalid-file handling, repeat prevention, and state transitions. 12. [ ] Add optional FFmpeg integration test for a short fixture. diff --git a/src/main/java/org/example/videoclips/folder/FolderVideoScanScheduler.java b/src/main/java/org/example/videoclips/folder/FolderVideoScanScheduler.java index d8278f5..de6e539 100644 --- a/src/main/java/org/example/videoclips/folder/FolderVideoScanScheduler.java +++ b/src/main/java/org/example/videoclips/folder/FolderVideoScanScheduler.java @@ -65,6 +65,8 @@ public class FolderVideoScanScheduler { log.info("Validated folder video candidate: {}", workingFile.getFileName()); FolderFfmpegClipper.ClipResult clipResult = clipper.clip(workingFile); log.info("Generated {} clips in {}", clipResult.clipCount(), clipResult.outputDirectory().getFileName()); + Path processedFile = moveToDirectory(workingFile, Path.of(properties.getProcessedDirectory())); + log.info("Moved successfully processed source to processed storage: {}", processedFile.getFileName()); return; } diff --git a/src/test/java/org/example/videoclips/folder/FolderVideoScanSchedulerTest.java b/src/test/java/org/example/videoclips/folder/FolderVideoScanSchedulerTest.java index 4255e87..ce7e9c6 100644 --- a/src/test/java/org/example/videoclips/folder/FolderVideoScanSchedulerTest.java +++ b/src/test/java/org/example/videoclips/folder/FolderVideoScanSchedulerTest.java @@ -96,7 +96,7 @@ class FolderVideoScanSchedulerTest { assertFalse(((AtomicBoolean) scanningField.get(scheduler)).get()); assertFalse(Files.exists(tempDir.resolve("1.mp4"))); - assertTrue(Files.exists(tempDir.resolve("working/1.mp4"))); + assertTrue(Files.exists(tempDir.resolve("processed/1.mp4"))); } @Test @@ -118,7 +118,7 @@ class FolderVideoScanSchedulerTest { scheduler.scan(); assertTrue(scheduler.findNextCandidate().isEmpty()); - assertEquals("video", Files.readString(tempDir.resolve("working/1.mp4"))); + assertEquals("video", Files.readString(tempDir.resolve("processed/1.mp4"))); } @Test @@ -147,6 +147,18 @@ class FolderVideoScanSchedulerTest { assertTrue(Files.exists(tempDir.resolve("working/invalid.mp4"))); } + @Test + void doesNotOverwriteExistingProcessedSource() throws Exception { + Files.writeString(tempDir.resolve("1.mp4"), "new video"); + Files.createDirectory(tempDir.resolve("processed")); + Files.writeString(tempDir.resolve("processed/1.mp4"), "existing video"); + + assertThrows(IllegalStateException.class, () -> scheduler(tempDir).scan()); + + assertEquals("existing video", Files.readString(tempDir.resolve("processed/1.mp4"))); + assertEquals("new video", Files.readString(tempDir.resolve("working/1.mp4"))); + } + @Test void failsWhenCandidateCannotBeMovedToWorkingDirectory() throws Exception { Path candidate = Files.writeString(tempDir.resolve("1.mp4"), "video"); @@ -189,6 +201,13 @@ class FolderVideoScanSchedulerTest { throw new IllegalStateException(ex); } properties.getFolderScheduler().setRejectedDirectory(rejectedDirectory.toString()); + Path processedDirectory = tempDir.resolve("processed"); + try { + Files.createDirectories(processedDirectory); + } catch (Exception ex) { + throw new IllegalStateException(ex); + } + properties.getFolderScheduler().setProcessedDirectory(processedDirectory.toString()); return new FolderVideoScanScheduler(properties, validator, clipper); }