feat(posts): add rebuild_content_html server function
New admin-only server function that re-renders content_html and toc_html for posts from their content_md: - rebuild_all=false: only processes posts where content_html IS NULL - rebuild_all=true: processes all non-deleted posts - Processes rows one at a time to avoid table locks - Invalidates post list and stats caches after rebuild
This commit is contained in:
parent
a975e45cc9
commit
2e9d123396
@ -10,6 +10,7 @@ mod list;
|
||||
mod search;
|
||||
mod tags;
|
||||
mod stats;
|
||||
mod rebuild;
|
||||
|
||||
pub use types::*;
|
||||
pub use create::create_post;
|
||||
@ -20,6 +21,7 @@ pub use list::{list_published_posts, list_posts, get_posts_by_tag};
|
||||
pub use search::search_posts;
|
||||
pub use tags::list_tags;
|
||||
pub use stats::get_post_stats;
|
||||
pub use rebuild::rebuild_content_html;
|
||||
|
||||
#[cfg(feature = "server")]
|
||||
pub use crate::api::markdown::render_markdown_enhanced;
|
||||
|
||||
61
src/api/posts/rebuild.rs
Normal file
61
src/api/posts/rebuild.rs
Normal file
@ -0,0 +1,61 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
#[cfg(feature = "server")]
|
||||
use super::helpers::get_current_admin_user;
|
||||
#[cfg(feature = "server")]
|
||||
use crate::api::error::AppError;
|
||||
use crate::db::pool::get_conn;
|
||||
|
||||
#[server(RebuildContentHtml, "/api")]
|
||||
pub async fn rebuild_content_html(rebuild_all: bool) -> Result<u64, ServerFnError> {
|
||||
let _user = get_current_admin_user().await?;
|
||||
|
||||
#[cfg(feature = "server")]
|
||||
{
|
||||
let client = get_conn().await.map_err(AppError::db_conn)?;
|
||||
|
||||
let query = if rebuild_all {
|
||||
"SELECT id, content_md FROM posts WHERE deleted_at IS NULL ORDER BY id"
|
||||
} else {
|
||||
"SELECT id, content_md FROM posts WHERE deleted_at IS NULL AND content_html IS NULL ORDER BY id"
|
||||
};
|
||||
|
||||
let rows = client.query(query, &[]).await.map_err(AppError::query)?;
|
||||
|
||||
let mut count: u64 = 0;
|
||||
|
||||
for row in &rows {
|
||||
let id: i32 = row.get(0);
|
||||
let content_md: String = row.get(1);
|
||||
|
||||
let rendered = crate::api::markdown::render_markdown_enhanced(&content_md);
|
||||
let toc_html = if rendered.toc_html.is_empty() {
|
||||
None::<String>
|
||||
} else {
|
||||
Some(rendered.toc_html)
|
||||
};
|
||||
|
||||
client
|
||||
.execute(
|
||||
"UPDATE posts SET content_html = $1, toc_html = $2, updated_at = NOW() WHERE id = $3",
|
||||
&[&rendered.html, &toc_html, &id],
|
||||
)
|
||||
.await
|
||||
.map_err(AppError::tx)?;
|
||||
|
||||
count += 1;
|
||||
}
|
||||
|
||||
if count > 0 {
|
||||
crate::cache::invalidate_post_lists();
|
||||
crate::cache::invalidate_post_stats();
|
||||
}
|
||||
|
||||
Ok(count)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "server"))]
|
||||
{
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user