diff --git a/crates/cli/commands/src/prune.rs b/crates/cli/commands/src/prune.rs index 813527360c..6a7fe0e1d3 100644 --- a/crates/cli/commands/src/prune.rs +++ b/crates/cli/commands/src/prune.rs @@ -12,6 +12,8 @@ use reth_node_metrics::{ server::{MetricServer, MetricServerConfig}, version::VersionInfo, }; +#[cfg(all(unix, feature = "edge"))] +use reth_provider::RocksDBProviderFactory; use reth_prune::PrunerBuilder; use reth_static_file::StaticFileProducer; use std::sync::Arc; @@ -85,7 +87,7 @@ impl> PruneComma const DELETE_LIMIT: usize = 20_000_000; let mut pruner = PrunerBuilder::new(config) .delete_limit(DELETE_LIMIT) - .build_with_provider_factory(provider_factory); + .build_with_provider_factory(provider_factory.clone()); let mut total_pruned = 0usize; loop { @@ -124,6 +126,14 @@ impl> PruneComma } } + // Flush and compact RocksDB to reclaim disk space after pruning + #[cfg(all(unix, feature = "edge"))] + { + info!(target: "reth::cli", "Flushing and compacting RocksDB..."); + provider_factory.rocksdb_provider().flush_and_compact()?; + info!(target: "reth::cli", "RocksDB compaction complete"); + } + Ok(()) } } diff --git a/crates/storage/provider/src/providers/rocksdb/provider.rs b/crates/storage/provider/src/providers/rocksdb/provider.rs index 69360c8a32..a7ed4ed8be 100644 --- a/crates/storage/provider/src/providers/rocksdb/provider.rs +++ b/crates/storage/provider/src/providers/rocksdb/provider.rs @@ -933,6 +933,32 @@ impl RocksDBProvider { Ok(()) } + /// Flushes and compacts all tables in `RocksDB`. + /// + /// This: + /// 1. Flushes all column family memtables to SST files + /// 2. Flushes the Write-Ahead Log (WAL) with sync + /// 3. Triggers manual compaction on all column families to reclaim disk space + /// + /// Use this after large delete operations (like pruning) to reclaim disk space. + /// + /// # Panics + /// Panics if the provider is in read-only mode. + #[instrument(level = "debug", target = "providers::rocksdb", skip_all)] + pub fn flush_and_compact(&self) -> ProviderResult<()> { + self.flush(ROCKSDB_TABLES)?; + + let db = self.0.db_rw(); + + for cf_name in ROCKSDB_TABLES { + if let Some(cf) = db.cf_handle(cf_name) { + db.compact_range_cf(&cf, None::<&[u8]>, None::<&[u8]>); + } + } + + Ok(()) + } + /// Creates a raw iterator over all entries in the specified table. /// /// Returns raw `(key_bytes, value_bytes)` pairs without decoding.