matrix_sdk/client/
caches.rs

1// Copyright 2025 The Matrix.org Foundation C.I.C.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use matrix_sdk_base::{store::WellKnownResponse, ttl_cache::TtlCache};
16use ruma::api::{
17    SupportedVersions,
18    client::discovery::get_authorization_server_metadata::v1::AuthorizationServerMetadata,
19};
20use tokio::sync::RwLock;
21
22/// A collection of in-memory data that the `Client` might want to cache to
23/// avoid hitting the homeserver every time users request the data.
24pub(crate) struct ClientCaches {
25    /// The supported versions of the homeserver.
26    ///
27    /// We only want to cache:
28    ///
29    /// - The versions prefilled with `ClientBuilder::server_versions()`
30    /// - The versions fetched from an *authenticated* request to the server.
31    pub(crate) supported_versions: RwLock<CachedValue<SupportedVersions>>,
32    /// Well-known information.
33    pub(super) well_known: RwLock<CachedValue<Option<WellKnownResponse>>>,
34    pub(crate) server_metadata: tokio::sync::Mutex<TtlCache<String, AuthorizationServerMetadata>>,
35}
36
37/// A cached value that can either be set or not set, used to avoid confusion
38/// between a value that is set to `None` (because it doesn't exist) and a value
39/// that has not been cached yet.
40#[derive(Clone)]
41pub(crate) enum CachedValue<Value> {
42    /// A value has been cached.
43    Cached(Value),
44    /// Nothing has been cached yet.
45    NotSet,
46}
47
48impl<Value> CachedValue<Value> {
49    /// Takes the value out of the `CachedValue`, leaving a `NotSet` in its
50    /// place.
51    pub(super) fn take(&mut self) -> Option<Value> {
52        let prev = std::mem::replace(self, Self::NotSet);
53
54        match prev {
55            Self::Cached(value) => Some(value),
56            Self::NotSet => None,
57        }
58    }
59}