1
0
Fork 0
mirror of https://gitlab.com/famedly/conduit.git synced 2025-08-11 17:50:59 +00:00

feat(spaces): sort space room children & simplify

This commit is contained in:
Matthias Ahouansou 2025-07-03 18:49:31 +01:00
parent 1a4a348ccf
commit b631621f8c
No known key found for this signature in database

View file

@ -1,5 +1,4 @@
use std::{ use std::{
collections::VecDeque,
fmt::{Display, Formatter}, fmt::{Display, Formatter},
str::FromStr, str::FromStr,
}; };
@ -457,7 +456,7 @@ impl Service {
max_depth: usize, max_depth: usize,
suggested_only: bool, suggested_only: bool,
) -> Result<client::space::get_hierarchy::v1::Response> { ) -> Result<client::space::get_hierarchy::v1::Response> {
let mut parents = VecDeque::new(); let mut parents = Vec::new();
// Don't start populating the results if we have to start at a specific room. // Don't start populating the results if we have to start at a specific room.
let mut populate_results = short_room_ids.is_empty(); let mut populate_results = short_room_ids.is_empty();
@ -489,27 +488,25 @@ impl Service {
get_parent_children_via(*summary.clone(), suggested_only) get_parent_children_via(*summary.clone(), suggested_only)
.into_iter() .into_iter()
.filter(|(room, _)| parents.iter().all(|parent| parent != room)) .filter(|(room, _)| parents.iter().all(|parent| parent != room))
.rev()
.collect(); .collect();
if populate_results { if populate_results {
results.push(summary_to_chunk(*summary.clone())) results.push(summary_to_chunk(*summary.clone()));
} else { } else {
let mut prev_child_in_short_ids = false;
children = children children = children
.into_iter() .into_iter()
.rev() .take_while(|(room, _)| {
.skip_while(|(room, _)| {
if let Ok(short) = services().rooms.short.get_shortroomid(room) if let Ok(short) = services().rooms.short.get_shortroomid(room)
{ {
short.as_ref() != short_room_ids.get(parents.len()) let tmp = prev_child_in_short_ids;
prev_child_in_short_ids =
short.as_ref() == short_room_ids.get(parents.len());
!tmp
} else { } else {
false false
} }
}) })
.collect::<Vec<_>>()
// skip_while doesn't implement DoubleEndedIterator, which is needed for rev
.into_iter()
.rev()
.collect(); .collect();
if children.is_empty() { if children.is_empty() {
@ -526,7 +523,7 @@ impl Service {
} }
if !children.is_empty() && parents.len() < max_depth { if !children.is_empty() && parents.len() < max_depth {
parents.push_back(current_room.clone()); parents.push(current_room.clone());
stack.push(children); stack.push(children);
} }
// Root room in the space hierarchy, we return an error if this one fails. // Root room in the space hierarchy, we return an error if this one fails.
@ -553,19 +550,18 @@ impl Service {
Ok(client::space::get_hierarchy::v1::Response { Ok(client::space::get_hierarchy::v1::Response {
next_batch: if let Some((room, _)) = next_room_to_traverse(&mut stack, &mut parents) { next_batch: if let Some((room, _)) = next_room_to_traverse(&mut stack, &mut parents) {
parents.pop_front(); parents.push(room);
parents.push_back(room);
let mut short_room_ids = vec![]; let mut short_room_ids = vec![];
for room in parents { for room in parents.into_iter().skip(1) {
short_room_ids.push(services().rooms.short.get_or_create_shortroomid(&room)?); short_room_ids.push(services().rooms.short.get_or_create_shortroomid(&room)?);
} }
Some( Some(
PagnationToken { PagnationToken {
short_room_ids, short_room_ids,
limit: UInt::new(max_depth as u64) limit: UInt::new(limit as u64)
.expect("When sent in request it must have been valid UInt"), .expect("When sent in request it must have been valid UInt"),
max_depth: UInt::new(max_depth as u64) max_depth: UInt::new(max_depth as u64)
.expect("When sent in request it must have been valid UInt"), .expect("When sent in request it must have been valid UInt"),
@ -583,11 +579,11 @@ impl Service {
fn next_room_to_traverse( fn next_room_to_traverse(
stack: &mut Vec<Vec<(OwnedRoomId, Vec<OwnedServerName>)>>, stack: &mut Vec<Vec<(OwnedRoomId, Vec<OwnedServerName>)>>,
parents: &mut VecDeque<OwnedRoomId>, parents: &mut Vec<OwnedRoomId>,
) -> Option<(OwnedRoomId, Vec<OwnedServerName>)> { ) -> Option<(OwnedRoomId, Vec<OwnedServerName>)> {
while stack.last().is_some_and(|s| s.is_empty()) { while stack.last().is_some_and(|s| s.is_empty()) {
stack.pop(); stack.pop();
parents.pop_back(); parents.pop();
} }
stack.last_mut().and_then(|s| s.pop()) stack.last_mut().and_then(|s| s.pop())
@ -727,18 +723,20 @@ fn get_parent_children_via(
parent: SpaceHierarchyParentSummary, parent: SpaceHierarchyParentSummary,
suggested_only: bool, suggested_only: bool,
) -> Vec<(OwnedRoomId, Vec<OwnedServerName>)> { ) -> Vec<(OwnedRoomId, Vec<OwnedServerName>)> {
parent let mut children = parent
.children_state .children_state
.iter() .iter()
.filter_map(|raw_ce| { .filter_map(|raw| raw.deserialize().ok())
raw_ce.deserialize().map_or(None, |ce| { .filter(|child| !suggested_only || child.content.suggested)
if suggested_only && !ce.content.suggested { .collect::<Vec<_>>();
None
} else { children.sort();
Some((ce.state_key, ce.content.via))
} children
}) .into_iter()
}) // We reverse, as we want to traverse the ones that come first in the list first (via `Vec::pop`)
.rev()
.map(|child| (child.state_key, child.content.via))
.collect() .collect()
} }
@ -767,7 +765,7 @@ mod tests {
], ],
"suggested": false "suggested": false
}, },
"origin_server_ts": 1629413349153, "origin_server_ts": 111,
"sender": "@alice:example.org", "sender": "@alice:example.org",
"state_key": "!foo:example.org", "state_key": "!foo:example.org",
"type": "m.space.child" "type": "m.space.child"
@ -782,7 +780,7 @@ mod tests {
], ],
"suggested": true "suggested": true
}, },
"origin_server_ts": 1629413349157, "origin_server_ts": 333,
"sender": "@alice:example.org", "sender": "@alice:example.org",
"state_key": "!bar:example.org", "state_key": "!bar:example.org",
"type": "m.space.child" "type": "m.space.child"
@ -794,9 +792,10 @@ mod tests {
"content": { "content": {
"via": [ "via": [
"example.org" "example.org"
] ],
"order": ""
}, },
"origin_server_ts": 1629413349160, "origin_server_ts": 222,
"sender": "@alice:example.org", "sender": "@alice:example.org",
"state_key": "!baz:example.org", "state_key": "!baz:example.org",
"type": "m.space.child" "type": "m.space.child"
@ -806,21 +805,22 @@ mod tests {
], ],
}; };
// it's in reverse order, so `pop` gives the first room to be fetched
assert_eq!( assert_eq!(
get_parent_children_via(summary.clone(), false), get_parent_children_via(summary.clone(), false),
vec![ vec![
(
owned_room_id!("!foo:example.org"),
vec![owned_server_name!("example.org")]
),
( (
owned_room_id!("!bar:example.org"), owned_room_id!("!bar:example.org"),
vec![owned_server_name!("example.org")] vec![owned_server_name!("example.org")]
), ),
(
owned_room_id!("!foo:example.org"),
vec![owned_server_name!("example.org")]
),
( (
owned_room_id!("!baz:example.org"), owned_room_id!("!baz:example.org"),
vec![owned_server_name!("example.org")] vec![owned_server_name!("example.org")]
) ),
] ]
); );
assert_eq!( assert_eq!(