mirror of
https://github.com/storytold/lightcraft.git
synced 2026-11-01 05:57:09 -06:00
LRC-LIB-MISSING: a slow count's timed refresh doesn't hold up settling
While a headless run settles, its simulated clock runs several times faster than wall time, so with every Missing Photos count pending, a count that takes about a second started the next 5 s refresh before the last one finished and settle() never ended (120 s timeout with a 1 s count, 48 s with 600 ms). That would also stall lightcraft-cli snapshot on a library on a slow share. Only the first count and a recount after a catalog change, which add or take away the Missing Photos row, are pending work now; the timed refresh is not. Settling takes as long as the count (1.0 s for 1 s, 3.0 s for 3 s). The regression test also checks that settling ends while a slow count refreshes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
142ddcff29
commit
9f7936c3c6
@@ -381,9 +381,11 @@ fn new_album_menu(app: &mut LightcraftApp, ui: &mut egui::Ui) {
|
||||
/// How many library photos have no file (Local browse records are not checked; see
|
||||
/// `cmd::missing::checked_path`). Checking stats every file, which on a network share takes
|
||||
/// seconds, so it runs on a worker thread: the count shown is the last finished one, refreshed
|
||||
/// at most every 5 s, and at once (after the running check) when the catalog changed. The check
|
||||
/// counts as pending sidebar work ([`super::fs_cached_running`]): the Missing Photos row it adds
|
||||
/// moves every row below it.
|
||||
/// at most every 5 s, and at once (after the running check) when the catalog changed. The first
|
||||
/// count and a recount after a catalog change are pending sidebar work
|
||||
/// ([`super::fs_cached_running`]): the Missing Photos row they add or take away moves every row
|
||||
/// below it. The timed refresh is not: it rarely changes the count, and on a share where counting
|
||||
/// takes seconds, a headless run's fast simulated clock would start the next one before settling.
|
||||
pub(super) fn missing_count(app: &mut LightcraftApp, ui: &mut egui::Ui) -> usize {
|
||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering::AcqRel, Ordering::Relaxed};
|
||||
#[derive(Clone, Default)]
|
||||
@@ -401,11 +403,13 @@ pub(super) fn missing_count(app: &mut LightcraftApp, ui: &mut egui::Ui) -> usize
|
||||
if !fresh && !job.running.load(Relaxed) {
|
||||
// the same scope as the Missing Photos view: library photos only, never Local browse records
|
||||
let paths = lightcraft_engine::cmd::missing::candidates(&app.session.catalog);
|
||||
let pending = (job.rev != rev).then(|| super::local::fs_running_counter(ui.ctx()));
|
||||
if let Some(p) = &pending {
|
||||
p.fetch_add(1, AcqRel);
|
||||
}
|
||||
job.running.store(true, Relaxed);
|
||||
job.at = now;
|
||||
job.rev = rev;
|
||||
let pending = super::local::fs_running_counter(ui.ctx());
|
||||
pending.fetch_add(1, AcqRel);
|
||||
#[cfg(test)]
|
||||
let test_delay = app.missing_count_test_delay;
|
||||
let (n, running, ctx, done) = (job.n.clone(), job.running.clone(), ui.ctx().clone(), pending.clone());
|
||||
@@ -418,14 +422,18 @@ pub(super) fn missing_count(app: &mut LightcraftApp, ui: &mut egui::Ui) -> usize
|
||||
n.store(missing, Relaxed);
|
||||
running.store(false, Relaxed);
|
||||
// after the count is stored: a frame that sees the pending count drop also sees the row
|
||||
done.fetch_sub(1, AcqRel);
|
||||
if let Some(d) = done {
|
||||
d.fetch_sub(1, AcqRel);
|
||||
}
|
||||
ctx.request_repaint();
|
||||
};
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
if std::thread::Builder::new().name("lc-missing-count".into()).spawn(work).is_err() {
|
||||
// no thread to spare: keep the last count and try again after the next 5 s
|
||||
job.running.store(false, Relaxed);
|
||||
pending.fetch_sub(1, AcqRel);
|
||||
if let Some(p) = &pending {
|
||||
p.fetch_sub(1, AcqRel);
|
||||
}
|
||||
}
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
work();
|
||||
|
||||
@@ -1883,6 +1883,9 @@ fn settling_waits_for_the_missing_photos_count() {
|
||||
std::thread::sleep(Duration::from_millis(5));
|
||||
}
|
||||
assert_eq!(widget(&h, "source:libfolder:/lc-missing-count/trip"), settled, "nothing moves the folder rows after settling");
|
||||
// the timed refresh of a slow count is not waited for: the fast simulated clock would start
|
||||
// the next one before the last finished, and settling would never end
|
||||
assert!(h.settle(Duration::from_secs(30)), "the sidebar settles while a slow count refreshes");
|
||||
}
|
||||
|
||||
/// Right-click a folder ▸ Set Color Label ▸ a colour: the folder's row shows the label's dot (a
|
||||
|
||||
Reference in New Issue
Block a user