Skip to content

Commit c74295c

Browse files
pixlwavepoljar
authored andcommitted
chore: Refactor ServerCapabilities into ServerInfo.
It has nothing to do with /capabilities so is confusing. We can use this new struct to combine the well-known response into a single cache too.
1 parent ec30e7b commit c74295c

File tree

12 files changed

+141
-151
lines changed

12 files changed

+141
-151
lines changed

bindings/matrix-sdk-ffi/src/client.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -725,11 +725,11 @@ impl Client {
725725

726726
/// Empty the server version and unstable features cache.
727727
///
728-
/// Since the SDK caches server capabilities (versions and unstable
729-
/// features), it's possible to have a stale entry in the cache. This
730-
/// functions makes it possible to force reset it.
731-
pub async fn reset_server_capabilities(&self) -> Result<(), ClientError> {
732-
Ok(self.inner.reset_server_capabilities().await?)
728+
/// Since the SDK caches server info (versions, unstable features,
729+
/// well-known etc), it's possible to have a stale entry in the cache.
730+
/// This functions makes it possible to force reset it.
731+
pub async fn reset_server_info(&self) -> Result<(), ClientError> {
732+
Ok(self.inner.reset_server_info().await?)
733733
}
734734
}
735735

crates/matrix-sdk-base/src/store/integration_tests.rs

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use serde_json::{json, value::Value as JsonValue};
3434

3535
use super::{
3636
send_queue::SentRequestKey, DependentQueuedRequestKind, DisplayName, DynStateStore,
37-
RoomLoadSettings, ServerCapabilities,
37+
RoomLoadSettings, ServerInfo,
3838
};
3939
use crate::{
4040
deserialized_responses::MemberEvent,
@@ -90,8 +90,8 @@ pub trait StateStoreIntegrationTests {
9090
async fn test_send_queue_dependents(&self);
9191
/// Test an update to a send queue dependent request.
9292
async fn test_update_send_queue_dependent(&self);
93-
/// Test saving/restoring server capabilities.
94-
async fn test_server_capabilities_saving(&self);
93+
/// Test saving/restoring server info.
94+
async fn test_server_info_saving(&self);
9595
/// Test fetching room infos based on [`RoomLoadSettings`].
9696
async fn test_get_room_infos(&self);
9797
}
@@ -472,34 +472,36 @@ impl StateStoreIntegrationTests for DynStateStore {
472472
);
473473
}
474474

475-
async fn test_server_capabilities_saving(&self) {
475+
async fn test_server_info_saving(&self) {
476476
let versions = &[MatrixVersion::V1_1, MatrixVersion::V1_2, MatrixVersion::V1_11];
477-
let server_caps = ServerCapabilities::new(
478-
versions,
477+
let server_info = ServerInfo::new(
478+
versions.iter().map(|version| version.to_string()).collect(),
479479
[("org.matrix.experimental".to_owned(), true)].into(),
480480
);
481481

482482
self.set_kv_data(
483-
StateStoreDataKey::ServerCapabilities,
484-
StateStoreDataValue::ServerCapabilities(server_caps.clone()),
483+
StateStoreDataKey::ServerInfo,
484+
StateStoreDataValue::ServerInfo(server_info.clone()),
485485
)
486486
.await
487487
.unwrap();
488488

489489
assert_let!(
490-
Ok(Some(StateStoreDataValue::ServerCapabilities(stored_caps))) =
491-
self.get_kv_data(StateStoreDataKey::ServerCapabilities).await
490+
Ok(Some(StateStoreDataValue::ServerInfo(stored_info))) =
491+
self.get_kv_data(StateStoreDataKey::ServerInfo).await
492492
);
493-
assert_eq!(stored_caps, server_caps);
493+
assert_eq!(stored_info, server_info);
494494

495-
let (stored_versions, stored_features) = stored_caps.maybe_decode().unwrap();
495+
let decoded_server_info = stored_info.maybe_decode().unwrap();
496+
let stored_versions = decoded_server_info.known_versions();
497+
let stored_features = decoded_server_info.unstable_features;
496498

497499
assert_eq!(stored_versions, versions);
498500
assert_eq!(stored_features.len(), 1);
499501
assert_eq!(stored_features.get("org.matrix.experimental"), Some(&true));
500502

501-
self.remove_kv_data(StateStoreDataKey::ServerCapabilities).await.unwrap();
502-
assert_matches!(self.get_kv_data(StateStoreDataKey::ServerCapabilities).await, Ok(None));
503+
self.remove_kv_data(StateStoreDataKey::ServerInfo).await.unwrap();
504+
assert_matches!(self.get_kv_data(StateStoreDataKey::ServerInfo).await, Ok(None));
503505
}
504506

505507
async fn test_sync_token_saving(&self) {
@@ -1807,9 +1809,9 @@ macro_rules! statestore_integration_tests {
18071809
}
18081810

18091811
#[async_test]
1810-
async fn test_server_capabilities_saving() {
1812+
async fn test_server_info_saving() {
18111813
let store = get_store().await.unwrap().into_state_store();
1812-
store.test_server_capabilities_saving().await
1814+
store.test_server_info_saving().await
18131815
}
18141816

18151817
#[async_test]

crates/matrix-sdk-base/src/store/memory_store.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use tracing::{debug, instrument, warn};
3737

3838
use super::{
3939
send_queue::{ChildTransactionId, QueuedRequest, SentRequestKey},
40-
traits::{ComposerDraft, ServerCapabilities},
40+
traits::{ComposerDraft, ServerInfo},
4141
DependentQueuedRequest, DependentQueuedRequestKind, QueuedRequestKind, Result, RoomInfo,
4242
RoomLoadSettings, StateChanges, StateStore, StoreError,
4343
};
@@ -54,7 +54,7 @@ struct MemoryStoreInner {
5454
composer_drafts: HashMap<(OwnedRoomId, Option<OwnedEventId>), ComposerDraft>,
5555
user_avatar_url: HashMap<OwnedUserId, OwnedMxcUri>,
5656
sync_token: Option<String>,
57-
server_capabilities: Option<ServerCapabilities>,
57+
server_info: Option<ServerInfo>,
5858
filters: HashMap<String, String>,
5959
utd_hook_manager_data: Option<GrowableBloom>,
6060
account_data: HashMap<GlobalAccountDataEventType, Raw<AnyGlobalAccountDataEvent>>,
@@ -149,8 +149,8 @@ impl StateStore for MemoryStore {
149149
StateStoreDataKey::SyncToken => {
150150
inner.sync_token.clone().map(StateStoreDataValue::SyncToken)
151151
}
152-
StateStoreDataKey::ServerCapabilities => {
153-
inner.server_capabilities.clone().map(StateStoreDataValue::ServerCapabilities)
152+
StateStoreDataKey::ServerInfo => {
153+
inner.server_info.clone().map(StateStoreDataValue::ServerInfo)
154154
}
155155
StateStoreDataKey::Filter(filter_name) => {
156156
inner.filters.get(filter_name).cloned().map(StateStoreDataValue::Filter)
@@ -222,11 +222,9 @@ impl StateStore for MemoryStore {
222222
value.into_composer_draft().expect("Session data not a composer draft"),
223223
);
224224
}
225-
StateStoreDataKey::ServerCapabilities => {
226-
inner.server_capabilities = Some(
227-
value
228-
.into_server_capabilities()
229-
.expect("Session data not containing server capabilities"),
225+
StateStoreDataKey::ServerInfo => {
226+
inner.server_info = Some(
227+
value.into_server_info().expect("Session data not containing server info"),
230228
);
231229
}
232230
StateStoreDataKey::SeenKnockRequests(room_id) => {
@@ -246,7 +244,7 @@ impl StateStore for MemoryStore {
246244
let mut inner = self.inner.write().unwrap();
247245
match key {
248246
StateStoreDataKey::SyncToken => inner.sync_token = None,
249-
StateStoreDataKey::ServerCapabilities => inner.server_capabilities = None,
247+
StateStoreDataKey::ServerInfo => inner.server_info = None,
250248
StateStoreDataKey::Filter(filter_name) => {
251249
inner.filters.remove(filter_name);
252250
}

crates/matrix-sdk-base/src/store/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ pub use self::{
8181
SentMediaInfo, SentRequestKey, SerializableEventContent,
8282
},
8383
traits::{
84-
ComposerDraft, ComposerDraftType, DynStateStore, IntoStateStore, ServerCapabilities,
85-
StateStore, StateStoreDataKey, StateStoreDataValue, StateStoreExt,
84+
ComposerDraft, ComposerDraftType, DynStateStore, IntoStateStore, ServerInfo, StateStore,
85+
StateStoreDataKey, StateStoreDataValue, StateStoreExt,
8686
},
8787
};
8888

crates/matrix-sdk-base/src/store/traits.rs

Lines changed: 37 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use async_trait::async_trait;
2424
use growable_bloom_filter::GrowableBloom;
2525
use matrix_sdk_common::AsyncTraitDeps;
2626
use ruma::{
27-
api::MatrixVersion,
27+
api::{client::discovery::get_supported_versions, MatrixVersion},
2828
events::{
2929
presence::PresenceEvent,
3030
receipt::{Receipt, ReceiptThread, ReceiptType},
@@ -950,12 +950,11 @@ where
950950
}
951951
}
952952

953-
/// Server capabilities returned by the /client/versions endpoint.
953+
/// Useful server info such as data returned by the /client/versions and
954+
/// .well-known/client/matrix endpoints.
954955
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
955-
pub struct ServerCapabilities {
956+
pub struct ServerInfo {
956957
/// Versions supported by the remote server.
957-
///
958-
/// This contains [`MatrixVersion`]s converted to strings.
959958
pub versions: Vec<String>,
960959

961960
/// List of unstable features and their enablement status.
@@ -966,34 +965,37 @@ pub struct ServerCapabilities {
966965
last_fetch_ts: f64,
967966
}
968967

969-
impl ServerCapabilities {
968+
impl ServerInfo {
970969
/// The number of milliseconds after which the data is considered stale.
971970
pub const STALE_THRESHOLD: f64 = (1000 * 60 * 60 * 24 * 7) as _; // seven days
972971

973-
/// Encode server capabilities into this serializable struct.
974-
pub fn new(versions: &[MatrixVersion], unstable_features: BTreeMap<String, bool>) -> Self {
975-
Self {
976-
versions: versions.iter().map(|item| item.to_string()).collect(),
977-
unstable_features,
978-
last_fetch_ts: now_timestamp_ms(),
979-
}
972+
/// Encode server info into this serializable struct.
973+
pub fn new(versions: Vec<String>, unstable_features: BTreeMap<String, bool>) -> Self {
974+
Self { versions, unstable_features, last_fetch_ts: now_timestamp_ms() }
980975
}
981976

982-
/// Decode server capabilities from this serializable struct.
977+
/// Decode server info from this serializable struct.
983978
///
984979
/// May return `None` if the data is considered stale, after
985980
/// [`Self::STALE_THRESHOLD`] milliseconds since the last time we stored
986981
/// it.
987-
pub fn maybe_decode(&self) -> Option<(Vec<MatrixVersion>, BTreeMap<String, bool>)> {
982+
pub fn maybe_decode(&self) -> Option<Self> {
988983
if now_timestamp_ms() - self.last_fetch_ts >= Self::STALE_THRESHOLD {
989984
None
990985
} else {
991-
Some((
992-
self.versions.iter().filter_map(|item| item.parse().ok()).collect(),
993-
self.unstable_features.clone(),
994-
))
986+
Some(self.clone())
995987
}
996988
}
989+
990+
/// Extracts known Matrix versions from the un-typed list of strings.
991+
///
992+
/// Note: Matrix versions that Ruma cannot parse, or does not know about,
993+
/// are discarded.
994+
pub fn known_versions(&self) -> Vec<MatrixVersion> {
995+
get_supported_versions::Response::new(self.versions.clone())
996+
.known_versions()
997+
.collect::<Vec<_>>()
998+
}
997999
}
9981000

9991001
/// Get the current timestamp as the number of milliseconds since Unix Epoch.
@@ -1011,8 +1013,8 @@ pub enum StateStoreDataValue {
10111013
/// The sync token.
10121014
SyncToken(String),
10131015

1014-
/// The server capabilities.
1015-
ServerCapabilities(ServerCapabilities),
1016+
/// The server info (versions, well-known etc).
1017+
ServerInfo(ServerInfo),
10161018

10171019
/// A filter with the given ID.
10181020
Filter(String),
@@ -1097,9 +1099,9 @@ impl StateStoreDataValue {
10971099
as_variant!(self, Self::ComposerDraft)
10981100
}
10991101

1100-
/// Get this value if it is the server capabilities metadata.
1101-
pub fn into_server_capabilities(self) -> Option<ServerCapabilities> {
1102-
as_variant!(self, Self::ServerCapabilities)
1102+
/// Get this value if it is the server info metadata.
1103+
pub fn into_server_info(self) -> Option<ServerInfo> {
1104+
as_variant!(self, Self::ServerInfo)
11031105
}
11041106

11051107
/// Get this value if it is the data for the ignored join requests.
@@ -1114,8 +1116,8 @@ pub enum StateStoreDataKey<'a> {
11141116
/// The sync token.
11151117
SyncToken,
11161118

1117-
/// The server capabilities,
1118-
ServerCapabilities,
1119+
/// The server info,
1120+
ServerInfo,
11191121

11201122
/// A filter with the given name.
11211123
Filter(&'a str),
@@ -1143,9 +1145,9 @@ pub enum StateStoreDataKey<'a> {
11431145
impl StateStoreDataKey<'_> {
11441146
/// Key to use for the [`SyncToken`][Self::SyncToken] variant.
11451147
pub const SYNC_TOKEN: &'static str = "sync_token";
1146-
/// Key to use for the [`ServerCapabilities`][Self::ServerCapabilities]
1148+
/// Key to use for the [`ServerInfo`][Self::ServerInfo]
11471149
/// variant.
1148-
pub const SERVER_CAPABILITIES: &'static str = "server_capabilities";
1150+
pub const SERVER_INFO: &'static str = "server_capabilities"; // Note: this is the old name, kept for backwards compatibility.
11491151
/// Key prefix to use for the [`Filter`][Self::Filter] variant.
11501152
pub const FILTER: &'static str = "filter";
11511153
/// Key prefix to use for the [`UserAvatarUrl`][Self::UserAvatarUrl]
@@ -1171,21 +1173,21 @@ impl StateStoreDataKey<'_> {
11711173

11721174
#[cfg(test)]
11731175
mod tests {
1174-
use super::{now_timestamp_ms, ServerCapabilities};
1176+
use super::{now_timestamp_ms, ServerInfo};
11751177

11761178
#[test]
1177-
fn test_stale_server_capabilities() {
1178-
let mut caps = ServerCapabilities {
1179+
fn test_stale_server_info() {
1180+
let mut server_info = ServerInfo {
11791181
versions: Default::default(),
11801182
unstable_features: Default::default(),
1181-
last_fetch_ts: now_timestamp_ms() - ServerCapabilities::STALE_THRESHOLD - 1.0,
1183+
last_fetch_ts: now_timestamp_ms() - ServerInfo::STALE_THRESHOLD - 1.0,
11821184
};
11831185

11841186
// Definitely stale.
1185-
assert!(caps.maybe_decode().is_none());
1187+
assert!(server_info.maybe_decode().is_none());
11861188

11871189
// Definitely not stale.
1188-
caps.last_fetch_ts = now_timestamp_ms() - 1.0;
1189-
assert!(caps.maybe_decode().is_some());
1190+
server_info.last_fetch_ts = now_timestamp_ms() - 1.0;
1191+
assert!(server_info.maybe_decode().is_some());
11901192
}
11911193
}

crates/matrix-sdk-indexeddb/src/state_store/mod.rs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use matrix_sdk_base::{
2727
store::{
2828
ChildTransactionId, ComposerDraft, DependentQueuedRequest, DependentQueuedRequestKind,
2929
QueuedRequest, QueuedRequestKind, RoomLoadSettings, SentRequestKey,
30-
SerializableEventContent, ServerCapabilities, StateChanges, StateStore, StoreError,
30+
SerializableEventContent, ServerInfo, StateChanges, StateStore, StoreError,
3131
},
3232
MinimalRoomMemberEvent, RoomInfo, RoomMemberships, StateStoreDataKey, StateStoreDataValue,
3333
};
@@ -400,10 +400,9 @@ impl IndexeddbStateStore {
400400
StateStoreDataKey::SyncToken => {
401401
self.encode_key(StateStoreDataKey::SYNC_TOKEN, StateStoreDataKey::SYNC_TOKEN)
402402
}
403-
StateStoreDataKey::ServerCapabilities => self.encode_key(
404-
StateStoreDataKey::SERVER_CAPABILITIES,
405-
StateStoreDataKey::SERVER_CAPABILITIES,
406-
),
403+
StateStoreDataKey::ServerInfo => {
404+
self.encode_key(StateStoreDataKey::SERVER_INFO, StateStoreDataKey::SERVER_INFO)
405+
}
407406
StateStoreDataKey::Filter(filter_name) => {
408407
self.encode_key(StateStoreDataKey::FILTER, (StateStoreDataKey::FILTER, filter_name))
409408
}
@@ -537,10 +536,10 @@ impl_state_store!({
537536
.map(|f| self.deserialize_value::<String>(&f))
538537
.transpose()?
539538
.map(StateStoreDataValue::SyncToken),
540-
StateStoreDataKey::ServerCapabilities => value
541-
.map(|f| self.deserialize_value::<ServerCapabilities>(&f))
539+
StateStoreDataKey::ServerInfo => value
540+
.map(|f| self.deserialize_value::<ServerInfo>(&f))
542541
.transpose()?
543-
.map(StateStoreDataValue::ServerCapabilities),
542+
.map(StateStoreDataValue::ServerInfo),
544543
StateStoreDataKey::Filter(_) => value
545544
.map(|f| self.deserialize_value::<String>(&f))
546545
.transpose()?
@@ -580,10 +579,8 @@ impl_state_store!({
580579
let serialized_value = match key {
581580
StateStoreDataKey::SyncToken => self
582581
.serialize_value(&value.into_sync_token().expect("Session data not a sync token")),
583-
StateStoreDataKey::ServerCapabilities => self.serialize_value(
584-
&value
585-
.into_server_capabilities()
586-
.expect("Session data not containing server capabilities"),
582+
StateStoreDataKey::ServerInfo => self.serialize_value(
583+
&value.into_server_info().expect("Session data not containing server info"),
587584
),
588585
StateStoreDataKey::Filter(_) => {
589586
self.serialize_value(&value.into_filter().expect("Session data not a filter"))

crates/matrix-sdk-sqlite/src/state_store.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -410,9 +410,7 @@ impl SqliteStateStore {
410410
fn encode_state_store_data_key(&self, key: StateStoreDataKey<'_>) -> Key {
411411
let key_s = match key {
412412
StateStoreDataKey::SyncToken => Cow::Borrowed(StateStoreDataKey::SYNC_TOKEN),
413-
StateStoreDataKey::ServerCapabilities => {
414-
Cow::Borrowed(StateStoreDataKey::SERVER_CAPABILITIES)
415-
}
413+
StateStoreDataKey::ServerInfo => Cow::Borrowed(StateStoreDataKey::SERVER_INFO),
416414
StateStoreDataKey::Filter(f) => {
417415
Cow::Owned(format!("{}:{f}", StateStoreDataKey::FILTER))
418416
}
@@ -1029,8 +1027,8 @@ impl StateStore for SqliteStateStore {
10291027
StateStoreDataKey::SyncToken => {
10301028
StateStoreDataValue::SyncToken(self.deserialize_value(&data)?)
10311029
}
1032-
StateStoreDataKey::ServerCapabilities => {
1033-
StateStoreDataValue::ServerCapabilities(self.deserialize_value(&data)?)
1030+
StateStoreDataKey::ServerInfo => {
1031+
StateStoreDataValue::ServerInfo(self.deserialize_value(&data)?)
10341032
}
10351033
StateStoreDataKey::Filter(_) => {
10361034
StateStoreDataValue::Filter(self.deserialize_value(&data)?)
@@ -1064,10 +1062,8 @@ impl StateStore for SqliteStateStore {
10641062
StateStoreDataKey::SyncToken => self.serialize_value(
10651063
&value.into_sync_token().expect("Session data not a sync token"),
10661064
)?,
1067-
StateStoreDataKey::ServerCapabilities => self.serialize_value(
1068-
&value
1069-
.into_server_capabilities()
1070-
.expect("Session data not containing server capabilities"),
1065+
StateStoreDataKey::ServerInfo => self.serialize_value(
1066+
&value.into_server_info().expect("Session data not containing server info"),
10711067
)?,
10721068
StateStoreDataKey::Filter(_) => {
10731069
self.serialize_value(&value.into_filter().expect("Session data not a filter"))?

0 commit comments

Comments
 (0)