69752bd6a2
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/claude-agent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
100 lines
3.1 KiB
Plaintext
100 lines
3.1 KiB
Plaintext
@startuml MonitorAlbumStream - Automatic Mode Happy Path
|
|
skinparam sequenceMessageAlign center
|
|
skinparam responseMessageBelowArrow true
|
|
title MonitorAlbumStream: Automatic Mode (Fire-and-Forget)
|
|
|
|
actor Client
|
|
participant "gRPC Server" as Server
|
|
participant "WorkflowRegistry" as Registry
|
|
participant "EventBus" as Bus
|
|
participant "monitorWorkflow\n(background goroutine)" as Workflow
|
|
database "PostgreSQL" as DB
|
|
participant "MusicAgregatorService" as Service
|
|
participant "IndexerService" as Indexer
|
|
participant "MagnetResolver" as Magnet
|
|
participant "TorrentClient\n(qBittorrent)" as QBit
|
|
|
|
== 1. Initialize Stream ==
|
|
|
|
Client -> Server: MonitorAlbumStream()
|
|
Server -> Client: stream established
|
|
|
|
Client -> Server: StartMonitorRequest
|
|
note right: album_id, quality\nmode = AUTOMATIC
|
|
|
|
== 2. Start or Subscribe to Workflow ==
|
|
|
|
Server -> Registry: GetOrCreate(albumID, quality)
|
|
|
|
alt New workflow
|
|
Registry --> Server: (entry, created=true)
|
|
|
|
Server -> Bus: Subscribe(topic)
|
|
note right #lightblue: Subscribe BEFORE\nstarting goroutine\n(no missed events)
|
|
|
|
Server -> Workflow: go workflow.run(entry.Ctx)
|
|
note right #lightyellow: Background goroutine.\nDecoupled from stream context.\nClient can disconnect freely.
|
|
else Existing workflow
|
|
Registry --> Server: (entry, created=false)
|
|
|
|
Server -> Bus: Subscribe(topic)
|
|
|
|
Server -> DB: Replay album_events\n(since last seq)
|
|
DB --> Server: historical events
|
|
Server ->> Client: replayed events
|
|
end
|
|
|
|
== 3. Event Bridge (concurrent) ==
|
|
|
|
note over Client, Workflow #lightblue
|
|
**Left side**: Event bus → gRPC stream bridge
|
|
**Right side**: Workflow executing in background
|
|
Both run concurrently. Client disconnect only stops the bridge.
|
|
end note
|
|
|
|
|||
|
|
|
|
Workflow -> DB: album_events.Create(FETCHING_METADATA)
|
|
Workflow -> Bus: Publish(FETCHING_METADATA)
|
|
Bus ->> Server: event notification
|
|
Server ->> Client: StatusUpdate(FETCHING_METADATA)
|
|
|
|
Workflow -> Service: getAlbumWithPersist()
|
|
Workflow -> DB: workflow_runs.Create(albumID, quality)
|
|
|
|
Workflow -> DB: album_events.Create(CHECKING_OWNED)
|
|
Workflow -> Bus: Publish(CHECKING_OWNED)
|
|
Bus ->> Server: event notification
|
|
Server ->> Client: StatusUpdate(CHECKING_OWNED)
|
|
|
|
Workflow -> Indexer: Search()
|
|
Workflow -> DB: album_events.Create(PARSING_RESULTS)
|
|
Workflow -> Bus: Publish(PARSING_RESULTS)
|
|
Bus ->> Server: event notification
|
|
Server ->> Client: StatusUpdate(PARSING_RESULTS)
|
|
|
|
Workflow -> Workflow: filterByQuality + selectBest
|
|
|
|
Workflow -> DB: saveTorrentAndDownload()
|
|
note right: DB save BEFORE qBit add\n(prevents orphan torrents)
|
|
Workflow -> QBit: AddMagnet()
|
|
|
|
Workflow -> DB: album_events.Create(COMPLETE)
|
|
Workflow -> Bus: Publish(COMPLETE)
|
|
Bus ->> Server: event notification
|
|
Server ->> Client: MonitorAlbumResponse
|
|
note right #lightgreen: Final result
|
|
|
|
Workflow -> DB: workflow_runs.SetCompleted()
|
|
Workflow -> Registry: Remove(albumID, quality)
|
|
|
|
== 4. Client Disconnect (Fire-and-Forget) ==
|
|
|
|
note over Client, Workflow #lightyellow
|
|
Client can disconnect at ANY point during the workflow.
|
|
The workflow goroutine continues independently.
|
|
Another client can subscribe to the same workflow later.
|
|
end note
|
|
|
|
@enduml
|