feat(tasks): 新增回收站自动清理后台任务
This commit is contained in:
parent
f5e19def1a
commit
0ba8f9f835
@ -64,6 +64,11 @@ fn main() {
|
|||||||
tasks::session_cleanup::run_cleanup().await;
|
tasks::session_cleanup::run_cleanup().await;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 启动后台定时任务:回收站自动清理
|
||||||
|
tokio::spawn(async {
|
||||||
|
tasks::post_purge::run_purge().await;
|
||||||
|
});
|
||||||
|
|
||||||
// 配置增量渲染缓存,默认缓存 3600 秒,可通过 SSR_CACHE_SECS 覆盖
|
// 配置增量渲染缓存,默认缓存 3600 秒,可通过 SSR_CACHE_SECS 覆盖
|
||||||
let config = ServeConfig::builder().incremental(
|
let config = ServeConfig::builder().incremental(
|
||||||
dioxus::server::IncrementalRendererConfig::default().invalidate_after(
|
dioxus::server::IncrementalRendererConfig::default().invalidate_after(
|
||||||
|
|||||||
@ -8,3 +8,6 @@ pub mod ip_purge;
|
|||||||
/// 定时删除已过期会话,避免 `sessions` 表无限增长。
|
/// 定时删除已过期会话,避免 `sessions` 表无限增长。
|
||||||
#[cfg(feature = "server")]
|
#[cfg(feature = "server")]
|
||||||
pub mod session_cleanup;
|
pub mod session_cleanup;
|
||||||
|
/// 定时清理回收站中超过保留期的已删除文章。
|
||||||
|
#[cfg(feature = "server")]
|
||||||
|
pub mod post_purge;
|
||||||
|
|||||||
74
src/tasks/post_purge.rs
Normal file
74
src/tasks/post_purge.rs
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
//! 回收站自动清理后台任务。
|
||||||
|
//!
|
||||||
|
//! 仅在 `server` feature 启用时编译,每天运行一次。
|
||||||
|
//! 每次执行前读取 settings 表:若自动清理关闭则跳过,否则按保留天数物理删除过期文章。
|
||||||
|
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use tokio::time::interval;
|
||||||
|
|
||||||
|
use crate::db::pool::get_conn;
|
||||||
|
use crate::models::settings::TrashSettings;
|
||||||
|
|
||||||
|
/// 启动回收站自动清理循环,每天触发一次。
|
||||||
|
///
|
||||||
|
/// 每次读取最新配置:若 `trash_auto_purge_enabled` 关闭则 no-op,
|
||||||
|
/// 否则删除 `deleted_at < NOW() - retention_days` 的文章。
|
||||||
|
/// 任何错误只记录日志,不中断循环。
|
||||||
|
pub async fn run_purge() {
|
||||||
|
let mut ticker = interval(Duration::from_secs(86400));
|
||||||
|
loop {
|
||||||
|
ticker.tick().await;
|
||||||
|
match get_conn().await {
|
||||||
|
Ok(client) => {
|
||||||
|
match purge_expired(&client).await {
|
||||||
|
Ok(n) => {
|
||||||
|
if n > 0 {
|
||||||
|
tracing::info!("Post auto-purge: removed {} expired trashed posts", n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => tracing::error!("Post auto-purge error: {:?}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => tracing::error!("Failed to get DB connection for post purge: {:?}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 读取配置并删除过期回收站文章,返回删除行数。
|
||||||
|
///
|
||||||
|
/// 抽取为独立函数便于单元测试(虽需 DB,但逻辑集中)。
|
||||||
|
async fn purge_expired(client: &tokio_postgres::Client) -> Result<u64, tokio_postgres::Error> {
|
||||||
|
// 读取配置,缺键时回退默认值。
|
||||||
|
let enabled: bool = client
|
||||||
|
.query_opt(
|
||||||
|
"SELECT value FROM settings WHERE key = 'trash_auto_purge_enabled'",
|
||||||
|
&[],
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
.and_then(|r| r.get::<_, String>("value").parse().ok())
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
|
if !enabled {
|
||||||
|
return Ok(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
let days: i32 = client
|
||||||
|
.query_opt(
|
||||||
|
"SELECT value FROM settings WHERE key = 'trash_retention_days'",
|
||||||
|
&[],
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
.and_then(|r| r.get::<_, String>("value").parse().ok())
|
||||||
|
.unwrap_or(30);
|
||||||
|
|
||||||
|
let days = TrashSettings::clamp_retention(days);
|
||||||
|
|
||||||
|
let n = client
|
||||||
|
.execute(
|
||||||
|
"DELETE FROM posts WHERE deleted_at IS NOT NULL AND deleted_at < NOW() - make_interval(days => $1)",
|
||||||
|
&[&days],
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
Ok(n)
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user