From 5d691f405eb6cb13f40ec420b5fe99d99fe5feb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20K=C3=B6sters?= Date: Sun, 30 Oct 2022 21:22:32 +0100 Subject: [PATCH 1/2] fix: stuck typing indicators --- src/database/key_value/rooms/edus/typing.rs | 43 +++++++++++++++++++++ src/service/rooms/edus/typing/data.rs | 3 ++ src/service/rooms/edus/typing/mod.rs | 42 ++------------------ 3 files changed, 49 insertions(+), 39 deletions(-) diff --git a/src/database/key_value/rooms/edus/typing.rs b/src/database/key_value/rooms/edus/typing.rs index 4a2f0f96..d50c000c 100644 --- a/src/database/key_value/rooms/edus/typing.rs +++ b/src/database/key_value/rooms/edus/typing.rs @@ -1,4 +1,5 @@ use std::collections::HashSet; +use std::mem; use ruma::{OwnedUserId, RoomId, UserId}; @@ -53,6 +54,48 @@ impl service::rooms::edus::typing::Data for KeyValueDatabase { Ok(()) } + fn typings_maintain( + &self, + room_id: &RoomId, + ) -> Result<()> { + let mut prefix = room_id.as_bytes().to_vec(); + prefix.push(0xff); + + let current_timestamp = utils::millis_since_unix_epoch(); + + let mut found_outdated = false; + + // Find all outdated edus before inserting a new one + for outdated_edu in self + .typingid_userid + .scan_prefix(prefix) + .map(|(key, _)| { + Ok::<_, Error>(( + key.clone(), + utils::u64_from_bytes( + &key.splitn(2, |&b| b == 0xff).nth(1).ok_or_else(|| { + Error::bad_database("RoomTyping has invalid timestamp or delimiters.") + })?[0..mem::size_of::()], + ) + .map_err(|_| Error::bad_database("RoomTyping has invalid timestamp bytes."))?, + )) + }) + .filter_map(|r| r.ok()) + .take_while(|&(_, timestamp)| timestamp < current_timestamp) + { + // This is an outdated edu (time > timestamp) + self.typingid_userid.remove(&outdated_edu.0)?; + found_outdated = true; + } + + if found_outdated { + self.roomid_lasttypingupdate + .insert(room_id.as_bytes(), &services().globals.next_count()?.to_be_bytes())?; + } + + Ok(()) + } + fn last_typing_update(&self, room_id: &RoomId) -> Result { Ok(self .roomid_lasttypingupdate diff --git a/src/service/rooms/edus/typing/data.rs b/src/service/rooms/edus/typing/data.rs index c4ad8673..3b1eecfb 100644 --- a/src/service/rooms/edus/typing/data.rs +++ b/src/service/rooms/edus/typing/data.rs @@ -10,6 +10,9 @@ pub trait Data: Send + Sync { /// Removes a user from typing before the timeout is reached. fn typing_remove(&self, user_id: &UserId, room_id: &RoomId) -> Result<()>; + /// Makes sure that typing events with old timestamps get removed. + fn typings_maintain(&self, room_id: &RoomId) -> Result<()>; + /// Returns the count of the last typing update in this room. fn last_typing_update(&self, room_id: &RoomId) -> Result; diff --git a/src/service/rooms/edus/typing/mod.rs b/src/service/rooms/edus/typing/mod.rs index d05ec900..6b066f06 100644 --- a/src/service/rooms/edus/typing/mod.rs +++ b/src/service/rooms/edus/typing/mod.rs @@ -21,54 +21,18 @@ impl Service { self.db.typing_remove(user_id, room_id) } - /* TODO: Do this in background thread? /// Makes sure that typing events with old timestamps get removed. fn typings_maintain( &self, room_id: &RoomId, - globals: &super::super::globals::Globals, ) -> Result<()> { - let mut prefix = room_id.as_bytes().to_vec(); - prefix.push(0xff); - - let current_timestamp = utils::millis_since_unix_epoch(); - - let mut found_outdated = false; - - // Find all outdated edus before inserting a new one - for outdated_edu in self - .typingid_userid - .scan_prefix(prefix) - .map(|(key, _)| { - Ok::<_, Error>(( - key.clone(), - utils::u64_from_bytes( - &key.splitn(2, |&b| b == 0xff).nth(1).ok_or_else(|| { - Error::bad_database("RoomTyping has invalid timestamp or delimiters.") - })?[0..mem::size_of::()], - ) - .map_err(|_| Error::bad_database("RoomTyping has invalid timestamp bytes."))?, - )) - }) - .filter_map(|r| r.ok()) - .take_while(|&(_, timestamp)| timestamp < current_timestamp) - { - // This is an outdated edu (time > timestamp) - self.typingid_userid.remove(&outdated_edu.0)?; - found_outdated = true; - } - - if found_outdated { - self.roomid_lasttypingupdate - .insert(room_id.as_bytes(), &globals.next_count()?.to_be_bytes())?; - } - - Ok(()) + self.db.typings_maintain(room_id) } - */ /// Returns the count of the last typing update in this room. pub fn last_typing_update(&self, room_id: &RoomId) -> Result { + self.typings_maintain(room_id)?; + self.db.last_typing_update(room_id) } From 0cf6545116f475db1e42f0c72ae30cdd2663f029 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20K=C3=B6sters?= Date: Sun, 30 Oct 2022 21:23:10 +0100 Subject: [PATCH 2/2] fix: not sending enough state on join --- src/api/client_server/sync.rs | 41 ++++++++++++--------- src/database/key_value/rooms/edus/typing.rs | 11 +++--- src/service/rooms/edus/typing/mod.rs | 5 +-- 3 files changed, 29 insertions(+), 28 deletions(-) diff --git a/src/api/client_server/sync.rs b/src/api/client_server/sync.rs index 5c1c23d5..94e4f5bb 100644 --- a/src/api/client_server/sync.rs +++ b/src/api/client_server/sync.rs @@ -388,13 +388,35 @@ async fn sync_helper( )) }; + let since_sender_member: Option = since_shortstatehash + .and_then(|shortstatehash| { + services() + .rooms + .state_accessor + .state_get( + shortstatehash, + &StateEventType::RoomMember, + sender_user.as_str(), + ) + .transpose() + }) + .transpose()? + .and_then(|pdu| { + serde_json::from_str(pdu.content.get()) + .map_err(|_| Error::bad_database("Invalid PDU in database.")) + .ok() + }); + + let joined_since_last_sync = + since_sender_member.map_or(true, |member| member.membership != MembershipState::Join); + let ( heroes, joined_member_count, invited_member_count, joined_since_last_sync, state_events, - ) = if since_shortstatehash.is_none() { + ) = if since_shortstatehash.is_none() || joined_since_last_sync { // Probably since = 0, we will do an initial sync let (joined_member_count, invited_member_count, heroes) = calculate_counts()?; @@ -487,23 +509,6 @@ async fn sync_helper( // Incremental /sync let since_shortstatehash = since_shortstatehash.unwrap(); - let since_sender_member: Option = services() - .rooms - .state_accessor - .state_get( - since_shortstatehash, - &StateEventType::RoomMember, - sender_user.as_str(), - )? - .and_then(|pdu| { - serde_json::from_str(pdu.content.get()) - .map_err(|_| Error::bad_database("Invalid PDU in database.")) - .ok() - }); - - let joined_since_last_sync = since_sender_member - .map_or(true, |member| member.membership != MembershipState::Join); - let mut state_events = Vec::new(); let mut lazy_loaded = HashSet::new(); diff --git a/src/database/key_value/rooms/edus/typing.rs b/src/database/key_value/rooms/edus/typing.rs index d50c000c..d2d43062 100644 --- a/src/database/key_value/rooms/edus/typing.rs +++ b/src/database/key_value/rooms/edus/typing.rs @@ -54,10 +54,7 @@ impl service::rooms::edus::typing::Data for KeyValueDatabase { Ok(()) } - fn typings_maintain( - &self, - room_id: &RoomId, - ) -> Result<()> { + fn typings_maintain(&self, room_id: &RoomId) -> Result<()> { let mut prefix = room_id.as_bytes().to_vec(); prefix.push(0xff); @@ -89,8 +86,10 @@ impl service::rooms::edus::typing::Data for KeyValueDatabase { } if found_outdated { - self.roomid_lasttypingupdate - .insert(room_id.as_bytes(), &services().globals.next_count()?.to_be_bytes())?; + self.roomid_lasttypingupdate.insert( + room_id.as_bytes(), + &services().globals.next_count()?.to_be_bytes(), + )?; } Ok(()) diff --git a/src/service/rooms/edus/typing/mod.rs b/src/service/rooms/edus/typing/mod.rs index 6b066f06..7d44f7d7 100644 --- a/src/service/rooms/edus/typing/mod.rs +++ b/src/service/rooms/edus/typing/mod.rs @@ -22,10 +22,7 @@ impl Service { } /// Makes sure that typing events with old timestamps get removed. - fn typings_maintain( - &self, - room_id: &RoomId, - ) -> Result<()> { + fn typings_maintain(&self, room_id: &RoomId) -> Result<()> { self.db.typings_maintain(room_id) }