diff --git a/changelog.d/1624.feature b/changelog.d/1624.feature new file mode 100644 index 000000000..e6a5a0ff4 --- /dev/null +++ b/changelog.d/1624.feature @@ -0,0 +1 @@ +Implemented option to deprioritize servers for room join requests. Contributed by @ezera. diff --git a/conduwuit-example.toml b/conduwuit-example.toml index 431bc85d5..41be26161 100644 --- a/conduwuit-example.toml +++ b/conduwuit-example.toml @@ -1409,6 +1409,20 @@ # #ignore_messages_from_server_names = [] +# List of server names that continuwuity will deprioritize (try last) when +# a client requests to join a room. +# +# This can be used to potentially speed up room join requests, by +# deprioritizing sending join requests through servers that are known to +# be large or slow. +# +# continuwuity will still send join requests to servers in this list if +# the room couldn't be joined via other servers it federates with. +# +# example: ["example.com"] +# +#deprioritize_joins_through_servers = [] + # Send messages from users that the user has ignored to the client. # # There is no way for clients to receive messages sent while a user was diff --git a/src/api/client/membership/join.rs b/src/api/client/membership/join.rs index 4c3a53d02..eb6fa3390 100644 --- a/src/api/client/membership/join.rs +++ b/src/api/client/membership/join.rs @@ -113,6 +113,7 @@ pub(crate) async fn join_room_by_id_route( servers.sort_unstable(); servers.dedup(); shuffle(&mut servers); + let servers = deprioritize(servers, &services.config.deprioritize_joins_through_servers); join_room_by_id_helper( &services, @@ -241,6 +242,7 @@ pub(crate) async fn join_room_by_id_or_alias_route( }, }; + let servers = deprioritize(servers, &services.config.deprioritize_joins_through_servers); let join_room_response = join_room_by_id_helper( &services, sender_user, @@ -890,3 +892,59 @@ async fn make_join_request( info!("All {} servers were unable to assist in joining {room_id} :(", servers.len()); Err!(BadServerResponse("No server available to assist in joining.")) } + +/// Moves deprioritized servers (if any) to the back of the list. +/// +/// No-op if we aren't given any servers to deprioritize. +fn deprioritize( + servers: Vec, + deprioritized: &[OwnedServerName], +) -> Vec { + if deprioritized.is_empty() { + return servers; + } + + let (mut depr, mut servers): (Vec<_>, Vec<_>) = + servers.into_iter().partition(|s| deprioritized.contains(s)); + servers.append(&mut depr); + servers +} + +#[cfg(test)] +mod tests { + use ruma::OwnedServerName; + + use super::*; + + #[test] + fn deprioritizing_servers_works() -> Result<(), Box> { + let servers = vec![ + "example.com".try_into()?, + "slow.invalid".try_into()?, + "example.org".try_into()?, + ]; + let depr = vec!["slow.invalid".try_into()?]; + let expected: Vec = vec![ + "example.com".try_into()?, + "example.org".try_into()?, + "slow.invalid".try_into()?, + ]; + + let servers = deprioritize(servers, &depr); + assert_eq!(servers, expected); + Ok(()) + } + + #[test] + fn empty_deprioritized_is_noop() -> Result<(), Box> { + let servers = vec![ + "example.com".try_into()?, + "slow.invalid".try_into()?, + "example.org".try_into()?, + ]; + + let depr_servers = deprioritize(servers.clone(), &[]); + assert_eq!(depr_servers, servers); + Ok(()) + } +} diff --git a/src/core/config/mod.rs b/src/core/config/mod.rs index b4dc2b870..a5772a8ce 100644 --- a/src/core/config/mod.rs +++ b/src/core/config/mod.rs @@ -1630,6 +1630,22 @@ pub struct Config { #[serde(default, with = "serde_regex")] pub ignore_messages_from_server_names: RegexSet, + /// List of server names that continuwuity will deprioritize (try last) when + /// a client requests to join a room. + /// + /// This can be used to potentially speed up room join requests, by + /// deprioritizing sending join requests through servers that are known to + /// be large or slow. + /// + /// continuwuity will still send join requests to servers in this list if + /// the room couldn't be joined via other servers it federates with. + /// + /// example: ["example.com"] + /// + /// default: [] + #[serde(default = "Vec::new")] + pub deprioritize_joins_through_servers: Vec, + /// Send messages from users that the user has ignored to the client. /// /// There is no way for clients to receive messages sent while a user was