forked from jsl/video_editing_poc
Complete folder scheduler verification
This commit is contained in:
parent
8e67566f0d
commit
c08acb5f18
|
|
@ -31,7 +31,7 @@ Note: the local machine's filesystem root is read-only in this workspace, so abs
|
|||
11. [x] Add unit tests for ordering, invalid-file handling, repeat prevention, and state transitions.
|
||||
12. [x] Add optional FFmpeg integration test for a short fixture.
|
||||
13. [x] Add local profile or documented runtime config for enabling the scheduler.
|
||||
14. [ ] Run verification and mark feature complete.
|
||||
14. [x] Run verification and mark feature complete.
|
||||
|
||||
## Format Recommendation
|
||||
|
||||
|
|
@ -87,8 +87,20 @@ mvn spring-boot:run -Dspring-boot.run.profiles=folder-scheduler-local
|
|||
|
||||
Place source videos in `input/source`. The service creates `input/working`, `input/processed`, and `input/rejected` at startup and writes clips to `output/clips/<video-name>`.
|
||||
|
||||
Producers must copy files with a temporary `.part`, `.tmp`, or `.download` suffix and atomically rename them to the final video filename only after the write completes. The scheduler ignores these temporary suffixes, preventing partially written videos from being rejected by `ffprobe`.
|
||||
|
||||
For production, keep the default absolute paths and mount persistent writable volumes at `/input` and `/output`. Run only one scheduler replica unless a cross-process lease is added.
|
||||
|
||||
## Completion Status
|
||||
|
||||
Completed on 2026-07-10.
|
||||
|
||||
- `mvn -q clean verify`: passed with 57 tests, 0 failures, 0 errors, and 0 skipped tests.
|
||||
- Real FFmpeg integration: a generated 17-second H.264/AAC source produced 3 MP4 clips.
|
||||
- JaCoCo scheduler package coverage: 1,009/1,009 instructions, 52/52 branches, and 205/205 lines covered (100%).
|
||||
- Coverage enforcement and the HTML/XML/CSV report run automatically during Maven `verify`.
|
||||
- Final review fixed conditional Spring component creation and explicit constructor injection; the disabled default profile and enabled scheduler pipeline both have context tests.
|
||||
|
||||
## Processing Rules
|
||||
|
||||
The scheduler should:
|
||||
|
|
|
|||
7
pom.xml
7
pom.xml
|
|
@ -135,6 +135,13 @@
|
|||
</rules>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>coverage-report</id>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>report</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package org.example.videoclips.folder;
|
||||
|
||||
import org.example.videoclips.config.VideoClippingProperties;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
|
|
@ -11,11 +13,13 @@ import java.util.List;
|
|||
import java.util.stream.Stream;
|
||||
|
||||
@Component
|
||||
@ConditionalOnProperty(name = "video-clipping.folder-scheduler.enabled", havingValue = "true")
|
||||
public class FolderFfmpegClipper {
|
||||
|
||||
private final VideoClippingProperties.FolderScheduler properties;
|
||||
private final ProcessExecutor processExecutor;
|
||||
|
||||
@Autowired
|
||||
public FolderFfmpegClipper(VideoClippingProperties videoClippingProperties) {
|
||||
this(videoClippingProperties, FolderFfmpegClipper::execute);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package org.example.videoclips.folder;
|
||||
|
||||
import org.example.videoclips.config.VideoClippingProperties;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
|
|
@ -13,6 +15,7 @@ import java.util.regex.Matcher;
|
|||
import java.util.regex.Pattern;
|
||||
|
||||
@Component
|
||||
@ConditionalOnProperty(name = "video-clipping.folder-scheduler.enabled", havingValue = "true")
|
||||
public class FolderVideoValidator {
|
||||
|
||||
private static final Set<String> ALLOWED_EXTENSIONS = Set.of("mp4", "mov", "m4v", "webm", "mkv");
|
||||
|
|
@ -20,6 +23,7 @@ public class FolderVideoValidator {
|
|||
private final VideoClippingProperties.FolderScheduler properties;
|
||||
private final ProcessExecutor processExecutor;
|
||||
|
||||
@Autowired
|
||||
public FolderVideoValidator(VideoClippingProperties videoClippingProperties) {
|
||||
this(videoClippingProperties, FolderVideoValidator::execute);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
package org.example.videoclips.folder;
|
||||
|
||||
import org.example.videoclips.config.VideoClippingProperties;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class FolderSchedulerSpringContextTest {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withBean(VideoClippingProperties.class)
|
||||
.withUserConfiguration(
|
||||
FolderVideoValidator.class,
|
||||
FolderFfmpegClipper.class,
|
||||
FolderVideoScanScheduler.class
|
||||
);
|
||||
|
||||
@Test
|
||||
void createsCompleteSchedulerPipelineWhenEnabled() {
|
||||
contextRunner
|
||||
.withPropertyValues("video-clipping.folder-scheduler.enabled=true")
|
||||
.run(context -> {
|
||||
assertThat(context).hasSingleBean(FolderVideoValidator.class);
|
||||
assertThat(context).hasSingleBean(FolderFfmpegClipper.class);
|
||||
assertThat(context).hasSingleBean(FolderVideoScanScheduler.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void doesNotCreateSchedulerPipelineWhenDisabled() {
|
||||
contextRunner.run(context -> {
|
||||
assertThat(context).doesNotHaveBean(FolderVideoValidator.class);
|
||||
assertThat(context).doesNotHaveBean(FolderFfmpegClipper.class);
|
||||
assertThat(context).doesNotHaveBean(FolderVideoScanScheduler.class);
|
||||
});
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue