From f956e727e4dc5ad0aff0a3e6a69025931d3ec8da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Kub=C3=ADk?= Date: Thu, 17 Nov 2022 23:26:56 +0100 Subject: [PATCH] feat(presence): refactor presence_since --- src/database/key_value/rooms/edus/presence.rs | 90 +++++++++++-------- 1 file changed, 52 insertions(+), 38 deletions(-) diff --git a/src/database/key_value/rooms/edus/presence.rs b/src/database/key_value/rooms/edus/presence.rs index 453e2dc0..763572ec 100644 --- a/src/database/key_value/rooms/edus/presence.rs +++ b/src/database/key_value/rooms/edus/presence.rs @@ -93,35 +93,31 @@ impl service::rooms::edus::presence::Data for KeyValueDatabase { &self, room_id: &RoomId, since: u64, - ) -> Result> { - let mut prefix = room_id.as_bytes().to_vec(); - prefix.push(0xff); + ) -> Result>> { + let services = &services(); + let mut user_timestamp: HashMap = self.userid_presenceupdate + .iter() + .map(|(user_id_bytes, update_bytes)| (UserId::parse(utils::string_from_bytes(user_id_bytes)), PresenceUpdate::from_be_bytes(update_bytes)?)) + .filter_map(|(user_id, presence_update)| { + if presence_update.count <= since || !services.rooms.state_cache.is_joined(user_id, room_id)? { + return None + } - let mut first_possible_edu = prefix.clone(); - first_possible_edu.extend_from_slice(&(since + 1).to_be_bytes()); // +1 so we don't send the event at since - let mut hashmap = HashMap::new(); + Some((user_id, presence_update.timestamp)) + }) + .collect(); - for (key, value) in self - .presenceid_presence - .iter_from(&first_possible_edu, false) - .take_while(|(key, _)| key.starts_with(&prefix)) - { - let user_id = UserId::parse( - utils::string_from_bytes( - key.rsplit(|&b| b == 0xff) - .next() - .expect("rsplit always returns an element"), - ) - .map_err(|_| Error::bad_database("Invalid UserId bytes in presenceid_presence."))?, - ) - .map_err(|_| Error::bad_database("Invalid UserId in presenceid_presence."))?; + Ok( + self.roomuserid_presenceevent + .iter() + .filter_map(|user_id_bytes, presence_bytes| (UserId::parse(utils::string_from_bytes(user_id_bytes)), presence_bytes)) + .filter_map(|user_id, presence_bytes| { + let timestamp = user_timestamp.get(user_id)?; - let presence = parse_presence_event(&value)?; - - hashmap.insert(user_id, presence); - } - - Ok(hashmap) + Some((user_id, parse_presence_event(presence_bytes, *timestamp)?)) + }) + .into_iter() + ) } fn presence_maintain( @@ -161,18 +157,36 @@ fn parse_presence_event(bytes: &[u8], presence_timestamp: u64) -> Result PresenceState { + let globals = &services().globals; + + return if last_active_ago < globals.presence_idle_timeout() { + PresenceState::Online + } else if last_active_ago < globals.presence_offline_timeout() { + PresenceState::Unavailable + } else { + PresenceState::Offline + }; +} + +/// Translates the timestamp representing last_active_ago to a diff from now. +fn translate_active_ago( + presence_event: &mut PresenceEvent, + last_active_ts: u64, +) { + let last_active_ago = millis_since_unix_epoch().saturating_sub(last_active_ts); + + presence_event.content.presence = determine_presence_state(last_active_ago); + + presence_event.content.last_active_ago = match presence_event.content.presence { + PresenceState::Online => None, + _ => Some(UInt::new_saturating(last_active_ago)), + } +}