progress bar host API works

progress
Avril 4 years ago
parent 58643b6440
commit 34ff9847cb
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -1,2 +1 @@
Add lolistealer-like async progress bar handler to State (check state.rs)
Rework logging macro calls to use new progress API

@ -28,7 +28,7 @@ use futures::{
async fn process_single(state: Arc<state::State>, path: impl AsRef<Path>) -> eyre::Result<()>
{
let path = path.as_ref();
debug_assert!(!path.is_file(), "process_single() expected a file, but {:?} is not one.", path);
debug_assert!(path.is_file(), "process_single() expected a file, but {:?} is not one.", path);
let _g = state.lock().await;
debug!("{:?} Processing", path);

@ -102,22 +102,47 @@ async fn validate_config(config: config::Config) -> eyre::Result<config::Config>
async fn begin() -> eyre::Result<i32>
{
use futures::prelude::*;
install()?;
let state = Arc::new(state::State::new(validate_config(config::Config::default()).await
.wrap_err(eyre!("Failed to validate config"))?));
info!("Validated config OK");
if args::process(|file| {
let state = Arc::clone(&state);
use futures::future::TryFutureExt;
process(state, file).inspect_err(|err| eprintln!("{:?}", err))
}).await
.wrap_err(eyre!("One or more child workers failed to complete successfully"))?
.len() == 0
{
args::usage();
}
Ok(0)
let (progress, progress_join) = {
let bar = termprogress::progress::Bar::new(50);
let (p, join) = progress::host(bar);
(p, join.map(|bar| match bar {
Ok(bar) => {
bar.complete();
Ok(())
},
Err(panic) => {
println!();
Err(panic)
},
}))
};
let state = Arc::new(state::State::new(validate_config(config::Config::default()).await
.wrap_err(eyre!("Failed to validate config"))?,
progress));
info!("Validated config OK");
if args::process(|file| {
let state = Arc::clone(&state);
use futures::future::TryFutureExt;
process(state, file).inspect_err(|err| eprintln!("{:?}", err))
}).await
.wrap_err(eyre!("One or more child workers failed to complete successfully"))?
.len() == 0
{
args::usage();
}
//Cleanup deferred in new `async` block to drop `state` before this block is ran.
async move {
progress_join.await?;
Ok::<_, eyre::Report>(0)
}.map(|res| res.wrap_err(eyre!("Cleanup failed")))
}.await
}
#[tokio::main]

@ -41,7 +41,10 @@ pub enum CommandKind
Bump(isize),
BumpHigh(isize),
Set{low: Option<usize>, high: Option<usize>},
Refresh,
/// Add a task to the tasklist
///
/// # Response
@ -58,6 +61,7 @@ pub enum CommandKind
Many(Vec<CommandKind>),
}
/// The type sent in response to a `Command`.
pub type Response = Option<Box<dyn std::any::Any + Send+ Sync + 'static>>;
#[derive(Debug)]
@ -131,7 +135,7 @@ impl State
}
/// A handle to a running async progress bar
#[derive(Debug, Clone)]
#[derive(Debug)]
pub struct Handle<B = Bar>
where B: ProgressBar,
{
@ -145,6 +149,19 @@ where B: ProgressBar,
dead: watch::Receiver<bool>,
}
impl<B: ProgressBar> Clone for Handle<B>
{
fn clone(&self)->Self
{
Self {
chan: self.chan.clone(),
bar: self.bar.clone(),
state: self.state.clone(),
dead: self.dead.clone(),
}
}
}
impl<B: ProgressBar> Handle<B>
{
/// Is the worker alive?
@ -235,7 +252,7 @@ impl fmt::Display for WorkerCommError
}
}
/// Host a progress bar detached
/// Host a progress bar and detach it
pub fn host<B: ProgressBar + Send + Sync + 'static>(bar: B) -> (Handle<B>, JoinHandle<B>)
{
let state = Arc::new(RwLock::new(Default::default()));
@ -255,6 +272,13 @@ pub fn host<B: ProgressBar + Send + Sync + 'static>(bar: B) -> (Handle<B>, JoinH
({
let mut tasks = tasklist::TaskList::new();
macro_rules! update_bar {
(refresh $($tt:tt)*) => {
{
let bar = bar.read().await;
bar.refresh();
update_bar!($($tt)*);
}
};
(to $state:ident $($tt:tt)*) => {
{
let mut bar = bar.write().await;
@ -301,6 +325,8 @@ pub fn host<B: ProgressBar + Send + Sync + 'static>(bar: B) -> (Handle<B>, JoinH
};
() => {};
}
update_bar!(refresh);
while let Some(Command(command, response)) = rx.recv().await {
let response = Arc::new(std::sync::Mutex::new(Some(response)));
@ -362,6 +388,14 @@ pub fn host<B: ProgressBar + Send + Sync + 'static>(bar: B) -> (Handle<B>, JoinH
update_bar!(to state);
},
CommandKind::Set{low: None, high: None} => (),
CommandKind::Set{low, high} => {
let mut state = state.write().await;
state.cur = low.unwrap_or(state.cur);
state.max = high.unwrap_or(state.max);
update_bar!(to state);
},
CommandKind::Line(line) => update_bar!(write line),
CommandKind::LineErr(line) => update_bar!(write error line),
@ -371,8 +405,7 @@ pub fn host<B: ProgressBar + Send + Sync + 'static>(bar: B) -> (Handle<B>, JoinH
CommandKind::RemoveTask(id) => {
send_response!(update_bar!(-task id title));
},
//TODO: Title
CommandKind::Refresh => update_bar!(refresh),
CommandKind::Many(_) => unimplemented!(),
}
}

@ -14,13 +14,14 @@ use futures::{
};
/// Contains state for a set of operations
//TODO: Add progress bar handler in here, when we get around to adding it.
#[derive(Debug)]
pub struct State
{
cfg: config::Config,
mtx: Option<Semaphore>,
stop: RwLock<()>,
progress: progress::Handle,
}
/// Guard for operations inside state
@ -30,12 +31,13 @@ pub struct Permit<'a>(RwLockReadGuard<'a, ()>, Option<SemaphorePermit<'a>>);
impl State
{
/// Create a new state
pub fn new(cfg: config::Config) -> Self
pub fn new(cfg: config::Config, progress: progress::Handle) -> Self
{
Self {
mtx: cfg.limit.map(|x| Semaphore::new(x.into())),
cfg,
stop: RwLock::new(()),
progress,
}
}

Loading…
Cancel
Save