mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-22 15:25:46 +00:00
b24a7fc5cb
* feat(analysis): native library backfill coordinator for advanced strategy Move advanced analytics scheduling from the webview loop into a Rust background worker (configure + spawn_blocking batch/enqueue), matching cover backfill. Scan hash+BPM gap tracks instead of the full library; suppress low-priority analysis UI events; limit loudness refresh IPC to the playback window. * fix(analysis): flat backfill configure IPC and restore probe track-perf Use flattened Tauri args like cover backfill so release/prod invoke works; keep emitting analysis:track-perf for library low-priority work so Performance Probe tpm/last-track stats update while waveform/enrichment UI events stay suppressed. * chore(analysis): fix clippy and drop duplicate TS backfill policy Allow too_many_arguments on library_analysis_backfill_configure for CI; remove unused frontend batch API and TS watermark helpers now owned in Rust; clarify analysis_emits_ui_events comment for low-priority track-perf. * docs: CHANGELOG and credits for PR #881 native analysis backfill
65 lines
1.9 KiB
Rust
65 lines
1.9 KiB
Rust
//! When the local library index is safe for background analysis backfill.
|
|
|
|
use crate::dto::local_tracks_max_updated_ms;
|
|
use crate::repos::{sync_state::SyncStateRepository, TrackRepository};
|
|
use crate::store::LibraryStore;
|
|
|
|
/// Mirrors frontend `libraryStatusIsReady` / `libraryIsReady` (spec §9.3).
|
|
pub fn library_server_is_ready(store: &LibraryStore, server_id: &str) -> Result<bool, String> {
|
|
let repo = SyncStateRepository::new(store);
|
|
let phase = repo
|
|
.get_sync_phase(server_id, "")
|
|
.map_err(|e| e.to_string())?;
|
|
|
|
let Some(phase) = phase else {
|
|
return Ok(has_any_local_tracks(store, server_id));
|
|
};
|
|
|
|
if phase == "ready" {
|
|
return Ok(true);
|
|
}
|
|
if phase == "initial_sync" {
|
|
let local = repo
|
|
.get_local_track_count(server_id, "")
|
|
.map_err(|e| e.to_string())?
|
|
.unwrap_or(0);
|
|
let server = repo
|
|
.get_server_track_count(server_id, "")
|
|
.map_err(|e| e.to_string())?
|
|
.unwrap_or(0);
|
|
if server > 0 && (local as f64 / server as f64) >= 0.95 {
|
|
return Ok(true);
|
|
}
|
|
return Ok(false);
|
|
}
|
|
if phase == "idle" {
|
|
if has_any_local_tracks(store, server_id) {
|
|
return Ok(true);
|
|
}
|
|
if repo
|
|
.has_last_full_sync_at(server_id, "")
|
|
.map_err(|e| e.to_string())?
|
|
{
|
|
return Ok(true);
|
|
}
|
|
if local_tracks_max_updated_ms(store, server_id)?
|
|
.is_some_and(|ms| ms > 0)
|
|
{
|
|
return Ok(true);
|
|
}
|
|
let local = repo
|
|
.get_local_track_count(server_id, "")
|
|
.map_err(|e| e.to_string())?
|
|
.unwrap_or(0);
|
|
return Ok(local > 0);
|
|
}
|
|
Ok(false)
|
|
}
|
|
|
|
fn has_any_local_tracks(store: &LibraryStore, server_id: &str) -> bool {
|
|
TrackRepository::new(store)
|
|
.count_live_tracks(server_id)
|
|
.map(|n| n > 0)
|
|
.unwrap_or(false)
|
|
}
|