koan_core/helpers/
sync.rs1use crate::db::connection::Database;
4use crate::remote::client::SubsonicClient;
5
6use super::*;
7
8#[derive(Debug, Default)]
10pub struct Synced {
11 pub library: crate::remote::sync::SyncResult,
12 pub favourites: FavouriteSync,
13 pub playlists: crate::playlists::PlaylistSync,
14 pub history: crate::remote::history::HistorySync,
15 pub dsp: crate::remote::dsp_sync::DspSync,
16}
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum Walk {
21 Always,
23 IfChanged,
27}
28
29pub fn sync_remote(
42 db: &Database,
43 client: &SubsonicClient,
44 walk: Walk,
45 url: &str,
46 username: &str,
47 progress: &(dyn Fn(crate::remote::sync::SyncProgress) + Sync),
48) -> Result<Synced, crate::remote::sync::SyncError> {
49 use crate::remote::sync;
50 static SYNCING: parking_lot::Mutex<()> = parking_lot::Mutex::new(());
55 let _one_at_a_time = SYNCING.lock();
56
57 let walked = sync::library_version(db, url);
58 let modified = client.library_modified(walked);
59 crate::remote::refusal::observe(client.auth(), &modified);
60 let version = modified
61 .inspect_err(|e| log::debug!("library version unavailable: {e}"))
62 .ok()
63 .flatten();
64 let library = if walk == Walk::IfChanged && version.is_some() && version == walked {
65 log::info!("library unchanged on the server; not walked");
66 sync::SyncResult::default()
67 } else {
68 let library = sync::sync_library(db, client, url, username, progress).inspect_err(|e| {
69 if let sync::SyncError::Subsonic(e) = e {
70 crate::remote::refusal::observe_error(client.auth(), e);
71 }
72 })?;
73 if library.is_complete()
74 && let Some(version) = version
75 {
76 sync::set_library_version(db, url, username, version)?;
77 }
78 library
79 };
80 Ok(Synced {
81 library,
82 favourites: reconcile_favourites(db, client),
83 playlists: crate::playlists::reconcile_playlists(db, client, url, username),
84 history: crate::remote::history::reconcile(db, client, url, username),
85 dsp: crate::remote::dsp_sync::reconcile(db, client, url),
86 })
87}