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