LR-IMP-LOCAL: Opening on Missing Photos no longer checks every original

Forgetting untouched Local records on open kept the visible photos, and on
Missing Photos working them out stats every original on the UI thread
before the availability worker runs. A 37k-photo library on a sleeping
SMB share froze the window for minutes. Missing Photos lists library
photos only, never Local records, so it can keep nothing: skip it.
This commit is contained in:
Alexander Bystrow
2026-10-16 13:46:30 +02:00
parent f34c7a8a89
commit bf82b57a0a
2 changed files with 40 additions and 1 deletions
+5 -1
View File
@@ -148,7 +148,11 @@ fn stamp_browsed(s: &mut Session, root: &str, files: &[String]) {
/// referred to by an undo / redo step.
fn in_use(s: &mut Session) -> std::collections::HashSet<PhotoId> {
let mut keep = held(s);
keep.extend(s.visible().iter().copied());
// Missing Photos lists library photos only, never Local records, so it keeps nothing here; and
// working it out checks every original (minutes on a sleeping NAS when the library opens on it)
if s.source != crate::LibrarySource::Missing {
keep.extend(s.visible().iter().copied());
}
keep
}
+35
View File
@@ -259,3 +259,38 @@ fn browsing_again_forgets_untouched_records_of_deleted_files() {
assert_eq!(s.catalog.to_snapshot(), expect);
let _ = std::fs::remove_dir_all(&root);
}
/// A library last shown on Missing Photos opens without checking its originals: that view holds
/// no Local records, so forgetting them needn't work it out (each check can wait for a sleeping
/// NAS; a big library on one froze the window for minutes on start-up).
#[test]
fn opening_on_missing_photos_checks_no_originals() {
let root = temp_dir("missing");
let (a, lib) = (root.join("a"), root.join("lib"));
for i in 0..5 {
png(&a.join(format!("m{i}.png")), i);
}
let clock = Arc::new(Mutex::new("2026-08-01T10:00:00".to_string()));
let mut s = open(&lib, &clock);
s.execute("library.import", &json!({"paths": [a.to_string_lossy()], "mode": "add"})).unwrap();
std::fs::remove_dir_all(&a).unwrap();
s.execute("library.source", &json!({"kind": "missing"})).unwrap();
assert_eq!(s.visible().len(), 5, "all five are missing");
s.close_library().unwrap();
drop(s);
let checks = Arc::new(std::sync::atomic::AtomicUsize::new(0));
let mut s = Session::new().with_fs();
let c = clock.clone();
s.clock = Box::new(move || c.lock().unwrap().clone());
let n = checks.clone();
s.media.availability.set_probe(Arc::new(move |p| {
n.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
Path::new(p).exists()
}));
s.open_library(&lib, false).unwrap();
assert_eq!(s.source, LibrarySource::Missing, "the view is restored");
assert_eq!(checks.load(std::sync::atomic::Ordering::SeqCst), 0, "opening checked originals");
assert!(s.library.as_ref().unwrap().forgot_local.is_some(), "forgetting still ran");
let _ = std::fs::remove_dir_all(&root);
}