feat: reimplement sweeper
This commit is contained in:
parent
17d194e75b
commit
396f9afcc9
6 changed files with 79 additions and 19 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1335,7 +1335,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nyazoom"
|
name = "nyazoom"
|
||||||
version = "0.2.2"
|
version = "0.2.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-bincode",
|
"async-bincode",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "nyazoom"
|
name = "nyazoom"
|
||||||
version = "0.2.2"
|
version = "0.2.4"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["Zynh Ludwig <Zynh0722@gmail.com>"]
|
authors = ["Zynh Ludwig <Zynh0722@gmail.com>"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
SELECT
|
SELECT
|
||||||
|
id,
|
||||||
cache_name,
|
cache_name,
|
||||||
downloads,
|
downloads >= max_downloads AS "out_of_downloads: bool",
|
||||||
max_downloads,
|
julianday('now') - julianday(uploaded) > 5 AS "too_old: bool"
|
||||||
julianday('now') - julianday(uploaded) AS age
|
|
||||||
FROM records
|
FROM records
|
||||||
WHERE downloads >= max_downloads OR age > 5;
|
WHERE downloads >= max_downloads OR julianday('now') - julianday(uploaded) > 5;
|
||||||
|
|
2
queries/records/remove_record_by_id.sql
Normal file
2
queries/records/remove_record_by_id.sql
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
DELETE FROM records
|
||||||
|
WHERE id = ?;
|
|
@ -10,6 +10,14 @@ pub struct CacheRecord {
|
||||||
pub max_downloads: i32,
|
pub max_downloads: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ExpiredRecord {
|
||||||
|
pub id: i64,
|
||||||
|
pub cache_name: String,
|
||||||
|
pub out_of_downloads: bool,
|
||||||
|
pub too_old: bool,
|
||||||
|
}
|
||||||
|
|
||||||
impl CacheRecord {
|
impl CacheRecord {
|
||||||
pub fn can_be_downloaded(&self) -> bool {
|
pub fn can_be_downloaded(&self) -> bool {
|
||||||
let dur_since_upload = Utc::now().signed_duration_since(self.uploaded);
|
let dur_since_upload = Utc::now().signed_duration_since(self.uploaded);
|
||||||
|
|
|
@ -1,28 +1,78 @@
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use sqlx::{sqlite::SqliteQueryResult, SqliteConnection};
|
||||||
use tracing::{info_span, Instrument};
|
use tracing::{info_span, Instrument};
|
||||||
|
|
||||||
use crate::state::AppState;
|
use crate::{db::ExpiredRecord, state::AppState, CACHE_DIR};
|
||||||
|
|
||||||
/// Spawn a repeating task that will clean files periodically
|
/// Spawn a repeating task that will clean files periodically
|
||||||
pub fn spawn(_state: AppState) {
|
pub fn spawn(state: AppState) {
|
||||||
tokio::spawn(
|
tokio::spawn(
|
||||||
async move {
|
async move {
|
||||||
|
tokio::time::sleep(Duration::from_secs(5)).await;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
tracing::debug!("Cleaning Sweep!");
|
||||||
|
|
||||||
|
let mut conn = state.pool.acquire().await.unwrap();
|
||||||
|
let expired_records_result =
|
||||||
|
sqlx::query_file_as!(ExpiredRecord, "queries/records/get_expired_records.sql")
|
||||||
|
.fetch_all(&mut *conn)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let expired_records = match expired_records_result {
|
||||||
|
Ok(r) => r,
|
||||||
|
Err(e) => {
|
||||||
|
tracing::error!(error = ?e);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let record_ids: Vec<i64> = expired_records.iter().map(|record| record.id).collect();
|
||||||
|
tracing::debug!(?record_ids, "Expired Records");
|
||||||
|
|
||||||
|
let mut too_old = 0;
|
||||||
|
let mut out_of_downloads = 0;
|
||||||
|
for record in expired_records.iter() {
|
||||||
|
let cache_path = CACHE_DIR.join(&record.cache_name);
|
||||||
|
|
||||||
|
if let Err(error) = std::fs::remove_file(&cache_path) {
|
||||||
|
if error.kind() == std::io::ErrorKind::NotFound {
|
||||||
|
tracing::warn!(path = ?cache_path, "Cache file not found")
|
||||||
|
} else {
|
||||||
|
tracing::error!(?error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tracing::debug!(id = record.id, "Removing record");
|
||||||
|
|
||||||
|
let remove_result = remove_record_by_id(&mut conn, record.id).await;
|
||||||
|
|
||||||
|
match remove_result {
|
||||||
|
Err(e) => {
|
||||||
|
tracing::error!(error = ?e, "Unable to remove expired record")
|
||||||
|
}
|
||||||
|
Ok(_) => {
|
||||||
|
too_old += record.too_old as u32;
|
||||||
|
out_of_downloads += record.out_of_downloads as u32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tracing::info!(too_old, out_of_downloads, "Cache items cleared");
|
||||||
|
|
||||||
tokio::time::sleep(Duration::from_secs(15 * 60)).await;
|
tokio::time::sleep(Duration::from_secs(15 * 60)).await;
|
||||||
|
|
||||||
tracing::info!("Cleaning Sweep!");
|
|
||||||
|
|
||||||
// let mut records = state.records.lock().await;
|
|
||||||
//
|
|
||||||
// for (key, record) in records.clone().into_iter() {
|
|
||||||
// if !record.can_be_downloaded() {
|
|
||||||
// tracing::info!("culling: {:?}", record);
|
|
||||||
// records.remove_record(&key).await.unwrap();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.instrument(info_span!("sweeper")),
|
.instrument(info_span!("sweeper")),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn remove_record_by_id(
|
||||||
|
conn: &mut SqliteConnection,
|
||||||
|
id: i64,
|
||||||
|
) -> sqlx::Result<SqliteQueryResult> {
|
||||||
|
sqlx::query_file!("queries/records/remove_record_by_id.sql", id)
|
||||||
|
.execute(conn)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue