diff --git a/cbd-tui/src/rpc.rs b/cbd-tui/src/rpc.rs index dad0e03..3b73ddc 100644 --- a/cbd-tui/src/rpc.rs +++ b/cbd-tui/src/rpc.rs @@ -87,12 +87,13 @@ pub struct RpcClient { /// /// The server-side folder providers mutate behind the client's back — /// saves and captures appear under `/crabidy` (`w`/`W`), files change on -/// disk under `/fs` — so a cached listing turns freshly captured content -/// invisible until a restart. Their listings are cheap local directory +/// disk under `/fs`, and `/orphans` is recomputed from the store on every +/// visit — so a cached listing turns freshly captured content (or a changed +/// orphan set) invisible until a restart. Their listings are cheap local /// walks on the server; always refetch them. Remote provider nodes (tidal, /// youtube) keep the cache that makes back-navigation instant. fn is_cacheable(path: &str) -> bool { - const MUTABLE_ROOTS: [&str; 2] = ["/crabidy", "/fs"]; + const MUTABLE_ROOTS: [&str; 3] = ["/crabidy", "/fs", "/orphans"]; !MUTABLE_ROOTS.iter().any(|root| { path == *root || (path.starts_with(root) && path.as_bytes().get(root.len()) == Some(&b'/')) }) @@ -398,6 +399,8 @@ mod tests { "/crabidy/current", "/crabidy/road trip", "/fs/music", + "/orphans", + "/orphans/stray.flac", ] { assert!(!is_cacheable(path), "{path}"); } @@ -408,5 +411,6 @@ mod tests { // …and prefix look-alikes are not swept up. assert!(is_cacheable("/fsdy")); assert!(is_cacheable("/crabidystore")); + assert!(is_cacheable("/orphansaurus")); } } diff --git a/cbd-web/src/state.rs b/cbd-web/src/state.rs index 4eca13d..d8269fc 100644 --- a/cbd-web/src/state.rs +++ b/cbd-web/src/state.rs @@ -69,9 +69,12 @@ pub fn delete_needs_confirmation(path: &str) -> bool { /// Whether a library listing may be cached client-side — same rule as /// the TUI (`cbd-tui/src/rpc.rs`): server-side folder providers mutate -/// behind the client's back and are cheap to re-list. +/// behind the client's back and are cheap to re-list. `/crabidy` (saves and +/// captures), `/fs` (files on disk), and `/orphans` (recomputed from the +/// store on every visit) all change server-side, so their listings are +/// always refetched. pub fn is_cacheable(path: &str) -> bool { - const MUTABLE_ROOTS: [&str; 4] = ["/captures", "/queues", "/bookmarks", "/fs"]; + const MUTABLE_ROOTS: [&str; 3] = ["/crabidy", "/fs", "/orphans"]; !MUTABLE_ROOTS.iter().any(|root| { path == *root || (path.starts_with(root) && path.as_bytes().get(root.len()) == Some(&b'/')) }) @@ -465,10 +468,21 @@ mod tests { #[test] fn mutable_roots_are_never_cacheable() { - for path in ["/captures", "/queues/x", "/bookmarks", "/fs/music"] { + for path in [ + "/crabidy", + "/crabidy/faves", + "/fs/music", + "/orphans", + "/orphans/stray.flac", + ] { assert!(!is_cacheable(path), "{path}"); } - for path in ["/tidal/playlists", "/youtube/search", "/capturesque"] { + for path in [ + "/tidal/playlists", + "/youtube/search", + "/crabidystore", + "/orphansaurus", + ] { assert!(is_cacheable(path), "{path}"); } }