Skip to main content

tuwunel_service/rooms/delete/
mod.rs

1use std::sync::Arc;
2
3use futures::{FutureExt, StreamExt};
4use ruma::RoomId;
5use tuwunel_core::{
6	Result, debug,
7	result::LogErr,
8	trace,
9	utils::{ReadyExt, future::BoolExt},
10	warn,
11};
12
13use crate::rooms::timeline::RoomMutexGuard;
14
15pub struct Service {
16	services: Arc<crate::services::OnceServices>,
17}
18
19impl crate::Service for Service {
20	fn build(args: &crate::Args<'_>) -> Result<Arc<Self>> {
21		Ok(Arc::new(Self { services: args.services.clone() }))
22	}
23
24	fn name(&self) -> &str { crate::service::make_name(std::module_path!()) }
25}
26
27impl Service {
28	pub async fn delete_if_empty_local(&self, room_id: &RoomId, state_lock: RoomMutexGuard) {
29		debug_assert!(
30			self.services.config.delete_rooms_after_leave,
31			"Caller must checking if delete_rooms_after_leave configured."
32		);
33
34		let has_local_users = self
35			.services
36			.state_cache
37			.local_users_in_room(room_id)
38			.boxed()
39			.into_future()
40			.map(|(next, ..)| next.as_ref().is_some());
41
42		let has_local_invites = self
43			.services
44			.state_cache
45			.local_users_invited_to_room(room_id)
46			.boxed()
47			.into_future()
48			.map(|(next, ..)| next.as_ref().is_some());
49
50		if has_local_users.or(has_local_invites).await {
51			trace!(?room_id, "Not deleting with local joined or invited");
52			return;
53		}
54
55		debug!(?room_id, "Preparing to delete room...");
56
57		self.services
58			.delete
59			.delete_room(room_id, false, state_lock)
60			.boxed()
61			.await
62			.expect("unhandled error during room deletion");
63	}
64
65	pub async fn delete_room(
66		&self,
67		room_id: &RoomId,
68		force: bool,
69		state_lock: RoomMutexGuard,
70	) -> Result {
71		debug!("Making all users leave the room {room_id} and forgetting it");
72		let mut users = self
73			.services
74			.state_cache
75			.room_members(room_id)
76			.ready_filter(|user| self.services.globals.user_is_local(user))
77			.boxed();
78
79		while let Some(user_id) = users.next().await {
80			debug!(
81				"Attempting leave for user {user_id} in room {room_id} (ignoring all errors, \
82				 evicting admins too)",
83			);
84
85			if let Err(e) = self
86				.services
87				.membership
88				.leave(user_id, room_id, Some("Room Deleted".into()), true, &state_lock)
89				.boxed()
90				.await
91			{
92				warn!("Failed to leave room: {e}");
93			}
94		}
95
96		debug!("Deleting all our room aliases for the room");
97		self.services
98			.alias
99			.local_aliases_for_room(room_id)
100			.for_each(async |local_alias| {
101				self.services
102					.alias
103					.remove_alias(local_alias)
104					.await
105					.log_err()
106					.ok();
107			})
108			.await;
109
110		debug!("Removing/unpublishing room from our room directory");
111		self.services.directory.set_not_public(room_id);
112
113		debug!("Deleting room's threads from database");
114		self.services
115			.threads
116			.delete_all_rooms_threads(room_id)
117			.await
118			.log_err()
119			.ok();
120
121		debug!("Deleting all the room's search token IDs from our database");
122		self.services
123			.search
124			.delete_all_search_tokenids_for_room(room_id)
125			.await
126			.log_err()
127			.ok();
128
129		debug!("Deleting all room's forward extremities from our database");
130		self.services
131			.state
132			.delete_all_rooms_forward_extremities(room_id)
133			.await
134			.log_err()
135			.ok();
136
137		debug!("Deleting all the room's event (PDU) references");
138		self.services
139			.pdu_metadata
140			.delete_all_referenced_for_room(room_id)
141			.await
142			.log_err()
143			.ok();
144
145		debug!("Deleting all the room's member counts");
146		self.services
147			.state_cache
148			.delete_room_join_counts(room_id, force)
149			.await
150			.log_err()
151			.ok();
152
153		debug!("Deleting all the room's private read receipts");
154		self.services
155			.read_receipt
156			.delete_all_read_receipts(room_id)
157			.await
158			.log_err()
159			.ok();
160
161		debug!("Deleting the room's last notifications read.");
162		self.services
163			.pusher
164			.delete_room_notification_read(room_id)
165			.await
166			.log_err()
167			.ok();
168
169		debug!("Final stages of deleting the room");
170
171		debug!("Deleting room state hash from our database");
172		self.services
173			.state
174			.delete_room_shortstatehash(room_id, &state_lock)
175			.log_err()
176			.ok();
177
178		debug!("Deleting PDUs");
179		self.services
180			.timeline
181			.delete_pdus(room_id)
182			.await
183			.log_err()
184			.ok();
185
186		debug!("Deleting internal room ID from our database");
187		self.services
188			.short
189			.delete_shortroomid(room_id)
190			.await
191			.log_err()
192			.ok();
193
194		debug!("Successfully deleted room {room_id} from our database");
195		Ok(())
196	}
197}