From 95d67a2c964923eac52d597078edee414e3ff878 Mon Sep 17 00:00:00 2001 From: madonuko Date: Tue, 23 Jul 2024 18:46:54 +0800 Subject: [PATCH] feat(update): show script count and refactor --- src/update.rs | 111 ++++++++++++++++++++++++++------------------------ 1 file changed, 58 insertions(+), 53 deletions(-) diff --git a/src/update.rs b/src/update.rs index fe93420..d280367 100644 --- a/src/update.rs +++ b/src/update.rs @@ -1,6 +1,7 @@ use anda_config::Manifest; use andax::{run, RPMSpec}; use color_eyre::Result; +use itertools::Itertools; use std::io::Write; use std::{ collections::BTreeMap, @@ -8,7 +9,6 @@ use std::{ }; use tracing::{debug, error, instrument, trace}; -// TODO: update script count? #[allow(clippy::arithmetic_side_effects)] #[instrument(skip(cfg))] pub fn update( @@ -17,77 +17,82 @@ pub fn update( fls: BTreeMap, ) -> Result<()> { let mut handlers = vec![]; - let project_count = cfg.project.len(); + let proj_len = cfg.project.len(); + let mut scr_len = 0; 'p: for (name, mut proj) in cfg.project { - if let Some(scr) = &proj.update { - trace!(name, scr = scr.to_str(), "Th start"); - let mut lbls = std::mem::take(&mut proj.labels); - lbls.extend(global_lbls.clone()); - if fls.iter().any(|(k, v)| lbls.get(k).is_some_and(|val| val != v)) { - continue 'p; - } - let fls = fls.clone(); - let alias = proj.alias.into_iter().flatten().next().clone().unwrap_or(name); - handlers.push(Builder::new().name(alias).spawn(move || { - let th = thread::current(); - let name = th.name().expect("No name for andax thread??"); - let scr = proj.update.expect("No update script? How did I get here??"); - let start = std::time::SystemTime::now(); - let sc = run(name, &scr, lbls, |sc| { - // we have to do it here as `Dynamic` in andax::Map nu Sync impl - let mut filters = andax::Map::new(); - for (k, v) in fls { - filters.insert(k.into(), v.into()); - } - sc.push("filters", filters); - if let Some(rpm) = &proj.rpm { - sc.push("rpm", RPMSpec::new(name.to_owned(), &scr, &rpm.spec)); - } - }); - let duration = std::time::SystemTime::now().duration_since(start).unwrap(); - if let Some(sc) = sc { - let rpm: RPMSpec = sc.get_value("rpm").expect("No rpm object in rhai scope"); - if let Err(e) = rpm.write() { - error!("{name}: Failed to write RPM: {e}"); - } - } - duration - })?); + let Some(scr) = &proj.update else { continue }; + scr_len += 1; + trace!(name, scr = scr.to_str(), "Th start"); + let mut lbls = std::mem::take(&mut proj.labels); + lbls.extend(global_lbls.clone()); + if fls.iter().any(|(k, v)| lbls.get(k).is_some_and(|val| val != v)) { + continue 'p; } + let fls = fls.clone(); + let alias = proj.alias.into_iter().flatten().next().clone().unwrap_or(name); + handlers.push(Builder::new().name(alias).spawn(move || { + let th = thread::current(); + let name = th.name().expect("No name for andax thread??"); + let scr = proj.update.expect("No update script? How did I get here??"); + let start = std::time::SystemTime::now(); + let sc = run(name, &scr, lbls, |sc| { + // we have to do it here as `Dynamic` in andax::Map nu Sync impl + let mut filters = andax::Map::new(); + for (k, v) in fls { + filters.insert(k.into(), v.into()); + } + sc.push("filters", filters); + if let Some(rpm) = &proj.rpm { + sc.push("rpm", RPMSpec::new(name.to_owned(), &scr, &rpm.spec)); + } + }); + let duration = std::time::SystemTime::now().duration_since(start).unwrap(); + if let Some(sc) = sc { + let rpm: RPMSpec = sc.get_value("rpm").expect("No rpm object in rhai scope"); + if let Err(e) = rpm.write() { + error!("{name}: Failed to write RPM: {e}"); + } + } + duration + })?); } - debug!("Joining {} threads", handlers.len()); - let mut tasks = vec![]; - let handlers_count = handlers.len(); - - for hdl in handlers { - let th = hdl.thread(); - let name = th.name().expect("No name for andax thread??").to_owned(); - match hdl.join() { - Ok(duration) => tasks.push((name, duration)), - Err(e) => error!("Panic @ `{name}` : {e:#?}"), - } + let hdl_len = handlers.len(); + if hdl_len == 0 { + tracing::info!("No tasks were run."); + return Ok(()); } + debug!("Joining {hdl_len} threads"); - tasks.sort_unstable_by(|(_, duration0), (_, duration1)| duration1.cmp(duration0)); + let mut tasks = handlers + .into_iter() + .filter_map(|hdl| { + let th = hdl.thread(); + let name = th.name().expect("No name for andax thread??").to_owned(); + hdl.join() + .inspect_err(|_| error!("Thread `{name}` panicked. This is most likely a bug.")) + .ok() + .map(|duration| (name, duration)) + }) + .sorted_unstable_by(|(_, duration0), (_, duration1)| duration1.cmp(duration0)); + let task_len = tasks.by_ref().count(); let pname_len = tasks - .iter() + .by_ref() .max_by(|(name0, _), (name1, _)| name0.len().cmp(&name1.len())) .map_or(13, |(name, _)| name.len()); let mut stdout = std::io::stdout(); writeln!( stdout, - "\nFinished running {}/{project_count} tasks, {} failed fatally.", - tasks.len(), - handlers_count - tasks.len() + "\nFinished running {task_len}/{scr_len} scripts out of {proj_len} projects, {} failed fatally.", + hdl_len - task_len ) .unwrap(); writeln!(stdout, "Here is a list of unfiltered tasks:\n").unwrap(); writeln!(stdout, "No. Time/ms Project/alias").unwrap(); writeln!(stdout, "═════╤════════╤═{}", "═".repeat(pname_len.max(13))).unwrap(); - for (n, (name, duration)) in tasks.into_iter().enumerate() { + for (n, (name, duration)) in tasks.enumerate() { let sep = if n % 2 == 0 { '┃' } else { '│' }; writeln!(stdout, "{:<5}{sep}{:>7} {sep} {name}", n + 1, duration.as_millis()).unwrap(); }