use crate::db::connection::Database;
use crate::remote::client::SubsonicClient;
use super::*;
#[derive(Debug, Default)]
pub struct Synced {
pub library: crate::remote::sync::SyncResult,
pub favourites: FavouriteSync,
pub playlists: crate::playlists::PlaylistSync,
pub history: crate::remote::history::HistorySync,
pub dsp: crate::remote::dsp_sync::DspSync,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Walk {
Always,
IfChanged,
}
pub fn sync_remote(
db: &Database,
client: &SubsonicClient,
walk: Walk,
url: &str,
username: &str,
progress: &(dyn Fn(crate::remote::sync::SyncProgress) + Sync),
) -> Result<Synced, crate::remote::sync::SyncError> {
use crate::remote::sync;
static SYNCING: parking_lot::Mutex<()> = parking_lot::Mutex::new(());
let _one_at_a_time = SYNCING.lock();
let walked = sync::library_version(db, url);
let modified = client.library_modified(walked);
crate::remote::refusal::observe(client.auth(), &modified);
let version = modified
.inspect_err(|e| log::debug!("library version unavailable: {e}"))
.ok()
.flatten();
let library = if walk == Walk::IfChanged && version.is_some() && version == walked {
log::info!("library unchanged on the server; not walked");
sync::SyncResult::default()
} else {
let library = sync::sync_library(db, client, url, username, progress).inspect_err(|e| {
if let sync::SyncError::Subsonic(e) = e {
crate::remote::refusal::observe_error(client.auth(), e);
}
})?;
if library.is_complete()
&& let Some(version) = version
{
sync::set_library_version(db, url, username, version)?;
}
library
};
Ok(Synced {
library,
favourites: reconcile_favourites(db, client),
playlists: crate::playlists::reconcile_playlists(db, client, url, username),
history: crate::remote::history::reconcile(db, client, url, username),
dsp: crate::remote::dsp_sync::reconcile(db, client, url),
})
}