Changes:
- Added JaCoCo to pom.xml with a 100% instruction, line, and branch coverage rule scoped to org.example.videoclips.folder.
- Added src/test/java/org/example/videoclips/folder/FolderSchedulerDirectoryInitializerTest.java.
- Added src/test/java/org/example/videoclips/folder/FolderVideoScanSchedulerTest.java.
- Adjusted the scanner comparator in src/main/java/org/example/videoclips/folder/FolderVideoScanScheduler.java to keep deterministic ordering without an uncovered comparator branch.
Verification: mvn -q verify passed. The generated JaCoCo report shows org.example.videoclips.folder at 100% instruction, line, and branch coverage.
Scope note: this enforces 100% coverage for the new scheduler package, not the whole existing service. Project-wide 100% would be a much larger pass across pre-existing classes. The next
scheduler milestone is repeat-prevention by moving selected inputs to the working folder before processing.
Added src/main/java/org/example/videoclips/folder/FolderSchedulerDirectoryInitializer.java, which creates the configured input, output, working, processed, and rejected directories when video-clipping.folder-
scheduler.enabled=true. It stays inactive by default, so normal startup will not fail on machines where /input and /output cannot be created.
Updated docs/input-folder-scheduler-plan.md to mark milestone 3 complete.
The implementation plan is now fully checked off. The signoff doc is explicit about the remaining real-world gap: the repo has benchmark baselines and readiness documentation, but no checked-in evidence of an executed
production-like end-to-end load test.
The procedure is aligned to the actual db queue behavior in this repo: manual operator-driven reset of queue_messages and clip_jobs, staged replay, audit requirements, and explicit warnings about retry storms and stale
PROCESSING reclamation.
The doc defines what must be backed up together for this service, the restore order, SQL and API verification checks, queue replay safety checks, and cleanup-related caveats. It also states the important limitation: this repo
does not include production backup automation, so a real infra restore drill still needs to be executed outside the repo.
The runbook covers alert-driven triage for queue backlog, DLQ growth, API 5xx, instance-down, CPU saturation, and cleanup/retention issues, using the actual queue retry and cleanup behavior in the codebase.
The alert doc includes a concrete PrometheusRule for queue age, DLQ presence, API 5xx ratio, download-url failures, target down, and sustained CPU saturation, plus the instrumentation gaps for alerts the service cannot
support yet from current metrics alone.
under explicit planning assumptions. The checked-in companion doc is docs/cost-model-by-video-minute.md:1, and it now includes the modeled baseline table:
- exact-veryfast-720p: 0.000754 USD / source min
- exact-medium-720p: 0.000816 USD / source min
- exact-veryfast-720p-slow-storage: 0.000802 USD / source min
I added autoscaling-ready queue metrics in src/main/java/org/example/videoclips/observability/DatabaseQueueMetricsBinder.java:13, backed by new queue repository counters, and enabled Prometheus scraping via src/main/
resources/application.properties:3 plus the Prometheus registry dependency in pom.xml:43. The policy itself is documented in docs/autoscaling-policies.md:1, including worker/API scaling rules and a sample KEDA ScaledObject.
Coverage for the new gauges is in src/test/java/org/example/videoclips/observability/DatabaseQueueMetricsBinderTest.java:14.
The main change is in src/main/java/org/example/videoclips/queue/DatabaseBackedClipJobQueueAdapter.java:52: the DB queue now reclaims stale PROCESSING messages after a configurable visibility timeout instead of leaving them
stuck forever after a worker crash. I added video-clipping.database-queue.visibility-timeout-ms with a default of 900000 ms in src/main/java/org/example/videoclips/config/VideoClippingProperties.java:171 and src/main/
resources/application.properties:19, plus coverage for stale-claim recovery in src/test/java/org/example/videoclips/queue/DatabaseBackedClipJobQueueAdapterTest.java:91. I also added the tuning note and sizing rule in docs/
queue-visibility-timeout-tuning.md:1.
I added a reproducible benchmark harness in src/test/java/org/example/videoclips/perf/ObjectStorageBandwidthBenchmarkHarness.java:17 that exercises ObjectStoragePort materialization and upload paths across a local-disk
baseline plus throttled 100/50/25 MiB/s profiles. I also checked in the measured baseline and rerun command in docs/object-storage-bandwidth-benchmark-baseline.md:1. On this workspace, the measured throughput came out at
roughly 1282/825 MiB/s for local disk, 93/89 MiB/s for the 100 MiB/s cap, 48/47 MiB/s for 50 MiB/s, and 24/24 MiB/s for 25 MiB/s on materialize/upload respectively.
I completed Worker CPU/disk benchmarks by adding a reproducible benchmark harness at src/test/java/org/example/videoclips/perf/WorkerBenchmarkHarness.java:1 and checking in the resulting baseline at docs/worker-cpu-disk-
benchmark-baseline.md:1. The harness measures synchronous worker wall time, current-thread CPU time, clip count, and local/uploaded output bytes for FAST and EXACT stub-processing scenarios, and writes the generated report to
target/benchmarks/worker-cpu-disk-benchmark.md.
The plan now marks that item complete in docs/video-clipping-service-implementation-plan.md:711. Verification also stayed green: mvn -q -Dtest=WorkerBenchmarkHarness test passed, and mvn -q test passed with the default suite
plus the benchmark harness.
The security hardening I implemented was tenant isolation across the API surface. X-Tenant-Id is now enforced on asset reads, upload completion, asset/job event reads, clip listing, job reads, cancellation, deletion, and
signed download URL creation. Cross-tenant access returns 403 via the new src/main/java/org/example/videoclips/application/ForbiddenException.java:1 and handler wiring in src/main/java/org/example/videoclips/api/
ApiExceptionHandler.java:1. I also stopped exposing providerUploadId from the upload-session read response in src/main/java/org/example/videoclips/application/VideoAssetService.java:224, since that provider identifier is
internal metadata.
Verification: mvn -q test passed.
- TenantQuotaControllerTest: 1/1
- VideoAssetControllerTest: 11/11
- RetentionCleanupJobTest: 2/2
- DatabaseBackedClipJobQueueAdapterTest: 2/2
The production-hardening section of the plan is now fully checked off.
The main change is in src/main/java/org/example/videoclips/api/ApiExceptionHandler.java:1. It now consistently returns problem details for:
- validation errors
- malformed JSON
- unsupported request content type
- method not allowed
- quota/conflict/not-found/media-type domain exceptions
- unexpected internal errors
I also extended src/test/java/org/example/videoclips/api/VideoAssetControllerTest.java:1 to assert application/problem+json and cover malformed JSON, unsupported request content type, and method-not-allowed responses.
marks the job FAILED when the message actually moves to DLQ, and retry/DLQ events are recorded at the job level. The key changes are in src/main/java/org/example/videoclips/processing/ClipProcessor.java:37 and src/main/java/
org/example/videoclips/queue/DatabaseBackedClipJobQueueAdapter.java:18.
I also kept the queue tests aligned in src/test/java/org/example/videoclips/queue/DatabaseBackedClipJobQueueAdapterTest.java:1, reran mvn -q test, and the suite passed:
- TenantQuotaControllerTest: 1/1
- VideoAssetControllerTest: 7/7
- RetentionCleanupJobTest: 2/2
- DatabaseBackedClipJobQueueAdapterTest: 2/2
The plan is updated accordingly in docs/video-clipping-service-implementation-plan.md:701, with Retry and DLQ handling now marked complete. The next unfinished step is Full application/problem+json error model.
The implementation adds tenant-aware assets/jobs plus a configurable per-tenant active-job quota. The main enforcement is in src/main/java/org/example/videoclips/application/VideoAssetService.java:165, backed by tenant fields
added to the domain/persistence model and migration src/main/resources/db/migration/V6__tenant_quota_support.sql:1. Requests can set X-Tenant-Id on asset creation, quota config lives in src/main/java/org/example/videoclips/
config/VideoClippingProperties.java:39, and quota violations now return 429 via src/main/java/org/example/videoclips/api/ApiExceptionHandler.java:44.
I also started that next step in code. The database-backed queue now retries failed jobs with configurable backoff and moves messages to a terminal DLQ status after the configured max attempts in src/main/java/org/example/
videoclips/queue/DatabaseBackedClipJobQueueAdapter.java:48. The new queue settings live in src/main/java/org/example/videoclips/config/VideoClippingProperties.java:133, and I added focused coverage in src/test/java/org/
example/videoclips/queue/DatabaseBackedClipJobQueueAdapterTest.java:1.
Verification: mvn -q test passed.
- VideoAssetControllerTest: 7/7
- RetentionCleanupJobTest: 2/2
- DatabaseBackedClipJobQueueAdapterTest: 2/2