refactor(posts): apply precise invalidation limit to batch_restore_posts

This commit is contained in:
xfy 2026-06-17 16:59:18 +08:00
parent ca212a2aab
commit c77f751377

View File

@ -218,6 +218,9 @@ pub async fn batch_restore_posts(post_ids: Vec<i32>) -> Result<CreatePostRespons
let mut client = get_conn().await.map_err(AppError::db_conn)?;
let tx = client.transaction().await.map_err(AppError::tx)?;
// 记录数较少时使用精准失效;否则回退到全量失效。
let use_precise = post_ids.len() <= PRECISE_INVALIDATION_LIMIT;
// 逐条恢复slug 冲突时自动加后缀;同时收集受影响的 slug 与标签。
let mut restored = 0u64;
let mut affected_slugs: Vec<String> = Vec::with_capacity(post_ids.len() * 2);
@ -227,7 +230,7 @@ pub async fn batch_restore_posts(post_ids: Vec<i32>) -> Result<CreatePostRespons
for id in &post_ids {
let row = tx
.query_opt(
"SELECT slug FROM posts WHERE id = $1 AND deleted_at IS NOT NULL",
"SELECT slug FROM posts WHERE id = $1 AND deleted_at IS NOT NULL FOR UPDATE",
&[&id],
)
.await
@ -236,6 +239,7 @@ pub async fn batch_restore_posts(post_ids: Vec<i32>) -> Result<CreatePostRespons
let current_slug: String = row.get("slug");
let new_slug = ensure_unique_slug(&tx, &current_slug, Some(*id)).await?;
if use_precise {
let tag_rows = tx
.query(
"SELECT t.name FROM tags t JOIN post_tags pt ON t.id = pt.tag_id WHERE pt.post_id = $1",
@ -246,6 +250,7 @@ pub async fn batch_restore_posts(post_ids: Vec<i32>) -> Result<CreatePostRespons
for tag_row in &tag_rows {
affected_tags.insert(tag_row.get(0));
}
}
let n = tx
.execute(
@ -256,13 +261,16 @@ pub async fn batch_restore_posts(post_ids: Vec<i32>) -> Result<CreatePostRespons
.map_err(AppError::tx)?;
restored += n;
if use_precise {
affected_slugs.push(current_slug);
affected_slugs.push(new_slug);
}
}
}
tx.commit().await.map_err(AppError::tx)?;
if use_precise {
// 精准失效:先去重 slug再统一失效列表/标签云/统计/标签文章。
let unique_slugs: std::collections::HashSet<String> =
affected_slugs.into_iter().collect();
@ -273,6 +281,10 @@ pub async fn batch_restore_posts(post_ids: Vec<i32>) -> Result<CreatePostRespons
crate::cache::invalidate_post_by_slug(slug).await;
}
crate::cache::invalidate_tag_posts_for(&affected_tags.into_iter().collect::<Vec<_>>()).await;
} else {
// 影响集过大时回退到全量失效,避免大量串行缓存操作。
crate::cache::invalidate_all_post_caches();
}
Ok(CreatePostResponse {
success: true,