From ddc8c3b46cd4d5481a7c5e000caaa08bf37d5849 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Sat, 27 Jul 2024 23:25:13 +0000 Subject: [PATCH] split presence data object into file; improve service encapsulations Signed-off-by: Jason Volk --- Cargo.toml | 1 + src/service/presence/data.rs | 3 +- src/service/presence/mod.rs | 86 ++++++-------------------------- src/service/presence/presence.rs | 65 ++++++++++++++++++++++++ src/service/users/mod.rs | 28 ++++++----- 5 files changed, 99 insertions(+), 84 deletions(-) create mode 100644 src/service/presence/presence.rs diff --git a/Cargo.toml b/Cargo.toml index 48e6ac1a..82163b31 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -851,6 +851,7 @@ style = { level = "warn", priority = -1 } ## some sadness # trivial assertions are quite alright assertions_on_constants = { level = "allow", priority = 1 } +module_inception = { level = "allow", priority = 1 } ################### suspicious = { level = "warn", priority = -1 } diff --git a/src/service/presence/data.rs b/src/service/presence/data.rs index 53f9d8c7..1a0293de 100644 --- a/src/service/presence/data.rs +++ b/src/service/presence/data.rs @@ -4,7 +4,8 @@ use conduit::{debug_warn, utils, Error, Result}; use database::Map; use ruma::{events::presence::PresenceEvent, presence::PresenceState, OwnedUserId, UInt, UserId}; -use crate::{globals, presence::Presence, users, Dep}; +use super::Presence; +use crate::{globals, users, Dep}; pub struct Data { presenceid_presence: Arc, diff --git a/src/service/presence/mod.rs b/src/service/presence/mod.rs index b8673304..a54a6d7c 100644 --- a/src/service/presence/mod.rs +++ b/src/service/presence/mod.rs @@ -1,81 +1,25 @@ mod data; +mod presence; use std::{sync::Arc, time::Duration}; use async_trait::async_trait; -use conduit::{checked, debug, error, utils, Error, Result, Server}; +use conduit::{checked, debug, error, Error, Result, Server}; use futures_util::{stream::FuturesUnordered, StreamExt}; -use ruma::{ - events::presence::{PresenceEvent, PresenceEventContent}, - presence::PresenceState, - OwnedUserId, UInt, UserId, -}; -use serde::{Deserialize, Serialize}; +use ruma::{events::presence::PresenceEvent, presence::PresenceState, OwnedUserId, UInt, UserId}; use tokio::{sync::Mutex, time::sleep}; -use self::data::Data; +use self::{data::Data, presence::Presence}; use crate::{globals, users, Dep}; -/// Represents data required to be kept in order to implement the presence -/// specification. -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct Presence { - state: PresenceState, - currently_active: bool, - last_active_ts: u64, - status_msg: Option, -} - -impl Presence { - #[must_use] - pub fn new(state: PresenceState, currently_active: bool, last_active_ts: u64, status_msg: Option) -> Self { - Self { - state, - currently_active, - last_active_ts, - status_msg, - } - } - - pub fn from_json_bytes(bytes: &[u8]) -> Result { - serde_json::from_slice(bytes).map_err(|_| Error::bad_database("Invalid presence data in database")) - } - - pub fn to_json_bytes(&self) -> Result> { - serde_json::to_vec(self).map_err(|_| Error::bad_database("Could not serialize Presence to JSON")) - } - - /// Creates a PresenceEvent from available data. - pub fn to_presence_event(&self, user_id: &UserId, users: &users::Service) -> Result { - let now = utils::millis_since_unix_epoch(); - let last_active_ago = if self.currently_active { - None - } else { - Some(UInt::new_saturating(now.saturating_sub(self.last_active_ts))) - }; - - Ok(PresenceEvent { - sender: user_id.to_owned(), - content: PresenceEventContent { - presence: self.state.clone(), - status_msg: self.status_msg.clone(), - currently_active: Some(self.currently_active), - last_active_ago, - displayname: users.displayname(user_id)?, - avatar_url: users.avatar_url(user_id)?, - }, - }) - } -} - pub struct Service { - services: Services, - pub db: Data, - pub timer_sender: loole::Sender<(OwnedUserId, Duration)>, - timer_receiver: Mutex>, + timer_sender: loole::Sender, + timer_receiver: Mutex>, timeout_remote_users: bool, idle_timeout: u64, offline_timeout: u64, + pub db: Data, + services: Services, } struct Services { @@ -84,6 +28,8 @@ struct Services { users: Dep, } +type TimerType = (OwnedUserId, Duration); + #[async_trait] impl crate::Service for Service { fn build(args: crate::Args<'_>) -> Result> { @@ -92,17 +38,17 @@ impl crate::Service for Service { let offline_timeout_s = config.presence_offline_timeout_s; let (timer_sender, timer_receiver) = loole::unbounded(); Ok(Arc::new(Self { - services: Services { - server: args.server.clone(), - globals: args.depend::("globals"), - users: args.depend::("users"), - }, - db: Data::new(&args), timer_sender, timer_receiver: Mutex::new(timer_receiver), timeout_remote_users: config.presence_timeout_remote_users, idle_timeout: checked!(idle_timeout_s * 1_000)?, offline_timeout: checked!(offline_timeout_s * 1_000)?, + db: Data::new(&args), + services: Services { + server: args.server.clone(), + globals: args.depend::("globals"), + users: args.depend::("users"), + }, })) } diff --git a/src/service/presence/presence.rs b/src/service/presence/presence.rs new file mode 100644 index 00000000..570008f2 --- /dev/null +++ b/src/service/presence/presence.rs @@ -0,0 +1,65 @@ +use std::sync::Arc; + +use conduit::{utils, Error, Result}; +use ruma::{ + events::presence::{PresenceEvent, PresenceEventContent}, + presence::PresenceState, + UInt, UserId, +}; +use serde::{Deserialize, Serialize}; + +use crate::users; + +/// Represents data required to be kept in order to implement the presence +/// specification. +#[derive(Serialize, Deserialize, Debug, Clone)] +pub(super) struct Presence { + state: PresenceState, + currently_active: bool, + last_active_ts: u64, + status_msg: Option, +} + +impl Presence { + #[must_use] + pub(super) fn new( + state: PresenceState, currently_active: bool, last_active_ts: u64, status_msg: Option, + ) -> Self { + Self { + state, + currently_active, + last_active_ts, + status_msg, + } + } + + pub(super) fn from_json_bytes(bytes: &[u8]) -> Result { + serde_json::from_slice(bytes).map_err(|_| Error::bad_database("Invalid presence data in database")) + } + + pub(super) fn to_json_bytes(&self) -> Result> { + serde_json::to_vec(self).map_err(|_| Error::bad_database("Could not serialize Presence to JSON")) + } + + /// Creates a PresenceEvent from available data. + pub(super) fn to_presence_event(&self, user_id: &UserId, users: &Arc) -> Result { + let now = utils::millis_since_unix_epoch(); + let last_active_ago = if self.currently_active { + None + } else { + Some(UInt::new_saturating(now.saturating_sub(self.last_active_ts))) + }; + + Ok(PresenceEvent { + sender: user_id.to_owned(), + content: PresenceEventContent { + presence: self.state.clone(), + status_msg: self.status_msg.clone(), + currently_active: Some(self.currently_active), + last_active_ago, + displayname: users.displayname(user_id)?, + avatar_url: users.avatar_url(user_id)?, + }, + }) + } +} diff --git a/src/service/users/mod.rs b/src/service/users/mod.rs index 4c80d0d3..46084415 100644 --- a/src/service/users/mod.rs +++ b/src/service/users/mod.rs @@ -26,19 +26,10 @@ use ruma::{ use self::data::Data; use crate::{admin, rooms, Dep}; -pub struct SlidingSyncCache { - lists: BTreeMap, - subscriptions: BTreeMap, - known_rooms: BTreeMap>, // For every room, the roomsince number - extensions: ExtensionsConfig, -} - -type DbConnections = Mutex>>>; - pub struct Service { - services: Services, + connections: DbConnections, pub db: Data, - pub connections: DbConnections, + services: Services, } struct Services { @@ -49,18 +40,29 @@ struct Services { impl crate::Service for Service { fn build(args: crate::Args<'_>) -> Result> { Ok(Arc::new(Self { + connections: StdMutex::new(BTreeMap::new()), + db: Data::new(&args), services: Services { admin: args.depend::("admin"), state_cache: args.depend::("rooms::state_cache"), }, - db: Data::new(&args), - connections: StdMutex::new(BTreeMap::new()), })) } fn name(&self) -> &str { crate::service::make_name(std::module_path!()) } } +type DbConnections = Mutex>; +type DbConnectionsKey = (OwnedUserId, OwnedDeviceId, String); +type DbConnectionsVal = Arc>; + +struct SlidingSyncCache { + lists: BTreeMap, + subscriptions: BTreeMap, + known_rooms: BTreeMap>, // For every room, the roomsince number + extensions: ExtensionsConfig, +} + impl Service { /// Check if a user has an account on this homeserver. #[inline]