yggdrasil/tasks/
post_purge.rs1use std::time::Duration;
7
8use tokio::time::interval;
9
10use crate::db::pool::get_conn;
11use crate::models::settings::TrashSettings;
12
13pub async fn run_purge() {
19 let mut ticker = interval(Duration::from_secs(86400));
20 loop {
21 match get_conn().await {
22 Ok(client) => match purge_expired(&client).await {
23 Ok(n) => {
24 if n > 0 {
25 tracing::info!("Post auto-purge: removed {} expired trashed posts", n);
26 }
27 }
28 Err(e) => tracing::error!("Post auto-purge error: {:?}", e),
29 },
30 Err(e) => tracing::error!("Failed to get DB connection for post purge: {:?}", e),
31 }
32 ticker.tick().await;
33 }
34}
35
36async fn purge_expired(client: &tokio_postgres::Client) -> Result<u64, tokio_postgres::Error> {
40 let enabled: bool = client
42 .query_opt(
43 "SELECT value FROM settings WHERE key = 'trash_auto_purge_enabled'",
44 &[],
45 )
46 .await?
47 .and_then(|r| r.get::<_, String>("value").parse().ok())
48 .unwrap_or(false);
49
50 if !enabled {
51 return Ok(0);
52 }
53
54 let days: i32 = client
55 .query_opt(
56 "SELECT value FROM settings WHERE key = 'trash_retention_days'",
57 &[],
58 )
59 .await?
60 .and_then(|r| r.get::<_, String>("value").parse().ok())
61 .unwrap_or(30);
62
63 let days = TrashSettings::clamp_retention(days);
64
65 let n = client
66 .execute(
67 "DELETE FROM posts WHERE deleted_at IS NOT NULL AND deleted_at < NOW() - make_interval(days => $1)",
68 &[&days],
69 )
70 .await?;
71 Ok(n)
72}