From 585a4a6eb729c2002f0cd06b0f298cd05779c1c5 Mon Sep 17 00:00:00 2001 From: ryan Date: Fri, 21 Feb 2025 15:11:11 +0300 Subject: [PATCH] fix(debug): add logging to solve db saving issues --- src/api.rs | 35 +++++++++++++++++++++++++++++------ src/components/items_list.rs | 14 +++++++++++--- src/db.rs | 34 +++++++++++++++++++++++++++++++++- 3 files changed, 73 insertions(+), 10 deletions(-) diff --git a/src/api.rs b/src/api.rs index 0c895a9..08cd26b 100644 --- a/src/api.rs +++ b/src/api.rs @@ -8,11 +8,15 @@ use std::sync::Arc; use tokio::sync::Mutex; #[cfg(feature = "ssr")] use crate::models::item::Item; +#[cfg(feature = "ssr")] +use std::collections::HashMap; +#[cfg(feature = "ssr")] +use leptos::logging::log; #[cfg(feature = "ssr")] -use serde::Deserialize; +use serde::{Deserialize, Serialize}; #[cfg(feature = "ssr")] -#[derive(Deserialize)] +#[derive(Serialize, Deserialize)] pub struct ItemRequest { pub url: String, pub item: Item, @@ -38,9 +42,27 @@ pub async fn create_item( db: web::Data>>, request: web::Json, ) -> HttpResponse { - match db.lock().await.insert_item_by_url(&request.url, &request.item).await { - Ok(_) => HttpResponse::Ok().body("Item created"), - Err(e) => HttpResponse::InternalServerError().body(e.to_string()), + let db = db.lock().await; + let url = request.url.clone(); + let item = request.item.clone(); + let item_id = request.item.id.clone(); + // request logging + log!("[API] Received item request - URL: {}, Item ID: {}", + request.url, request.item.id); + + // raw JSON logging + let raw_json = serde_json::to_string(&request.into_inner()).unwrap(); + log!("[API] Raw request JSON: {}", raw_json); + + match db.insert_item_by_url(&url, &item).await { + Ok(_) => { + log!("[API] Successfully saved item ID: {}", item_id); + HttpResponse::Ok().json(item) + }, + Err(e) => { + log!("[API] Database error: {:?}", e); + HttpResponse::BadRequest().body(format!("Database error: {}", e)) + } } } @@ -79,8 +101,9 @@ pub async fn delete_property( #[cfg(feature = "ssr")] pub async fn get_items_by_url( db: web::Data>>, - url: web::Path, + query: web::Query>, ) -> HttpResponse { + let url = query.get("url").unwrap_or(&String::new()).to_string(); let db = db.lock().await; match db.get_items_by_url(&url).await { Ok(items) => HttpResponse::Ok().json(items), diff --git a/src/components/items_list.rs b/src/components/items_list.rs index 5a1382a..f0413cc 100644 --- a/src/components/items_list.rs +++ b/src/components/items_list.rs @@ -33,7 +33,8 @@ pub async fn load_items_from_db(current_url: &str) -> Result, String> Ok(items) } else { - Err(format!("Failed to fetch items: {}", response.status_text())) + let body = response.text().await.unwrap_or_default(); + Err(format!("Server error ({}): {}", response.status(), body)) } } @@ -152,10 +153,12 @@ pub fn ItemsList( // Function to send an item to the backend API async fn save_item_to_db(item: Item, selected_properties: ReadSignal>, current_url: String) { + + let custom_props = item.custom_properties.clone(); // Use a reactive closure to access `selected_properties` let custom_properties: HashMap = (move || { let selected_props = selected_properties.get(); // Access the signal inside a reactive closure - item.custom_properties + custom_props .into_iter() .filter(|(key, _)| selected_props.contains_key(key)) // Use the extracted value .collect() @@ -167,6 +170,9 @@ pub fn ItemsList( url: String, item: Item, } + + log!("[FRONTEND] Saving item - ID: {}, Name: '{}', Properties: {:?}", + item.id, item.name, item.custom_properties); let item_to_send = ItemRequest { url: current_url.to_string(), @@ -178,12 +184,14 @@ pub fn ItemsList( custom_properties, // Use the filtered HashMap }, }; - + let response = gloo_net::http::Request::post("/api/items") .json(&item_to_send) .unwrap() .send() .await; + + log!("[FRONTEND] Save response status: {:?}", response.as_ref().map(|r| r.status())); match response { Ok(resp) => { diff --git a/src/db.rs b/src/db.rs index c8533fa..a090a4e 100644 --- a/src/db.rs +++ b/src/db.rs @@ -7,6 +7,7 @@ mod db_impl { use leptos::logging; use std::collections::HashMap; use crate::models::item::Item; + use leptos::logging::log; // Define a struct to represent a database connection #[derive(Debug)] @@ -207,13 +208,20 @@ mod db_impl { url: &str, item: &Item ) -> Result<(), Error> { + // Log before DB operations + log!("[DATABASE] Inserting item - ID: {}, Name: '{}'", item.id, item.name); let conn = self.conn.lock().await; + // Get or create URL record let url_id = match self.get_url_id(url).await { Ok(Some(id)) => id, _ => self.insert_url(url).await?, }; - + + // Log final SQL parameters + log!("[DATABASE] SQL params - ID: {}, URL ID: {}, Name: '{}'", + item.id, url_id, item.name); + // Insert item with URL relationship conn.execute( "INSERT INTO items (id, url_id, name, description, wikidata_id) @@ -231,6 +239,7 @@ mod db_impl { &[&item.id, &prop_id.to_string(), &value], )?; } + log!("[DATABASE] Successfully inserted item ID: {}", item.id); Ok(()) } @@ -262,6 +271,29 @@ mod db_impl { logging::log!("Property deleted from the database for URL: {}", url); Ok(()) } + // function to log database state + pub async fn debug_dump(&self) -> Result<(), Error> { + let conn = self.conn.lock().await; + log!("[DATABASE DEBUG] URLs:"); + let mut stmt = conn.prepare("SELECT id, url FROM urls")?; + let urls = stmt.query_map([], |row| { + Ok(format!("ID: {}, URL: {}", row.get::<_, i64>(0)?, row.get::<_, String>(1)?)) + })?; + for url in urls { + log!("[DATABASE DEBUG] {}", url?); + } + + log!("[DATABASE DEBUG] Items:"); + let mut stmt = conn.prepare("SELECT id, name FROM items")?; + let items = stmt.query_map([], |row| { + Ok(format!("ID: {}, Name: '{}'", row.get::<_, String>(0)?, row.get::<_, String>(1)?)) + })?; + for item in items { + log!("[DATABASE DEBUG] {}", item?); + } + + Ok(()) + } } // Define a struct to represent an item in the database