fix: fetch more than one prev event

next
Timo Kösters 2021-08-14 21:56:15 +02:00
parent 1d46569929
commit ecd1e45a44
No known key found for this signature in database
GPG Key ID: 356E705610F626D5
1 changed files with 389 additions and 356 deletions

View File

@ -867,17 +867,19 @@ pub async fn handle_incoming_pdu<'a>(
.map_err(|_| "Failed to ask database for event.".to_owned())? .map_err(|_| "Failed to ask database for event.".to_owned())?
.ok_or_else(|| "Failed to find create event in db.".to_owned())?; .ok_or_else(|| "Failed to find create event in db.".to_owned())?;
let (incoming_pdu, val) = handle_outlier_pdu(origin, &create_event, event_id, room_id, value, db, pub_key_map).await?; let (incoming_pdu, val) = handle_outlier_pdu(
origin,
&create_event,
event_id,
room_id,
value,
db,
pub_key_map,
)
.await?;
// 8. if not timeline event: stop // 8. if not timeline event: stop
if !is_timeline_event if !is_timeline_event {
|| incoming_pdu.origin_server_ts
< db.rooms
.first_pdu_in_room(&room_id)
.map_err(|_| "Error loading first room event.".to_owned())?
.expect("Room exists")
.origin_server_ts
{
return Ok(None); return Ok(None);
} }
@ -893,16 +895,45 @@ pub async fn handle_incoming_pdu<'a>(
&room_id, &room_id,
pub_key_map, pub_key_map,
) )
.await.pop() { .await
.pop()
{
if incoming_pdu.origin_server_ts
> db.rooms
.first_pdu_in_room(&room_id)
.map_err(|_| "Error loading first room event.".to_owned())?
.expect("Room exists")
.origin_server_ts
{
todo_outlier_stack.extend(pdu.prev_events.iter().cloned());
todo_timeline_stack.push((pdu, json)); todo_timeline_stack.push((pdu, json));
} }
} }
}
while let Some(prev) = todo_timeline_stack.pop() { while let Some(prev) = todo_timeline_stack.pop() {
upgrade_outlier_to_timeline_pdu(prev.0, prev.1, &create_event, origin, db, room_id, pub_key_map).await?; upgrade_outlier_to_timeline_pdu(
prev.0,
prev.1,
&create_event,
origin,
db,
room_id,
pub_key_map,
)
.await?;
} }
upgrade_outlier_to_timeline_pdu(incoming_pdu, val, &create_event, origin, db, room_id, pub_key_map).await upgrade_outlier_to_timeline_pdu(
incoming_pdu,
val,
&create_event,
origin,
db,
room_id,
pub_key_map,
)
.await
} }
fn handle_outlier_pdu<'a>( fn handle_outlier_pdu<'a>(
@ -913,7 +944,8 @@ fn handle_outlier_pdu<'a>(
value: BTreeMap<String, CanonicalJsonValue>, value: BTreeMap<String, CanonicalJsonValue>,
db: &'a Database, db: &'a Database,
pub_key_map: &'a RwLock<BTreeMap<String, BTreeMap<String, String>>>, pub_key_map: &'a RwLock<BTreeMap<String, BTreeMap<String, String>>>,
) -> AsyncRecursiveType<'a, StdResult<(Arc<PduEvent>, BTreeMap<String, CanonicalJsonValue>), String>> { ) -> AsyncRecursiveType<'a, StdResult<(Arc<PduEvent>, BTreeMap<String, CanonicalJsonValue>), String>>
{
Box::pin(async move { Box::pin(async move {
let start_time = Instant::now(); let start_time = Instant::now();
@ -1062,9 +1094,8 @@ fn handle_outlier_pdu<'a>(
.map_err(|_| "Failed to add pdu as outlier.".to_owned())?; .map_err(|_| "Failed to add pdu as outlier.".to_owned())?;
debug!("Added pdu as outlier."); debug!("Added pdu as outlier.");
Ok((incoming_pdu,val)) Ok((incoming_pdu, val))
}) })
} }
async fn upgrade_outlier_to_timeline_pdu( async fn upgrade_outlier_to_timeline_pdu(
@ -1107,7 +1138,7 @@ async fn upgrade_outlier_to_timeline_pdu(
) )
.await .await
.into_iter() .into_iter()
.map(|(pdu,_)| { .map(|(pdu, _)| {
( (
( (
pdu.kind.clone(), pdu.kind.clone(),
@ -1120,7 +1151,8 @@ async fn upgrade_outlier_to_timeline_pdu(
}) })
.collect::<HashMap<_, _>>(); .collect::<HashMap<_, _>>();
let prev_pdu = db.rooms.get_pdu(prev_event).ok().flatten().ok_or_else(|| { let prev_pdu =
db.rooms.get_pdu(prev_event).ok().flatten().ok_or_else(|| {
"Could not find prev event, but we know the state.".to_owned() "Could not find prev event, but we know the state.".to_owned()
})?; })?;
@ -1163,15 +1195,19 @@ async fn upgrade_outlier_to_timeline_pdu(
let mut state = HashMap::new(); let mut state = HashMap::new();
for (pdu, _) in state_vec { for (pdu, _) in state_vec {
match state.entry((pdu.kind.clone(), pdu.state_key.clone().ok_or_else(|| "Found non-state pdu in state events.".to_owned())?)) { match state.entry((
pdu.kind.clone(),
pdu.state_key
.clone()
.ok_or_else(|| "Found non-state pdu in state events.".to_owned())?,
)) {
Entry::Vacant(v) => { Entry::Vacant(v) => {
v.insert(pdu); v.insert(pdu);
} }
Entry::Occupied(_) => { Entry::Occupied(_) => return Err(
return Err( "State event's type and state_key combination exists multiple times."
"State event's type and state_key combination exists multiple times.".to_owned(), .to_owned(),
) ),
}
} }
} }
@ -1228,7 +1264,6 @@ async fn upgrade_outlier_to_timeline_pdu(
None None
}; };
if !state_res::event_auth::auth_check( if !state_res::event_auth::auth_check(
&room_version, &room_version,
&incoming_pdu, &incoming_pdu,
@ -1535,9 +1570,7 @@ pub(crate) fn fetch_and_handle_outliers<'a>(
) )
.await .await
{ {
Ok((pdu, json)) => { Ok((pdu, json)) => (pdu, Some(json)),
(pdu, Some(json))
}
Err(e) => { Err(e) => {
warn!("Authentication of event {} failed: {:?}", id, e); warn!("Authentication of event {} failed: {:?}", id, e);
back_off(id.clone()); back_off(id.clone());