diff --git a/lib/crates/fabro-cli/src/commands/runs/rm.rs b/lib/crates/fabro-cli/src/commands/runs/rm.rs index 0f7e71d8d..cd9e910ad 100644 --- a/lib/crates/fabro-cli/src/commands/runs/rm.rs +++ b/lib/crates/fabro-cli/src/commands/runs/rm.rs @@ -7,6 +7,7 @@ use fabro_store::Store; use tracing::warn; use fabro_sandbox::reconnect::reconnect as reconnect_sandbox; +use fabro_workflow::run_lookup::RunInfo; use fabro_workflow::run_lookup::{resolve_run_combined, runs_base}; use fabro_workflow::run_status::{RunStatus, RunStatusRecord, write_run_status}; @@ -68,50 +69,8 @@ async fn remove_from( continue; } - write_run_status(&run.path, RunStatus::Removing, None); - let run_store = match store.open_run_reader(&run.run_id).await { - Ok(run_store) => run_store, - Err(err) => { - warn!( - run_id = %run.run_id, - error = %err, - "failed to open run store during removal" - ); - None - } - }; - if let Some(run_store) = run_store.as_ref() { - if let Err(err) = run_store - .put_status(&RunStatusRecord::new(RunStatus::Removing, None)) - .await - { - warn!( - run_id = %run.run_id, - error = %err, - "failed to save removing status to store" - ); - } - } - - if let Some(record) = load_sandbox_record(&run.path, run_store.as_deref()).await { - if record.provider != "local" { - match reconnect_sandbox(&record).await { - Ok(sandbox) => { - if let Err(err) = sandbox.cleanup().await { - warn!(run_id = %run.run_id, error = %err, "sandbox cleanup failed"); - } - } - Err(err) => { - warn!(run_id = %run.run_id, error = %err, "sandbox reconnect failed"); - } - } - } - } - let run_id = run.run_id.to_string(); - if let Err(err) = std::fs::remove_dir_all(&run.path) - .with_context(|| format!("failed to delete {}", run.path.display())) - { + if let Err(err) = remove_run_dir_with_cleanup(store, &run).await { if !globals.json { eprintln!("error: {identifier}: {err}"); } @@ -126,11 +85,7 @@ async fn remove_from( if !globals.json { eprintln!("{}", short_run_id(&run_id)); } - if let Err(err) = store - .delete_run(&run.run_id) - .await - .with_context(|| format!("failed to delete store state for {}", run.run_id)) - { + if let Err(err) = delete_run_store_state(store, &run).await { if !globals.json { eprintln!("error: {identifier}: {err}"); } @@ -155,6 +110,63 @@ async fn remove_from( Ok(()) } +pub(crate) async fn remove_run_with_cleanup(store: &dyn Store, run: &RunInfo) -> Result<()> { + remove_run_dir_with_cleanup(store, run).await?; + delete_run_store_state(store, run).await +} + +async fn remove_run_dir_with_cleanup(store: &dyn Store, run: &RunInfo) -> Result<()> { + write_run_status(&run.path, RunStatus::Removing, None); + let run_store = match store.open_run_reader(&run.run_id).await { + Ok(run_store) => run_store, + Err(err) => { + warn!( + run_id = %run.run_id, + error = %err, + "failed to open run store during removal" + ); + None + } + }; + if let Some(run_store) = run_store.as_ref() { + if let Err(err) = run_store + .put_status(&RunStatusRecord::new(RunStatus::Removing, None)) + .await + { + warn!( + run_id = %run.run_id, + error = %err, + "failed to save removing status to store" + ); + } + } + + if let Some(record) = load_sandbox_record(&run.path, run_store.as_deref()).await { + if record.provider != "local" { + match reconnect_sandbox(&record).await { + Ok(sandbox) => { + if let Err(err) = sandbox.cleanup().await { + warn!(run_id = %run.run_id, error = %err, "sandbox cleanup failed"); + } + } + Err(err) => { + warn!(run_id = %run.run_id, error = %err, "sandbox reconnect failed"); + } + } + } + } + + std::fs::remove_dir_all(&run.path) + .with_context(|| format!("failed to delete {}", run.path.display())) +} + +async fn delete_run_store_state(store: &dyn Store, run: &RunInfo) -> Result<()> { + store + .delete_run(&run.run_id) + .await + .with_context(|| format!("failed to delete store state for {}", run.run_id)) +} + async fn load_sandbox_record( run_dir: &Path, run_store: Option<&dyn fabro_store::RunStore>, diff --git a/lib/crates/fabro-cli/src/commands/system/prune.rs b/lib/crates/fabro-cli/src/commands/system/prune.rs index d0148fc5f..20c4ec5ad 100644 --- a/lib/crates/fabro-cli/src/commands/system/prune.rs +++ b/lib/crates/fabro-cli/src/commands/system/prune.rs @@ -10,6 +10,7 @@ use tracing::{debug, info}; use fabro_workflow::run_lookup::{StatusFilter, filter_runs, runs_base, scan_runs_combined}; use crate::args::{GlobalArgs, RunsPruneArgs}; +use crate::commands::runs::rm::remove_run_with_cleanup; use crate::shared::{format_size, print_json_pretty}; use crate::store; use crate::user_config::load_user_settings_with_globals; @@ -120,11 +121,7 @@ async fn prune_from( if args.yes { for run in &filtered { info!(run_id = %run.run_id, path = %run.path.display(), "deleting run"); - std::fs::remove_dir_all(&run.path)?; - store - .delete_run(&run.run_id) - .await - .with_context(|| format!("failed to delete store state for {}", run.run_id))?; + remove_run_with_cleanup(store, run).await?; } if globals.json { print_json_pretty(&serde_json::json!({