Polish: cluster-ref-sweep --apply #85
+38
-2
@@ -230,6 +230,13 @@ enum Cmd {
|
||||
/// reaped before someone can rebuild against them.
|
||||
#[arg(long, default_value_t = 14)]
|
||||
retention_days: u64,
|
||||
/// Polish (2026-07-14): actually forget the stale
|
||||
/// ref-tracking records. Without this flag the command is
|
||||
/// dry-run only. Blob data is untouched — eviction happens
|
||||
/// on the next `cluster-gc` when the fingerprint's tag pin
|
||||
/// disappears (nobody pins it any more).
|
||||
#[arg(long)]
|
||||
apply: bool,
|
||||
},
|
||||
/// Phase 7d (2026-07-14): take a point-in-time snapshot of every
|
||||
/// blob currently in the local store. Snapshots are cheap
|
||||
@@ -371,7 +378,8 @@ async fn main() -> Result<()> {
|
||||
gitea_url,
|
||||
gitea_token,
|
||||
retention_days,
|
||||
} => cmd_cluster_ref_sweep(&cfg, &gitea_url, gitea_token, retention_days).await?,
|
||||
apply,
|
||||
} => cmd_cluster_ref_sweep(&cfg, &gitea_url, gitea_token, retention_days, apply).await?,
|
||||
Cmd::ClusterSnapshotCreate { name } => cmd_cluster_snapshot_create(&cfg, &name).await?,
|
||||
Cmd::ClusterSnapshotList => cmd_cluster_snapshot_list(&cfg).await?,
|
||||
Cmd::ClusterSnapshotShow { name } => cmd_cluster_snapshot_show(&cfg, &name).await?,
|
||||
@@ -777,6 +785,7 @@ async fn cmd_cluster_ref_sweep(
|
||||
gitea_url: &str,
|
||||
gitea_token: Option<String>,
|
||||
retention_days: u64,
|
||||
apply: bool,
|
||||
) -> Result<()> {
|
||||
use cluster::gitea::GiteaClient;
|
||||
use cluster::ref_tracking::RefTracking;
|
||||
@@ -872,13 +881,40 @@ async fn cmd_cluster_ref_sweep(
|
||||
}
|
||||
}
|
||||
println!();
|
||||
println!("dry-run: no records modified. Use `forget` per fp to prune records");
|
||||
if apply {
|
||||
// Polish (2026-07-14): actually forget the stale records.
|
||||
// Blob data untouched — the next cluster-gc reclaims disk
|
||||
// once the fp's associated tag pins drop off.
|
||||
let mut forgotten = 0usize;
|
||||
let mut errors = 0usize;
|
||||
for fp in &stale {
|
||||
match rt.forget(fp).await {
|
||||
Ok(true) => forgotten += 1,
|
||||
Ok(false) => {} // already gone
|
||||
Err(e) => {
|
||||
errors += 1;
|
||||
eprintln!("warn: forget({}) failed: {e}", hex_bytes(fp));
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("applied: forgot {forgotten} ref-tracking records ({errors} errors)");
|
||||
} else {
|
||||
println!("dry-run: no records modified. Re-run with --apply to prune.");
|
||||
}
|
||||
println!("(blob eviction on next cluster-gc handles the actual disk reclaim).");
|
||||
println!("total elapsed: {:?}", started.elapsed());
|
||||
println!("────────────────────────────────────────────────────");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn hex_bytes(bytes: &[u8; 32]) -> String {
|
||||
let mut s = String::with_capacity(64);
|
||||
for b in bytes {
|
||||
s.push_str(&format!("{b:02x}"));
|
||||
}
|
||||
s
|
||||
}
|
||||
|
||||
async fn cmd_cluster_peer_status(
|
||||
peer: &str,
|
||||
rpc_addr: SocketAddr,
|
||||
|
||||
Reference in New Issue
Block a user