improvement: optimize state storage

This commit is contained in:
Timo Kösters 2021-03-17 22:30:25 +01:00
parent 44425a903a
commit 100307c936
No known key found for this signature in database
GPG key ID: 24DA7517711A2BA4
9 changed files with 341 additions and 254 deletions

View file

@ -106,7 +106,6 @@ pub async fn leave_room_route(
ErrorKind::BadState,
"Cannot leave a room you are not a member of.",
))?
.1
.content,
)
.expect("from_value::<Raw<..>> can never fail")
@ -195,7 +194,6 @@ pub async fn kick_user_route(
ErrorKind::BadState,
"Cannot kick member that's not in the room.",
))?
.1
.content,
)
.expect("Raw::from_value always works")
@ -251,7 +249,7 @@ pub async fn ban_user_route(
is_direct: None,
third_party_invite: None,
}),
|(_, event)| {
|event| {
let mut event =
serde_json::from_value::<Raw<member::MemberEventContent>>(event.content)
.expect("Raw::from_value always works")
@ -302,7 +300,6 @@ pub async fn unban_user_route(
ErrorKind::BadState,
"Cannot unban a user who is not banned.",
))?
.1
.content,
)
.expect("from_value::<Raw<..>> can never fail")
@ -617,10 +614,7 @@ async fn join_room_by_id_helper(
&db.globals,
)?;
}
let mut long_id = room_id.as_bytes().to_vec();
long_id.push(0xff);
long_id.extend_from_slice(id.as_bytes());
state.insert((pdu.kind.clone(), state_key.clone()), long_id);
state.insert((pdu.kind.clone(), state_key.clone()), pdu.event_id.clone());
}
}
@ -629,7 +623,7 @@ async fn join_room_by_id_helper(
pdu.kind.clone(),
pdu.state_key.clone().expect("join event has state key"),
),
pdu_id.clone(),
pdu.event_id.clone(),
);
db.rooms.force_state(room_id, state, &db.globals)?;

View file

@ -49,7 +49,6 @@ pub async fn set_displayname_route(
"Tried to send displayname update for user not in the room.",
)
})?
.1
.content
.clone(),
)
@ -144,7 +143,6 @@ pub async fn set_avatar_url_route(
"Tried to send avatar url update for user not in the room.",
)
})?
.1
.content
.clone(),
)

View file

