feat: 视频缓存自动清理

- 应用启动时后台清理 video_cache 目录
- 删除超过 30 天未修改的缓存文件
- 总容量超 500MB 时,按修改时间删最旧文件直到 300MB
- 不阻塞首屏加载
This commit is contained in:
小鱼开发
2026-05-21 16:00:55 +08:00
parent 59bfadcb99
commit ec3b2b87ed
+68 -1
View File
@@ -46,6 +46,71 @@ pub struct ApiResponse<T> {
pub data: Option<T>,
}
// ============================================================
// 视频缓存清理
// ============================================================
/// 清理 video_cache 目录
///
/// 策略:
/// 1. 删除超过 30 天未修改的文件
/// 2. 总容量超过 500MB 时,按修改时间删最旧文件直到 300MB
fn clean_video_cache(app_data_dir: &std::path::Path) {
let cache_dir = app_data_dir.join("video_cache");
if !cache_dir.exists() {
return;
}
let max_age = std::time::Duration::from_secs(30 * 24 * 60 * 60);
let max_total_size: u64 = 500 * 1024 * 1024;
let target_size: u64 = 300 * 1024 * 1024;
let now = std::time::SystemTime::now();
let mut entries: Vec<(std::path::PathBuf, std::time::SystemTime, u64)> = Vec::new();
let mut total_size: u64 = 0;
let read_dir = match std::fs::read_dir(&cache_dir) {
Ok(d) => d,
Err(e) => {
eprintln!("[cache] 无法读取缓存目录: {}", e);
return;
}
};
for entry in read_dir.flatten() {
let Ok(metadata) = entry.metadata() else { continue };
if !metadata.is_file() { continue; }
let mtime = metadata.modified().unwrap_or(now);
let size = metadata.len();
total_size += size;
entries.push((entry.path(), mtime, size));
}
// 1. 删除超过 30 天的文件
let mut deleted_size: u64 = 0;
for (path, mtime, size) in &entries {
if now.duration_since(*mtime).unwrap_or_default() > max_age {
if std::fs::remove_file(path).is_ok() {
deleted_size += size;
}
}
}
// 2. 容量超限,删最旧的
let remaining_size = total_size.saturating_sub(deleted_size);
if remaining_size > max_total_size {
let mut sorted = entries;
sorted.sort_by_key(|(_, mtime, _)| *mtime);
let mut to_free = remaining_size.saturating_sub(target_size);
for (path, _, size) in sorted {
if to_free == 0 { break; }
if path.exists() && std::fs::remove_file(&path).is_ok() {
to_free = to_free.saturating_sub(size);
}
}
}
}
// ============================================================
// 应用入口
// ============================================================
@@ -69,7 +134,9 @@ pub fn run() {
.setup(|app| {
// 初始化应用数据目录(所有业务数据的根目录)
if let Ok(app_data_dir) = app.path().app_local_data_dir() {
crate::storage::init_app_data_dir(app_data_dir);
crate::storage::init_app_data_dir(app_data_dir.clone());
// 后台清理过期视频缓存,不阻塞首屏
std::thread::spawn(move || clean_video_cache(&app_data_dir));
}
// 窗口初始 visible=falsesetup 阶段先显示窗口