1use color_eyre::eyre::Result;
2use tano_providers::local::parse_song::ParsedSong;
3use tokio::sync::{mpsc, oneshot};
4
5use crate::{
6 actor::{DatabaseActor, cmd::DatabaseCmd, run_database_actor},
7 album::Album,
8 artist::Artist,
9 local_song::{LocalSong, SyncLocalSong},
10 song::Song,
11};
12
13const DATABASE_ACTOR_KILLED: &str = "DatabaseActor task has been killed";
14
15#[derive(Clone)]
16pub struct DatabaseActorHandle {
17 sender: mpsc::Sender<DatabaseCmd>,
18}
19
20impl Default for DatabaseActorHandle {
21 fn default() -> Self {
22 let (sender, receiver) = mpsc::channel(8);
23 let actor = DatabaseActor::new(receiver);
24 tokio::spawn(run_database_actor(actor));
25
26 Self { sender }
27 }
28}
29
30impl DatabaseActorHandle {
31 pub async fn get_songs(&self) -> Result<Vec<Song>> {
32 let (send, recv) = oneshot::channel();
33 let cmd = DatabaseCmd::GetSongs { respond_to: send };
34
35 let _ = self.sender.send(cmd).await;
36 recv.await.expect(DATABASE_ACTOR_KILLED)
37 }
38
39 pub async fn get_albums(&self) -> Result<Vec<Album>> {
40 let (send, recv) = oneshot::channel();
41 let cmd = DatabaseCmd::GetAlbums { respond_to: send };
42
43 let _ = self.sender.send(cmd).await;
44 recv.await.expect(DATABASE_ACTOR_KILLED)
45 }
46
47 pub async fn get_album_artists(&self, album_id: i64) -> Result<Vec<Artist>> {
48 let (send, recv) = oneshot::channel();
49 let cmd = DatabaseCmd::GetAlbumArtists {
50 album_id,
51 respond_to: send,
52 };
53
54 let _ = self.sender.send(cmd).await;
55 recv.await.expect(DATABASE_ACTOR_KILLED)
56 }
57
58 pub async fn get_album(&self, id: i64) -> Result<Option<Album>> {
59 let (send, recv) = oneshot::channel();
60 let cmd = DatabaseCmd::GetAlbum {
61 id,
62 respond_to: send,
63 };
64
65 let _ = self.sender.send(cmd).await;
66 recv.await.expect(DATABASE_ACTOR_KILLED)
67 }
68
69 pub async fn get_album_songs(&self, album_id: i64) -> Result<Vec<Song>> {
70 let (send, recv) = oneshot::channel();
71 let cmd = DatabaseCmd::GetAlbumSongs {
72 album_id,
73 respond_to: send,
74 };
75
76 let _ = self.sender.send(cmd).await;
77 recv.await.expect(DATABASE_ACTOR_KILLED)
78 }
79
80 pub async fn get_artists(&self) -> Result<Vec<Artist>> {
81 let (send, recv) = oneshot::channel();
82 let cmd = DatabaseCmd::GetArtists { respond_to: send };
83
84 let _ = self.sender.send(cmd).await;
85 recv.await.expect(DATABASE_ACTOR_KILLED)
86 }
87
88 pub async fn get_sync_local_songs(&self, provider_id: u64) -> Result<Vec<SyncLocalSong>> {
89 let (send, recv) = oneshot::channel();
90 let cmd = DatabaseCmd::GetSyncLocalSong {
91 respond_to: send,
92 provider_id,
93 };
94
95 let _ = self.sender.send(cmd).await;
96 recv.await.expect(DATABASE_ACTOR_KILLED)
97 }
98
99 pub async fn get_song_ids(&self) -> Result<Vec<i64>> {
100 let (send, recv) = oneshot::channel();
101 let cmd = DatabaseCmd::GetSongIds { respond_to: send };
102
103 let _ = self.sender.send(cmd).await;
104 recv.await.expect(DATABASE_ACTOR_KILLED)
105 }
106
107 pub async fn sync_local_songs(
108 &self,
109 provider_id: u64,
110 new_songs: Vec<ParsedSong>,
111 updated_songs: Vec<(i64, ParsedSong)>,
112 to_update_path: Vec<(i64, String)>,
113 to_delete_ids: Vec<i64>,
114 ) -> Result<()> {
115 let (send, recv) = oneshot::channel();
116 let cmd = DatabaseCmd::SyncLocalSongs {
117 provider_id,
118 new_songs,
119 updated_songs,
120 to_update_path,
121 to_delete_ids,
122 respond_to: send,
123 };
124
125 let _ = self.sender.send(cmd).await;
126 recv.await.expect(DATABASE_ACTOR_KILLED)
127 }
128
129 pub async fn load_database(&self) -> Result<()> {
130 let (send, recv) = oneshot::channel();
131 let cmd = DatabaseCmd::LoadDatabase { respond_to: send };
132
133 let _ = self.sender.send(cmd).await;
134 recv.await.expect(DATABASE_ACTOR_KILLED)
135 }
136
137 pub async fn get_local_song_by_path(
138 &self,
139 provider_id: u64,
140 path: String,
141 ) -> Result<Option<LocalSong>> {
142 let (send, recv) = oneshot::channel();
143 let cmd = DatabaseCmd::GetLocalSongByPath {
144 provider_id,
145 path,
146 respond_to: send,
147 };
148 let _ = self.sender.send(cmd).await;
149 recv.await.expect(DATABASE_ACTOR_KILLED)
150 }
151
152 pub async fn get_local_song_by_inode(
153 &self,
154 provider_id: u64,
155 inode: i64,
156 ) -> Result<Option<LocalSong>> {
157 let (send, recv) = oneshot::channel();
158 let cmd = DatabaseCmd::GetLocalSongByInode {
159 provider_id,
160 inode,
161 respond_to: send,
162 };
163 let _ = self.sender.send(cmd).await;
164 recv.await.expect(DATABASE_ACTOR_KILLED)
165 }
166
167 pub async fn update_local_song_path(&self, id: i64, path: String) -> Result<()> {
168 let (send, recv) = oneshot::channel();
169 let cmd = DatabaseCmd::UpdateLocalSongPath {
170 id,
171 path,
172 respond_to: send,
173 };
174 let _ = self.sender.send(cmd).await;
175 recv.await.expect(DATABASE_ACTOR_KILLED)
176 }
177
178 pub async fn insert_local_song(
179 &self,
180 provider_id: u64,
181 parsed_song: ParsedSong,
182 ) -> Result<i64> {
183 let (send, recv) = oneshot::channel();
184 let cmd = DatabaseCmd::InsertLocalSong {
185 provider_id,
186 parsed_song,
187 respond_to: send,
188 };
189 let _ = self.sender.send(cmd).await;
190 recv.await.expect(DATABASE_ACTOR_KILLED)
191 }
192
193 pub async fn update_local_song(
194 &self,
195 provider_id: u64,
196 id: i64,
197 parsed_song: ParsedSong,
198 ) -> Result<()> {
199 let (send, recv) = oneshot::channel();
200 let cmd = DatabaseCmd::UpdateLocalSong {
201 provider_id,
202 id,
203 parsed_song,
204 respond_to: send,
205 };
206 let _ = self.sender.send(cmd).await;
207 recv.await.expect(DATABASE_ACTOR_KILLED)
208 }
209
210 pub async fn delete_local_song(&self, id: i64) -> Result<()> {
211 let (send, recv) = oneshot::channel();
212 let cmd = DatabaseCmd::DeleteLocalSong {
213 id,
214 respond_to: send,
215 };
216 let _ = self.sender.send(cmd).await;
217 recv.await.expect(DATABASE_ACTOR_KILLED)
218 }
219}