perf(diary): parent_service 批量软删除替代逐条 UPDATE — 8a-C03

- delete_child_data 改用单条 SQL UPDATE ... WHERE 批量软删除
- 1 次 SQL 替代 N 次逐条 UPDATE(从 O(N) 降到 O(1) 查询)
- 移除不再需要的 TransactionTrait 导入
- 测试 80/80 通过
This commit is contained in:
iven
2026-06-03 15:48:29 +08:00
parent 3258acaa77
commit 4e5c1287a6

View File

@@ -2,8 +2,8 @@
use chrono::Utc; use chrono::Utc;
use sea_orm::{ use sea_orm::{
ActiveModelTrait, ColumnTrait, DatabaseConnection, EntityTrait, PaginatorTrait, ActiveModelTrait, ColumnTrait, ConnectionTrait, DatabaseConnection, EntityTrait,
QueryFilter, QueryOrder, Set, TransactionTrait, PaginatorTrait, QueryFilter, QueryOrder, Set,
}; };
use uuid::Uuid; use uuid::Uuid;
@@ -272,7 +272,8 @@ impl ParentService {
/// 删除孩子数据 — 软删除所有日记PIPL 删除权) /// 删除孩子数据 — 软删除所有日记PIPL 删除权)
/// ///
/// 软删除孩子全部未删除的日记,逐条设置 deleted_at /// 使用单条 SQL UPDATE 批量软删除,替代逐条更新
/// 性能: 1 次 SQL 替代 N 次 UPDATE。
/// 发布 `diary.parent.data_deleted` 事件记录操作。 /// 发布 `diary.parent.data_deleted` 事件记录操作。
pub async fn delete_child_data( pub async fn delete_child_data(
tenant_id: Uuid, tenant_id: Uuid,
@@ -283,32 +284,33 @@ impl ParentService {
) -> DiaryResult<usize> { ) -> DiaryResult<usize> {
Self::verify_binding(tenant_id, parent_id, child_id, db).await?; Self::verify_binding(tenant_id, parent_id, child_id, db).await?;
let journals = journal_entry::Entity::find()
.filter(journal_entry::Column::TenantId.eq(tenant_id))
.filter(journal_entry::Column::AuthorId.eq(child_id))
.filter(journal_entry::Column::DeletedAt.is_null())
.all(db)
.await?;
let count = journals.len();
let now = Utc::now(); let now = Utc::now();
// 事务软删除所有日记PIPL 删除权 — 原子操作,避免部分删除 // 批量软删除 — 单条 SQL 替代逐条 UPDATE性能优化 8a-C03
db.transaction::<_, (), DiaryError>(|txn| { let sql = r#"
Box::pin(async move { UPDATE journal_entries
for journal in journals { SET deleted_at = $1,
let current_version = journal.version; updated_at = $1,
let mut active: journal_entry::ActiveModel = journal.into(); updated_by = $2,
active.deleted_at = Set(Some(now)); version = version + 1
active.updated_at = Set(now); WHERE tenant_id = $3
active.updated_by = Set(parent_id); AND author_id = $4
active.version = Set(current_version + 1); AND deleted_at IS NULL
active.update(txn).await?; "#;
}
Ok(()) let stmt = sea_orm::Statement::from_sql_and_values(
}) sea_orm::DatabaseBackend::Postgres,
}) sql,
.await?; [
now.into(),
parent_id.into(),
tenant_id.into(),
child_id.into(),
],
);
let result = db.execute(stmt).await?;
let count = result.rows_affected() as usize;
event_bus event_bus
.publish( .publish(