diff --git a/src/cli/delete_room.rs b/src/cli/delete_room.rs index e5fc677b..65ee6f5c 100644 --- a/src/cli/delete_room.rs +++ b/src/cli/delete_room.rs @@ -4,9 +4,94 @@ use std::error::Error; +use ruma::RoomId; +use tracing as t; + use super::DeleteRoomArgs; +use crate::{ + config, database::KeyValueDatabase, services, utils, PduEvent, Services, +}; /// Subcommand entrypoint pub(crate) async fn run(args: DeleteRoomArgs) -> Result<(), Box> { + let config = config::load(args.config.config.as_ref()).await?; + + let db = Box::leak(Box::new(KeyValueDatabase::load_or_create(&config)?)); + + Services::build(db, config, None)?.install(); + + services().globals.err_if_server_name_changed()?; + + db.apply_migrations().await?; + + pdus(db, &args.room_id); + Ok(()) } + +/// Delete PDUs +fn pdus(db: &KeyValueDatabase, room_id: &RoomId) { + let mut count = 0_usize; + + let filter_map = |(k, v): (Vec, Vec)| { + let pdu = match serde_json::from_slice::(&v) { + Ok(x) => x, + Err(error) => { + t::warn!( + %error, + key = utils::u8_slice_to_hex(&k), + "Failed to deserialize PDU, skipping it", + ); + return None; + } + }; + + if pdu.room_id != room_id { + return None; + } + + Some((k, pdu)) + }; + + // Accepted PDUs + for (k, v) in db.pduid_pdu.iter().filter_map(filter_map) { + if let Err(error) = db.eventid_pduid.remove(v.event_id.as_bytes()) { + t::warn!( + %error, + key = utils::u8_slice_to_hex(&k), + "Failed to delete event ID to PDU ID relationship", + ); + + continue; + } + + if let Err(error) = db.pduid_pdu.remove(&k) { + t::warn!( + %error, + key = utils::u8_slice_to_hex(&k), + "Failed to delete PDU", + ); + + continue; + } + + count += 1; + } + + // Outlier PDUs + for (k, _) in db.eventid_outlierpdu.iter().filter_map(filter_map) { + if let Err(error) = db.eventid_outlierpdu.remove(&k) { + t::warn!( + %error, + key = utils::u8_slice_to_hex(&k), + "Failed to delete PDU", + ); + + continue; + } + + count += 1; + } + + t::info!(count, "Deleted PDUs"); +}