Skip to content
Rymflux Documentation
Esc
navigateopen⌘Jpreview
On this page

C4 Level 2 — Container diagram

C4 Level 2 — Container diagram

Diagram

C4Container
  title Container Diagram — Rymflux v1

  Person(listener, "Listener", "End user consuming audio")

  System_Boundary(rymflux, "Rymflux Desktop App") {
    Container(svelte_shell, "Shell UI", "Svelte + TypeScript", "Navigation, Home/Lobby, mini-player, room registry")
    Container(music_room, "Music Room", "Svelte + TypeScript", "Browse albums/artists/genres, search, player expansion, queue view")

    Container(backend, "Rust Backend", "Rust (Tauri)", "Single process hosting all core services")
    ContainerDb(sqlite, "Library Database", "SQLite", "library_items, content_resolution, playlists, playback_history")
  }

  System_Ext(plugin_proc, "Plugin Processes", "External executables (Python, Go, etc.)")
  System_Ext(audio_dev, "Audio Output", "OS audio device")

  Rel(listener, svelte_shell, "Interacts with", "GUI")
  Rel(svelte_shell, music_room, "Contains", "Svelte component tree")
  Rel(svelte_shell, backend, "Commands + events", "Tauri IPC bridge")

  Rel(backend, plugin_proc, "stdin/stdout JSON-RPC", "Launch on demand, idle timeout")
  Rel(backend, audio_dev, "Decoded PCM buffers", "phonic (cpal) output stream")
  Rel(backend, sqlite, "Reads/writes", "rusqlite")

Backend services (within the Rust process)

These are logical modules within the single Rust process, not separate deployable units:

┌────────────────────────────────────────────────────┐
│                    Rust Backend                     │
│                                                    │
│  ┌────────────────┐  ┌────────────────────┐       │
│  │ Plugin          │  │ Search             │       │
│  │ Runtime         │  │ Manager            │       │
│  │                 │  │                    │       │
│  │ • Discovery     │  │ • Dispatch         │       │
│  │ • Lifecycle     │  │ • Timeout          │       │
│  │ • IPC bridge    │  │ • Merge/dedup      │       │
│  │ • stderr capt.  │  │ • Config           │       │
│  └───────┬─────────┘  └─────┬──────────────┘       │
│          │                  │                       │
│          ▼                  ▼                       │
│  ┌────────────────┐  ┌────────────────────┐       │
│  │ Playback        │  │ Library            │       │
│  │ Engine          │  │ Service            │       │
│  │                 │  │                    │       │
│  │ • phonic        │  │ • rusqlite         │       │
│  │ • symphonia(w)  │  │ • Favorites        │       │
│  │ • rubato(w)     │  │ • Playlists        │       │
│  │ • cpal(w)       │  │                    │       │
│  │ • Queue control │  │ • History          │       │
│  └────────────────┘  └─────┬──────────────┘       │
│                             │                       │
│                             ▼                       │
│                    ┌────────────────┐               │
│                    │    SQLite      │               │
│                    │    (file)      │               │
│                    └────────────────┘               │
└────────────────────────────────────────────────────┘

Service responsibilities

Service Responsibility Key dependencies
Plugin Runtime Scan plugins directory on startup, parse manifests, launch plugin processes on first request, supervise lifecycle (timeout, crash recovery, idle termination), capture stderr std::process::Command, tokio::io for stdin/stdout
Search Manager Accept start_search command, dispatch JSON-RPC search requests to all plugins with search capability, collect results with per-plugin timeout, merge/deduplicate, emit search_result and search_done events Plugin Runtime (to send requests), tokio::select!, SearchConfig
Playback Engine Accept URL or file path, play via phonic (symphonia decode + rubato resample + cpal output), manage PlaybackHandle, emit playback_state events from status channel phonic, tokio::sync::mpsc for playback status
Library Service CRUD for favorites, playlists, history. Content resolution lookup (content UUID to (plugin_id, foreign_id)). Deduplication on first save rusqlite, content resolution table

Container interaction patterns

Search flow

Listener types query
       |
       v
Svelte Shell invoke("start_search", { query: "..." })
       |
       v
Rust: Search Manager
       | tokio::select! across N plugin processes
       +-- Plugin A responds -> emit("search_result", { plugin: "A", results: [...] })
       +-- Plugin B times out -> emit("search_error", { plugin: "B", error: "timeout" })
       +-- All done -> emit("search_done", { total: 42 })
       |
       v
Svelte Shell / Music Room
       +-- listen("search_result") -> append + deduplicate results
       +-- listen("search_error") -> show per-plugin notification
       +-- listen("search_done") -> show "N results from M plugins"

Playback flow

Listener presses play on a track in Music Room
       |
       v
Music Room resolve content UUID -> invoke("resolve_content", { id: "..." })
       |
       v
Rust: Library Service -> content_resolution table -> (plugin_id, foreign_id)
       |
       v
Rust: Plugin Runtime -> send JSON-RPC stream request to plugin
       |
       v
Plugin returns {"url": "https://...", "content_type": "audio/mpeg"}
       |
       v
Rust: Playback Engine -> phonic plays (symphonia decodes -> rubato resamples -> cpal outputs)
       |
       v
Rust emits "playback_state" -> Svelte mini-player updates

Startup flow

App launches (Tauri)
       |
       v
Rust: Plugin Runtime -> scan ~/.rymflux/plugins/
       |
       +-- Parse each plugin.toml
       +-- Validate manifest
       +-- Register valid plugins
       |
       v
Rust: Library Service -> open SQLite, run migrations
       |
       v
Rust: emit("platform_ready", { plugins: [...] })
       |
       v
Svelte Shell -> render Home, populate room list

(w) throughout the backend diagram = wrapped by phonic. symphonia, rubato, and cpal are consumed via the phonic crate, not linked directly.

Technology decisions

Component Technology Rationale
Desktop shell Tauri v2 Cross-platform, small binary, Rust backend
Frontend UI Svelte 5 + TypeScript Reactive, compiled, minimal overhead
Audio engine phonic Wraps cpal + symphonia + rubato. Built-in playback status events, sample-accurate scheduling, DSP effects
Database rusqlite Embeddable, relational, well-tested
Async runtime tokio Required by Tauri, supports async process supervision
Plugin IPC JSON-RPC 2.0 over stdin/stdout Language-agnostic, zero networking, well-understood
HTTP client reqwest Fetch stream URLs, battle-tested

Was this page helpful?