From 5fa1bb6edd83c4d5bd475dfdd027c80d63a7a43e Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Mon, 26 May 2025 15:21:34 -0400 Subject: [PATCH 1/8] Changes to coverartQueue migrations --- migrations/20250420185217_init_migration.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migrations/20250420185217_init_migration.sql b/migrations/20250420185217_init_migration.sql index aafe6e0..e5a6d6a 100644 --- a/migrations/20250420185217_init_migration.sql +++ b/migrations/20250420185217_init_migration.sql @@ -20,7 +20,7 @@ CREATE TABLE IF NOT EXISTS "metadataQueue" ( -- Table to store queued coverart CREATE TABLE IF NOT EXISTS "coverartQueue" ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - data BYTEA NOT NULL, + data BYTEA NULL, song_queue_id UUID NULL ); -- 2.47.3 From 3290b2e3ccee23a42444bda548c67cca26a38958 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Mon, 26 May 2025 15:49:24 -0400 Subject: [PATCH 2/8] Added endpoint to wipe data from coverart queue --- src/callers/coverart.rs | 67 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/src/callers/coverart.rs b/src/callers/coverart.rs index 988d0ce..c0e73e2 100644 --- a/src/callers/coverart.rs +++ b/src/callers/coverart.rs @@ -38,6 +38,13 @@ pub mod request { pub coverart_queue_id: uuid::Uuid, } } + + pub mod wipe_data_from_coverart_queue { + #[derive(Debug, serde::Deserialize, serde::Serialize)] + pub struct Request { + pub coverart_queue_id: uuid::Uuid + } + } } pub mod response { @@ -84,6 +91,14 @@ pub mod response { pub data: Vec, } } + + pub mod wipe_data_from_coverart_queue { + #[derive(Debug, Default, serde::Deserialize, serde::Serialize)] + pub struct Response { + pub message: String, + pub data: Vec, + } + } } pub mod db { @@ -246,6 +261,29 @@ pub mod db { Err(_) => Err(sqlx::Error::RowNotFound), } } + + pub async fn wipe_data(pool: &sqlx::PgPool, coverart_queue_id: &uuid::Uuid) -> Result { + let result = sqlx::query( + r#" + UPDATE "coverartQueue" SET data = NULL WHERE id = $1 RETURNING id; + "# + ) + .bind(coverart_queue_id) + .fetch_one(pool) + .await + .map_err(|e| { + eprintln!("Error updating query: {:?}", e); + }); + + match result { + Ok(row) => { + Ok(row.try_get("id").map_err(|_e| sqlx::Error::RowNotFound).unwrap()) + } + Err(_) => { + Err(sqlx::Error::RowNotFound) + } + } + } } pub mod cov_db { @@ -508,4 +546,33 @@ pub mod endpoint { } } } + + pub async fn wipe_data_from_coverart_queue(axum::Extension(pool): axum::Extension, + axum::Json(payload): axum::Json,) -> ( + axum::http::StatusCode, + axum::Json, + ) { + let mut response = super::response::wipe_data_from_coverart_queue::Response::default(); + let coverart_queue_id = payload.coverart_queue_id; + + match super::db::get_coverart_queue_with_id(&pool, &coverart_queue_id).await { + Ok(coverart_queue) => { + match super::db::wipe_data(&pool, &coverart_queue.id).await { + Ok(id) => { + response.message = String::from("Success"); + response.data.push(id); + (axum::http::StatusCode::OK, axum::Json(response)) + } + Err(err) => { + response.message = err.to_string(); + (axum::http::StatusCode::BAD_REQUEST, axum::Json(response)) + } + } + } + Err(err) => { + response.message = err.to_string(); + (axum::http::StatusCode::NOT_FOUND, axum::Json(response)) + } + } + } } -- 2.47.3 From 78c371b0a43d50ac7331adce5760486b1ae1f865 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Mon, 26 May 2025 15:52:09 -0400 Subject: [PATCH 3/8] Added constant for endpoint --- src/callers/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/callers/mod.rs b/src/callers/mod.rs index d5e85a5..e15f55d 100644 --- a/src/callers/mod.rs +++ b/src/callers/mod.rs @@ -12,6 +12,7 @@ pub mod endpoints { pub const QUEUECOVERARTDATA: &str = "/api/v2/coverart/queue/data"; pub const QUEUECOVERARTLINK: &str = "/api/v2/coverart/queue/link"; pub const QUEUESONGDATAWIPE: &str = "/api/v2/song/queue/data/wipe"; + pub const QUEUECOVERARTDATAWIPE: &str = "/api/v2/coverart/queue/data/wipe"; pub const CREATESONG: &str = "/api/v2/song"; pub const CREATECOVERART: &str = "/api/v2/coverart"; -- 2.47.3 From 9d37fd108b286112c1dc2c8e627713bdf13f487e Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Mon, 26 May 2025 15:52:28 -0400 Subject: [PATCH 4/8] Endpoint is now available --- src/main.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main.rs b/src/main.rs index 785abb3..73f7892 100644 --- a/src/main.rs +++ b/src/main.rs @@ -101,6 +101,9 @@ pub mod init { crate::callers::endpoints::QUEUECOVERARTLINK, patch(crate::callers::coverart::endpoint::link), ) + .route(crate::callers::endpoints::QUEUECOVERARTDATAWIPE, + patch(crate::callers::coverart::endpoint::wipe_data_from_coverart_queue) + ) .route( crate::callers::endpoints::CREATESONG, post(crate::callers::song::endpoint::create_metadata), -- 2.47.3 From 3b5786f7387d3fdced4bde36b3610e6cc6d208f9 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Mon, 26 May 2025 15:53:47 -0400 Subject: [PATCH 5/8] Added test Need to complete --- src/main.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main.rs b/src/main.rs index 73f7892..3b947e6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1639,4 +1639,9 @@ mod tests { let _ = db_mgr::drop_database(&tm_pool, &db_name).await; } + + // TODO: Complete test + #[tokio::test] + async fn test_wipe_data_from_coverart_queue() { + } } -- 2.47.3 From 570ebb26612ba9c560b5def2fc279dea6a5f6cfa Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Mon, 26 May 2025 16:49:51 -0400 Subject: [PATCH 6/8] Test is working --- src/main.rs | 245 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 232 insertions(+), 13 deletions(-) diff --git a/src/main.rs b/src/main.rs index 3b947e6..38fa2e4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -371,6 +371,21 @@ mod tests { app.clone().oneshot(req).await } + + async fn create_coverart_req(app: &axum::Router, song_id: &uuid::Uuid, coverart_id: &uuid::Uuid) -> Result { + let payload = serde_json::json!({ + "song_id": song_id, + "coverart_queue_id": coverart_id + }); + let req = axum::http::Request::builder() + .method(axum::http::Method::POST) + .uri(crate::callers::endpoints::CREATECOVERART) + .header(axum::http::header::CONTENT_TYPE, "application/json") + .body(axum::body::Body::from(payload.to_string())) + .unwrap(); + app.clone().oneshot(req).await + } + async fn create_song_req( app: &axum::Router, song_queue_id: &uuid::Uuid, @@ -1457,19 +1472,7 @@ mod tests { "Should not be empty" ); - let payload = serde_json::json!({ - "song_id": song_id, - "coverart_queue_id": resp_coverart_id, - }); - - match app.clone().oneshot( - axum::http::Request::builder() - .method(axum::http::Method::POST) - .uri(crate::callers::endpoints::CREATECOVERART) - .header(axum::http::header::CONTENT_TYPE, "application/json") - .body(axum::body::Body::from(payload.to_string())) - .unwrap() - ).await { + match create_coverart_req(&app, &song_id, &resp_coverart_id).await { Ok(response) => { let resp = get_resp_data::< crate::callers::coverart::response::create_coverart::Response, @@ -1643,5 +1646,221 @@ mod tests { // TODO: Complete test #[tokio::test] async fn test_wipe_data_from_coverart_queue() { + let tm_pool = db_mgr::get_pool().await.unwrap(); + let db_name = db_mgr::generate_db_name().await; + + match db_mgr::create_database(&tm_pool, &db_name).await { + Ok(_) => { + println!("Success"); + } + Err(err) => { + assert!(false, "Error: {:?}", err); + } + } + + let pool = db_mgr::connect_to_db(&db_name).await.unwrap(); + db::migrations(&pool).await; + + let app = init::app(pool).await; + + // Send request + match song_queue_req(&app).await { + Ok(response) => { + let resp = + get_resp_data::(response).await; + assert_eq!(false, resp.data.is_empty(), "Should not be empty"); + assert_eq!(false, resp.data[0].is_nil(), "Should not be empty"); + let song_queue_id = resp.data[0]; + assert_eq!(false, song_queue_id.is_nil(), "Should not be empty"); + + match queue_metadata_req(&app, &resp.data[0]).await { + Ok(response) => { + let resp = + get_resp_data::(response) + .await; + assert_eq!(false, resp.data.is_empty(), "Should not be empty"); + + let id = resp.data[0]; + + match fetch_metadata_queue_req(&app, &id).await { + Ok(response) => { + let resp = get_resp_data::< + crate::callers::metadata::response::fetch_metadata::Response, + >(response) + .await; + assert_eq!(false, resp.data.is_empty(), "Data should not be empty"); + let song_q_id = resp.data[0].song_queue_id; + + match create_song_req(&app, &song_q_id).await { + Ok(response) => { + let resp = get_resp_data::(response).await; + assert_eq!( + false, + resp.data.is_empty(), + "No songs found, Response {:?}", + resp + ); + let song = &resp.data[0]; + let song_id = song.id; + assert_eq!( + false, + song_id.is_nil(), + "Song id should not be nil {:?}", + song + ); + + eprintln!("Song: {:?}", song); + + match upload_coverart_queue_req(&app).await { + Ok(response) => { + let resp = get_resp_data::< + crate::callers::coverart::response::Response, + >( + response + ) + .await; + assert_eq!( + false, + resp.data.is_empty(), + "Should not be empty" + ); + let coverart_id = resp.data[0]; + assert_eq!( + false, + coverart_id.is_nil(), + "Should not be empty" + ); + + match coverart_queue_song_queue_link_req( + &app, + &coverart_id, + &song_queue_id, + ) + .await + { + Ok(response) => { + let resp = get_resp_data::< + crate::callers::coverart::response::link::Response, + >(response) + .await; + assert_eq!( + false, + resp.data.is_empty(), + "Should not be empty" + ); + let resp_coverart_id = + resp.data[0].coverart_id; + let resp_song_queue_id = + resp.data[0].song_queue_id; + + assert_eq!( + false, + resp_coverart_id.is_nil(), + "Should not be empty" + ); + assert_eq!( + false, + resp_song_queue_id.is_nil(), + "Should not be empty" + ); + + match get_queued_coverart( + &app, + &resp_coverart_id, + ) + .await + { + Ok(response) => { + let resp = get_resp_data::< + crate::callers::coverart::response::fetch_coverart_no_data::Response, + >(response) + .await; + assert_eq!( + false, + resp.data.is_empty(), + "Should not be empty" + ); + + match create_coverart_req(&app, &song_id, &resp_coverart_id).await { + Ok(response) => { + let resp = get_resp_data::< + crate::callers::coverart::response::create_coverart::Response, + >(response) + .await; + assert_eq!( + false, + resp.data.is_empty(), + "Should not be empty" + ); + + let payload = serde_json::json!({ + "coverart_queue_id": resp_coverart_id + }); + + match app.clone().oneshot( + axum::http::Request::builder() + .method(axum::http::Method::PATCH) + .uri(crate::callers::endpoints::QUEUECOVERARTDATAWIPE) + .header(axum::http::header::CONTENT_TYPE, "application/json") + .body(axum::body::Body::from(payload.to_string())) + .unwrap() + ).await { + Ok(response) => { + let resp = get_resp_data::< + crate::callers::coverart::response::wipe_data_from_coverart_queue::Response, + >(response) + .await; + assert_eq!( + false, + resp.data.is_empty(), + "Should not be empty" + ); + } + Err(err) => { + assert!(false, "Error: {:?}", err); + } + } + } + Err(err) => { + assert!(false, "Error: {:?}", err); + } + } + } + Err(err) => { + assert!(false, "Error: {:?}", err); + } + } + } + Err(err) => { + assert!(false, "Error: {:?}", err); + } + } + } + Err(err) => { + assert!(false, "Error: {:?}", err); + } + } + } + Err(err) => { + assert!(false, "Error: {:?}", err); + } + } + } + Err(err) => { + assert!(false, "Error: {:?}", err); + } + } + } + Err(err) => { + assert!(false, "Error: {:?}", err); + } + } + } + Err(err) => { + assert!(false, "Error: {:?}", err); + } + }; + + let _ = db_mgr::drop_database(&tm_pool, &db_name).await; } } -- 2.47.3 From c7809a44cf1830ba06fb793ab6130cf078131b39 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Mon, 26 May 2025 16:50:42 -0400 Subject: [PATCH 7/8] Code formatting --- src/callers/coverart.rs | 72 +++++++++++++++++++++-------------------- src/main.rs | 42 ++++++++++++++++++------ 2 files changed, 70 insertions(+), 44 deletions(-) diff --git a/src/callers/coverart.rs b/src/callers/coverart.rs index c0e73e2..6336d4d 100644 --- a/src/callers/coverart.rs +++ b/src/callers/coverart.rs @@ -42,7 +42,7 @@ pub mod request { pub mod wipe_data_from_coverart_queue { #[derive(Debug, serde::Deserialize, serde::Serialize)] pub struct Request { - pub coverart_queue_id: uuid::Uuid + pub coverart_queue_id: uuid::Uuid, } } } @@ -262,26 +262,28 @@ pub mod db { } } - pub async fn wipe_data(pool: &sqlx::PgPool, coverart_queue_id: &uuid::Uuid) -> Result { + pub async fn wipe_data( + pool: &sqlx::PgPool, + coverart_queue_id: &uuid::Uuid, + ) -> Result { let result = sqlx::query( r#" UPDATE "coverartQueue" SET data = NULL WHERE id = $1 RETURNING id; - "# - ) - .bind(coverart_queue_id) - .fetch_one(pool) - .await - .map_err(|e| { - eprintln!("Error updating query: {:?}", e); - }); + "#, + ) + .bind(coverart_queue_id) + .fetch_one(pool) + .await + .map_err(|e| { + eprintln!("Error updating query: {:?}", e); + }); match result { - Ok(row) => { - Ok(row.try_get("id").map_err(|_e| sqlx::Error::RowNotFound).unwrap()) - } - Err(_) => { - Err(sqlx::Error::RowNotFound) - } + Ok(row) => Ok(row + .try_get("id") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap()), + Err(_) => Err(sqlx::Error::RowNotFound), } } } @@ -547,32 +549,32 @@ pub mod endpoint { } } - pub async fn wipe_data_from_coverart_queue(axum::Extension(pool): axum::Extension, - axum::Json(payload): axum::Json,) -> ( + pub async fn wipe_data_from_coverart_queue( + axum::Extension(pool): axum::Extension, + axum::Json(payload): axum::Json, + ) -> ( axum::http::StatusCode, axum::Json, - ) { - let mut response = super::response::wipe_data_from_coverart_queue::Response::default(); - let coverart_queue_id = payload.coverart_queue_id; + ) { + let mut response = super::response::wipe_data_from_coverart_queue::Response::default(); + let coverart_queue_id = payload.coverart_queue_id; - match super::db::get_coverart_queue_with_id(&pool, &coverart_queue_id).await { - Ok(coverart_queue) => { - match super::db::wipe_data(&pool, &coverart_queue.id).await { - Ok(id) => { - response.message = String::from("Success"); - response.data.push(id); - (axum::http::StatusCode::OK, axum::Json(response)) - } - Err(err) => { - response.message = err.to_string(); - (axum::http::StatusCode::BAD_REQUEST, axum::Json(response)) - } - } + match super::db::get_coverart_queue_with_id(&pool, &coverart_queue_id).await { + Ok(coverart_queue) => match super::db::wipe_data(&pool, &coverart_queue.id).await { + Ok(id) => { + response.message = String::from("Success"); + response.data.push(id); + (axum::http::StatusCode::OK, axum::Json(response)) } Err(err) => { response.message = err.to_string(); - (axum::http::StatusCode::NOT_FOUND, axum::Json(response)) + (axum::http::StatusCode::BAD_REQUEST, axum::Json(response)) } + }, + Err(err) => { + response.message = err.to_string(); + (axum::http::StatusCode::NOT_FOUND, axum::Json(response)) } + } } } diff --git a/src/main.rs b/src/main.rs index 38fa2e4..869096b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -101,9 +101,10 @@ pub mod init { crate::callers::endpoints::QUEUECOVERARTLINK, patch(crate::callers::coverart::endpoint::link), ) - .route(crate::callers::endpoints::QUEUECOVERARTDATAWIPE, - patch(crate::callers::coverart::endpoint::wipe_data_from_coverart_queue) - ) + .route( + crate::callers::endpoints::QUEUECOVERARTDATAWIPE, + patch(crate::callers::coverart::endpoint::wipe_data_from_coverart_queue), + ) .route( crate::callers::endpoints::CREATESONG, post(crate::callers::song::endpoint::create_metadata), @@ -371,8 +372,11 @@ mod tests { app.clone().oneshot(req).await } - - async fn create_coverart_req(app: &axum::Router, song_id: &uuid::Uuid, coverart_id: &uuid::Uuid) -> Result { + async fn create_coverart_req( + app: &axum::Router, + song_id: &uuid::Uuid, + coverart_id: &uuid::Uuid, + ) -> Result { let payload = serde_json::json!({ "song_id": song_id, "coverart_queue_id": coverart_id @@ -1472,7 +1476,13 @@ mod tests { "Should not be empty" ); - match create_coverart_req(&app, &song_id, &resp_coverart_id).await { + match create_coverart_req( + &app, + &song_id, + &resp_coverart_id, + ) + .await + { Ok(response) => { let resp = get_resp_data::< crate::callers::coverart::response::create_coverart::Response, @@ -1485,7 +1495,11 @@ mod tests { ); } Err(err) => { - assert!(false, "Error: {:?}", err); + assert!( + false, + "Error: {:?}", + err + ); } } } @@ -1781,7 +1795,13 @@ mod tests { "Should not be empty" ); - match create_coverart_req(&app, &song_id, &resp_coverart_id).await { + match create_coverart_req( + &app, + &song_id, + &resp_coverart_id, + ) + .await + { Ok(response) => { let resp = get_resp_data::< crate::callers::coverart::response::create_coverart::Response, @@ -1822,7 +1842,11 @@ mod tests { } } Err(err) => { - assert!(false, "Error: {:?}", err); + assert!( + false, + "Error: {:?}", + err + ); } } } -- 2.47.3 From a92b1dbed1c2d084ef85921f05f5f1f126212b61 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Mon, 26 May 2025 16:55:40 -0400 Subject: [PATCH 8/8] Removed TODO --- src/main.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 869096b..6c87a1d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1657,7 +1657,6 @@ mod tests { let _ = db_mgr::drop_database(&tm_pool, &db_name).await; } - // TODO: Complete test #[tokio::test] async fn test_wipe_data_from_coverart_queue() { let tm_pool = db_mgr::get_pool().await.unwrap(); -- 2.47.3