From e161b5f01e8597ed23ed3557f8021518bb74c309 Mon Sep 17 00:00:00 2001 From: Erwan Leboucher Date: Sun, 26 Jul 2026 10:19:34 +0200 Subject: [PATCH] perf: Fetch joined member count once per event when notifying --- changelog.d/+push-joined-count.perf.md | 1 + src/service/pusher/mod.rs | 65 ++++++++++++++++---------- src/service/rooms/timeline/append.rs | 16 ++++--- 3 files changed, 51 insertions(+), 31 deletions(-) create mode 100644 changelog.d/+push-joined-count.perf.md diff --git a/changelog.d/+push-joined-count.perf.md b/changelog.d/+push-joined-count.perf.md new file mode 100644 index 000000000..00627ac9d --- /dev/null +++ b/changelog.d/+push-joined-count.perf.md @@ -0,0 +1 @@ +Fetch the joined member count once per event instead of once per notified user. diff --git a/src/service/pusher/mod.rs b/src/service/pusher/mod.rs index 42cfda34d..3051c8ea1 100644 --- a/src/service/pusher/mod.rs +++ b/src/service/pusher/mod.rs @@ -347,6 +347,42 @@ impl Service { Ok(()) } + pub async fn push_joined_count(&self, room_id: &RoomId) -> UInt { + self.services + .state_cache + .room_joined_count(room_id) + .await + .unwrap_or(1) + .try_into() + .unwrap_or_else(|_| uint!(0)) + } + + #[tracing::instrument(skip(self, user), level = "debug")] + pub async fn push_condition_ctx( + &self, + user: &UserId, + power_levels: RoomPowerLevels, + room_id: &RoomId, + room_joined_count: UInt, + ) -> PushConditionRoomCtx { + let power_levels = PushConditionPowerLevelsCtx::from(power_levels); + + let user_display_name = self + .services + .users + .displayname(user) + .await + .unwrap_or_else(|_| user.localpart().to_owned()); + + PushConditionRoomCtx::new( + room_id.to_owned(), + room_joined_count, + user.to_owned(), + user_display_name, + ) + .with_power_levels(power_levels) + } + #[tracing::instrument(skip(self, user, ruleset, pdu), level = "debug")] pub async fn get_actions<'a>( &self, @@ -356,31 +392,10 @@ impl Service { pdu: &Raw, room_id: &RoomId, ) -> &'a [Action] { - let power_levels = PushConditionPowerLevelsCtx::from(power_levels); - - let room_joined_count = self - .services - .state_cache - .room_joined_count(room_id) - .await - .unwrap_or(1) - .try_into() - .unwrap_or_else(|_| uint!(0)); - - let user_display_name = self - .services - .users - .displayname(user) - .await - .unwrap_or_else(|_| user.localpart().to_owned()); - - let ctx = PushConditionRoomCtx::new( - room_id.to_owned(), - room_joined_count, - user.to_owned(), - user_display_name, - ) - .with_power_levels(power_levels); + let room_joined_count = self.push_joined_count(room_id).await; + let ctx = self + .push_condition_ctx(user, power_levels, room_id, room_joined_count) + .await; ruleset.get_actions(pdu, &ctx).await } diff --git a/src/service/rooms/timeline/append.rs b/src/service/rooms/timeline/append.rs index 377781160..6730f3fd2 100644 --- a/src/service/rooms/timeline/append.rs +++ b/src/service/rooms/timeline/append.rs @@ -26,12 +26,13 @@ use ruma::{ CanonicalJsonObject, CanonicalJsonValue, EventId, OwnedEventId, OwnedRoomId, RoomId, RoomVersionId, UserId, events::{ - GlobalAccountDataEventType, TimelineEventType, + AnySyncTimelineEvent, GlobalAccountDataEventType, TimelineEventType, push_rules::PushRulesEvent, room::{encrypted::Relation, redaction::RoomRedactionEventContent}, }, push::{Action, Ruleset, Tweak}, room_version_rules::RoomVersionRules, + serde::Raw, }; use super::{ExtractBody, ExtractRelatesTo, ExtractRelatesToEventId, RoomMutexGuard}; @@ -427,7 +428,9 @@ impl super::Service { return; } - let serialized = pdu.to_format(); + let serialized: Raw = pdu.to_format(); + let room_joined_count = self.services.pusher.push_joined_count(room_id).await; + for user in &push_targets { let rules_for_user = self .services @@ -442,12 +445,13 @@ impl super::Service { let mut highlight = false; let mut notify = false; - for action in self + let ctx = self .services .pusher - .get_actions(user, &rules_for_user, power_levels.clone(), &serialized, room_id) - .await - { + .push_condition_ctx(user, power_levels.clone(), room_id, room_joined_count) + .await; + + for action in rules_for_user.get_actions(&serialized, &ctx).await { match action { | Action::Notify => notify = true, | Action::SetTweak(Tweak::Highlight(