@startuml MonitorAlbumStream - Automatic Mode Happy Path skinparam sequenceMessageAlign center skinparam responseMessageBelowArrow true title MonitorAlbumStream: Automatic Mode (Status Updates Only) actor Client participant "gRPC Server" as Server participant "monitorWorkflow" as Workflow participant "MusicAgregatorService" as Service participant "MetadataService" as Metadata database "metadata-agregator\n(gRPC)" as MetaGRPC database "PostgreSQL" as DB participant "IndexerService\n(Jackett)" as Indexer participant "MagnetResolver" as Magnet participant "TorrentClient\n(qBittorrent)" as QBit participant "River Queue" as River == 1. Initialize Bidirectional Stream == Client -> Server: MonitorAlbumStream() note right: Opens bidirectional\ngRPC stream Server -> Client: stream established Client -> Server: StartMonitorRequest note right: album_id, quality, tracker\nmode = AUTOMATIC Server -> Workflow: newMonitorWorkflow(stream, req, service) note right: Creates workflow with\ndecisions channel and\nreceiver goroutine == 2. Fetch Album Metadata == Workflow ->> Client: StatusUpdate(FETCHING_METADATA) note right #lightblue: "Fetching metadata..." Workflow -> Service: getAlbumWithPersist(ctx, album_id) Service -> Metadata: GetAlbum(album_id) Metadata -> MetaGRPC: GetAlbum(id) MetaGRPC --> Metadata: Album Metadata -> DB: artists.Create / albums.Create Metadata --> Service: Album Workflow ->> Client: StatusUpdate(FETCHING_METADATA) note right #lightblue: "Got: Artist - Title"\nData: StreamAlbumInfo == 3. Check If Already Owned == Workflow ->> Client: StatusUpdate(CHECKING_OWNED) note right #lightblue: "Checking ownership..." Workflow -> DB: downloads.HasAlbumInQuality() DB --> Workflow: false == 4. Search Indexers == Workflow ->> Client: StatusUpdate(SEARCHING_INDEXER) note right #lightblue: "Searching indexers..." Workflow -> Indexer: Search(query, tracker) Indexer --> Workflow: SearchResponse (N items) == 5. Parse Releases == loop for each search result Workflow -> Magnet: Resolve(magnet_uri) Magnet --> Workflow: torrent metadata Workflow -> Workflow: ParseTorrent() end Workflow ->> Client: StatusUpdate(PARSING_RESULTS) note right #lightblue: "Parsed M from N torrents"\nData: TorrentList == 6. Filter by Quality == Workflow ->> Client: StatusUpdate(FILTERING_QUALITY) note right #lightblue: "Filtering by quality..." Workflow -> Workflow: filterByQuality(parsed, quality) == 7. Select Best Release == Workflow -> Workflow: selectBestRelease(filtered) note right: Highest seeder count wins\n(automatic selection) Workflow ->> Client: StatusUpdate(SELECTING_RELEASE) note right #lightblue: "Selected: Title (N seeders)"\nData: ReleaseInfo == 8. Add to Torrent Client == Workflow ->> Client: StatusUpdate(ADDING_TORRENT) note right #lightblue: "Adding torrent..." Workflow -> QBit: AddMagnet(magnet_uri) QBit --> Workflow: OK == 9. Persist & Schedule == Workflow ->> Client: StatusUpdate(SAVING) note right #lightblue: "Saving to database..." Workflow -> DB: torrents.Create / downloads.Create Workflow -> River: Insert(PollDownloadArgs) == 10. Return Result == Workflow ->> Client: StatusUpdate(COMPLETE) note right #lightblue: "Download started" Workflow ->> Client: MonitorAlbumResponse note right #lightgreen: Final result with:\nalbum, artist, release, download Server -> Server: Close stream @enduml