lazy-construct presence; avoids useless db queries in sender and syncer.

Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
Jason Volk 2024-04-16 02:00:54 -07:00 committed by June
parent 8b003e6be2
commit 33cc3d56c1
5 changed files with 16 additions and 11 deletions

View file

@ -571,7 +571,7 @@ async fn process_presence_updates(
presence_updates: &mut HashMap<OwnedUserId, PresenceEvent>, since: u64, syncing_user: &OwnedUserId, presence_updates: &mut HashMap<OwnedUserId, PresenceEvent>, since: u64, syncing_user: &OwnedUserId,
) -> Result<()> { ) -> Result<()> {
// Take presence updates // Take presence updates
for (user_id, _, presence_event) in services().presence.presence_since(since) { for (user_id, _, presence_bytes) in services().presence.presence_since(since) {
if !services() if !services()
.rooms .rooms
.state_cache .state_cache
@ -580,6 +580,8 @@ async fn process_presence_updates(
continue; continue;
} }
use crate::service::presence::Presence;
let presence_event = Presence::from_json_bytes_to_event(&presence_bytes, &user_id)?;
match presence_updates.entry(user_id) { match presence_updates.entry(user_id) {
Entry::Vacant(slot) => { Entry::Vacant(slot) => {
slot.insert(presence_event); slot.insert(presence_event);

View file

@ -92,16 +92,13 @@ impl service::presence::Data for KeyValueDatabase {
Ok(()) Ok(())
} }
fn presence_since<'a>(&'a self, since: u64) -> Box<dyn Iterator<Item = (OwnedUserId, u64, PresenceEvent)> + 'a> { fn presence_since<'a>(&'a self, since: u64) -> Box<dyn Iterator<Item = (OwnedUserId, u64, Vec<u8>)> + 'a> {
Box::new( Box::new(
self.presenceid_presence self.presenceid_presence
.iter() .iter()
.flat_map(|(key, presence_bytes)| -> Result<(OwnedUserId, u64, PresenceEvent)> { .flat_map(|(key, presence_bytes)| -> Result<(OwnedUserId, u64, Vec<u8>)> {
let (count, user_id) = presenceid_parse(&key)?; let (count, user_id) = presenceid_parse(&key)?;
let presence = Presence::from_json_bytes(&presence_bytes)?; Ok((user_id, count, presence_bytes))
let presence_event = presence.to_presence_event(&user_id)?;
Ok((user_id, count, presence_event))
}) })
.filter(move |(_, count, _)| *count > since), .filter(move |(_, count, _)| *count > since),
) )

View file

@ -17,5 +17,5 @@ pub trait Data: Send + Sync {
/// Returns the most recent presence updates that happened after the event /// Returns the most recent presence updates that happened after the event
/// with id `since`. /// with id `since`.
fn presence_since<'a>(&'a self, since: u64) -> Box<dyn Iterator<Item = (OwnedUserId, u64, PresenceEvent)> + 'a>; fn presence_since<'a>(&'a self, since: u64) -> Box<dyn Iterator<Item = (OwnedUserId, u64, Vec<u8>)> + 'a>;
} }

View file

@ -35,6 +35,11 @@ impl Presence {
} }
} }
pub fn from_json_bytes_to_event(bytes: &[u8], user_id: &UserId) -> Result<PresenceEvent> {
let presence = Self::from_json_bytes(bytes)?;
presence.to_presence_event(user_id)
}
pub fn from_json_bytes(bytes: &[u8]) -> Result<Self> { pub fn from_json_bytes(bytes: &[u8]) -> Result<Self> {
serde_json::from_slice(bytes).map_err(|_| Error::bad_database("Invalid presence data in database")) serde_json::from_slice(bytes).map_err(|_| Error::bad_database("Invalid presence data in database"))
} }
@ -169,7 +174,7 @@ impl Service {
/// Returns the most recent presence updates that happened after the event /// Returns the most recent presence updates that happened after the event
/// with id `since`. /// with id `since`.
pub fn presence_since(&self, since: u64) -> Box<dyn Iterator<Item = (OwnedUserId, u64, PresenceEvent)>> { pub fn presence_since(&self, since: u64) -> Box<dyn Iterator<Item = (OwnedUserId, u64, Vec<u8>)>> {
self.db.presence_since(since) self.db.presence_since(since)
} }

View file

@ -28,7 +28,7 @@ use ruma::{
use tokio::sync::{Mutex, Semaphore}; use tokio::sync::{Mutex, Semaphore};
use tracing::{error, warn}; use tracing::{error, warn};
use crate::{services, utils::calculate_hash, Config, Error, PduEvent, Result}; use crate::{service::presence::Presence, services, utils::calculate_hash, Config, Error, PduEvent, Result};
pub mod appservice; pub mod appservice;
pub mod data; pub mod data;
@ -493,7 +493,7 @@ pub fn select_edus_presence(
) -> Result<bool> { ) -> Result<bool> {
// Look for presence updates for this server // Look for presence updates for this server
let mut presence_updates = Vec::new(); let mut presence_updates = Vec::new();
for (user_id, count, presence_event) in services().presence.presence_since(since) { for (user_id, count, presence_bytes) in services().presence.presence_since(since) {
*max_edu_count = cmp::max(count, *max_edu_count); *max_edu_count = cmp::max(count, *max_edu_count);
if user_id.server_name() != services().globals.server_name() { if user_id.server_name() != services().globals.server_name() {
@ -508,6 +508,7 @@ pub fn select_edus_presence(
continue; continue;
} }
let presence_event = Presence::from_json_bytes_to_event(&presence_bytes, &user_id)?;
presence_updates.push(PresenceUpdate { presence_updates.push(PresenceUpdate {
user_id, user_id,
presence: presence_event.content.presence, presence: presence_event.content.presence,