#![warn(clippy::missing_docs_in_private_items)] //! Implementation of the `get-room-states` command use std::{cmp::Ordering, sync::Arc}; use ruma::events::StateEventType; use serde::Serialize; use super::GetRoomStatesArgs; use crate::{ config, database::KeyValueDatabase, error, services, PduEvent, Services, }; mod cache; mod recompute; /// Serializable information about a state event #[derive(Serialize, PartialEq, Eq)] struct StateEvent { /// The kind of state event kind: StateEventType, /// The `state_key` of the event key: String, /// The event itself event: Arc, } impl Ord for StateEvent { fn cmp(&self, other: &Self) -> Ordering { Ordering::Equal .then_with(|| self.event.room_id.cmp(&other.event.room_id)) .then_with(|| self.kind.cmp(&other.kind)) .then_with(|| self.key.cmp(&other.key)) .then_with(|| self.event.event_id.cmp(&other.event.event_id)) } } impl PartialOrd for StateEvent { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } /// Subcommand entrypoint pub(crate) async fn run( args: GetRoomStatesArgs, ) -> Result<(), error::DumpStateCommand> { use error::DumpStateCommand as Error; let config = config::load(args.config.config.as_ref()).await?; let db = Box::leak(Box::new( KeyValueDatabase::load_or_create(&config).map_err(Error::Database)?, )); Services::new(db, config, None) .map_err(Error::InitializeServices)? .install(); services().globals.err_if_server_name_changed()?; db.apply_migrations().await.map_err(Error::Database)?; let room_states = if args.recompute { recompute::get_room_states(db) } else { cache::get_room_states().await }; serde_json::to_writer(std::io::stdout(), &room_states)?; Ok(()) }