# Distributed Architecture Adaptation **Task**: AZ-172_distributed_architecture_adaptation **Name**: Adapt detections module for distributed architecture: stream-based input & DB-driven AI config **Description**: Replace the co-located file-path-based detection flow with stream-based input and DB-driven configuration, enabling UI to run on a separate device from the detections API. **Complexity**: 5 points **Dependencies**: Annotations service (C# backend) needs endpoints for per-user AI config and Media management **Component**: Architecture **Jira**: AZ-172 ## Problem The detections module assumes co-located deployment (same machine as the WPF UI). The UI sends local file paths, and inference reads files directly from disk: - `inference.pyx` → `_process_video()` opens local video via `cv2.VideoCapture(video_name)` - `inference.pyx` → `_process_images()` reads local images via `cv2.imread(path)` - `ai_config.pyx` has a `paths: list[str]` field carrying local filesystem paths - `AIRecognitionConfig` is passed from UI as a dict (via the `config_dict` parameter in `run_detect`) In the new distributed architecture, UI runs on a separate device (laptop, tablet, phone). The detections module is a standalone API on a different device. Local file paths are meaningless. ## Outcome - Video detection works with streamed input (no local file paths required) - Video is simultaneously saved to disk and processed frame-by-frame - Image detection works with uploaded bytes (no local file paths required) - AIRecognitionConfig is fetched from DB by userId, not passed from UI - Media table records created on upload with correct XxHash64 Id, path, type, status - Old path-based code removed ## Subtasks | Jira | Summary | Points | |------|---------|--------| | AZ-173 | Replace path-based `run_detect` with stream-based API in `inference.pyx` | 3 | | AZ-174 | Fetch AIRecognitionConfig from DB by userId instead of UI-passed config | 2 | | AZ-175 | Integrate Media table: create record on upload, store file, track status | 2 | | AZ-176 | Clean up obsolete path-based code and old methods | 1 | ## Acceptance Criteria **AC-1: Stream-based video detection** Given a video is uploaded via HTTP to the detection API When the detections module processes it Then frames are decoded and run through inference without requiring a local file path from the caller **AC-2: Concurrent write and detect for video** Given a video stream is being received When the detection module processes it Then the stream is simultaneously written to persistent storage AND processed frame-by-frame for detection **AC-3: Stream-based image detection** Given an image is uploaded via HTTP to the detection API When the detections module processes it Then the image bytes are decoded and run through inference without requiring a local file path **AC-4: DB-driven AI config** Given a detection request arrives with a userId (from JWT) When the detection module needs AIRecognitionConfig Then it fetches AIRecognitionSettings + CameraSettings from the DB via the annotations service, not from the request payload **AC-5: Default config on user creation** Given a new user is created in the system When their account is provisioned Then default AIRecognitionSettings and CameraSettings rows are created for that user **AC-6: Media record lifecycle** Given a file is uploaded for detection When the upload is received Then a Media record is created (XxHash64 Id, Name, Path, MediaType, UserId) and MediaStatus transitions through New → AIProcessing → AIProcessed (or Error) **AC-7: Old code removed** Given the refactoring is complete When the codebase is reviewed Then no references to `paths` in AIRecognitionConfig, no `cv2.VideoCapture(local_path)`, no `cv2.imread(local_path)`, and no `is_video(filepath)` remain ## File Changes | File | Action | Description | |------|--------|-------------| | `src/inference.pyx` | Modified | Replace `run_detect` with stream-based methods; remove path iteration | | `src/ai_config.pxd` | Modified | Remove `paths` field | | `src/ai_config.pyx` | Modified | Remove `paths` field; adapt `from_dict` | | `src/main.py` | Modified | Fetch config from DB; handle Media records; adapt endpoints | | `src/loader_http_client.pyx` | Modified | Add method to fetch user AI config from annotations service | ## Technical Notes - `cv2.VideoCapture` can read from a named pipe or a file being appended to. Alternative: feed frames via a queue from the HTTP upload handler, or use PyAV for direct byte-stream decoding - The annotations service (C# backend) owns the DB. Config retrieval requires API endpoints on that service - XxHash64 ID generation algorithm is documented in `_docs/00_database_schema.md` - Token management (JWT refresh) is already implemented in `main.py` via `TokenManager` - DB tables `AIRecognitionSettings` and `CameraSettings` exist in schema but are not yet linked to `Users`; need FK or join table ## Risks & Mitigation **Risk 1: Concurrent write + read of video file** - *Risk*: `cv2.VideoCapture` may fail or stall reading an incomplete file - *Mitigation*: Use a frame queue pipeline (one thread writes, another reads) or PyAV for byte-stream decoding **Risk 2: Annotations service API dependency** - *Risk*: New endpoints needed on the C# backend for config retrieval and Media management - *Mitigation*: Define API contract upfront; detections module can use fallback defaults if service is unreachable **Risk 3: Config-to-User linking not yet in DB** - *Risk*: `AIRecognitionSettings` and `CameraSettings` tables have no FK to `Users` - *Mitigation*: Add `UserId` FK or create a `UserAIConfig` join table in the backend migration