From 3a03114cb9abcff0ef7df00a763627284fd7a702 Mon Sep 17 00:00:00 2001 From: Test User Date: Thu, 23 Jul 2026 00:13:50 +0200 Subject: [PATCH] Always refetch /orphans (and fix the web client's stale cache roots) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The clients cache library listings except for server-mutable folder roots. /orphans is recomputed from the store on every visit, so a cached listing froze the orphan set until a client restart. Add /orphans to the TUI's mutable-roots list so entering the provider always re-walks. The web client's list was also stale from the store refactor — it still named the removed /captures, /queues, /bookmarks providers and omitted /crabidy, so /crabidy (and now /orphans) listings went stale there too. Reset it to the real mutable roots: /crabidy, /fs, /orphans. Co-Authored-By: Claude Opus 4.8 (1M context) --- cbd-tui/src/rpc.rs | 10 +++++++--- cbd-web/src/state.rs | 22 ++++++++++++++++++---- 2 files changed, 25 insertions(+), 7 deletions(-) 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}"); } }