diff --git a/queries/records/get_and_update.sql b/queries/records/get_and_update.sql index 52ba101..e8803fc 100644 --- a/queries/records/get_and_update.sql +++ b/queries/records/get_and_update.sql @@ -1,8 +1,6 @@ -UPDATE record +UPDATE records SET downloads = downloads + 1 -WHERE cache_name = ? -RETURNING - cache_name, - uploaded, - downloads, - max_downloads; +WHERE + cache_name = ? + AND downloads < max_downloads + AND julianday('now') - julianday(uploaded) > 5; diff --git a/src/lib.rs b/src/lib.rs index 4874d87..3a8f04e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,3 +8,7 @@ pub mod views; pub use router::*; pub use state::*; pub use views::*; + +use std::{path::PathBuf, sync::LazyLock}; + +pub static CACHE_DIR: LazyLock = LazyLock::new(|| PathBuf::from("./.cache/serve")); diff --git a/src/router/download.rs b/src/router/download.rs index e5311d6..6d2649d 100644 --- a/src/router/download.rs +++ b/src/router/download.rs @@ -8,7 +8,7 @@ use axum::{ use reqwest::StatusCode; use tokio_util::io::ReaderStream; -use crate::{AppState, AsyncRemoveRecord}; +use crate::{AppState, CACHE_DIR}; pub fn get_download_router() -> Router { Router::new().route("/:id", get(download)) @@ -18,23 +18,25 @@ async fn download( axum::extract::Path(id): axum::extract::Path, State(state): State, ) -> Result { - { - let mut records = state.records.lock().await; - if let Some(record) = records - .get_mut(&id) - .filter(|record| record.can_be_downloaded()) - { - record.downloads += 1; + let mut conn = state.pool.acquire().await.unwrap(); - let file = tokio::fs::File::open(&record.file).await.unwrap(); + let rows_affected = sqlx::query_file!("queries/records/get_and_update.sql", id) + .execute(&mut *conn) + .await + .map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()))? + .rows_affected(); - return Ok(axum::response::Response::builder() - .header("Content-Type", "application/zip") - .body(Body::from_stream(ReaderStream::new(file))) - .unwrap()); - } else { - records.remove_record(&id).await.unwrap() - } + drop(conn); + + if rows_affected > 0 { + let file = tokio::fs::File::open(CACHE_DIR.join(id)) + .await + .map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()))?; + + return Ok(axum::response::Response::builder() + .header("Content-Type", "application/zip") + .body(Body::from_stream(ReaderStream::new(file))) + .unwrap()); } Ok(Redirect::to("/404.html").into_response())