@ -380,7 +380,6 @@ pub async fn upgrade_room_route(
db.rooms
.room_state_get(&body.room_id, &EventType::RoomCreate, "")?
.ok_or_else(|| Error::bad_database("Found room without m.room.create event."))?
.1
.content,
)
.expect("Raw::from_value always works")
@ -452,7 +451,7 @@ pub async fn upgrade_room_route(
// Replicate transferable state events to the new room
for event_type in transferable_state_events {
let event_content = match db.rooms.room_state_get(&body.room_id, &event_type, "")? {
Some((_, v)) => v.content.clone(),
Some(v) => v.content.clone(),
None => continue, // Skipping missing events.
};
@ -482,7 +481,6 @@ pub async fn upgrade_room_route(
db.rooms
.room_state_get(&body.room_id, &EventType::RoomPowerLevels, "")?
.ok_or_else(|| Error::bad_database("Found room without m.room.create event."))?
.1
.content,
)
.expect("database contains invalid PDU")

View file

@ -112,7 +112,7 @@ pub async fn get_state_events_route(
&& !matches!(
db.rooms
.room_state_get(&body.room_id, &EventType::RoomHistoryVisibility, "")?
.map(|(_, event)| {
.map(|event| {
serde_json::from_value::<HistoryVisibilityEventContent>(event.content)
.map_err(|_| {
Error::bad_database(
@ -159,7 +159,7 @@ pub async fn get_state_events_for_key_route(
&& !matches!(
db.rooms
.room_state_get(&body.room_id, &EventType::RoomHistoryVisibility, "")?
.map(|(_, event)| {
.map(|event| {
serde_json::from_value::<HistoryVisibilityEventContent>(event.content)
.map_err(|_| {
Error::bad_database(
@ -183,8 +183,7 @@ pub async fn get_state_events_for_key_route(
.ok_or(Error::BadRequest(
ErrorKind::NotFound,
"State event not found.",
))?
.1;
))?;
Ok(get_state_events_for_key::Response {
content: serde_json::value::to_raw_value(&event.content)
@ -211,7 +210,7 @@ pub async fn get_state_events_for_empty_key_route(
&& !matches!(
db.rooms
.room_state_get(&body.room_id, &EventType::RoomHistoryVisibility, "")?
.map(|(_, event)| {
.map(|event| {
serde_json::from_value::<HistoryVisibilityEventContent>(event.content)
.map_err(|_| {
Error::bad_database(
@ -235,8 +234,7 @@ pub async fn get_state_events_for_empty_key_route(
.ok_or(Error::BadRequest(
ErrorKind::NotFound,
"State event not found.",
))?
.1;
))?;
Ok(get_state_events_for_empty_key::Response {
content: serde_json::value::to_raw_value(&event.content)

View file

@ -96,7 +96,7 @@ pub async fn sync_events_route(
// Database queries:
let current_state_hash = db.rooms.current_state_hash(&room_id)?;
let current_shortstatehash = db.rooms.current_shortstatehash(&room_id)?;
// These type is Option<Option<_>>. The outer Option is None when there is no event between
// since and the current room state, meaning there should be no updates.
@ -109,9 +109,11 @@ pub async fn sync_events_route(
.next()
.is_some();
let since_state_hash = first_pdu_before_since
.as_ref()
.map(|pdu| db.rooms.pdu_state_hash(&pdu.as_ref().ok()?.0).ok()?);
let since_shortstatehash = first_pdu_before_since.as_ref().map(|pdu| {
db.rooms
.pdu_shortstatehash(&pdu.as_ref().ok()?.1.event_id)
.ok()?
});
let (
heroes,
@ -119,7 +121,7 @@ pub async fn sync_events_route(
invited_member_count,
joined_since_last_sync,
state_events,
) = if pdus_after_since && Some(&current_state_hash) != since_state_hash.as_ref() {
) = if pdus_after_since && Some(current_shortstatehash) != since_shortstatehash {
let current_state = db.rooms.room_state_full(&room_id)?;
let current_members = current_state
.iter()
@ -129,11 +131,18 @@ pub async fn sync_events_route(
let encrypted_room = current_state
.get(&(EventType::RoomEncryption, "".to_owned()))
.is_some();
let since_state = since_state_hash.as_ref().map(|state_hash| {
state_hash
.as_ref()
.and_then(|state_hash| db.rooms.state_full(&room_id, &state_hash).ok())
});
let since_state = since_shortstatehash
.as_ref()
.map(|since_shortstatehash| {
Ok::<_, Error>(
since_shortstatehash
.map(|since_shortstatehash| {
db.rooms.state_full(&room_id, since_shortstatehash)
})
.transpose()?,
)
})
.transpose()?;
let since_encryption = since_state.as_ref().map(|state| {
state
@ -496,16 +505,16 @@ pub async fn sync_events_route(
.and_then(|pdu| pdu.ok())
.and_then(|pdu| {
db.rooms
.pdu_state_hash(&pdu.0)
.pdu_shortstatehash(&pdu.1.event_id)
.ok()?
.ok_or_else(|| Error::bad_database("Pdu in db doesn't have a state hash."))
.ok()
})
.and_then(|state_hash| {
.and_then(|shortstatehash| {
db.rooms
.state_get(
&room_id,
&state_hash,
shortstatehash,
&EventType::RoomMember,
sender_user.as_str(),
)
@ -513,14 +522,14 @@ pub async fn sync_events_route(
.ok_or_else(|| Error::bad_database("State hash in db doesn't have a state."))
.ok()
})
.and_then(|(pdu_id, pdu)| {
.and_then(|pdu| {
serde_json::from_value::<Raw<ruma::events::room::member::MemberEventContent>>(
pdu.content.clone(),
)
.expect("Raw::from_value always works")
.deserialize()
.map_err(|_| Error::bad_database("Invalid PDU in database."))
.map(|content| (pdu_id, pdu, content))
.map(|content| (pdu, content))
.ok()
}) {
since_member
@ -529,7 +538,7 @@ pub async fn sync_events_route(
continue;
};
let left_since_last_sync = since_member.2.membership == MembershipState::Join;
let left_since_last_sync = since_member.1.membership == MembershipState::Join;
let left_room = if left_since_last_sync {
device_list_left.extend(
@ -550,10 +559,10 @@ pub async fn sync_events_route(
let pdus = db.rooms.pdus_since(&sender_user, &room_id, since)?;
let mut room_events = pdus
.filter_map(|pdu| pdu.ok()) // Filter out buggy events
.take_while(|(pdu_id, _)| since_member.0 != pdu_id)
.take_while(|(pdu_id, pdu)| &since_member.0 != pdu)
.map(|(_, pdu)| pdu.to_sync_room_event())
.collect::<Vec<_>>();
room_events.push(since_member.1.to_sync_room_event());
room_events.push(since_member.0.to_sync_room_event());
sync_events::LeftRoom {
account_data: sync_events::AccountData { events: Vec::new() },