refactor(posts): use precise cache invalidation in create/update/delete
This commit is contained in:
parent
c528936abb
commit
82b070e7ac
@ -139,17 +139,14 @@ pub async fn create_post(
|
|||||||
|
|
||||||
tx.commit().await.map_err(AppError::tx)?;
|
tx.commit().await.map_err(AppError::tx)?;
|
||||||
|
|
||||||
// 写入成功后失效文章列表、标签与统计缓存。
|
// 写入成功后按粒度失效相关缓存。
|
||||||
crate::cache::invalidate_post_lists();
|
crate::cache::invalidate_post_lists();
|
||||||
crate::cache::invalidate_all_tags();
|
crate::cache::invalidate_all_tags();
|
||||||
crate::cache::invalidate_post_stats();
|
crate::cache::invalidate_post_stats();
|
||||||
// 失效按 slug 缓存,避免之前缓存的 404 继续命中。
|
// 失效按 slug 缓存,避免之前缓存的 404 继续命中。
|
||||||
crate::cache::invalidate_post_by_slug(&final_slug).await;
|
crate::cache::invalidate_post_by_slug(&final_slug).await;
|
||||||
|
// 失效该文章涉及的所有标签下文章列表缓存。
|
||||||
// 失效该文章涉及的所有标签缓存。
|
crate::cache::invalidate_tag_posts_for(&tags_cleaned).await;
|
||||||
for tag_name in &tags_cleaned {
|
|
||||||
crate::cache::invalidate_posts_by_tag(tag_name).await;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(CreatePostResponse {
|
Ok(CreatePostResponse {
|
||||||
success: true,
|
success: true,
|
||||||
|
|||||||
@ -27,6 +27,34 @@ pub async fn delete_post(post_id: i32) -> Result<CreatePostResponse, ServerFnErr
|
|||||||
{
|
{
|
||||||
let client = get_conn().await.map_err(AppError::db_conn)?;
|
let client = get_conn().await.map_err(AppError::db_conn)?;
|
||||||
|
|
||||||
|
// 在软删除前查询 slug 与标签,用于后续精准失效缓存。
|
||||||
|
let slug_row = client
|
||||||
|
.query_opt(
|
||||||
|
"SELECT slug FROM posts WHERE id = $1 AND deleted_at IS NULL",
|
||||||
|
&[&post_id],
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(AppError::query)?;
|
||||||
|
|
||||||
|
let Some(slug_row) = slug_row else {
|
||||||
|
return Ok(CreatePostResponse {
|
||||||
|
success: false,
|
||||||
|
message: "文章不存在".to_string(),
|
||||||
|
post_id: None,
|
||||||
|
slug: None,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
let slug: String = slug_row.get(0);
|
||||||
|
|
||||||
|
let tag_rows = client
|
||||||
|
.query(
|
||||||
|
"SELECT t.name FROM tags t JOIN post_tags pt ON t.id = pt.tag_id WHERE pt.post_id = $1",
|
||||||
|
&[&post_id],
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(AppError::query)?;
|
||||||
|
let tags: Vec<String> = tag_rows.iter().map(|r| r.get(0)).collect();
|
||||||
|
|
||||||
// 软删除:仅影响未被删除的文章。
|
// 软删除:仅影响未被删除的文章。
|
||||||
let result = client
|
let result = client
|
||||||
.execute(
|
.execute(
|
||||||
@ -45,14 +73,18 @@ pub async fn delete_post(post_id: i32) -> Result<CreatePostResponse, ServerFnErr
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除后所有文章相关缓存均失效。
|
// 删除后按影响范围精准失效缓存。
|
||||||
crate::cache::invalidate_all_post_caches();
|
crate::cache::invalidate_post_lists();
|
||||||
|
crate::cache::invalidate_all_tags();
|
||||||
|
crate::cache::invalidate_post_stats();
|
||||||
|
crate::cache::invalidate_post_by_slug(&slug).await;
|
||||||
|
crate::cache::invalidate_tag_posts_for(&tags).await;
|
||||||
|
|
||||||
Ok(CreatePostResponse {
|
Ok(CreatePostResponse {
|
||||||
success: true,
|
success: true,
|
||||||
message: "删除成功".to_string(),
|
message: "删除成功".to_string(),
|
||||||
post_id: Some(post_id),
|
post_id: Some(post_id),
|
||||||
slug: None,
|
slug: Some(slug),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -198,17 +198,17 @@ pub async fn update_post(
|
|||||||
// 失效文章列表、标签、当前 slug 与统计缓存。
|
// 失效文章列表、标签、当前 slug 与统计缓存。
|
||||||
crate::cache::invalidate_post_lists();
|
crate::cache::invalidate_post_lists();
|
||||||
crate::cache::invalidate_all_tags();
|
crate::cache::invalidate_all_tags();
|
||||||
crate::cache::invalidate_post_by_slug(&final_slug).await;
|
|
||||||
crate::cache::invalidate_post_stats();
|
crate::cache::invalidate_post_stats();
|
||||||
|
crate::cache::invalidate_post_by_slug(&final_slug).await;
|
||||||
|
|
||||||
// 合并旧标签与新标签,统一失效标签下的文章列表缓存。
|
// 合并旧标签与新标签,统一失效标签下的文章列表缓存。
|
||||||
let all_tags_to_invalidate: std::collections::HashSet<String> = old_tags
|
let all_tags_to_invalidate: Vec<String> = old_tags
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain(tags_for_invalidation.into_iter())
|
.chain(tags_for_invalidation.into_iter())
|
||||||
|
.collect::<std::collections::HashSet<_>>()
|
||||||
|
.into_iter()
|
||||||
.collect();
|
.collect();
|
||||||
for tag_name in &all_tags_to_invalidate {
|
crate::cache::invalidate_tag_posts_for(&all_tags_to_invalidate).await;
|
||||||
crate::cache::invalidate_posts_by_tag(tag_name).await;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 若 slug 发生变更,额外失效旧 slug 缓存。
|
// 若 slug 发生变更,额外失效旧 slug 缓存。
|
||||||
if let Some(ref old) = old_slug {
|
if let Some(ref old) = old_slug {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user