feat: add /disk-cache endpoint to manually clear disk cache

This commit is contained in:
rustmailer
2025-10-30 06:37:40 +08:00
parent 64b57f4ac2
commit a51b95815c
2 changed files with 72 additions and 3 deletions
+56 -3
View File
@@ -5,8 +5,8 @@
use crate::{
modules::{
database::{
async_find_impl, delete_impl, list_all_impl, manager::DB_MANAGER, update_impl,
upsert_impl,
async_find_impl, batch_delete_impl, delete_impl, list_all_impl, manager::DB_MANAGER,
update_impl, upsert_impl,
},
error::{code::ErrorCode, RustMailerResult},
settings::dir::DATA_DIR_MANAGER,
@@ -20,6 +20,7 @@ use serde::{Deserialize, Serialize};
use std::{
path::{Path, PathBuf},
sync::LazyLock,
time::Instant,
};
use sysinfo::Disks;
use tokio::io::AsyncWriteExt;
@@ -60,6 +61,39 @@ impl CacheItem {
upsert_impl(DB_MANAGER.meta_db(), self).await
}
pub async fn clear() -> RustMailerResult<()> {
const BATCH_SIZE: usize = 200;
let mut total_deleted = 0usize;
let start_time = Instant::now();
loop {
let deleted = batch_delete_impl(DB_MANAGER.meta_db(), move |rw| {
let to_delete: Vec<CacheItem> = rw
.scan()
.primary()
.map_err(|e| raise_error!(format!("{:#?}", e), ErrorCode::InternalError))?
.all()
.map_err(|e| raise_error!(format!("{:#?}", e), ErrorCode::InternalError))?
.filter_map(Result::ok) // filter only Ok values
.take(BATCH_SIZE)
.collect();
Ok(to_delete)
})
.await?;
total_deleted += deleted;
// If this batch is empty, break the loop
if deleted == 0 {
break;
}
}
info!(
"Finished deleting cacheitems total_deleted={} in {:?}",
total_deleted,
start_time.elapsed()
);
Ok(())
}
pub async fn check_exist(key: &str) -> RustMailerResult<bool> {
let item = async_find_impl::<CacheItem>(DB_MANAGER.meta_db(), key.to_string()).await?;
Ok(item.is_some())
@@ -159,6 +193,23 @@ impl DiskCache {
Ok(Some(reader))
}
pub async fn clear(&self) -> RustMailerResult<()> {
CacheItem::clear().await?;
let cache_dir_str = match self.cache_dir.to_str() {
Some(dir) => dir,
None => {
error!("Failed to convert cache_dir to string");
return Err(raise_error!(
"Failed to convert cache_dir to string".into(),
ErrorCode::InternalError
));
}
};
cacache::clear(cache_dir_str)
.await
.map_err(|e| raise_error!(format!("{:#?}", e), ErrorCode::InternalError))
}
pub async fn clean_cache_if_needed(&self) {
let cache_items = match CacheItem::list().await {
Ok(items) => {
@@ -211,7 +262,9 @@ impl DiskCache {
// Helper function to handle item removal
async fn remove_cache_item(cache_dir: &str, item: &CacheItem) -> Result<(), String> {
cacache::remove(cache_dir, &item.key)
cacache::RemoveOpts::new()
.remove_fully(true)
.remove(cache_dir, &item.key)
.await
.map_err(|e| format!("Failed to remove cache item from disk: {:?}", e))?;
item.delete()