datatrash/src/deleter.rs

71 lines
2.3 KiB
Rust
Raw Normal View History

2022-02-26 23:34:57 +00:00
use futures_util::TryStreamExt;
use sqlx::{postgres::PgPool, Row};
2022-02-27 00:50:29 +00:00
use std::cmp::max;
2022-02-26 23:34:57 +00:00
use std::path::{Path, PathBuf};
2022-02-27 00:50:29 +00:00
use time::ext::NumericalStdDuration;
use time::OffsetDateTime;
2022-02-26 23:34:57 +00:00
use tokio::fs;
use tokio::sync::mpsc::Receiver;
use tokio::time::timeout;
2020-07-09 17:27:24 +00:00
2022-02-26 23:34:57 +00:00
pub(crate) async fn delete_old_files(mut receiver: Receiver<()>, db: PgPool, files_dir: PathBuf) {
2020-07-09 17:27:24 +00:00
loop {
2022-02-26 23:34:57 +00:00
wait_for_file_expiry(&mut receiver, &db).await;
2020-07-13 13:29:40 +00:00
2022-02-27 00:50:29 +00:00
let now = OffsetDateTime::now_utc();
let mut rows = sqlx::query("SELECT file_id FROM files WHERE files.valid_till < $1")
2020-07-13 13:29:40 +00:00
.bind(now)
.fetch(&db);
while let Some(row) = rows.try_next().await.expect("could not load expired files") {
let file_id: String = row.try_get("file_id").expect("we selected this column");
delete_content(&file_id, &files_dir)
.await
.expect("could not delete file");
2020-07-09 17:27:24 +00:00
}
2020-07-13 13:29:40 +00:00
sqlx::query("DELETE FROM files WHERE valid_till < $1")
2020-07-13 13:29:40 +00:00
.bind(now)
2020-07-09 17:27:24 +00:00
.execute(&db)
.await
.expect("could not delete expired files from database");
}
}
pub(crate) async fn delete_by_id(
db: &PgPool,
file_id: &str,
files_dir: &Path,
) -> Result<(), sqlx::Error> {
2021-09-11 00:08:47 +00:00
delete_content(file_id, files_dir).await?;
sqlx::query("DELETE FROM files WHERE file_id = $1")
.bind(file_id)
.execute(db)
.await?;
Ok(())
}
async fn delete_content(file_id: &str, files_dir: &Path) -> Result<(), std::io::Error> {
let path = files_dir.join(file_id);
2022-02-26 23:34:57 +00:00
if fs::remove_file(&path).await.is_ok() {
log::info!("delete file {}", file_id);
}
Ok(())
}
2022-02-26 23:34:57 +00:00
async fn wait_for_file_expiry(receiver: &mut Receiver<()>, db: &PgPool) {
2022-02-27 00:50:29 +00:00
let valid_till: (Option<OffsetDateTime>,) =
sqlx::query_as("SELECT MIN(valid_till) as min from files")
2021-09-24 20:51:13 +00:00
.fetch_one(db)
.await
.expect("could not fetch expiring files from database");
2022-02-27 00:50:29 +00:00
let next_timeout: std::time::Duration = match valid_till.0 {
Some(valid_till) => (max(
0,
valid_till.unix_timestamp() - OffsetDateTime::now_utc().unix_timestamp(),
) as u64)
.std_seconds(),
None => 1_u64.std_days(),
2020-07-09 17:27:24 +00:00
};
2022-02-27 00:50:29 +00:00
let _ = timeout(next_timeout, receiver.recv()).await;
2020-07-09 17:27:24 +00:00
}