Room deletion (fixes #43)
This commit is contained in:
@@ -65,3 +65,17 @@ pub(super) async fn exists(&self, room_id: OwnedRoomId) -> Result {
|
|||||||
|
|
||||||
self.write_str(&format!("{result}")).await
|
self.write_str(&format!("{result}")).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[admin_command]
|
||||||
|
pub(super) async fn delete_room(&self, room_id: OwnedRoomId) -> Result {
|
||||||
|
if self.services.admin.is_admin_room(&room_id).await {
|
||||||
|
return Err!("Cannot delete admin room");
|
||||||
|
}
|
||||||
|
|
||||||
|
self.services.delete.delete_room(room_id).await?;
|
||||||
|
|
||||||
|
self.write_str("Successfully deleted the room from our database.")
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
@@ -56,4 +56,9 @@ pub(super) enum RoomCommand {
|
|||||||
Exists {
|
Exists {
|
||||||
room_id: OwnedRoomId,
|
room_id: OwnedRoomId,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// - Delete room
|
||||||
|
DeleteRoom {
|
||||||
|
room_id: OwnedRoomId,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
160
src/service/rooms/delete/mod.rs
Normal file
160
src/service/rooms/delete/mod.rs
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use futures::StreamExt;
|
||||||
|
use ruma::OwnedRoomId;
|
||||||
|
use tuwunel_core::{Result, debug, result::LogErr, utils::ReadyExt, warn};
|
||||||
|
|
||||||
|
pub struct Service {
|
||||||
|
services: Arc<crate::services::OnceServices>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl crate::Service for Service {
|
||||||
|
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
|
||||||
|
Ok(Arc::new(Self { services: args.services.clone() }))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn name(&self) -> &str { crate::service::make_name(std::module_path!()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Service {
|
||||||
|
pub async fn delete_room(&self, room_id: OwnedRoomId) -> Result {
|
||||||
|
// ban the room locally so new users cannot join while we're in the process of
|
||||||
|
// deleting it
|
||||||
|
debug!("Banning room {}", &room_id);
|
||||||
|
self.services.metadata.ban_room(&room_id);
|
||||||
|
|
||||||
|
debug!("Making all users leave the room {room_id} and forgetting it");
|
||||||
|
let mut users = self
|
||||||
|
.services
|
||||||
|
.state_cache
|
||||||
|
.room_members(&room_id)
|
||||||
|
.ready_filter(|user| self.services.globals.user_is_local(user))
|
||||||
|
.boxed();
|
||||||
|
|
||||||
|
while let Some(user_id) = users.next().await {
|
||||||
|
debug!(
|
||||||
|
"Attempting leave for user {user_id} in room {room_id} (ignoring all errors, \
|
||||||
|
evicting admins too)",
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Err(e) = self
|
||||||
|
.services
|
||||||
|
.membership
|
||||||
|
.remote_leave(user_id, &room_id)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
warn!("Failed to leave room: {e}");
|
||||||
|
}
|
||||||
|
|
||||||
|
self.services
|
||||||
|
.state_cache
|
||||||
|
.forget(&room_id, user_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!("Disabling incoming federation on room {}", &room_id);
|
||||||
|
self.services.metadata.disable_room(&room_id);
|
||||||
|
|
||||||
|
debug!("Deleting all our room aliases for the room");
|
||||||
|
self.services
|
||||||
|
.alias
|
||||||
|
.local_aliases_for_room(&room_id)
|
||||||
|
.for_each(async |local_alias| {
|
||||||
|
self.services
|
||||||
|
.alias
|
||||||
|
.remove_alias(local_alias, &self.services.globals.server_user)
|
||||||
|
.await
|
||||||
|
.log_err()
|
||||||
|
.ok();
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
debug!("Removing/unpublishing room from our room directory");
|
||||||
|
self.services.directory.set_not_public(&room_id);
|
||||||
|
|
||||||
|
debug!("Deleting room's threads from database");
|
||||||
|
self.services
|
||||||
|
.threads
|
||||||
|
.delete_all_rooms_threads(&room_id)
|
||||||
|
.await
|
||||||
|
.log_err()
|
||||||
|
.ok();
|
||||||
|
|
||||||
|
debug!("Deleting all the room's search token IDs from our database");
|
||||||
|
self.services
|
||||||
|
.search
|
||||||
|
.delete_all_search_tokenids_for_room(&room_id)
|
||||||
|
.await
|
||||||
|
.log_err()
|
||||||
|
.ok();
|
||||||
|
|
||||||
|
debug!("Deleting all room's forward extremities from our database");
|
||||||
|
self.services
|
||||||
|
.state
|
||||||
|
.delete_all_rooms_forward_extremities(&room_id)
|
||||||
|
.await
|
||||||
|
.log_err()
|
||||||
|
.ok();
|
||||||
|
|
||||||
|
debug!("Deleting all the room's event (PDU) references");
|
||||||
|
self.services
|
||||||
|
.pdu_metadata
|
||||||
|
.delete_all_referenced_for_room(&room_id)
|
||||||
|
.await
|
||||||
|
.log_err()
|
||||||
|
.ok();
|
||||||
|
|
||||||
|
debug!("Deleting all the room's member counts");
|
||||||
|
self.services
|
||||||
|
.state_cache
|
||||||
|
.delete_room_join_counts(&room_id)
|
||||||
|
.await
|
||||||
|
.log_err()
|
||||||
|
.ok();
|
||||||
|
|
||||||
|
debug!("Deleting all the room's private read receipts");
|
||||||
|
self.services
|
||||||
|
.read_receipt
|
||||||
|
.delete_all_read_receipts(&room_id)
|
||||||
|
.await
|
||||||
|
.log_err()
|
||||||
|
.ok();
|
||||||
|
|
||||||
|
debug!("Final stages of deleting the room");
|
||||||
|
|
||||||
|
debug!("Obtaining a mutex state lock for safety and future database operations");
|
||||||
|
let state_lock = self.services.state.mutex.lock(&room_id).await;
|
||||||
|
|
||||||
|
debug!("Deleting room state hash from our database");
|
||||||
|
self.services
|
||||||
|
.state
|
||||||
|
.delete_room_shortstatehash(&room_id, &state_lock)
|
||||||
|
.await
|
||||||
|
.log_err()
|
||||||
|
.ok();
|
||||||
|
|
||||||
|
debug!("Deleting PDUs");
|
||||||
|
self.services
|
||||||
|
.timeline
|
||||||
|
.delete_pdus(&room_id)
|
||||||
|
.await
|
||||||
|
.log_err()
|
||||||
|
.ok();
|
||||||
|
|
||||||
|
debug!("Deleting internal room ID from our database");
|
||||||
|
self.services
|
||||||
|
.short
|
||||||
|
.delete_shortroomid(&room_id)
|
||||||
|
.await
|
||||||
|
.log_err()
|
||||||
|
.ok();
|
||||||
|
|
||||||
|
// TODO: add option to keep a room banned (`--block` or `--ban`)
|
||||||
|
self.services.metadata.enable_room(&room_id);
|
||||||
|
self.services.metadata.unban_room(&room_id);
|
||||||
|
|
||||||
|
drop(state_lock);
|
||||||
|
|
||||||
|
debug!("Successfully deleted room {} from our database", &room_id);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
pub mod alias;
|
pub mod alias;
|
||||||
pub mod auth_chain;
|
pub mod auth_chain;
|
||||||
|
pub mod delete;
|
||||||
pub mod directory;
|
pub mod directory;
|
||||||
pub mod event_handler;
|
pub mod event_handler;
|
||||||
pub mod lazy_loading;
|
pub mod lazy_loading;
|
||||||
|
|||||||
@@ -3,16 +3,18 @@ use std::{mem::size_of, sync::Arc};
|
|||||||
use futures::{Stream, StreamExt};
|
use futures::{Stream, StreamExt};
|
||||||
use ruma::{EventId, RoomId, UserId, api::Direction};
|
use ruma::{EventId, RoomId, UserId, api::Direction};
|
||||||
use tuwunel_core::{
|
use tuwunel_core::{
|
||||||
|
Result,
|
||||||
arrayvec::ArrayVec,
|
arrayvec::ArrayVec,
|
||||||
matrix::{Event, PduCount},
|
matrix::{Event, PduCount},
|
||||||
result::LogErr,
|
result::LogErr,
|
||||||
|
trace,
|
||||||
utils::{
|
utils::{
|
||||||
ReadyExt,
|
ReadyExt,
|
||||||
stream::{TryIgnore, WidebandExt},
|
stream::{TryIgnore, WidebandExt},
|
||||||
u64_from_u8,
|
u64_from_u8,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use tuwunel_database::Map;
|
use tuwunel_database::{Interfix, Map};
|
||||||
|
|
||||||
use crate::rooms::{
|
use crate::rooms::{
|
||||||
short::{ShortEventId, ShortRoomId},
|
short::{ShortEventId, ShortRoomId},
|
||||||
@@ -126,4 +128,20 @@ impl Data {
|
|||||||
.await
|
.await
|
||||||
.is_ok()
|
.is_ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(super) async fn delete_all_referenced_for_room(&self, room_id: &RoomId) -> Result {
|
||||||
|
let prefix = (room_id, Interfix);
|
||||||
|
|
||||||
|
self.referencedevents
|
||||||
|
.keys_prefix_raw(&prefix)
|
||||||
|
.ignore_err()
|
||||||
|
.ready_for_each(|key| {
|
||||||
|
trace!("Removing key: {key:?}");
|
||||||
|
self.referencedevents.remove(key);
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,4 +126,11 @@ impl Service {
|
|||||||
pub async fn is_event_soft_failed(&self, event_id: &EventId) -> bool {
|
pub async fn is_event_soft_failed(&self, event_id: &EventId) -> bool {
|
||||||
self.db.is_event_soft_failed(event_id).await
|
self.db.is_event_soft_failed(event_id).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(skip(self), level = "debug")]
|
||||||
|
pub async fn delete_all_referenced_for_room(&self, room_id: &RoomId) -> Result {
|
||||||
|
self.db
|
||||||
|
.delete_all_referenced_for_room(room_id)
|
||||||
|
.await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ use ruma::{
|
|||||||
serde::Raw,
|
serde::Raw,
|
||||||
};
|
};
|
||||||
use tuwunel_core::{
|
use tuwunel_core::{
|
||||||
Result,
|
Result, trace,
|
||||||
utils::{ReadyExt, stream::TryIgnore},
|
utils::{ReadyExt, stream::TryIgnore},
|
||||||
};
|
};
|
||||||
use tuwunel_database::{Deserialized, Json, Map};
|
use tuwunel_database::{Deserialized, Interfix, Json, Map};
|
||||||
|
|
||||||
pub(super) struct Data {
|
pub(super) struct Data {
|
||||||
roomuserid_privateread: Arc<Map>,
|
roomuserid_privateread: Arc<Map>,
|
||||||
@@ -120,4 +120,38 @@ impl Data {
|
|||||||
.deserialized()
|
.deserialized()
|
||||||
.unwrap_or(0)
|
.unwrap_or(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(super) async fn delete_all_read_receipts(&self, room_id: &RoomId) -> Result {
|
||||||
|
let prefix = (room_id, Interfix);
|
||||||
|
|
||||||
|
self.roomuserid_privateread
|
||||||
|
.keys_prefix_raw(&prefix)
|
||||||
|
.ignore_err()
|
||||||
|
.ready_for_each(|key| {
|
||||||
|
trace!("Removing key: {key:?}");
|
||||||
|
self.roomuserid_privateread.remove(key);
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
self.roomuserid_lastprivatereadupdate
|
||||||
|
.keys_prefix_raw(&prefix)
|
||||||
|
.ignore_err()
|
||||||
|
.ready_for_each(|key| {
|
||||||
|
trace!("Removing key: {key:?}");
|
||||||
|
self.roomuserid_lastprivatereadupdate.remove(key);
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
self.readreceiptid_readreceipt
|
||||||
|
.keys_prefix_raw(&prefix)
|
||||||
|
.ignore_err()
|
||||||
|
.ready_for_each(|key| {
|
||||||
|
trace!("Removing key: {key:?}");
|
||||||
|
self.readreceiptid_readreceipt.remove(key);
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,6 +145,10 @@ impl Service {
|
|||||||
.last_privateread_update(user_id, room_id)
|
.last_privateread_update(user_id, room_id)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn delete_all_read_receipts(&self, room_id: &RoomId) -> Result {
|
||||||
|
self.db.delete_all_read_receipts(room_id).await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
|||||||
@@ -7,12 +7,13 @@ use tuwunel_core::{
|
|||||||
arrayvec::ArrayVec,
|
arrayvec::ArrayVec,
|
||||||
implement,
|
implement,
|
||||||
matrix::event::{Event, Matches},
|
matrix::event::{Event, Matches},
|
||||||
|
trace,
|
||||||
utils::{
|
utils::{
|
||||||
ArrayVecExt, IterStream, ReadyExt, set,
|
ArrayVecExt, IterStream, ReadyExt, set,
|
||||||
stream::{TryIgnore, WidebandExt},
|
stream::{TryIgnore, WidebandExt},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use tuwunel_database::{Map, keyval::Val};
|
use tuwunel_database::{Interfix, Map, keyval::Val};
|
||||||
|
|
||||||
use crate::rooms::{
|
use crate::rooms::{
|
||||||
short::ShortRoomId,
|
short::ShortRoomId,
|
||||||
@@ -197,6 +198,23 @@ fn search_pdu_ids_query_word(
|
|||||||
.ready_take_while(move |key| key.starts_with(&prefix))
|
.ready_take_while(move |key| key.starts_with(&prefix))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[implement(Service)]
|
||||||
|
pub async fn delete_all_search_tokenids_for_room(&self, room_id: &RoomId) -> Result {
|
||||||
|
let prefix = (room_id, Interfix);
|
||||||
|
|
||||||
|
self.db
|
||||||
|
.tokenids
|
||||||
|
.keys_prefix_raw(&prefix)
|
||||||
|
.ignore_err()
|
||||||
|
.ready_for_each(|key| {
|
||||||
|
trace!("Removing key: {key:?}");
|
||||||
|
self.db.tokenids.remove(key);
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Splits a string into tokens used as keys in the search inverted index
|
/// Splits a string into tokens used as keys in the search inverted index
|
||||||
///
|
///
|
||||||
/// This may be used to tokenize both message bodies (for indexing) or search
|
/// This may be used to tokenize both message bodies (for indexing) or search
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use futures::{Stream, StreamExt};
|
|||||||
use ruma::{EventId, RoomId, events::StateEventType};
|
use ruma::{EventId, RoomId, events::StateEventType};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
pub use tuwunel_core::matrix::pdu::{ShortEventId, ShortId, ShortRoomId, ShortStateKey};
|
pub use tuwunel_core::matrix::pdu::{ShortEventId, ShortId, ShortRoomId, ShortStateKey};
|
||||||
use tuwunel_core::{Result, err, implement, matrix::StateKey, utils, utils::IterStream};
|
use tuwunel_core::{Err, Result, err, implement, matrix::StateKey, utils, utils::IterStream};
|
||||||
use tuwunel_database::{Deserialized, Get, Map, Qry};
|
use tuwunel_database::{Deserialized, Get, Map, Qry};
|
||||||
|
|
||||||
pub struct Service {
|
pub struct Service {
|
||||||
@@ -258,3 +258,19 @@ pub async fn get_or_create_shortroomid(&self, room_id: &RoomId) -> ShortRoomId {
|
|||||||
*short
|
*short
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[implement(Service)]
|
||||||
|
pub async fn delete_shortroomid(&self, room_id: &RoomId) -> Result {
|
||||||
|
if self
|
||||||
|
.db
|
||||||
|
.roomid_shortroomid
|
||||||
|
.exists(room_id)
|
||||||
|
.await
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
|
self.db.roomid_shortroomid.remove(room_id);
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err!(Database("not found"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,8 +16,10 @@ use tuwunel_core::{
|
|||||||
matrix::{RoomVersionRules, StateKey, TypeStateKey, room_version},
|
matrix::{RoomVersionRules, StateKey, TypeStateKey, room_version},
|
||||||
result::{AndThenRef, FlatOk},
|
result::{AndThenRef, FlatOk},
|
||||||
state_res::{StateMap, auth_types_for_event},
|
state_res::{StateMap, auth_types_for_event},
|
||||||
|
trace,
|
||||||
utils::{
|
utils::{
|
||||||
IterStream, MutexMap, MutexMapGuard, ReadyExt, calculate_hash,
|
IterStream, MutexMap, MutexMapGuard, ReadyExt, calculate_hash,
|
||||||
|
mutex_map::Guard,
|
||||||
stream::{BroadbandExt, TryIgnore},
|
stream::{BroadbandExt, TryIgnore},
|
||||||
},
|
},
|
||||||
warn,
|
warn,
|
||||||
@@ -523,4 +525,30 @@ impl Service {
|
|||||||
self.db.roomid_pduleaves.put_raw(key, event_id);
|
self.db.roomid_pduleaves.put_raw(key, event_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) async fn delete_all_rooms_forward_extremities(&self, room_id: &RoomId) -> Result {
|
||||||
|
let prefix = (room_id, Interfix);
|
||||||
|
|
||||||
|
self.db
|
||||||
|
.roomid_pduleaves
|
||||||
|
.keys_prefix_raw(&prefix)
|
||||||
|
.ignore_err()
|
||||||
|
.ready_for_each(|key| {
|
||||||
|
trace!("Removing key: {key:?}");
|
||||||
|
self.db.roomid_pduleaves.remove(key);
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) async fn delete_room_shortstatehash(
|
||||||
|
&self,
|
||||||
|
room_id: &RoomId,
|
||||||
|
_mutex_lock: &Guard<OwnedRoomId, ()>,
|
||||||
|
) -> Result {
|
||||||
|
self.db.roomid_shortstatehash.remove(room_id);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ use ruma::{
|
|||||||
use tuwunel_core::{
|
use tuwunel_core::{
|
||||||
Result, implement,
|
Result, implement,
|
||||||
result::LogErr,
|
result::LogErr,
|
||||||
|
trace,
|
||||||
utils::{ReadyExt, stream::TryIgnore},
|
utils::{ReadyExt, stream::TryIgnore},
|
||||||
warn,
|
warn,
|
||||||
};
|
};
|
||||||
@@ -562,3 +563,89 @@ pub async fn is_left(&self, user_id: &UserId, room_id: &RoomId) -> bool {
|
|||||||
.await
|
.await
|
||||||
.is_ok()
|
.is_ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[implement(Service)]
|
||||||
|
#[tracing::instrument(skip(self), level = "trace")]
|
||||||
|
pub async fn delete_room_join_counts(&self, room_id: &RoomId) -> Result {
|
||||||
|
let prefix = (room_id, Interfix);
|
||||||
|
|
||||||
|
self.db.roomid_knockedcount.remove(room_id);
|
||||||
|
|
||||||
|
self.db.roomid_invitedcount.remove(room_id);
|
||||||
|
|
||||||
|
self.db.roomid_inviteviaservers.remove(room_id);
|
||||||
|
|
||||||
|
self.db.roomid_joinedcount.remove(room_id);
|
||||||
|
|
||||||
|
self.db
|
||||||
|
.roomserverids
|
||||||
|
.keys_prefix(&prefix)
|
||||||
|
.ignore_err()
|
||||||
|
.ready_for_each(|key: (&RoomId, &ServerName)| {
|
||||||
|
trace!("Removing key: {key:?}");
|
||||||
|
self.db.roomserverids.del(key);
|
||||||
|
|
||||||
|
let reverse_key = (key.1, key.0);
|
||||||
|
trace!("Removing reverse key: {reverse_key:?}");
|
||||||
|
self.db.serverroomids.del(reverse_key);
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
self.db
|
||||||
|
.roomuserid_invitecount
|
||||||
|
.keys_prefix(&prefix)
|
||||||
|
.ignore_err()
|
||||||
|
.ready_for_each(|key: (&RoomId, &UserId)| {
|
||||||
|
trace!("Removing key: {key:?}");
|
||||||
|
self.db.roomuserid_invitecount.del(key);
|
||||||
|
|
||||||
|
let reverse_key = (key.1, key.0);
|
||||||
|
trace!("Removing reverse key: {reverse_key:?}");
|
||||||
|
self.db.userroomid_invitestate.del(reverse_key);
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
self.db
|
||||||
|
.roomuserid_joined
|
||||||
|
.keys_prefix(&prefix)
|
||||||
|
.ignore_err()
|
||||||
|
.ready_for_each(|key: (&RoomId, &UserId)| {
|
||||||
|
trace!("Removing key: {key:?}");
|
||||||
|
self.db.roomuserid_joined.del(key);
|
||||||
|
|
||||||
|
let reverse_key = (key.1, key.0);
|
||||||
|
trace!("Removing reverse key: {reverse_key:?}");
|
||||||
|
self.db.userroomid_joined.del(reverse_key);
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
self.db
|
||||||
|
.roomuserid_knockedcount
|
||||||
|
.keys_prefix(&prefix)
|
||||||
|
.ignore_err()
|
||||||
|
.ready_for_each(|key: (&RoomId, &UserId)| {
|
||||||
|
trace!("Removing key: {key:?}");
|
||||||
|
self.db.roomuserid_knockedcount.del(key);
|
||||||
|
|
||||||
|
let reverse_key = (key.1, key.0);
|
||||||
|
trace!("Removing reverse key: {reverse_key:?}");
|
||||||
|
self.db.userroomid_knockedstate.del(reverse_key);
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
self.db
|
||||||
|
.roomuserid_leftcount
|
||||||
|
.keys_prefix(&prefix)
|
||||||
|
.ignore_err()
|
||||||
|
.ready_for_each(|key: (&RoomId, &UserId)| {
|
||||||
|
trace!("Removing key: {key:?}");
|
||||||
|
self.db.roomuserid_leftcount.del(key);
|
||||||
|
|
||||||
|
let reverse_key = (key.1, key.0);
|
||||||
|
trace!("Removing reverse key: {reverse_key:?}");
|
||||||
|
self.db.userroomid_leftstate.del(reverse_key);
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,12 +9,13 @@ use serde_json::json;
|
|||||||
use tuwunel_core::{
|
use tuwunel_core::{
|
||||||
Event, Result, err,
|
Event, Result, err,
|
||||||
matrix::pdu::{PduCount, PduEvent, PduId, RawPduId},
|
matrix::pdu::{PduCount, PduEvent, PduId, RawPduId},
|
||||||
|
trace,
|
||||||
utils::{
|
utils::{
|
||||||
ReadyExt,
|
ReadyExt,
|
||||||
stream::{TryIgnore, WidebandExt},
|
stream::{TryIgnore, WidebandExt},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use tuwunel_database::{Deserialized, Map};
|
use tuwunel_database::{Deserialized, Interfix, Map};
|
||||||
|
|
||||||
pub struct Service {
|
pub struct Service {
|
||||||
db: Data,
|
db: Data,
|
||||||
@@ -191,4 +192,20 @@ impl Service {
|
|||||||
.await
|
.await
|
||||||
.deserialized()
|
.deserialized()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) async fn delete_all_rooms_threads(&self, room_id: &RoomId) -> Result {
|
||||||
|
let prefix = (room_id, Interfix);
|
||||||
|
|
||||||
|
self.db
|
||||||
|
.threadid_userids
|
||||||
|
.keys_prefix_raw(&prefix)
|
||||||
|
.ignore_err()
|
||||||
|
.ready_for_each(|key| {
|
||||||
|
trace!("Removing key: {key:?}");
|
||||||
|
self.db.threadid_userids.remove(key);
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ pub use tuwunel_core::matrix::pdu::{PduId, RawPduId};
|
|||||||
use tuwunel_core::{
|
use tuwunel_core::{
|
||||||
Err, Result, at, err, implement,
|
Err, Result, at, err, implement,
|
||||||
matrix::pdu::{PduCount, PduEvent},
|
matrix::pdu::{PduCount, PduEvent},
|
||||||
|
trace,
|
||||||
utils::{
|
utils::{
|
||||||
MutexMap, MutexMapGuard,
|
MutexMap, MutexMapGuard,
|
||||||
result::{LogErr, NotFound},
|
result::{LogErr, NotFound},
|
||||||
@@ -413,3 +414,30 @@ pub async fn get_pdu_id(&self, event_id: &EventId) -> Result<RawPduId> {
|
|||||||
.await
|
.await
|
||||||
.map(|handle| RawPduId::from(&*handle))
|
.map(|handle| RawPduId::from(&*handle))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[implement(Service)]
|
||||||
|
pub async fn delete_pdus(&self, room_id: &RoomId) -> Result {
|
||||||
|
self.count_to_id(room_id, PduCount::min(), Direction::Forward)
|
||||||
|
.map_ok(move |current| {
|
||||||
|
let prefix = current.shortroomid();
|
||||||
|
self.db
|
||||||
|
.pduid_pdu
|
||||||
|
.raw_stream_from(¤t)
|
||||||
|
.ready_try_take_while(move |(key, _)| Ok(key.starts_with(&prefix)))
|
||||||
|
.ready_try_for_each(|(key, value)| {
|
||||||
|
trace!("Removing PDU {key:?}");
|
||||||
|
self.db.pduid_pdu.remove(key);
|
||||||
|
let pdu = serde_json::from_slice::<PduEvent>(value)?;
|
||||||
|
|
||||||
|
let event_id = &pdu.event_id;
|
||||||
|
let room_id2 = &pdu.room_id;
|
||||||
|
trace!("Removed {event_id} {room_id2}");
|
||||||
|
self.db.eventid_pduid.remove(event_id);
|
||||||
|
self.db.eventid_outlierpdu.remove(event_id);
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.try_flatten()
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ pub struct Services {
|
|||||||
pub resolver: Arc<resolver::Service>,
|
pub resolver: Arc<resolver::Service>,
|
||||||
pub alias: Arc<rooms::alias::Service>,
|
pub alias: Arc<rooms::alias::Service>,
|
||||||
pub auth_chain: Arc<rooms::auth_chain::Service>,
|
pub auth_chain: Arc<rooms::auth_chain::Service>,
|
||||||
|
pub delete: Arc<rooms::delete::Service>,
|
||||||
pub directory: Arc<rooms::directory::Service>,
|
pub directory: Arc<rooms::directory::Service>,
|
||||||
pub event_handler: Arc<rooms::event_handler::Service>,
|
pub event_handler: Arc<rooms::event_handler::Service>,
|
||||||
pub lazy_loading: Arc<rooms::lazy_loading::Service>,
|
pub lazy_loading: Arc<rooms::lazy_loading::Service>,
|
||||||
@@ -112,6 +113,7 @@ impl Services {
|
|||||||
pusher: build!(pusher::Service),
|
pusher: build!(pusher::Service),
|
||||||
alias: build!(rooms::alias::Service),
|
alias: build!(rooms::alias::Service),
|
||||||
auth_chain: build!(rooms::auth_chain::Service),
|
auth_chain: build!(rooms::auth_chain::Service),
|
||||||
|
delete: build!(rooms::delete::Service),
|
||||||
directory: build!(rooms::directory::Service),
|
directory: build!(rooms::directory::Service),
|
||||||
event_handler: build!(rooms::event_handler::Service),
|
event_handler: build!(rooms::event_handler::Service),
|
||||||
lazy_loading: build!(rooms::lazy_loading::Service),
|
lazy_loading: build!(rooms::lazy_loading::Service),
|
||||||
@@ -189,7 +191,7 @@ impl Services {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn services(&self) -> [Arc<dyn Service>; 40] {
|
pub(crate) fn services(&self) -> [Arc<dyn Service>; 41] {
|
||||||
[
|
[
|
||||||
self.account_data.clone(),
|
self.account_data.clone(),
|
||||||
self.admin.clone(),
|
self.admin.clone(),
|
||||||
@@ -205,6 +207,7 @@ impl Services {
|
|||||||
self.pusher.clone(),
|
self.pusher.clone(),
|
||||||
self.alias.clone(),
|
self.alias.clone(),
|
||||||
self.auth_chain.clone(),
|
self.auth_chain.clone(),
|
||||||
|
self.delete.clone(),
|
||||||
self.directory.clone(),
|
self.directory.clone(),
|
||||||
self.event_handler.clone(),
|
self.event_handler.clone(),
|
||||||
self.lazy_loading.clone(),
|
self.lazy_loading.clone(),
|
||||||
|
|||||||
Reference in New Issue
Block a user