-
Notifications
You must be signed in to change notification settings - Fork 131
ostree: Use indicatif + async for lock wait #1536
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
cgwalters
commented
Aug 20, 2025
- Indicatif instead of eprintln! ensures we handle ttys vs not always; on a non-tty we're silent
- Use a proper async task instead of a try+sleep loop
- But do try once outside of the await to make the happy path avoid emitting a wait message
- Indicatif instead of eprintln! ensures we handle ttys vs not always; on a non-tty we're silent - Use a proper async task instead of a try+sleep loop - But do try once outside of the await to make the happy path avoid emitting a wait message Signed-off-by: Colin Walters <walters@verbum.org>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces a nice improvement by using indicatif
for a better user experience when waiting for a sysroot lock, replacing a manual print and sleep loop. The new async_task_with_spinner
utility is a good abstraction. My review includes a suggestion to refactor the lock acquisition logic to reduce code duplication and another to improve the panic safety of the new spinner utility.
if sysroot.try_lock()? { | ||
return Ok(Self { | ||
sysroot: sysroot.clone(), | ||
unowned: false, | ||
}); | ||
} | ||
async_task_with_spinner("Waiting for sysroot lock...", sysroot.lock_future()).await?; | ||
Ok(Self { | ||
sysroot: sysroot.clone(), | ||
unowned: false, | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic to construct the SysrootLock
is duplicated. You can refactor this to avoid repetition by handling the case where the lock isn't immediately available, and then having a single point of SysrootLock
creation. This will make the code more maintainable.
if sysroot.try_lock()? { | |
return Ok(Self { | |
sysroot: sysroot.clone(), | |
unowned: false, | |
}); | |
} | |
async_task_with_spinner("Waiting for sysroot lock...", sysroot.lock_future()).await?; | |
Ok(Self { | |
sysroot: sysroot.clone(), | |
unowned: false, | |
}) | |
if !sysroot.try_lock()? { | |
async_task_with_spinner("Waiting for sysroot lock...", sysroot.lock_future()).await?; | |
} | |
Ok(Self { | |
sysroot: sysroot.clone(), | |
unowned: false, | |
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, but not worth blocking over
let pb = indicatif::ProgressBar::new_spinner(); | ||
let style = indicatif::ProgressStyle::default_bar(); | ||
pb.set_style(style.template("{spinner} {msg}").unwrap()); | ||
pb.set_message(msg.to_string()); | ||
pb.enable_steady_tick(Duration::from_millis(150)); | ||
let r = f.await; | ||
pb.finish_and_clear(); | ||
r |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the future f
panics, the await
will unwind the stack and pb.finish_and_clear()
will not be called, leaving the spinner on the screen. Using a RAII guard to manage the ProgressBar
's lifetime ensures that it's cleaned up correctly even in the case of a panic.
let pb = indicatif::ProgressBar::new_spinner(); | |
let style = indicatif::ProgressStyle::default_bar(); | |
pb.set_style(style.template("{spinner} {msg}").unwrap()); | |
pb.set_message(msg.to_string()); | |
pb.enable_steady_tick(Duration::from_millis(150)); | |
let r = f.await; | |
pb.finish_and_clear(); | |
r | |
let pb = indicatif::ProgressBar::new_spinner(); | |
let style = indicatif::ProgressStyle::default_bar(); | |
pb.set_style(style.template("{spinner} {msg}").unwrap()); | |
pb.set_message(msg.to_string()); | |
pb.enable_steady_tick(Duration::from_millis(150)); | |
struct Guard(indicatif::ProgressBar); | |
impl Drop for Guard { | |
fn drop(&mut self) { | |
self.0.finish_and_clear(); | |
} | |
} | |
let _guard = Guard(pb); | |
f.await |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow that's kinda wild that it noticed that. While I guess it's true... if we panic it's not like the fact that the spinner isn't cleared is the most jarring UX from the whole thing 😆
Fallout in #1547 |