#![warn(clippy::missing_docs_in_private_items)] //! Implementation of the `delete-room` subcommand 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"); }