feat: add explicit error logging and startup validation
- Add DATABASE_URL validation on server startup (exit early with clear error) - Add tracing::error! to all server functions in api/auth.rs - Bulk add tracing::error! to all database error handlers in api/posts.rs - Server 500 errors now log detailed context to terminal
This commit is contained in:
parent
b6cabe489f
commit
5695b1c62b
@ -91,12 +91,18 @@ pub async fn register(
|
|||||||
let client = DB_POOL
|
let client = DB_POOL
|
||||||
.get()
|
.get()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("数据库连接失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("Register DB connection failed: {}", e);
|
||||||
|
ServerFnError::new(format!("数据库连接失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
let admin_count: i64 = client
|
let admin_count: i64 = client
|
||||||
.query_one("SELECT COUNT(*) FROM users WHERE role = 'admin'", &[])
|
.query_one("SELECT COUNT(*) FROM users WHERE role = 'admin'", &[])
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("查询失败: {}", e)))?
|
.map_err(|e| {
|
||||||
|
tracing::error!("Register admin count query failed: {}", e);
|
||||||
|
ServerFnError::new(format!("查询失败: {}", e))
|
||||||
|
})?
|
||||||
.get(0);
|
.get(0);
|
||||||
|
|
||||||
if admin_count > 0 {
|
if admin_count > 0 {
|
||||||
@ -108,7 +114,10 @@ pub async fn register(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let password_hash = password::hash_password(&password)
|
let password_hash = password::hash_password(&password)
|
||||||
.map_err(|e| ServerFnError::new(format!("密码哈希失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("Register password hash failed: {}", e);
|
||||||
|
ServerFnError::new(format!("密码哈希失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
let result = client
|
let result = client
|
||||||
.query_one(
|
.query_one(
|
||||||
@ -146,7 +155,10 @@ pub async fn login(
|
|||||||
let client = DB_POOL
|
let client = DB_POOL
|
||||||
.get()
|
.get()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("数据库连接失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("Login DB connection failed: {}", e);
|
||||||
|
ServerFnError::new(format!("数据库连接失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
let row = match client
|
let row = match client
|
||||||
.query_opt(
|
.query_opt(
|
||||||
@ -163,12 +175,18 @@ pub async fn login(
|
|||||||
token: None,
|
token: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Err(e) => return Err(ServerFnError::new(format!("查询失败: {}", e))),
|
Err(e) => {
|
||||||
|
tracing::error!("Login user query failed: {}", e);
|
||||||
|
return Err(ServerFnError::new(format!("查询失败: {}", e)));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let password_hash: String = row.get("password_hash");
|
let password_hash: String = row.get("password_hash");
|
||||||
let valid = password::verify_password(&password, &password_hash)
|
let valid = password::verify_password(&password, &password_hash)
|
||||||
.map_err(|e| ServerFnError::new(format!("密码验证失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("Login password verify failed: {}", e);
|
||||||
|
ServerFnError::new(format!("密码验证失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
if !valid {
|
if !valid {
|
||||||
return Ok(AuthResponse {
|
return Ok(AuthResponse {
|
||||||
@ -188,7 +206,10 @@ pub async fn login(
|
|||||||
&[&user_id, &token, &expires_at],
|
&[&user_id, &token, &expires_at],
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("创建 session 失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("Login session insert failed: {}", e);
|
||||||
|
ServerFnError::new(format!("创建 session 失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
let cookie = format!(
|
let cookie = format!(
|
||||||
"session={token}; HttpOnly; Path=/; Max-Age={}; SameSite=Lax",
|
"session={token}; HttpOnly; Path=/; Max-Age={}; SameSite=Lax",
|
||||||
@ -224,7 +245,10 @@ pub async fn logout() -> Result<AuthResponse, ServerFnError> {
|
|||||||
let client = DB_POOL
|
let client = DB_POOL
|
||||||
.get()
|
.get()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("数据库连接失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("Logout DB connection failed: {}", e);
|
||||||
|
ServerFnError::new(format!("数据库连接失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
// 清除 cookie
|
// 清除 cookie
|
||||||
if let Some(ctx) = dioxus::fullstack::FullstackContext::current() {
|
if let Some(ctx) = dioxus::fullstack::FullstackContext::current() {
|
||||||
@ -241,7 +265,10 @@ pub async fn logout() -> Result<AuthResponse, ServerFnError> {
|
|||||||
client
|
client
|
||||||
.execute("DELETE FROM sessions WHERE token = $1", &[&t])
|
.execute("DELETE FROM sessions WHERE token = $1", &[&t])
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("删除 session 失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("Logout session delete failed: {}", e);
|
||||||
|
ServerFnError::new(format!("删除 session 失败: {}", e))
|
||||||
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(AuthResponse {
|
Ok(AuthResponse {
|
||||||
@ -277,7 +304,10 @@ pub async fn get_current_user() -> Result<CurrentUserResponse, ServerFnError> {
|
|||||||
let client = DB_POOL
|
let client = DB_POOL
|
||||||
.get()
|
.get()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("数据库连接失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("GetCurrentUser DB connection failed: {}", e);
|
||||||
|
ServerFnError::new(format!("数据库连接失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
let row = client
|
let row = client
|
||||||
.query_opt(
|
.query_opt(
|
||||||
@ -288,7 +318,10 @@ pub async fn get_current_user() -> Result<CurrentUserResponse, ServerFnError> {
|
|||||||
&[&token],
|
&[&token],
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("查询失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("GetCurrentUser session query failed: {}", e);
|
||||||
|
ServerFnError::new(format!("查询失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
let user = match row {
|
let user = match row {
|
||||||
Some(row) => {
|
Some(row) => {
|
||||||
|
|||||||
185
src/api/posts.rs
185
src/api/posts.rs
@ -48,7 +48,10 @@ async fn get_current_admin_user() -> Result<User, ServerFnError> {
|
|||||||
let client = DB_POOL
|
let client = DB_POOL
|
||||||
.get()
|
.get()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("数据库连接失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("DB connection failed: {}", e);
|
||||||
|
ServerFnError::new(format!("数据库连接失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
let row = client
|
let row = client
|
||||||
.query_opt(
|
.query_opt(
|
||||||
@ -59,7 +62,10 @@ async fn get_current_admin_user() -> Result<User, ServerFnError> {
|
|||||||
&[&token],
|
&[&token],
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("查询失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("query failed: {}", e);
|
||||||
|
ServerFnError::new(format!("查询失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
let user = match row {
|
let user = match row {
|
||||||
Some(row) => {
|
Some(row) => {
|
||||||
@ -221,7 +227,10 @@ async fn set_post_tags(
|
|||||||
client
|
client
|
||||||
.execute("DELETE FROM post_tags WHERE post_id = $1", &[&post_id])
|
.execute("DELETE FROM post_tags WHERE post_id = $1", &[&post_id])
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("删除标签关联失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("delete tag links failed: {}", e);
|
||||||
|
ServerFnError::new(format!("删除标签关联失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
for tag_name in tags {
|
for tag_name in tags {
|
||||||
let tag_name = tag_name.trim();
|
let tag_name = tag_name.trim();
|
||||||
@ -237,7 +246,10 @@ async fn set_post_tags(
|
|||||||
&[&tag_name],
|
&[&tag_name],
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("创建标签失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("create tag failed: {}", e);
|
||||||
|
ServerFnError::new(format!("创建标签失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
match row {
|
match row {
|
||||||
Some(r) => r.get(0),
|
Some(r) => r.get(0),
|
||||||
@ -246,7 +258,10 @@ async fn set_post_tags(
|
|||||||
let row = client
|
let row = client
|
||||||
.query_opt("SELECT id FROM tags WHERE name = $1", &[&tag_name])
|
.query_opt("SELECT id FROM tags WHERE name = $1", &[&tag_name])
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("查询标签失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("query tag failed: {}", e);
|
||||||
|
ServerFnError::new(format!("查询标签失败: {}", e))
|
||||||
|
})?;
|
||||||
row.map(|r| r.get(0))
|
row.map(|r| r.get(0))
|
||||||
.ok_or_else(|| ServerFnError::new(format!("标签不存在: {}", tag_name)))?
|
.ok_or_else(|| ServerFnError::new(format!("标签不存在: {}", tag_name)))?
|
||||||
}
|
}
|
||||||
@ -259,7 +274,10 @@ async fn set_post_tags(
|
|||||||
&[&post_id, &tag_id],
|
&[&post_id, &tag_id],
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("关联标签失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("link tag failed: {}", e);
|
||||||
|
ServerFnError::new(format!("关联标签失败: {}", e))
|
||||||
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -401,7 +419,10 @@ pub async fn create_post(
|
|||||||
let mut client = DB_POOL
|
let mut client = DB_POOL
|
||||||
.get()
|
.get()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("数据库连接失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("DB connection failed: {}", e);
|
||||||
|
ServerFnError::new(format!("数据库连接失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
let final_slug = ensure_unique_slug(&client, &base_slug, None).await?;
|
let final_slug = ensure_unique_slug(&client, &base_slug, None).await?;
|
||||||
let content_html = render_markdown(&content_md);
|
let content_html = render_markdown(&content_md);
|
||||||
@ -417,7 +438,10 @@ pub async fn create_post(
|
|||||||
let tx = client
|
let tx = client
|
||||||
.transaction()
|
.transaction()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("事务开始失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("transaction start failed: {}", e);
|
||||||
|
ServerFnError::new(format!("事务开始失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
let row = tx
|
let row = tx
|
||||||
.query_one(
|
.query_one(
|
||||||
@ -436,7 +460,10 @@ pub async fn create_post(
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("创建文章失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("create post failed: {}", e);
|
||||||
|
ServerFnError::new(format!("创建文章失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
let post_id: i32 = row.get(0);
|
let post_id: i32 = row.get(0);
|
||||||
|
|
||||||
@ -458,7 +485,10 @@ pub async fn create_post(
|
|||||||
&[&tag_name.as_str()],
|
&[&tag_name.as_str()],
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("创建标签失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("create tag failed: {}", e);
|
||||||
|
ServerFnError::new(format!("创建标签失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
match row {
|
match row {
|
||||||
Some(r) => r.get(0),
|
Some(r) => r.get(0),
|
||||||
@ -466,7 +496,10 @@ pub async fn create_post(
|
|||||||
let row = tx
|
let row = tx
|
||||||
.query_opt("SELECT id FROM tags WHERE name = $1", &[&tag_name.as_str()])
|
.query_opt("SELECT id FROM tags WHERE name = $1", &[&tag_name.as_str()])
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("查询标签失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("query tag failed: {}", e);
|
||||||
|
ServerFnError::new(format!("查询标签失败: {}", e))
|
||||||
|
})?;
|
||||||
row.map(|r| r.get(0))
|
row.map(|r| r.get(0))
|
||||||
.ok_or_else(|| ServerFnError::new(format!("标签不存在: {}", tag_name)))?
|
.ok_or_else(|| ServerFnError::new(format!("标签不存在: {}", tag_name)))?
|
||||||
}
|
}
|
||||||
@ -478,13 +511,19 @@ pub async fn create_post(
|
|||||||
&[&post_id, &tag_id],
|
&[&post_id, &tag_id],
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("关联标签失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("link tag failed: {}", e);
|
||||||
|
ServerFnError::new(format!("关联标签失败: {}", e))
|
||||||
|
})?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tx.commit()
|
tx.commit()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("事务提交失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("transaction commit failed: {}", e);
|
||||||
|
ServerFnError::new(format!("事务提交失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
Ok(CreatePostResponse {
|
Ok(CreatePostResponse {
|
||||||
success: true,
|
success: true,
|
||||||
@ -509,7 +548,10 @@ pub async fn update_post(
|
|||||||
let mut client = DB_POOL
|
let mut client = DB_POOL
|
||||||
.get()
|
.get()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("数据库连接失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("DB connection failed: {}", e);
|
||||||
|
ServerFnError::new(format!("数据库连接失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
// Verify ownership
|
// Verify ownership
|
||||||
let exists: bool = client
|
let exists: bool = client
|
||||||
@ -554,7 +596,10 @@ pub async fn update_post(
|
|||||||
let tx = client
|
let tx = client
|
||||||
.transaction()
|
.transaction()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("事务开始失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("transaction start failed: {}", e);
|
||||||
|
ServerFnError::new(format!("事务开始失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
// Check if status changed to published and was not published before
|
// Check if status changed to published and was not published before
|
||||||
let old_status_row = tx
|
let old_status_row = tx
|
||||||
@ -563,7 +608,10 @@ pub async fn update_post(
|
|||||||
&[&post_id],
|
&[&post_id],
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("查询失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("query failed: {}", e);
|
||||||
|
ServerFnError::new(format!("查询失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
let published_at = if post_status == PostStatus::Published {
|
let published_at = if post_status == PostStatus::Published {
|
||||||
let was_published = old_status_row
|
let was_published = old_status_row
|
||||||
@ -600,7 +648,10 @@ pub async fn update_post(
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("更新文章失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("update post failed: {}", e);
|
||||||
|
ServerFnError::new(format!("更新文章失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
// Update tags
|
// Update tags
|
||||||
let tags_cleaned: Vec<String> = tags
|
let tags_cleaned: Vec<String> = tags
|
||||||
@ -611,7 +662,10 @@ pub async fn update_post(
|
|||||||
|
|
||||||
tx.execute("DELETE FROM post_tags WHERE post_id = $1", &[&post_id])
|
tx.execute("DELETE FROM post_tags WHERE post_id = $1", &[&post_id])
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("删除旧标签失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("delete old tags failed: {}", e);
|
||||||
|
ServerFnError::new(format!("删除旧标签失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
for tag_name in &tags_cleaned {
|
for tag_name in &tags_cleaned {
|
||||||
let tag_id: i32 = {
|
let tag_id: i32 = {
|
||||||
@ -621,7 +675,10 @@ pub async fn update_post(
|
|||||||
&[&tag_name.as_str()],
|
&[&tag_name.as_str()],
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("创建标签失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("create tag failed: {}", e);
|
||||||
|
ServerFnError::new(format!("创建标签失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
match row {
|
match row {
|
||||||
Some(r) => r.get(0),
|
Some(r) => r.get(0),
|
||||||
@ -629,7 +686,10 @@ pub async fn update_post(
|
|||||||
let row = tx
|
let row = tx
|
||||||
.query_opt("SELECT id FROM tags WHERE name = $1", &[&tag_name.as_str()])
|
.query_opt("SELECT id FROM tags WHERE name = $1", &[&tag_name.as_str()])
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("查询标签失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("query tag failed: {}", e);
|
||||||
|
ServerFnError::new(format!("查询标签失败: {}", e))
|
||||||
|
})?;
|
||||||
row.map(|r| r.get(0))
|
row.map(|r| r.get(0))
|
||||||
.ok_or_else(|| ServerFnError::new(format!("标签不存在: {}", tag_name)))?
|
.ok_or_else(|| ServerFnError::new(format!("标签不存在: {}", tag_name)))?
|
||||||
}
|
}
|
||||||
@ -641,12 +701,18 @@ pub async fn update_post(
|
|||||||
&[&post_id, &tag_id],
|
&[&post_id, &tag_id],
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("关联标签失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("link tag failed: {}", e);
|
||||||
|
ServerFnError::new(format!("关联标签失败: {}", e))
|
||||||
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
tx.commit()
|
tx.commit()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("事务提交失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("transaction commit failed: {}", e);
|
||||||
|
ServerFnError::new(format!("事务提交失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
Ok(CreatePostResponse {
|
Ok(CreatePostResponse {
|
||||||
success: true,
|
success: true,
|
||||||
@ -661,7 +727,10 @@ pub async fn get_post_by_slug(slug: String) -> Result<SinglePostResponse, Server
|
|||||||
let client = DB_POOL
|
let client = DB_POOL
|
||||||
.get()
|
.get()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("数据库连接失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("DB connection failed: {}", e);
|
||||||
|
ServerFnError::new(format!("数据库连接失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
let row = client
|
let row = client
|
||||||
.query_opt(
|
.query_opt(
|
||||||
@ -671,7 +740,10 @@ pub async fn get_post_by_slug(slug: String) -> Result<SinglePostResponse, Server
|
|||||||
&[&slug],
|
&[&slug],
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("查询失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("query failed: {}", e);
|
||||||
|
ServerFnError::new(format!("查询失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
let post = match row {
|
let post = match row {
|
||||||
Some(row) => Some(row_to_post(&client, &row).await),
|
Some(row) => Some(row_to_post(&client, &row).await),
|
||||||
@ -686,7 +758,10 @@ pub async fn list_published_posts() -> Result<PostListResponse, ServerFnError> {
|
|||||||
let client = DB_POOL
|
let client = DB_POOL
|
||||||
.get()
|
.get()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("数据库连接失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("DB connection failed: {}", e);
|
||||||
|
ServerFnError::new(format!("数据库连接失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
let rows = client
|
let rows = client
|
||||||
.query(
|
.query(
|
||||||
@ -697,7 +772,10 @@ pub async fn list_published_posts() -> Result<PostListResponse, ServerFnError> {
|
|||||||
&[],
|
&[],
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("查询失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("query failed: {}", e);
|
||||||
|
ServerFnError::new(format!("查询失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
let mut posts = Vec::new();
|
let mut posts = Vec::new();
|
||||||
for row in &rows {
|
for row in &rows {
|
||||||
@ -714,7 +792,10 @@ pub async fn list_posts() -> Result<PostListResponse, ServerFnError> {
|
|||||||
let client = DB_POOL
|
let client = DB_POOL
|
||||||
.get()
|
.get()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("数据库连接失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("DB connection failed: {}", e);
|
||||||
|
ServerFnError::new(format!("数据库连接失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
let rows = client
|
let rows = client
|
||||||
.query(
|
.query(
|
||||||
@ -725,7 +806,10 @@ pub async fn list_posts() -> Result<PostListResponse, ServerFnError> {
|
|||||||
&[],
|
&[],
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("查询失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("query failed: {}", e);
|
||||||
|
ServerFnError::new(format!("查询失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
let mut posts = Vec::new();
|
let mut posts = Vec::new();
|
||||||
for row in &rows {
|
for row in &rows {
|
||||||
@ -742,7 +826,10 @@ pub async fn delete_post(post_id: i32) -> Result<CreatePostResponse, ServerFnErr
|
|||||||
let client = DB_POOL
|
let client = DB_POOL
|
||||||
.get()
|
.get()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("数据库连接失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("DB connection failed: {}", e);
|
||||||
|
ServerFnError::new(format!("数据库连接失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
let result = client
|
let result = client
|
||||||
.execute(
|
.execute(
|
||||||
@ -750,7 +837,10 @@ pub async fn delete_post(post_id: i32) -> Result<CreatePostResponse, ServerFnErr
|
|||||||
&[&post_id],
|
&[&post_id],
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("删除失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("delete failed: {}", e);
|
||||||
|
ServerFnError::new(format!("删除失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
if result == 0 {
|
if result == 0 {
|
||||||
return Ok(CreatePostResponse {
|
return Ok(CreatePostResponse {
|
||||||
@ -774,7 +864,10 @@ pub async fn list_tags() -> Result<TagListResponse, ServerFnError> {
|
|||||||
let client = DB_POOL
|
let client = DB_POOL
|
||||||
.get()
|
.get()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("数据库连接失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("DB connection failed: {}", e);
|
||||||
|
ServerFnError::new(format!("数据库连接失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
let rows = client
|
let rows = client
|
||||||
.query(
|
.query(
|
||||||
@ -787,7 +880,10 @@ pub async fn list_tags() -> Result<TagListResponse, ServerFnError> {
|
|||||||
&[],
|
&[],
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("查询失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("query failed: {}", e);
|
||||||
|
ServerFnError::new(format!("查询失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
let tags: Vec<Tag> = rows
|
let tags: Vec<Tag> = rows
|
||||||
.iter()
|
.iter()
|
||||||
@ -806,7 +902,10 @@ pub async fn get_posts_by_tag(tag_name: String) -> Result<PostListResponse, Serv
|
|||||||
let client = DB_POOL
|
let client = DB_POOL
|
||||||
.get()
|
.get()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("数据库连接失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("DB connection failed: {}", e);
|
||||||
|
ServerFnError::new(format!("数据库连接失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
let rows = client
|
let rows = client
|
||||||
.query(
|
.query(
|
||||||
@ -819,7 +918,10 @@ pub async fn get_posts_by_tag(tag_name: String) -> Result<PostListResponse, Serv
|
|||||||
&[&tag_name],
|
&[&tag_name],
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("查询失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("query failed: {}", e);
|
||||||
|
ServerFnError::new(format!("查询失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
let mut posts = Vec::new();
|
let mut posts = Vec::new();
|
||||||
for row in &rows {
|
for row in &rows {
|
||||||
@ -836,7 +938,10 @@ pub async fn get_post_stats() -> Result<PostStatsResponse, ServerFnError> {
|
|||||||
let client = DB_POOL
|
let client = DB_POOL
|
||||||
.get()
|
.get()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("数据库连接失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("DB connection failed: {}", e);
|
||||||
|
ServerFnError::new(format!("数据库连接失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
let total: i64 = client
|
let total: i64 = client
|
||||||
.query_one("SELECT COUNT(*) FROM posts WHERE deleted_at IS NULL", &[])
|
.query_one("SELECT COUNT(*) FROM posts WHERE deleted_at IS NULL", &[])
|
||||||
@ -876,7 +981,10 @@ pub async fn search_posts(query: String) -> Result<PostListResponse, ServerFnErr
|
|||||||
let client = DB_POOL
|
let client = DB_POOL
|
||||||
.get()
|
.get()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("数据库连接失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("DB connection failed: {}", e);
|
||||||
|
ServerFnError::new(format!("数据库连接失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
let search_pattern = format!("%{}%", query);
|
let search_pattern = format!("%{}%", query);
|
||||||
|
|
||||||
@ -890,7 +998,10 @@ pub async fn search_posts(query: String) -> Result<PostListResponse, ServerFnErr
|
|||||||
&[&search_pattern],
|
&[&search_pattern],
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(format!("查询失败: {}", e)))?;
|
.map_err(|e| {
|
||||||
|
tracing::error!("query failed: {}", e);
|
||||||
|
ServerFnError::new(format!("查询失败: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
let mut posts = Vec::new();
|
let mut posts = Vec::new();
|
||||||
for row in &rows {
|
for row in &rows {
|
||||||
|
|||||||
@ -20,6 +20,12 @@ fn main() {
|
|||||||
)
|
)
|
||||||
.init();
|
.init();
|
||||||
|
|
||||||
|
if std::env::var("DATABASE_URL").is_err() {
|
||||||
|
tracing::error!("DATABASE_URL environment variable not set. Make sure .env exists or the variable is exported.");
|
||||||
|
eprintln!("ERROR: DATABASE_URL environment variable not set");
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
dioxus::server::serve(|| async move {
|
dioxus::server::serve(|| async move {
|
||||||
use dioxus::server::{axum, DioxusRouterExt, ServeConfig};
|
use dioxus::server::{axum, DioxusRouterExt, ServeConfig};
|
||||||
use tower_http::trace::TraceLayer;
|
use tower_http::trace::TraceLayer;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user