WIP: Refactor the IDatabase calls to write directly to the database #271

Draft
wojtek wants to merge 12 commits from 268---refactor-the-idatabase-calls-to-write-directly-to-the-database into main
3 changed files with 57 additions and 41 deletions
Showing only changes of commit 38a2e1f33c - Show all commits

View File

@ -2,10 +2,9 @@ use crate::core::{
collection::{ collection::{
album::{Album, AlbumId}, album::{Album, AlbumId},
artist::{Artist, ArtistId}, artist::{Artist, ArtistId},
merge::{MergeCollections, NormalMap}, Collection,
string, Collection,
}, },
musichoard::{filter::CollectionFilter, Error, LibArtist, MusicHoard}, musichoard::{filter::CollectionFilter, Error, MusicHoard},
}; };
pub trait IMusicHoardBase { pub trait IMusicHoardBase {
@ -32,7 +31,6 @@ impl<Database, Library> IMusicHoardBase for MusicHoard<Database, Library> {
pub trait IMusicHoardBasePrivate { pub trait IMusicHoardBasePrivate {
fn sort_albums_and_tracks<'a, COL: Iterator<Item = &'a mut Vec<Album>>>(collection: COL); fn sort_albums_and_tracks<'a, COL: Iterator<Item = &'a mut Vec<Album>>>(collection: COL);
fn merge_collections<It: IntoIterator<Item = Artist>>(&self, database: It) -> Collection;
fn filter_collection(&self) -> Collection; fn filter_collection(&self) -> Collection;
fn filter_artist(&self, artist: &Artist) -> Option<Artist>; fn filter_artist(&self, artist: &Artist) -> Option<Artist>;
@ -63,26 +61,6 @@ impl<Database, Library> IMusicHoardBasePrivate for MusicHoard<Database, Library>
} }
} }
fn merge_collections<It: IntoIterator<Item = Artist>>(&self, database: It) -> Collection {
let mut primary = NormalMap::<LibArtist>::new();
let mut secondary = NormalMap::<Artist>::new();
for (normal_name, artist) in self.library_cache.clone().into_iter() {
primary.insert(normal_name, artist);
}
for artist in database.into_iter() {
secondary.insert(string::normalize_string(&artist.meta.name), artist);
}
let (mut collection, left) = MergeCollections::merge_by_name(primary, secondary);
// TODO: Insert what's left into the DB to get IDs and then append to collection.
collection.sort_unstable();
collection
}
fn filter_collection(&self) -> Collection { fn filter_collection(&self) -> Collection {
let iter = self.collection.iter(); let iter = self.collection.iter();
iter.flat_map(|a| self.filter_artist(a)).collect() iter.flat_map(|a| self.filter_artist(a)).collect()

View File

@ -4,7 +4,8 @@ use crate::{
collection::{ collection::{
album::{AlbumInfo, AlbumMbRef, AlbumMeta}, album::{AlbumInfo, AlbumMbRef, AlbumMeta},
artist::ArtistInfo, artist::ArtistInfo,
merge::Merge, merge::{Merge, MergeCollections, NormalMap},
string,
}, },
core::{ core::{
collection::{ collection::{
@ -13,11 +14,15 @@ use crate::{
Collection, Collection,
}, },
interface::database::IDatabase, interface::database::IDatabase,
musichoard::{base::IMusicHoardBasePrivate, Error, MusicHoard, NoDatabase}, musichoard::{
base::IMusicHoardBasePrivate, Error, IntoId, LibArtist, MusicHoard, NoDatabase,
},
}, },
}; };
pub trait IMusicHoardDatabase { pub trait IMusicHoardDatabase {
fn merge_collections(&mut self) -> Result<Collection, Error>;
fn reload_database(&mut self) -> Result<(), Error>; fn reload_database(&mut self) -> Result<(), Error>;
fn merge_artist_info<Id: AsRef<ArtistId>>( fn merge_artist_info<Id: AsRef<ArtistId>>(
@ -64,11 +69,34 @@ pub trait IMusicHoardDatabase {
} }
impl<Database: IDatabase, Library> IMusicHoardDatabase for MusicHoard<Database, Library> { impl<Database: IDatabase, Library> IMusicHoardDatabase for MusicHoard<Database, Library> {
fn reload_database(&mut self) -> Result<(), Error> { fn merge_collections(&mut self) -> Result<Collection, Error> {
let mut database_cache = self.database.load()?; let mut database = self.database.load()?;
Self::sort_albums_and_tracks(database_cache.iter_mut().map(|a| &mut a.albums)); Self::sort_albums_and_tracks(database.iter_mut().map(|a| &mut a.albums));
self.collection = self.merge_collections(database_cache); let mut primary = NormalMap::<LibArtist>::new();
for (normal_name, artist) in self.library_cache.clone().into_iter() {
primary.insert(normal_name, artist);
}
let mut secondary = NormalMap::<Artist>::new();
for artist in database.into_iter() {
secondary.insert(string::normalize_string(&artist.meta.name), artist);
}
let (mut collection, lib_artists) = MergeCollections::merge_by_name(primary, secondary);
for lib_artist in lib_artists.into_iter() {
let id = self.database.insert_artist(&lib_artist.meta)?;
collection.push(lib_artist.into_id(&id));
}
collection.sort_unstable();
Ok(collection)
}
fn reload_database(&mut self) -> Result<(), Error> {
self.collection = self.merge_collections()?;
self.filtered = self.filter_collection(); self.filtered = self.filter_collection();
Ok(()) Ok(())

View File

@ -1,20 +1,24 @@
use std::collections::HashMap; use std::collections::HashMap;
use crate::{ use crate::{
collection::string::{self, NormalString}, collection::{
artist::ArtistId,
merge::IntoId,
string::{self, NormalString},
},
core::{ core::{
collection::{ collection::{
album::{Album, AlbumDate, AlbumId, AlbumMbRef}, album::{Album, AlbumDate, AlbumId, AlbumMbRef},
track::{Track, TrackId, TrackNum, TrackQuality}, track::{Track, TrackId, TrackNum, TrackQuality},
Collection,
}, },
interface::{ interface::{
database::IDatabase, database::IDatabase,
library::{ILibrary, Item, Query}, library::{ILibrary, Item, Query},
}, },
musichoard::{ musichoard::{
base::IMusicHoardBasePrivate, database::IMusicHoardDatabasePrivate, Error, LibArtist, base::IMusicHoardBasePrivate,
MusicHoard, NoDatabase, database::{IMusicHoardDatabase, IMusicHoardDatabasePrivate},
Error, LibArtist, MusicHoard, NoDatabase,
}, },
}, },
}; };
@ -25,28 +29,34 @@ pub trait IMusicHoardLibrary {
impl<Library: ILibrary> IMusicHoardLibrary for MusicHoard<NoDatabase, Library> { impl<Library: ILibrary> IMusicHoardLibrary for MusicHoard<NoDatabase, Library> {
fn rescan_library(&mut self) -> Result<(), Error> { fn rescan_library(&mut self) -> Result<(), Error> {
self.collection = self.rescan_library_inner(vec![])?; self.rescan_library_inner()?;
self.collection = self
.library_cache
.values()
.cloned()
.enumerate()
.map(|(ix, la)| la.into_id(&ArtistId(ix)))
.collect();
self.collection.sort_unstable();
self.commit() self.commit()
} }
} }
impl<Database: IDatabase, Library: ILibrary> IMusicHoardLibrary for MusicHoard<Database, Library> { impl<Database: IDatabase, Library: ILibrary> IMusicHoardLibrary for MusicHoard<Database, Library> {
fn rescan_library(&mut self) -> Result<(), Error> { fn rescan_library(&mut self) -> Result<(), Error> {
let mut database_cache = self.database.load()?; self.rescan_library_inner()?;
Self::sort_albums_and_tracks(database_cache.iter_mut().map(|a| &mut a.albums)); self.collection = self.merge_collections()?;
self.collection = self.rescan_library_inner(database_cache)?;
self.commit() self.commit()
} }
} }
impl<Database, Library: ILibrary> MusicHoard<Database, Library> { impl<Database, Library: ILibrary> MusicHoard<Database, Library> {
fn rescan_library_inner(&mut self, database: Collection) -> Result<Collection, Error> { fn rescan_library_inner(&mut self) -> Result<(), Error> {
let items = self.library.list(&Query::new())?; let items = self.library.list(&Query::new())?;
self.library_cache = Self::items_to_artists(items)?; self.library_cache = Self::items_to_artists(items)?;
Self::sort_albums_and_tracks(self.library_cache.values_mut().map(|la| &mut la.albums)); Self::sort_albums_and_tracks(self.library_cache.values_mut().map(|la| &mut la.albums));
Ok(())
Ok(self.merge_collections(database))
} }
fn items_to_artists(items: Vec<Item>) -> Result<HashMap<NormalString, LibArtist>, Error> { fn items_to_artists(items: Vec<Item>) -> Result<HashMap<NormalString, LibArtist>, Error> {