refactor(spaces): extract event type helpers and PL sync loop
Some checks failed
Documentation / Build and Deploy Documentation (pull_request) Has been skipped
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 5s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 5s
Update flake hashes / update-flake-hashes (pull_request) Failing after 5s

Extract StateEventType constructor helpers to avoid repeated
to_owned() allocations at each call site. Extract
sync_power_levels_for_children to consolidate 3 identical loops.
This commit is contained in:
ember33 2026-03-19 18:17:33 +01:00
parent 482f9145e6
commit 07c38c3339
2 changed files with 62 additions and 36 deletions

View file

@ -13,6 +13,22 @@ use serde_json::value::to_raw_value;
use crate::{admin_command, admin_command_dispatch};
fn roles_event_type() -> StateEventType {
StateEventType::from(SPACE_ROLES_EVENT_TYPE.to_owned())
}
fn member_event_type() -> StateEventType {
StateEventType::from(SPACE_ROLE_MEMBER_EVENT_TYPE.to_owned())
}
fn room_event_type() -> StateEventType {
StateEventType::from(SPACE_ROLE_ROOM_EVENT_TYPE.to_owned())
}
fn cascading_event_type() -> StateEventType {
StateEventType::from(SPACE_CASCADING_EVENT_TYPE.to_owned())
}
macro_rules! resolve_room_as_space {
($self:expr, $space:expr) => {{
let space_id = $self.services.rooms.alias.resolve(&$space).await?;
@ -159,7 +175,7 @@ pub enum SpaceRolesCommand {
#[admin_command]
async fn list(&self, space: OwnedRoomOrAliasId) -> Result {
let space_id = resolve_space!(self, space);
let roles_event_type = StateEventType::from(SPACE_ROLES_EVENT_TYPE.to_owned());
let roles_event_type = roles_event_type();
let content: SpaceRolesEventContent = self
.services
@ -195,7 +211,7 @@ async fn add(
power_level: Option<i64>,
) -> Result {
let space_id = resolve_space!(self, space);
let roles_event_type = StateEventType::from(SPACE_ROLES_EVENT_TYPE.to_owned());
let roles_event_type = roles_event_type();
let mut content: SpaceRolesEventContent = self
.services
@ -223,7 +239,7 @@ async fn add(
#[admin_command]
async fn remove(&self, space: OwnedRoomOrAliasId, role_name: String) -> Result {
let space_id = resolve_space!(self, space);
let roles_event_type = StateEventType::from(SPACE_ROLES_EVENT_TYPE.to_owned());
let roles_event_type = roles_event_type();
let mut content: SpaceRolesEventContent = self
.services
@ -239,7 +255,7 @@ async fn remove(&self, space: OwnedRoomOrAliasId, role_name: String) -> Result {
send_space_state!(self, space_id, SPACE_ROLES_EVENT_TYPE, "", &content);
let member_event_type = StateEventType::from(SPACE_ROLE_MEMBER_EVENT_TYPE.to_owned());
let member_event_type = member_event_type();
let server_user = &self.services.globals.server_user;
if let Ok(shortstatehash) = self
.services
@ -282,7 +298,7 @@ async fn remove(&self, space: OwnedRoomOrAliasId, role_name: String) -> Result {
}
// Cascade: remove the role from all rooms' role requirement events
let room_event_type = StateEventType::from(SPACE_ROLE_ROOM_EVENT_TYPE.to_owned());
let room_event_type = room_event_type();
let room_entries: Vec<(_, ruma::OwnedEventId)> = self
.services
@ -330,7 +346,7 @@ async fn assign(
) -> Result {
let space_id = resolve_space!(self, space);
let roles_event_type = StateEventType::from(SPACE_ROLES_EVENT_TYPE.to_owned());
let roles_event_type = roles_event_type();
let role_defs: SpaceRolesEventContent = self
.services
.rooms
@ -343,7 +359,7 @@ async fn assign(
return Err!("Role '{role_name}' does not exist in this space.");
}
let member_event_type = StateEventType::from(SPACE_ROLE_MEMBER_EVENT_TYPE.to_owned());
let member_event_type = member_event_type();
let mut content: SpaceRoleMemberEventContent = self
.services
@ -373,7 +389,7 @@ async fn revoke(
role_name: String,
) -> Result {
let space_id = resolve_space!(self, space);
let member_event_type = StateEventType::from(SPACE_ROLE_MEMBER_EVENT_TYPE.to_owned());
let member_event_type = member_event_type();
let mut content: SpaceRoleMemberEventContent = self
.services
@ -405,7 +421,7 @@ async fn require(
) -> Result {
let space_id = resolve_space!(self, space);
let roles_event_type = StateEventType::from(SPACE_ROLES_EVENT_TYPE.to_owned());
let roles_event_type = roles_event_type();
let role_defs: SpaceRolesEventContent = self
.services
.rooms
@ -418,7 +434,7 @@ async fn require(
return Err!("Role '{role_name}' does not exist in this space.");
}
let room_event_type = StateEventType::from(SPACE_ROLE_ROOM_EVENT_TYPE.to_owned());
let room_event_type = room_event_type();
let mut content: SpaceRoleRoomEventContent = self
.services
@ -450,7 +466,7 @@ async fn unrequire(
role_name: String,
) -> Result {
let space_id = resolve_space!(self, space);
let room_event_type = StateEventType::from(SPACE_ROLE_ROOM_EVENT_TYPE.to_owned());
let room_event_type = room_event_type();
let mut content: SpaceRoleRoomEventContent = self
.services
@ -566,7 +582,7 @@ async fn status(&self, space: OwnedRoomOrAliasId) -> Result {
let space_id = resolve_room_as_space!(self, space);
let global_default = self.services.rooms.roles.is_enabled();
let cascading_event_type = StateEventType::from(SPACE_CASCADING_EVENT_TYPE.to_owned());
let cascading_event_type = cascading_event_type();
let per_space_override: Option<bool> = self
.services
.rooms

View file

@ -40,6 +40,22 @@ use tokio::sync::RwLock;
use crate::{Dep, globals, rooms};
fn roles_event_type() -> StateEventType {
StateEventType::from(SPACE_ROLES_EVENT_TYPE.to_owned())
}
fn member_event_type() -> StateEventType {
StateEventType::from(SPACE_ROLE_MEMBER_EVENT_TYPE.to_owned())
}
fn room_event_type() -> StateEventType {
StateEventType::from(SPACE_ROLE_ROOM_EVENT_TYPE.to_owned())
}
fn cascading_event_type() -> StateEventType {
StateEventType::from(SPACE_CASCADING_EVENT_TYPE.to_owned())
}
pub struct Service {
services: Services,
server: Arc<Server>,
@ -164,7 +180,7 @@ pub fn is_enabled(&self) -> bool { self.server.config.space_permission_cascading
#[implement(Service)]
pub async fn is_enabled_for_space(&self, space_id: &RoomId) -> bool {
let cascading_event_type = StateEventType::from(SPACE_CASCADING_EVENT_TYPE.to_owned());
let cascading_event_type = cascading_event_type();
if let Ok(content) = self
.services
.state_accessor
@ -183,7 +199,7 @@ pub async fn ensure_default_roles(&self, space_id: &RoomId) -> Result {
return Ok(());
}
let roles_event_type = StateEventType::from(SPACE_ROLES_EVENT_TYPE.to_owned());
let roles_event_type = roles_event_type();
if self
.services
.state_accessor
@ -246,7 +262,7 @@ pub async fn populate_space(&self, space_id: &RoomId) {
debug_warn!("Space roles cache exceeded capacity, cleared");
}
let roles_event_type = StateEventType::from(SPACE_ROLES_EVENT_TYPE.to_owned());
let roles_event_type = roles_event_type();
if let Ok(content) = self
.services
.state_accessor
@ -259,7 +275,7 @@ pub async fn populate_space(&self, space_id: &RoomId) {
.insert(space_id.to_owned(), content.roles);
}
let member_event_type = StateEventType::from(SPACE_ROLE_MEMBER_EVENT_TYPE.to_owned());
let member_event_type = member_event_type();
let shortstatehash = match self.services.state.get_room_shortstatehash(space_id).await {
| Ok(hash) => hash,
| Err(e) => {
@ -298,7 +314,7 @@ pub async fn populate_space(&self, space_id: &RoomId) {
.await
.insert(space_id.to_owned(), user_roles_map);
let room_event_type = StateEventType::from(SPACE_ROLE_ROOM_EVENT_TYPE.to_owned());
let room_event_type = room_event_type();
let mut room_reqs_map: HashMap<OwnedRoomId, HashSet<String>> = HashMap::new();
self.services
@ -653,6 +669,16 @@ async fn invite_and_join_user(
Ok(())
}
#[implement(Service)]
async fn sync_power_levels_for_children(&self, space_id: &RoomId) {
let child_rooms = self.get_child_rooms(space_id).await;
for child_room_id in &child_rooms {
if let Err(e) = self.sync_power_levels(space_id, child_room_id).await {
debug_warn!(room_id = %child_room_id, error = ?e, "Failed to sync power levels");
}
}
}
impl Service {
pub fn handle_state_event_change(
self: &Arc<Self>,
@ -683,12 +709,7 @@ impl Service {
match event_type.as_str() {
| SPACE_ROLES_EVENT_TYPE => {
let child_rooms = this.get_child_rooms(&space_id).await;
for child_room_id in &child_rooms {
if let Err(e) = this.sync_power_levels(&space_id, child_room_id).await {
debug_warn!(room_id = %child_room_id, error = ?e, "Failed to sync power levels");
}
}
this.sync_power_levels_for_children(&space_id).await;
let space_members: Vec<OwnedUserId> = this
.services
.state_cache
@ -715,13 +736,7 @@ impl Service {
{
debug_warn!(user_id = %user_id, error = ?e, "Space role auto-kick failed");
}
let child_rooms = this.get_child_rooms(&space_id).await;
for child_room_id in &child_rooms {
if let Err(e) = this.sync_power_levels(&space_id, child_room_id).await
{
debug_warn!(room_id = %child_room_id, error = ?e, "Failed to sync power levels");
}
}
this.sync_power_levels_for_children(&space_id).await;
}
},
| SPACE_ROLE_ROOM_EVENT_TYPE => {
@ -869,12 +884,7 @@ impl Service {
if let Err(e) = this.auto_join_qualifying_rooms(&space_id, &user_id).await {
debug_warn!(user_id = %user_id, error = ?e, "Auto-join on Space join failed");
}
let child_rooms = this.get_child_rooms(&space_id).await;
for child_room_id in &child_rooms {
if let Err(e) = this.sync_power_levels(&space_id, child_room_id).await {
debug_warn!(room_id = %child_room_id, error = ?e, "Failed to sync power levels on join");
}
}
this.sync_power_levels_for_children(&space_id).await;
});
}
}