Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(sdk): Welcome sliding_sync::Version and sliding_sync::VersionBuilder #3889

Merged
merged 11 commits into from
Aug 27, 2024
8 changes: 7 additions & 1 deletion bindings/matrix-sdk-ffi/src/client_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use matrix_sdk::{
ruma::{ServerName, UserId},
sliding_sync::{
Error as MatrixSlidingSyncError, VersionBuilder as MatrixSlidingSyncVersionBuilder,
VersionBuilderError,
},
Client as MatrixClient, ClientBuildError as MatrixClientBuildError, HttpError, IdParseError,
RumaApiError,
Expand Down Expand Up @@ -195,8 +196,11 @@ pub enum ClientBuildError {
#[error(transparent)]
WellKnownDeserializationError(DeserializationError),
#[error(transparent)]
#[allow(dead_code)] // rustc's drunk, this is used
SlidingSync(MatrixSlidingSyncError),
#[error(transparent)]
SlidingSyncVersion(VersionBuilderError),
#[error(transparent)]
Sdk(MatrixClientBuildError),
#[error("Failed to build the client: {message}")]
Generic { message: String },
Expand All @@ -213,7 +217,9 @@ impl From<MatrixClientBuildError> for ClientBuildError {
MatrixClientBuildError::AutoDiscovery(FromHttpResponseError::Deserialization(e)) => {
ClientBuildError::WellKnownDeserializationError(e)
}
MatrixClientBuildError::SlidingSync(e) => ClientBuildError::SlidingSync(e),
MatrixClientBuildError::SlidingSyncVersion(e) => {
ClientBuildError::SlidingSyncVersion(e)
}
_ => ClientBuildError::Sdk(e),
}
}
Expand Down
8 changes: 4 additions & 4 deletions crates/matrix-sdk/src/client/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -564,8 +564,8 @@ async fn discover_homeserver_from_server_name_or_url(
if let Ok(homeserver_url) = Url::parse(&server_name_or_url) {
// Make sure the URL is definitely for a homeserver.
match get_supported_versions(&homeserver_url, http_client).await {
Ok(_) => {
return Ok((homeserver_url, None, None));
Ok(response) => {
return Ok((homeserver_url, None, Some(response)));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤦 of course! Thanks for the fix.

}
Err(e) => {
debug!(error = %e, "Checking supported versions failed.");
Expand Down Expand Up @@ -804,10 +804,10 @@ pub enum ClientBuildError {
#[error("Error looking up the .well-known endpoint on auto-discovery")]
AutoDiscovery(FromHttpResponseError<RumaApiError>),

/// Error from sliding sync.
/// Error when building the sliding sync version.
#[cfg(feature = "experimental-sliding-sync")]
#[error(transparent)]
SlidingSync(#[from] crate::sliding_sync::Error),
SlidingSyncVersion(#[from] crate::sliding_sync::VersionBuilderError),

/// An error encountered when trying to parse the homeserver url.
#[error(transparent)]
Expand Down
4 changes: 2 additions & 2 deletions crates/matrix-sdk/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,13 +459,13 @@ impl Client {
self.inner.homeserver.read().unwrap().clone()
}

/// Get the sliding version.
/// Get the sliding sync version.
#[cfg(feature = "experimental-sliding-sync")]
pub fn sliding_sync_version(&self) -> SlidingSyncVersion {
self.inner.sliding_sync_version.read().unwrap().clone()
}

/// Override the sliding version.
/// Override the sliding sync version.
#[cfg(feature = "experimental-sliding-sync")]
pub fn set_sliding_sync_version(&self, version: SlidingSyncVersion) {
let mut lock = self.inner.sliding_sync_version.write().unwrap();
Expand Down
93 changes: 46 additions & 47 deletions crates/matrix-sdk/src/sliding_sync/client.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::collections::BTreeMap;

use as_variant::as_variant;
use imbl::Vector;
use matrix_sdk_base::{sliding_sync::http, sync::SyncResponse, PreviousEventsProvider};
use ruma::{
Expand All @@ -14,13 +15,13 @@ use ruma::{
use tracing::error;
use url::Url;

use super::{Error, SlidingSync, SlidingSyncBuilder};
use super::{SlidingSync, SlidingSyncBuilder};
use crate::{config::RequestConfig, Client, Result, SlidingSyncRoom};

/// A sliding sync version.
#[derive(Clone, Debug)]
pub enum Version {
/// No version. Useful to represent that sliding sync is disable for
/// No version. Useful to represent that sliding sync is disabled for
/// example, and that the version is unknown.
None,

Expand All @@ -41,13 +42,35 @@ impl Version {
}

pub(crate) fn overriding_url(&self) -> Option<&Url> {
match self {
Self::Proxy { url } => Some(url),
_ => None,
}
as_variant!(self, Self::Proxy { url } => url)
}
}

/// An error when building a version.
#[derive(thiserror::Error, Debug)]
pub enum VersionBuilderError {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎵 This is the story of a lazy man 🎵 with an awesome non-lazy co-worker 🎶

/// The `.well-known` response is not set.
#[error("`.well-known` is not set")]
WellKnownNotSet,

/// `.well-known` does not contain a `sliding_sync_proxy` entry.
#[error("`.well-known` does not contain a `sliding_sync_proxy` entry")]
NoSlidingSyncInWellKnown,

/// The `sliding_sync_proxy` URL in .well-known` is not valid ({0}).
#[error("the `sliding_sync_proxy` URL in .well-known` is not valid ({0})")]
UnparsableSlidingSyncUrl(url::ParseError),

/// The `/versions` response is not set.
#[error("The `/versions` response is not set")]
MissingVersionsResponse,

/// `/versions` does not contain `org.matrix.simplified_msc3575` in its
/// `unstable_features`, or it's not set to true.
#[error("`/versions` does not contain `org.matrix.simplified_msc3575` in its `unstable_features`, or it's not set to true.")]
NativeVersionIsUnset,
}

/// A builder for [`Version`].
#[derive(Clone, Debug)]
pub enum VersionBuilder {
Expand Down Expand Up @@ -87,7 +110,7 @@ impl VersionBuilder {
self,
well_known: Option<&discover_homeserver::Response>,
versions: Option<&get_supported_versions::Response>,
) -> Result<Version, Error> {
) -> Result<Version, VersionBuilderError> {
Ok(match self {
Self::None => Version::None,

Expand All @@ -97,42 +120,27 @@ impl VersionBuilder {

Self::DiscoverProxy => {
let Some(well_known) = well_known else {
return Err(Error::VersionCannotBeDiscovered(
"`.well-known` is `None`".to_owned(),
));
return Err(VersionBuilderError::WellKnownNotSet);
};

let Some(info) = &well_known.sliding_sync_proxy else {
return Err(Error::VersionCannotBeDiscovered(
"`.well-known` does not contain a `sliding_sync_proxy` entry".to_owned(),
));
return Err(VersionBuilderError::NoSlidingSyncInWellKnown);
};

let url = Url::parse(&info.url).map_err(|e| {
Error::VersionCannotBeDiscovered(format!(
"`.well-known` contains an invalid `sliding_sync_proxy` entry ({e})"
))
})?;
let url =
Url::parse(&info.url).map_err(VersionBuilderError::UnparsableSlidingSyncUrl)?;

Version::Proxy { url }
}

Self::DiscoverNative => {
let Some(versions) = versions else {
return Err(Error::VersionCannotBeDiscovered(
"`/versions` is `None`".to_owned(),
));
return Err(VersionBuilderError::MissingVersionsResponse);
};

match versions.unstable_features.get("org.matrix.simplified_msc3575") {
Some(value) if *value => Version::Native,
_ => {
return Err(Error::VersionCannotBeDiscovered(
"`/versions` does not contain `org.matrix.simplified_msc3575` in its \
`unstable_features`"
.to_owned(),
))
}
_ => return Err(VersionBuilderError::NativeVersionIsUnset),
}
}
})
Expand Down Expand Up @@ -324,9 +332,11 @@ mod tests {
Mock, ResponseTemplate,
};

use super::{discover_homeserver, get_supported_versions, Error, Version, VersionBuilder};
use super::{discover_homeserver, get_supported_versions, Version, VersionBuilder};
use crate::{
error::Result, sliding_sync::http, test_utils::logged_in_client_with_server,
error::Result,
sliding_sync::{http, VersionBuilderError},
test_utils::logged_in_client_with_server,
SlidingSyncList, SlidingSyncMode,
};

Expand Down Expand Up @@ -373,9 +383,7 @@ mod tests {
fn test_version_builder_discover_proxy_no_well_known() {
assert_matches!(
VersionBuilder::DiscoverProxy.build(None, None),
Err(Error::VersionCannotBeDiscovered(msg)) => {
assert_eq!(msg, "`.well-known` is `None`");
}
Err(VersionBuilderError::WellKnownNotSet)
);
}

Expand All @@ -388,9 +396,7 @@ mod tests {

assert_matches!(
VersionBuilder::DiscoverProxy.build(Some(&response), None),
Err(Error::VersionCannotBeDiscovered(msg)) => {
assert_eq!(msg, "`.well-known` does not contain a `sliding_sync_proxy` entry");
}
Err(VersionBuilderError::NoSlidingSyncInWellKnown)
);
}

Expand All @@ -404,8 +410,8 @@ mod tests {

assert_matches!(
VersionBuilder::DiscoverProxy.build(Some(&response), None),
Err(Error::VersionCannotBeDiscovered(msg)) => {
assert_eq!(msg, "`.well-known` contains an invalid `sliding_sync_proxy` entry (relative URL without a base)");
Err(VersionBuilderError::UnparsableSlidingSyncUrl(err)) => {
assert_eq!(err.to_string(), "relative URL without a base");
}
);
}
Expand All @@ -425,9 +431,7 @@ mod tests {
fn test_version_builder_discover_native_no_supported_versions() {
assert_matches!(
VersionBuilder::DiscoverNative.build(None, None),
Err(Error::VersionCannotBeDiscovered(msg)) => {
assert_eq!(msg, "`/versions` is `None`".to_owned());
}
Err(VersionBuilderError::MissingVersionsResponse)
);
}

Expand All @@ -438,12 +442,7 @@ mod tests {

assert_matches!(
VersionBuilder::DiscoverNative.build(None, Some(&response)),
Err(Error::VersionCannotBeDiscovered(msg)) => {
assert_eq!(
msg,
"`/versions` does not contain `org.matrix.simplified_msc3575` in its `unstable_features`".to_owned()
);
}
Err(VersionBuilderError::NativeVersionIsUnset)
);
}

Expand Down
5 changes: 0 additions & 5 deletions crates/matrix-sdk/src/sliding_sync/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,6 @@ pub enum Error {
#[error("Sliding sync version is missing")]
VersionIsMissing,

/// Sliding sync version has been configured to be discovered,
/// but it has failed. See [`crate::sliding_sync::Version`].
#[error("Sliding sync version cannot be discovered: {0}")]
VersionCannotBeDiscovered(String),

/// The response we've received from the server can't be parsed or doesn't
/// match up with the current expectations on the client side. A
/// `sync`-restart might be required.
Expand Down
6 changes: 4 additions & 2 deletions crates/matrix-sdk/src/sliding_sync/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ use tracing::{debug, error, info, instrument, trace, warn, Instrument, Span};

#[cfg(feature = "e2e-encryption")]
use self::utils::JoinHandleExt as _;
pub use self::{builder::*, error::*, list::*, room::*};
pub use self::{builder::*, client::VersionBuilderError, error::*, list::*, room::*};
use self::{
cache::restore_sliding_sync_state,
client::SlidingSyncResponseProcessor,
Expand All @@ -74,6 +74,8 @@ pub(super) struct SlidingSyncInner {
/// Used to distinguish different connections to the sliding sync proxy.
id: String,

/// Either an overridden sliding sync [`Version`], or one inherited from the
/// client.
version: Version,
bnjbvr marked this conversation as resolved.
Show resolved Hide resolved

/// The HTTP Matrix client.
Expand Down Expand Up @@ -2005,7 +2007,7 @@ mod tests {
assert_matches!(sync.version(), Version::Native);
}

// Sliding can override the configuration from the client.
// Sliding sync can override the configuration from the client.
{
let url = Url::parse("https://bar.matrix/").unwrap();
let sync = client
Expand Down
Loading