From 8dfa5fc37e6d7e289e102a3b657f003d9c3317ad Mon Sep 17 00:00:00 2001 From: Simon Laux Date: Fri, 12 Dec 2025 21:15:12 +0100 Subject: [PATCH] api: add blob dir size to storage info (#7605) closes #7598 --- Cargo.lock | 2 +- Cargo.toml | 1 + deltachat-jsonrpc/Cargo.toml | 1 - deltachat-jsonrpc/src/api.rs | 11 ++--------- src/storage_usage.rs | 23 +++++++++++++++++++++++ 5 files changed, 27 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9930f6c7c..1972e34f8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1388,6 +1388,7 @@ dependencies = [ "tracing", "url", "uuid", + "walkdir", "webpki-roots", ] @@ -1429,7 +1430,6 @@ dependencies = [ "tempfile", "tokio", "typescript-type-def", - "walkdir", "yerpc", ] diff --git a/Cargo.toml b/Cargo.toml index c502647ec..dc9155fab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -111,6 +111,7 @@ toml = "0.9" tracing = "0.1.41" url = "2" uuid = { version = "1", features = ["serde", "v4"] } +walkdir = "2.5.0" webpki-roots = "0.26.8" [dev-dependencies] diff --git a/deltachat-jsonrpc/Cargo.toml b/deltachat-jsonrpc/Cargo.toml index 543586c76..18339ca33 100644 --- a/deltachat-jsonrpc/Cargo.toml +++ b/deltachat-jsonrpc/Cargo.toml @@ -19,7 +19,6 @@ yerpc = { workspace = true, features = ["anyhow_expose", "openrpc"] } typescript-type-def = { version = "0.5.13", features = ["json_value"] } tokio = { workspace = true } sanitize-filename = { workspace = true } -walkdir = "2.5.0" base64 = { workspace = true } [dev-dependencies] diff --git a/deltachat-jsonrpc/src/api.rs b/deltachat-jsonrpc/src/api.rs index 7f1d57b48..36821b610 100644 --- a/deltachat-jsonrpc/src/api.rs +++ b/deltachat-jsonrpc/src/api.rs @@ -35,14 +35,13 @@ use deltachat::qr_code_generator::{generate_backup_qr, get_securejoin_qr_svg}; use deltachat::reaction::{get_msg_reactions, send_reaction}; use deltachat::securejoin; use deltachat::stock_str::StockMessage; -use deltachat::storage_usage::get_storage_usage; +use deltachat::storage_usage::{get_blobdir_storage_usage, get_storage_usage}; use deltachat::webxdc::StatusUpdateSerial; use deltachat::EventEmitter; use sanitize_filename::is_sanitized; use tokio::fs; use tokio::sync::{watch, Mutex, RwLock}; use types::login_param::EnteredLoginParam; -use walkdir::WalkDir; use yerpc::rpc; pub mod types; @@ -330,13 +329,7 @@ impl CommandApi { async fn get_account_file_size(&self, account_id: u32) -> Result { let ctx = self.get_context(account_id).await?; let dbfile = ctx.get_dbfile().metadata()?.len(); - let total_size = WalkDir::new(ctx.get_blobdir()) - .max_depth(2) - .into_iter() - .filter_map(|entry| entry.ok()) - .filter_map(|entry| entry.metadata().ok()) - .filter(|metadata| metadata.is_file()) - .fold(0, |acc, m| acc + m.len()); + let total_size = get_blobdir_storage_usage(&ctx); Ok(dbfile + total_size) } diff --git a/src/storage_usage.rs b/src/storage_usage.rs index 0b7ba6a95..72e7967d0 100644 --- a/src/storage_usage.rs +++ b/src/storage_usage.rs @@ -2,6 +2,7 @@ use crate::{context::Context, message::MsgId}; use anyhow::Result; use humansize::{BINARY, format_size}; +use walkdir::WalkDir; /// Storage Usage Report /// Useful for debugging space usage problems in the deltachat database. @@ -14,11 +15,15 @@ pub struct StorageUsage { /// count and total size of status updates /// for the 10 webxdc apps with the most size usage in status updates pub largest_webxdc_data: Vec<(MsgId, u64, u64)>, + /// Total size of all files in the blobdir + pub blobdir_size: u64, } impl std::fmt::Display for StorageUsage { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { writeln!(f, "Storage Usage:")?; + let blobdir_size = format_size(self.blobdir_size, BINARY); + writeln!(f, "[Blob Directory Size]: {blobdir_size}")?; let human_db_size = format_size(self.db_size, BINARY); writeln!(f, "[Database Size]: {human_db_size}")?; writeln!(f, "[Largest Tables]:")?; @@ -46,6 +51,10 @@ impl std::fmt::Display for StorageUsage { /// Get storage usage information for the Context's database pub async fn get_storage_usage(ctx: &Context) -> Result { + let context_clone = ctx.clone(); + let blobdir_size = + tokio::task::spawn_blocking(move || get_blobdir_storage_usage(&context_clone)); + let page_size: u64 = ctx .sql .query_get_value("PRAGMA page_size", ()) @@ -101,9 +110,23 @@ pub async fn get_storage_usage(ctx: &Context) -> Result { ) .await?; + let blobdir_size = blobdir_size.await?; + Ok(StorageUsage { db_size: page_size * page_count, largest_tables, largest_webxdc_data, + blobdir_size, }) } + +/// Returns storage usage of the blob directory +pub fn get_blobdir_storage_usage(ctx: &Context) -> u64 { + WalkDir::new(ctx.get_blobdir()) + .max_depth(2) + .into_iter() + .filter_map(|entry| entry.ok()) + .filter_map(|entry| entry.metadata().ok()) + .filter(|metadata| metadata.is_file()) + .fold(0, |acc, m| acc + m.len()) +}