actually, just copy dump-state

This commit is contained in:
Charles Hall 2024-11-02 12:46:22 -07:00
parent 4e1691fc9d
commit 346ee5cd81
No known key found for this signature in database
GPG key ID: 7B8E0645816E07CF

View file

@ -3,6 +3,7 @@
//! Implementation of the `repair` subcommand //! Implementation of the `repair` subcommand
use std::{ use std::{
cmp::Ordering as CmpOrdering,
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
error::Error, error::Error,
sync::{ sync::{
@ -18,23 +19,43 @@ use petgraph::{
}; };
use rayon::iter::{IntoParallelIterator, ParallelIterator}; use rayon::iter::{IntoParallelIterator, ParallelIterator};
use ruma::{ use ruma::{
events::{ events::{StateEventType, TimelineEventType},
room::member::MembershipState, StateEventType, TimelineEventType,
},
state_res::StateMap, state_res::StateMap,
EventId, RoomId, RoomVersionId, UserId, EventId, RoomId, RoomVersionId, UserId,
}; };
use serde::Deserialize; use serde::{Deserialize, Serialize};
use tracing as t; use tracing as t;
use super::RepairArgs; use super::RepairArgs;
use crate::{config, database::KeyValueDatabase, utils, PduEvent}; use crate::{config, database::KeyValueDatabase, utils, PduEvent};
/// Extractor to read just the membership state /// Serializable information about a state event
#[derive(Deserialize)] #[derive(Serialize, PartialEq, Eq)]
struct ExtractMembership { struct StateEvent {
/// Membership state /// The kind of state event
membership: MembershipState, kind: StateEventType,
/// The `state_key` of the event
key: String,
/// The event itself
event: Arc<PduEvent>,
}
impl Ord for StateEvent {
fn cmp(&self, other: &Self) -> CmpOrdering {
CmpOrdering::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<CmpOrdering> {
Some(self.cmp(other))
}
} }
/// Extractor to read just the `room_version` field /// Extractor to read just the `room_version` field
@ -69,91 +90,43 @@ pub(crate) async fn run(args: RepairArgs) -> Result<(), Box<dyn Error>> {
let states = resolve_room_states(&db, graphs); let states = resolve_room_states(&db, graphs);
repair_roomuserid_joined(&db, &states)?; let mut serializable_state = Vec::new();
t::info!("Done"); for (_, state) in states {
serializable_state.extend(state.into_iter().filter_map(
Ok(()) |((kind, key), event)| {
} let event = match get_either_pdu_by_event_id(&db, &event) {
Ok(Some(x)) => Arc::new(x),
/// Repair the `roomuserid_joined` map Ok(None) => {
#[t::instrument(skip(db, states))] t::warn!(event_id = %event, "Unknown event, omitting");
fn repair_roomuserid_joined( return None;
db: &KeyValueDatabase, }
states: &HashMap<Arc<RoomId>, StateMap<Arc<EventId>>>,
) -> Result<(), Box<dyn Error>> {
t::info!(
length = db.roomuserid_joined.iter().count(),
"Original length of map",
);
db.roomuserid_joined.clear()?;
for (room_id, state) in states {
let states =
state.iter().filter_map(|((kind, key), id)| {
if *kind != StateEventType::RoomMember {
return None;
}
let user_id = UserId::parse(key).inspect_err(|error| {
t::error!(
%error,
%key,
event_id = %id,
"Failed to parse m.room.member state key as user ID",
);
}).ok()?;
let pdu = get_accepted_pdu_by_event_id(db, id).ok()??;
let membership = match serde_json::from_str(pdu.content.get()) {
Ok(ExtractMembership {
membership,
}) => membership,
Err(error) => { Err(error) => {
t::warn!( t::warn!(
%error, %error,
event_id = %id, event_id = %event,
"Failed to deserialize PDU content", "Failed to get event, omitting",
); );
return None; return None;
} }
}; };
Some((user_id, membership)) let x = StateEvent {
}); kind,
key,
event,
};
for (user_id, membership) in states { Some(x)
let is_joined = match membership { },
MembershipState::Invite ));
| MembershipState::Ban
| MembershipState::Leave => false,
MembershipState::Join => true,
state => {
t::warn!(
%room_id,
%user_id,
%state,
"Unsupported membership state",
);
false
}
};
if !is_joined {
continue;
}
let key = [room_id.as_bytes(), user_id.as_bytes()].join(&0xFF);
db.roomuserid_joined.insert(&key, &[])?;
}
} }
t::info!(length = db.roomuserid_joined.iter().count(), "New length of map"); serializable_state.sort_unstable();
serde_json::to_writer(std::io::stdout(), &serializable_state)?;
t::info!("Done");
Ok(()) Ok(())
} }