mirror of
https://github.com/euzu/tuliprox.git
synced 2026-10-05 15:32:31 +02:00
Task 13, steps 1 and 3. The recording worker held `Arc<ActiveProviderManager>` and `Arc<ConnectionManager>` directly, so the execution path could not be exercised without a real provider. Three plan items are blocked on exactly that: ffmpeg started once at the padded start and stopped once at the padded end (task 12), worker cancellation happening once (task 11), and exactly one worker start (task 16). None of them is a test-writing problem -- there was nothing to stand in for. `RecordingCapacityPort` is the seam: capacities for an input, acquire, release, and the signal that wakes waiters. Four methods, which is all the worker ever used of two managers. It is object-safe on purpose -- boxed futures rather than async fn in trait -- so `RecordingCtx` holds one behind `dyn` and the DVR does not become generic over its provider. `ProviderCapacityAdapter` in `backend/app` implements it over the real managers, which is where provider detail belongs. It does nothing else: no files, no strategy choice, no ffmpeg, no state changes. That is what step 1 asks the adapter not to do, and keeping it to four delegating methods is what makes it obvious it does not. `AppState` gains `recording_capacity` rather than the view renaming a handle, because the view macro's rule is that field names match on both sides -- a view renaming a handle would be a view lying about what it reads. `StubCapacity` is the payoff: a provider that is full, or has room, that counts what was asked of it. Its two tests are thin, but the point is that a worker can now be run against a provider that never grants a slot without waiting on a real one to be busy. Not done, and still needing Design section 9.1: steps 2 and 5, the per-field hot reload matrix. Step 4 landed earlier and step 6 already passed.