Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions bindings/matrix-sdk-ffi/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ All notable changes to this project will be documented in this file.

## [Unreleased] - ReleaseDate

### Breaking changes

- `Client::reset_server_info()` has been split into `reset_supported_versions()`
and `reset_well_known()`.
([#5910](https://github.com/matrix-org/matrix-rust-sdk/pull/5910))

## [0.15.0] - 2025-11-27

### Breaking changes
Expand Down
19 changes: 14 additions & 5 deletions bindings/matrix-sdk-ffi/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1008,11 +1008,20 @@ impl Client {

/// Empty the server version and unstable features cache.
///
/// Since the SDK caches server info (versions, unstable features,
/// well-known etc), it's possible to have a stale entry in the cache.
/// This functions makes it possible to force reset it.
pub async fn reset_server_info(&self) -> Result<(), ClientError> {
Ok(self.inner.reset_server_info().await?)
/// Since the SDK caches the supported versions, it's possible to have a
/// stale entry in the cache. This functions makes it possible to force
/// reset it.
pub async fn reset_supported_versions(&self) -> Result<(), ClientError> {
Ok(self.inner.reset_supported_versions().await?)
}

/// Empty the well-known cache.
///
/// Since the SDK caches the well-known, it's possible to have a stale
/// entry in the cache. This functions makes it possible to force reset
/// it.
pub async fn reset_well_known(&self) -> Result<(), ClientError> {
Ok(self.inner.reset_well_known().await?)
}
}

Expand Down
11 changes: 11 additions & 0 deletions crates/matrix-sdk-base/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@ All notable changes to this project will be documented in this file.

## [Unreleased] - ReleaseDate

### Refactor

- [**breaking**] `ServerInfo` has been renamed to `SupportedVersionsResponse`,
and its `well_known` field has been removed. It is also wrapped in a
`TtlStoreValue` that handles the expiration of the data, rather than calling
`maybe_decode()`. Its constructor has been removed since all its fields are
now public.
([#5910](https://github.com/matrix-org/matrix-rust-sdk/pull/5910))
- `StateStoreData(Key/Value)::ServerInfo` has been split into the
`SupportedVersions` and `WellKnown` variants.

## [0.15.0] - 2025-11-27

### Refactor
Expand Down
95 changes: 68 additions & 27 deletions crates/matrix-sdk-base/src/store/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ use ruma::{
use serde_json::{json, value::Value as JsonValue};

use super::{
DependentQueuedRequestKind, DisplayName, DynStateStore, RoomLoadSettings, ServerInfo,
WellKnownResponse, send_queue::SentRequestKey,
DependentQueuedRequestKind, DisplayName, DynStateStore, RoomLoadSettings,
SupportedVersionsResponse, TtlStoreValue, WellKnownResponse, send_queue::SentRequestKey,
};
use crate::{
RoomInfo, RoomMemberships, RoomState, StateChanges, StateStoreDataKey, StateStoreDataValue,
Expand Down Expand Up @@ -101,8 +101,10 @@ pub trait StateStoreIntegrationTests {
async fn test_send_queue_dependents(&self) -> TestResult;
/// Test an update to a send queue dependent request.
async fn test_update_send_queue_dependent(&self) -> TestResult;
/// Test saving/restoring server info.
async fn test_server_info_saving(&self) -> TestResult;
/// Test saving/restoring the supported versions of the server.
async fn test_supported_versions_saving(&self) -> TestResult;
/// Test saving/restoring the well-known info of the server.
async fn test_well_known_saving(&self) -> TestResult;
/// Test fetching room infos based on [`RoomLoadSettings`].
async fn test_get_room_infos(&self) -> TestResult;
/// Test loading thread subscriptions.
Expand Down Expand Up @@ -486,41 +488,74 @@ impl StateStoreIntegrationTests for DynStateStore {
Ok(())
}

async fn test_server_info_saving(&self) -> TestResult {
async fn test_supported_versions_saving(&self) -> TestResult {
let versions =
BTreeSet::from([MatrixVersion::V1_1, MatrixVersion::V1_2, MatrixVersion::V1_11]);
let server_info = ServerInfo::new(
versions.iter().map(|version| version.as_str().unwrap().to_owned()).collect(),
[("org.matrix.experimental".to_owned(), true)].into(),
Some(WellKnownResponse {
homeserver: HomeserverInfo::new("matrix.example.com".to_owned()),
identity_server: None,
tile_server: None,
rtc_foci: vec![RtcFocusInfo::livekit("livekit.example.com".to_owned())],
}),
);
let supported_versions = SupportedVersionsResponse {
versions: versions.iter().map(|version| version.as_str().unwrap().to_owned()).collect(),
unstable_features: [("org.matrix.experimental".to_owned(), true)].into(),
};

self.set_kv_data(
StateStoreDataKey::ServerInfo,
StateStoreDataValue::ServerInfo(server_info.clone()),
StateStoreDataKey::SupportedVersions,
StateStoreDataValue::SupportedVersions(TtlStoreValue::new(supported_versions.clone())),
)
.await?;

assert_let!(
Ok(Some(StateStoreDataValue::ServerInfo(stored_info))) =
self.get_kv_data(StateStoreDataKey::ServerInfo).await
Ok(Some(StateStoreDataValue::SupportedVersions(stored_supported_versions))) =
self.get_kv_data(StateStoreDataKey::SupportedVersions).await
);
assert_eq!(stored_info, server_info);

let decoded_server_info = stored_info.maybe_decode().unwrap();
let stored_supported = decoded_server_info.supported_versions();
assert_let!(Some(stored_supported_versions) = stored_supported_versions.into_data());
assert_eq!(supported_versions, stored_supported_versions);

let stored_supported = stored_supported_versions.supported_versions();
assert_eq!(stored_supported.versions, versions);
assert_eq!(stored_supported.features.len(), 1);
assert!(stored_supported.features.contains(&FeatureFlag::from("org.matrix.experimental")));

self.remove_kv_data(StateStoreDataKey::ServerInfo).await?;
assert_matches!(self.get_kv_data(StateStoreDataKey::ServerInfo).await, Ok(None));
self.remove_kv_data(StateStoreDataKey::SupportedVersions).await?;
assert_matches!(self.get_kv_data(StateStoreDataKey::SupportedVersions).await, Ok(None));

Ok(())
}

async fn test_well_known_saving(&self) -> TestResult {
let well_known = WellKnownResponse {
homeserver: HomeserverInfo::new("matrix.example.com".to_owned()),
identity_server: None,
tile_server: None,
rtc_foci: vec![RtcFocusInfo::livekit("livekit.example.com".to_owned())],
};

self.set_kv_data(
StateStoreDataKey::WellKnown,
StateStoreDataValue::WellKnown(TtlStoreValue::new(Some(well_known.clone()))),
)
.await?;

assert_let!(
Ok(Some(StateStoreDataValue::WellKnown(stored_well_known))) =
self.get_kv_data(StateStoreDataKey::WellKnown).await
);
assert_let!(Some(stored_well_known) = stored_well_known.into_data());
assert_eq!(stored_well_known, Some(well_known));

self.remove_kv_data(StateStoreDataKey::WellKnown).await?;
assert_matches!(self.get_kv_data(StateStoreDataKey::WellKnown).await, Ok(None));

self.set_kv_data(
StateStoreDataKey::WellKnown,
StateStoreDataValue::WellKnown(TtlStoreValue::new(None)),
)
.await?;

assert_let!(
Ok(Some(StateStoreDataValue::WellKnown(stored_well_known))) =
self.get_kv_data(StateStoreDataKey::WellKnown).await
);
assert_let!(Some(stored_well_known) = stored_well_known.into_data());
assert_eq!(stored_well_known, None);

Ok(())
}
Expand Down Expand Up @@ -2023,9 +2058,15 @@ macro_rules! statestore_integration_tests {
}

#[async_test]
async fn test_server_info_saving() -> TestResult {
async fn test_supported_versions_saving() -> TestResult {
let store = get_store().await?.into_state_store();
store.test_supported_versions_saving().await
}

#[async_test]
async fn test_well_known_saving() -> TestResult {
let store = get_store().await?.into_state_store();
store.test_server_info_saving().await
store.test_well_known_saving().await
}

#[async_test]
Expand Down
30 changes: 21 additions & 9 deletions crates/matrix-sdk-base/src/store/memory_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,10 @@ use tracing::{debug, instrument, warn};

use super::{
DependentQueuedRequest, DependentQueuedRequestKind, QueuedRequestKind, Result, RoomInfo,
RoomLoadSettings, StateChanges, StateStore, StoreError,
RoomLoadSettings, StateChanges, StateStore, StoreError, SupportedVersionsResponse,
TtlStoreValue, WellKnownResponse,
send_queue::{ChildTransactionId, QueuedRequest, SentRequestKey},
traits::{ComposerDraft, ServerInfo},
traits::ComposerDraft,
};
use crate::{
MinimalRoomMemberEvent, RoomMemberships, StateStoreDataKey, StateStoreDataValue,
Expand All @@ -58,7 +59,8 @@ struct MemoryStoreInner {
composer_drafts: HashMap<(OwnedRoomId, Option<OwnedEventId>), ComposerDraft>,
user_avatar_url: HashMap<OwnedUserId, OwnedMxcUri>,
sync_token: Option<String>,
server_info: Option<ServerInfo>,
supported_versions: Option<TtlStoreValue<SupportedVersionsResponse>>,
well_known: Option<TtlStoreValue<Option<WellKnownResponse>>>,
filters: HashMap<String, String>,
utd_hook_manager_data: Option<GrowableBloom>,
one_time_key_uploaded_error: bool,
Expand Down Expand Up @@ -156,8 +158,11 @@ impl StateStore for MemoryStore {
StateStoreDataKey::SyncToken => {
inner.sync_token.clone().map(StateStoreDataValue::SyncToken)
}
StateStoreDataKey::ServerInfo => {
inner.server_info.clone().map(StateStoreDataValue::ServerInfo)
StateStoreDataKey::SupportedVersions => {
inner.supported_versions.clone().map(StateStoreDataValue::SupportedVersions)
}
StateStoreDataKey::WellKnown => {
inner.well_known.clone().map(StateStoreDataValue::WellKnown)
}
StateStoreDataKey::Filter(filter_name) => {
inner.filters.get(filter_name).cloned().map(StateStoreDataValue::Filter)
Expand Down Expand Up @@ -239,11 +244,17 @@ impl StateStore for MemoryStore {
value.into_composer_draft().expect("Session data not a composer draft"),
);
}
StateStoreDataKey::ServerInfo => {
inner.server_info = Some(
value.into_server_info().expect("Session data not containing server info"),
StateStoreDataKey::SupportedVersions => {
inner.supported_versions = Some(
value
.into_supported_versions()
.expect("Session data not containing supported versions"),
);
}
StateStoreDataKey::WellKnown => {
inner.well_known =
Some(value.into_well_known().expect("Session data not containing well-known"));
}
StateStoreDataKey::SeenKnockRequests(room_id) => {
inner.seen_knock_requests.insert(
room_id.to_owned(),
Expand All @@ -267,7 +278,8 @@ impl StateStore for MemoryStore {
let mut inner = self.inner.write().unwrap();
match key {
StateStoreDataKey::SyncToken => inner.sync_token = None,
StateStoreDataKey::ServerInfo => inner.server_info = None,
StateStoreDataKey::SupportedVersions => inner.supported_versions = None,
StateStoreDataKey::WellKnown => inner.well_known = None,
StateStoreDataKey::Filter(filter_name) => {
inner.filters.remove(filter_name);
}
Expand Down
5 changes: 3 additions & 2 deletions crates/matrix-sdk-base/src/store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,9 @@ pub use self::{
},
traits::{
ComposerDraft, ComposerDraftType, DraftAttachment, DraftAttachmentContent, DraftThumbnail,
DynStateStore, IntoStateStore, ServerInfo, StateStore, StateStoreDataKey,
StateStoreDataValue, StateStoreExt, ThreadSubscriptionCatchupToken, WellKnownResponse,
DynStateStore, IntoStateStore, StateStore, StateStoreDataKey, StateStoreDataValue,
StateStoreExt, SupportedVersionsResponse, ThreadSubscriptionCatchupToken, TtlStoreValue,
WellKnownResponse,
},
};

Expand Down
Loading
Loading