Split software arch desc for easier manintenance. Many fixes related to next video playing and remote playback
This commit is contained in:
@@ -414,6 +414,107 @@ impl MediaRepository for HybridRepository {
|
||||
|
||||
self.parallel_race(cache_future, server_future).await
|
||||
}
|
||||
|
||||
// ===== Playlist Methods =====
|
||||
|
||||
async fn create_playlist(
|
||||
&self,
|
||||
name: &str,
|
||||
item_ids: &[String],
|
||||
) -> Result<PlaylistCreatedResult, RepoError> {
|
||||
// Write operation - delegate directly to server
|
||||
self.online.create_playlist(name, item_ids).await
|
||||
}
|
||||
|
||||
async fn delete_playlist(&self, playlist_id: &str) -> Result<(), RepoError> {
|
||||
// Write operation - delegate directly to server
|
||||
self.online.delete_playlist(playlist_id).await
|
||||
}
|
||||
|
||||
async fn rename_playlist(&self, playlist_id: &str, name: &str) -> Result<(), RepoError> {
|
||||
// Write operation - delegate directly to server
|
||||
self.online.rename_playlist(playlist_id, name).await
|
||||
}
|
||||
|
||||
async fn get_playlist_items(
|
||||
&self,
|
||||
playlist_id: &str,
|
||||
) -> Result<Vec<PlaylistEntry>, RepoError> {
|
||||
let offline = Arc::clone(&self.offline);
|
||||
let offline_for_save = Arc::clone(&self.offline);
|
||||
let online = Arc::clone(&self.online);
|
||||
let playlist_id = playlist_id.to_string();
|
||||
let playlist_id_clone = playlist_id.clone();
|
||||
let playlist_id_for_save = playlist_id.clone();
|
||||
|
||||
let cache_future = self.cache_with_timeout(async move {
|
||||
offline.get_playlist_items(&playlist_id).await
|
||||
});
|
||||
|
||||
let server_future = async move {
|
||||
online.get_playlist_items(&playlist_id_clone).await
|
||||
};
|
||||
|
||||
let (cache_result, server_result) = tokio::join!(cache_future, server_future);
|
||||
|
||||
let cache_had_content = cache_result.as_ref()
|
||||
.map(|data| data.has_content())
|
||||
.unwrap_or(false);
|
||||
|
||||
if cache_had_content {
|
||||
// If server also succeeded, update cache in background
|
||||
if let Ok(server_entries) = server_result {
|
||||
tokio::spawn(async move {
|
||||
if let Err(e) = offline_for_save.save_playlist_items_to_cache(&playlist_id_for_save, &server_entries).await {
|
||||
warn!("[HybridRepo] Failed to update playlist cache: {:?}", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
return cache_result;
|
||||
}
|
||||
|
||||
// Cache miss - use server result
|
||||
match server_result {
|
||||
Ok(entries) => {
|
||||
let entries_clone = entries.clone();
|
||||
tokio::spawn(async move {
|
||||
if let Err(e) = offline_for_save.save_playlist_items_to_cache(&playlist_id_for_save, &entries_clone).await {
|
||||
warn!("[HybridRepo] Failed to save playlist items to cache: {:?}", e);
|
||||
}
|
||||
});
|
||||
Ok(entries)
|
||||
}
|
||||
Err(e) => cache_result.or(Err(e)),
|
||||
}
|
||||
}
|
||||
|
||||
async fn add_to_playlist(
|
||||
&self,
|
||||
playlist_id: &str,
|
||||
item_ids: &[String],
|
||||
) -> Result<(), RepoError> {
|
||||
// Write operation - delegate directly to server
|
||||
self.online.add_to_playlist(playlist_id, item_ids).await
|
||||
}
|
||||
|
||||
async fn remove_from_playlist(
|
||||
&self,
|
||||
playlist_id: &str,
|
||||
entry_ids: &[String],
|
||||
) -> Result<(), RepoError> {
|
||||
// Write operation - delegate directly to server
|
||||
self.online.remove_from_playlist(playlist_id, entry_ids).await
|
||||
}
|
||||
|
||||
async fn move_playlist_item(
|
||||
&self,
|
||||
playlist_id: &str,
|
||||
item_id: &str,
|
||||
new_index: u32,
|
||||
) -> Result<(), RepoError> {
|
||||
// Write operation - delegate directly to server
|
||||
self.online.move_playlist_item(playlist_id, item_id, new_index).await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -562,6 +663,34 @@ mod tests {
|
||||
async fn get_similar_items(&self, _item_id: &str, _limit: Option<usize>) -> Result<SearchResult, RepoError> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
async fn create_playlist(&self, _name: &str, _item_ids: &[String]) -> Result<PlaylistCreatedResult, RepoError> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
async fn delete_playlist(&self, _playlist_id: &str) -> Result<(), RepoError> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
async fn rename_playlist(&self, _playlist_id: &str, _name: &str) -> Result<(), RepoError> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
async fn get_playlist_items(&self, _playlist_id: &str) -> Result<Vec<PlaylistEntry>, RepoError> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
async fn add_to_playlist(&self, _playlist_id: &str, _item_ids: &[String]) -> Result<(), RepoError> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
async fn remove_from_playlist(&self, _playlist_id: &str, _entry_ids: &[String]) -> Result<(), RepoError> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
async fn move_playlist_item(&self, _playlist_id: &str, _item_id: &str, _new_index: u32) -> Result<(), RepoError> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Mock online repository that returns predefined items
|
||||
@@ -691,6 +820,34 @@ mod tests {
|
||||
async fn get_similar_items(&self, _item_id: &str, _limit: Option<usize>) -> Result<SearchResult, RepoError> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
async fn create_playlist(&self, _name: &str, _item_ids: &[String]) -> Result<PlaylistCreatedResult, RepoError> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
async fn delete_playlist(&self, _playlist_id: &str) -> Result<(), RepoError> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
async fn rename_playlist(&self, _playlist_id: &str, _name: &str) -> Result<(), RepoError> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
async fn get_playlist_items(&self, _playlist_id: &str) -> Result<Vec<PlaylistEntry>, RepoError> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
async fn add_to_playlist(&self, _playlist_id: &str, _item_ids: &[String]) -> Result<(), RepoError> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
async fn remove_from_playlist(&self, _playlist_id: &str, _entry_ids: &[String]) -> Result<(), RepoError> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
async fn move_playlist_item(&self, _playlist_id: &str, _item_id: &str, _new_index: u32) -> Result<(), RepoError> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
fn create_test_item(id: &str, name: &str) -> MediaItem {
|
||||
|
||||
Reference in New Issue
Block a user