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:
@@ -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(
|
||||||
|
|||||||
Reference in New Issue
Block a user