From 02fa0ba0b836cdad0db518c12a8ffd523a27485b Mon Sep 17 00:00:00 2001 From: timedout Date: Sun, 25 Jan 2026 15:43:56 +0000 Subject: [PATCH] perf: Optimise account deactivation process --- src/admin/user/commands.rs | 12 +------ src/api/client/account.rs | 67 +++++++++++++++++--------------------- 2 files changed, 30 insertions(+), 49 deletions(-) diff --git a/src/admin/user/commands.rs b/src/admin/user/commands.rs index 5fa76b88..9fef83c5 100644 --- a/src/admin/user/commands.rs +++ b/src/admin/user/commands.rs @@ -3,10 +3,7 @@ use std::{ fmt::Write as _, }; -use api::client::{ - full_user_deactivate, join_room_by_id_helper, leave_all_rooms, leave_room, remote_leave_room, - update_avatar_url, update_displayname, -}; +use api::client::{full_user_deactivate, join_room_by_id_helper, leave_room, remote_leave_room}; use conduwuit::{ Err, Result, debug, debug_warn, error, info, is_equal_to, matrix::{Event, pdu::PduBuilder}, @@ -227,9 +224,6 @@ pub(super) async fn deactivate(&self, no_leave_rooms: bool, user_id: String) -> full_user_deactivate(self.services, &user_id, &all_joined_rooms) .boxed() .await?; - update_displayname(self.services, &user_id, None, &all_joined_rooms).await; - update_avatar_url(self.services, &user_id, None, None, &all_joined_rooms).await; - leave_all_rooms(self.services, &user_id).await; } self.write_str(&format!("User {user_id} has been deactivated")) @@ -406,10 +400,6 @@ pub(super) async fn deactivate_all(&self, no_leave_rooms: bool, force: bool) -> full_user_deactivate(self.services, &user_id, &all_joined_rooms) .boxed() .await?; - update_displayname(self.services, &user_id, None, &all_joined_rooms).await; - update_avatar_url(self.services, &user_id, None, None, &all_joined_rooms) - .await; - leave_all_rooms(self.services, &user_id).await; } }, } diff --git a/src/api/client/account.rs b/src/api/client/account.rs index d9779e0b..d27dc2a2 100644 --- a/src/api/client/account.rs +++ b/src/api/client/account.rs @@ -26,6 +26,7 @@ use ruma::{ events::{ GlobalAccountDataEventType, StateEventType, room::{ + member::{MembershipState, RoomMemberEventContent}, message::RoomMessageEventContent, power_levels::{RoomPowerLevels, RoomPowerLevelsEventContent}, }, @@ -815,22 +816,10 @@ pub(crate) async fn deactivate_route( .collect() .await; - super::update_displayname(&services, sender_user, None, &all_joined_rooms).await; - super::update_avatar_url(&services, sender_user, None, None, &all_joined_rooms).await; - full_user_deactivate(&services, sender_user, &all_joined_rooms) .boxed() .await?; - info!("User {sender_user} deactivated their account."); - - if services.server.config.admin_room_notices { - services - .admin - .notice(&format!("User {sender_user} deactivated their account.")) - .await; - } - Ok(deactivate::v3::Response { id_server_unbind_result: ThirdPartyIdRemovalStatus::NoSupport, }) @@ -907,9 +896,6 @@ pub async fn full_user_deactivate( ) -> Result<()> { services.users.deactivate_account(user_id).await.ok(); - super::update_displayname(services, user_id, None, all_joined_rooms).await; - super::update_avatar_url(services, user_id, None, None, all_joined_rooms).await; - services .users .all_profile_keys(user_id) @@ -918,9 +904,11 @@ pub async fn full_user_deactivate( }) .await; - for room_id in all_joined_rooms { - let state_lock = services.rooms.state.mutex.lock(room_id).await; + // TODO: Rescind all user invites + let mut pdu_queue: Vec<(PduBuilder, &OwnedRoomId)> = Vec::new(); + + for room_id in all_joined_rooms { let room_power_levels = services .rooms .state_accessor @@ -948,30 +936,33 @@ pub async fn full_user_deactivate( if user_can_demote_self { let mut power_levels_content = room_power_levels.unwrap_or_default(); power_levels_content.users.remove(user_id); - - // ignore errors so deactivation doesn't fail - match services - .rooms - .timeline - .build_and_append_pdu( - PduBuilder::state(String::new(), &power_levels_content), - user_id, - Some(room_id), - &state_lock, - ) - .await - { - | Err(e) => { - warn!(%room_id, %user_id, "Failed to demote user's own power level: {e}"); - }, - | _ => { - info!("Demoted {user_id} in {room_id} as part of account deactivation"); - }, - } + let pl_evt = PduBuilder::state(String::new(), &power_levels_content); + pdu_queue.push((pl_evt, room_id)); } + + // Leave the room + pdu_queue.push(( + PduBuilder::state(user_id.to_string(), &RoomMemberEventContent { + avatar_url: None, + blurhash: None, + membership: MembershipState::Leave, + displayname: None, + join_authorized_via_users_server: None, + reason: None, + is_direct: None, + third_party_invite: None, + redact_events: None, + }), + room_id, + )); + + // TODO: Redact all messages sent by the user in the room } - super::leave_all_rooms(services, user_id).boxed().await; + super::update_all_rooms(services, pdu_queue, user_id).await; + for room_id in all_joined_rooms { + services.rooms.state_cache.forget(&room_id, user_id); + } Ok(()) }