Files
continuwuity/src/service/rooms/event_handler/fetch_state.rs
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

85 lines
2.2 KiB
Rust
Raw Normal View History

use std::collections::{HashMap, hash_map};
2024-11-08 07:30:52 +00:00
use conduwuit::{Err, Event, Result, debug, debug_warn, err, implement};
2024-11-08 07:30:52 +00:00
use futures::FutureExt;
use ruma::{
EventId, OwnedEventId, RoomId, ServerName, api::federation::event::get_room_state_ids,
events::StateEventType,
2024-11-08 07:30:52 +00:00
};
use crate::rooms::short::ShortStateKey;
2024-11-08 07:30:52 +00:00
/// Call /state_ids to find out what the state at this pdu is. We trust the
/// server's response to some extend (sic), but we still do a lot of checks
/// on the events
#[implement(super::Service)]
2025-01-02 05:30:51 +00:00
#[tracing::instrument(
2025-01-14 05:20:42 +00:00
level = "debug",
2025-01-02 05:30:51 +00:00
skip_all,
fields(%origin),
)]
pub(super) async fn fetch_state<Pdu>(
&self,
origin: &ServerName,
create_event: &Pdu,
room_id: &RoomId,
2024-11-08 07:30:52 +00:00
event_id: &EventId,
) -> Result<Option<HashMap<u64, OwnedEventId>>>
where
Pdu: Event + Send + Sync,
{
2024-11-08 07:30:52 +00:00
let res = self
.services
.sending
.send_federation_request(origin, get_room_state_ids::v1::Request {
room_id: room_id.to_owned(),
event_id: event_id.to_owned(),
})
2024-11-08 07:30:52 +00:00
.await
2025-01-02 05:30:51 +00:00
.inspect_err(|e| debug_warn!("Fetching state for event failed: {e}"))?;
2024-11-08 07:30:52 +00:00
debug!("Fetching state events");
let state_ids = res.pdu_ids.iter().map(AsRef::as_ref);
2024-11-08 07:30:52 +00:00
let state_vec = self
.fetch_and_handle_outliers(origin, state_ids, create_event, room_id)
2024-11-08 07:30:52 +00:00
.boxed()
.await;
let mut state: HashMap<ShortStateKey, OwnedEventId> = HashMap::with_capacity(state_vec.len());
2024-11-08 07:30:52 +00:00
for (pdu, _) in state_vec {
let state_key = pdu
.state_key()
.ok_or_else(|| err!(Database("Found non-state pdu in state events.")))?;
2024-11-08 07:30:52 +00:00
let shortstatekey = self
.services
.short
.get_or_create_shortstatekey(&pdu.kind().to_string().into(), state_key)
2024-11-08 07:30:52 +00:00
.await;
match state.entry(shortstatekey) {
| hash_map::Entry::Vacant(v) => {
v.insert(pdu.event_id().to_owned());
2024-11-08 07:30:52 +00:00
},
2025-03-02 23:15:05 -05:00
| hash_map::Entry::Occupied(_) => {
return Err!(Database(
2024-11-08 07:30:52 +00:00
"State event's type and state_key combination exists multiple times.",
2025-03-02 23:15:05 -05:00
));
},
2024-11-08 07:30:52 +00:00
}
}
// The original create event must still be in the state
let create_shortstatekey = self
.services
.short
.get_shortstatekey(&StateEventType::RoomCreate, "")
.await?;
if state.get(&create_shortstatekey).map(AsRef::as_ref) != Some(create_event.event_id()) {
2024-11-08 07:30:52 +00:00
return Err!(Database("Incoming event refers to wrong create event."));
}
Ok(Some(state))
}