-
Notifications
You must be signed in to change notification settings - Fork 0
Daemon Startup and State
Relevant source files
The following files were used as context for generating this wiki page:
This page details the lifecycle of the aurora-daemon from the initial execution of the binary to the point where it is ready to handle client requests. The startup sequence involves daemonization, initializing audio hardware, opening the persistent database, indexing the music library, and launching several background management threads.
The main() function serves as the initial entry point. Its primary responsibility is to detach the process from the terminal and initialize the asynchronous runtime.
-
Tracing Initialization: The system starts
tracing_subscriberfor logging daemon/src/main.rs:29-29. -
Daemonization: If no command-line arguments are provided, the process uses the
daemonizecrate to fork into the background daemon/src/main.rs:31-40. It sets up a PID file at/tmp/aurora-daemon.pidand redirects standard output to/tmp/aurora-daemon.outdaemon/src/main.rs:24-26. -
Runtime Setup: A multi-threaded
tokioruntime is built with I/O and time drivers enabled to execute theasync_main()function daemon/src/main.rs:42-48.
Immediately upon entering async_main(), a dedicated thread is spawned to monitor TERM_SIGNALS (SIGINT, SIGTERM). When a signal is received, it performs cleanup by deleting the Unix socket and PID files before exiting daemon/src/main.rs:52-63.
Sources: daemon/src/main.rs:24-63
The core of the daemon is the StateStruct, wrapped in an Arc<Mutex<...>> to allow shared access across multiple tasks and threads daemon/src/types/mod.rs:10-10.
The daemon uses the rodio crate for audio playback. It opens the default output stream and creates a Sink connected to the mixer daemon/src/main.rs:65-69. This sink is later stored in the StateStruct to control playback daemon/src/types/state_impl/mod.rs:20-20.
-
Database: The daemon opens a connection to the SQLite database via
helpers::db::open()daemon/src/main.rs:71-71. -
Indexing: It identifies the user's music directory (defaulting to
~/Music) and callshelpers::build_indexto scan the filesystem and sync metadata with the database daemon/src/main.rs:73-76. -
Persistence Loading: Play history and "liked" song IDs are loaded from the database into memory-efficient structures (
VecDequeandHashSetrespectively) daemon/src/main.rs:77-78.
The StateStruct is instantiated with the gathered components:
| Field | Type | Description |
|---|---|---|
index |
SongIndex |
A HashMap mapping Uuid to SongMeta daemon/src/types/mod.rs:9-9. |
sink |
Arc<Sink> |
The Rodio audio sink daemon/src/types/state_impl/mod.rs:20-20. |
theme |
Theme |
Loaded from config.toml via theme_thread::get_config() daemon/src/main.rs:87-87. |
db |
Db |
Thread-safe handle to the SQLite database daemon/src/types/state_impl/mod.rs:29-29. |
Sources: daemon/src/main.rs:65-94, daemon/src/types/state_impl/mod.rs:16-30
The following diagram illustrates the sequence of operations during the async_main execution.
sequenceDiagram
participant M as async_main
participant A as Audio Hardware
participant D as SQLite (Db)
participant S as StateStruct
participant T as Background Threads
M->>M: Spawn Signal Handler Thread
M->>A: rodio::OutputStreamBuilder::open_default_stream()
M->>A: rodio::Sink::connect_new()
M->>D: helpers::db::open()
M->>D: helpers::build_index(music_dir, db)
M->>D: helpers::load_history() / load_liked()
M->>S: Construct StateStruct (Arc<Mutex<...>>)
M->>T: tokio::spawn(watcher_thread)
M->>T: tokio::spawn(file_watcher_thread)
M->>T: tokio::spawn(mpris_thread)
M->>T: tokio::spawn(theme_thread)
M->>M: UnixListener::bind(/tmp/aurora-daemon.sock)
Sources: daemon/src/main.rs:51-112
Once the StateStruct is initialized, the daemon spawns four critical background tasks using tokio::spawn. Each task receives a clone of the Arc<State> to interact with the system status.
-
watcher_thread: Monitors therodio::Sinkto detect when a track finishes, triggering auto-advance to the next song in the queue daemon/src/main.rs:97-97. -
file_watcher_thread: Watches the filesystem for changes in the music directory to trigger incremental re-indexing daemon/src/main.rs:100-100. -
mpris_thread: Provides D-Bus integration, allowing Linux desktop environments to control playback daemon/src/main.rs:103-103. -
theme_thread: Watches for changes in theconfig.tomlfile to update the UI theme across all connected clients in real-time daemon/src/main.rs:106-106.
Sources: daemon/src/main.rs:96-106
The final stage of startup is the listener loop. The daemon binds to the Unix domain socket at /tmp/aurora-daemon.sock daemon/src/main.rs:108-112.
When a client (like aurora-player) connects:
- The socket is split into an
OwnedReadHalfand anOwnedWriteHalfdaemon/src/main.rs:117-117. - The writer is wrapped in
Arc<Mutex<...>>and added tostate.clientsso the daemon can broadcast status updates daemon/src/main.rs:118-122. - A new tokio task is spawned to run
handlers::handle_client, which processes incomingRequestobjects daemon/src/main.rs:126-132. - Upon client disconnection, the task removes the client's writer from the
state.clientsvector daemon/src/main.rs:133-141.
graph TD
subgraph "Code Entity Space"
MAIN["main() / async_main()"]
STATE["StateStruct"]
LISTENER["UnixListener"]
HANDLER["handle_client()"]
SINK["rodio::Sink"]
end
subgraph "Natural Language Space"
START["Process Entry"]
MEM["Shared Global State"]
IPC["Unix Socket Server"]
REQ["Request Processing"]
AUDIO["Audio Output"]
end
START --> MAIN
MEM --> STATE
IPC --> LISTENER
REQ --> HANDLER
AUDIO --> SINK
MAIN -- "initializes" --> STATE
MAIN -- "starts" --> LISTENER
LISTENER -- "spawns" --> HANDLER
STATE -- "controls" --> SINK
Sources: daemon/src/main.rs:115-143, daemon/src/types/state_impl/mod.rs:16-30
Overview
aurora-daemon
- Background Service
- Startup & State Init
- Request Handlers & Dispatch
- Playback Engine & Audio
- Library Indexing & Watching
- Playlists, Liked & History
- Background Threads
aurora-protocol
aurora-player
Reference