@startuml MonitorAlbumStream Protocol skinparam sequenceMessageAlign center title MonitorAlbumStream: Message Protocol participant "Client" as C participant "Server" as S == Stream Initialization == C -> S: gRPC MonitorAlbumStream() note right: Opens bidirectional stream == Request Messages (Client -> Server) == C -> S: MonitorAlbumStreamRequest note right #lightblue **oneof message:** - **start**: StartMonitorRequest - album_id (required) - quality: LOSSLESS | LOSSY | UNSPECIFIED - mode: AUTOMATIC (0) | MANUAL (1) - indexer_options: {tracker} - **decision**: UserDecision - prompt_id (must match pending prompt) - confirm | selected_id | selected_ids - **cancel**: CancelRequest - Gracefully terminates workflow end note == Response Messages (Server -> Client) == S -> C: MonitorAlbumStreamResponse note left #lightgreen **oneof message:** - **status**: StatusUpdate - step: MonitorStep enum - message: human-readable text - data: StreamAlbumInfo | TorrentList | ReleaseInfo - **prompt**: PromptForDecision - prompt_id: unique identifier - type: CONFIRM | SELECT_ONE | SELECT_MANY - message: prompt text - timeout_seconds: response deadline - options: confirm | select_one | select_many config - **result**: MonitorAlbumResponse - Final response (stream ends after this) - **error**: ErrorUpdate - failed_step: where error occurred - message: error description - recoverable: bool end note == Monitor Steps (Status Updates) == note over C, S #lightyellow **MonitorStep Enum:** 1. FETCHING_METADATA - Getting album info from metadata service 2. CHECKING_OWNED - Checking if already downloaded 3. SEARCHING_INDEXER - Querying Jackett/indexers 4. PARSING_RESULTS - Resolving magnets, parsing torrents 5. FILTERING_QUALITY - Applying quality filter 6. SELECTING_RELEASE - Choosing best/user-selected release 7. ADDING_TORRENT - Adding to qBittorrent 8. SAVING - Persisting to database 9. COMPLETE - Workflow finished end note == Prompt Types (Manual Mode) == note over C, S #orange **CONFIRM** (yes/no decision) - confirm_label, cancel_label - default_value: bool **SELECT_ONE** (pick one option) - options: [{id, label, description}] - default_id: pre-selected option **SELECT_MANY** (pick multiple options) - options: [{id, label, description}] - default_ids: pre-selected options - min_selections, max_selections end note == Data Payloads == note over C, S #lightblue **StreamAlbumInfo** (at FETCHING_METADATA) - artist, title, release_date, already_owned, owned_quality **TorrentList** (at PARSING_RESULTS) - torrents: [{id, title, tracker, seeders, format, lossless}] **ReleaseInfo** (at SELECTING_RELEASE) - info_hash, format, bit_depth, sample_rate, seeders, tracker end note == Timeout Behavior == note over C, S #pink When prompt times out (max: 300s): - Server uses **default decision** value - Workflow continues automatically - No error is raised Timeout is capped server-side at 300s. If timeout_seconds on prompt is 0 or exceeds max, 300s is used. end note @enduml