diff --git a/src/callers/mod.rs b/src/callers/mod.rs index 5abbb9f..e6ff83a 100644 --- a/src/callers/mod.rs +++ b/src/callers/mod.rs @@ -3,5 +3,6 @@ pub mod song; pub mod endpoints { pub const QUEUESONG: &str = "/api/v2/song/queue"; + pub const NEXTQUEUESONG: &str = "/api/v2/song/queue/next"; pub const QUEUEMETADATA: &str = "/api/v2/song/metadata/queue"; } diff --git a/src/callers/song.rs b/src/callers/song.rs index 0f89887..f436340 100644 --- a/src/callers/song.rs +++ b/src/callers/song.rs @@ -15,6 +15,16 @@ pub mod response { pub message: String, pub data: Vec, } + + pub mod fetch_queue_song { + use serde::{Deserialize, Serialize}; + + #[derive(Default, Deserialize, Serialize)] + pub struct Response { + pub message: String, + pub data: Vec, + } + } } mod song_queue { @@ -23,7 +33,7 @@ mod song_queue { pub mod status { pub const PENDING: &str = "pending"; // Will be used later on - pub const _PROCESSING: &str = "processing"; + pub const PROCESSING: &str = "processing"; pub const _DONE: &str = "done"; } @@ -32,6 +42,14 @@ mod song_queue { pub id: uuid::Uuid, } + #[derive(Debug, serde::Deserialize, serde::Serialize, sqlx::FromRow)] + pub struct SongQueue { + pub id: uuid::Uuid, + pub filename: String, + pub status: String, + pub data: Vec, + } + pub async fn insert( pool: &sqlx::PgPool, data: &Vec, @@ -63,6 +81,46 @@ mod song_queue { Err(_err) => Err(sqlx::Error::RowNotFound), } } + + pub async fn get_most_recent_and_update( + pool: &sqlx::PgPool, + ) -> Result { + let result = sqlx::query( + r#" + UPDATE "songQueue" + SET status = $1 + WHERE id = ( + SELECT id FROM "songQueue" + WHERE status = $2 + ORDER BY id + FOR UPDATE SKIP LOCKED + LIMIT 1 + ) + RETURNING *; + "#, + ) + .bind(status::PROCESSING) + .bind(status::PENDING) + .fetch_one(pool) + .await + .map_err(|e| { + eprintln!("Error inserting: {}", e); + }); + + match result { + Ok(row) => { + Ok(SongQueue{ + id: row.try_get("id").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + filename: row.try_get("filename").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + status: row.try_get("status").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + data: row.try_get("data").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + }) + } + Err(err) => { + Err(sqlx::Error::RowNotFound) + } + } + } } pub mod endpoint { @@ -117,4 +175,19 @@ pub mod endpoint { (StatusCode::OK, Json(response)) } + + pub async fn fetch_queue_song(axum::Extension(pool): axum::Extension, + ) -> (StatusCode, Json) { + let mut response = super::response::fetch_queue_song::Response::default(); + + match song_queue::get_most_recent_and_update(&pool).await { + Ok(_q) => { + (StatusCode::OK, Json(response)) + } + Err(err) => { + response.message = err.to_string(); + (StatusCode::BAD_REQUEST, Json(response)) + } + } + } } diff --git a/src/main.rs b/src/main.rs index aafcc52..c064ad9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -69,6 +69,9 @@ pub mod init { crate::callers::endpoints::QUEUESONG, post(crate::callers::song::endpoint::queue_song), ) + .route(crate::callers::endpoints::NEXTQUEUESONG, + get(crate::callers::song::endpoint::fetch_queue_song), + ) .route( crate::callers::endpoints::QUEUEMETADATA, post(crate::callers::metadata::endpoint::queue_metadata),