atagen

matrix-rust-sdk

public
Star0
Watch0

Commit 7a0452c1960f

tarball

atagen <boss@atagen.co>2026-10-26 07:33 UTC

3 files changed+36-3
room: never wait on the server to label an undecryptable event

crypto_context_info awaited backups().exists_on_server() for every UTD the timeline handles, under its state lock, and with nothing cached that is a room_keys/version request. Opening an encrypted room waited on it, and an erroring endpoint cost one request per UTD in series. It now reads the cache or guesses from the local backup state while one background fetch fills it. The answer only feeds UtdCause's historical labels.
Modified file: crates/matrix-sdk/src/encryption/backups/mod.rs+30 additions
@@ -416,6 +416,36 @@ impl Backups {
416416 Ok(exists_on_server)
417417 }
418418
419+ /// The cached answer to [`Self::exists_on_server`], or while nothing is cached, whether
420+ /// backups are enabled locally, with a fetch filling the cache in the background.
421+ ///
422+ /// For callers that must not wait on the network, such as UTD classification, which
423+ /// runs under the timeline's state lock for every undecryptable event it handles.
424+ pub(crate) fn exists_on_server_without_waiting(&self) -> bool {
425+ use std::sync::atomic::Ordering;
426+
427+ let state = &self.client.inner.e2ee.backup_state;
428+ if let Some(cached) = state.backup_exists_on_server() {
429+ return cached;
430+ }
431+ if !state.refreshing_exists_on_server.swap(true, Ordering::AcqRel) {
432+ let backups = self.clone();
433+ matrix_sdk_common::executor::spawn(async move {
434+ if let Err(error) = backups.fetch_exists_on_server().await {
435+ warn!("Couldn't check whether a backup exists on the server: {error:?}");
436+ }
437+ backups
438+ .client
439+ .inner
440+ .e2ee
441+ .backup_state
442+ .refreshing_exists_on_server
443+ .store(false, Ordering::Release);
444+ });
445+ }
446+ self.state() == BackupState::Enabled
447+ }
448+
419449 /// Does a backup exist on the server?
420450 ///
421451 /// This method is identical to [`Self::fetch_exists_on_server`] except that
Modified file: crates/matrix-sdk/src/encryption/backups/types.rs+5 additions−1 deletions
@@ -13,7 +13,7 @@
1313 // limitations under the License.
1414
1515 use std::{
16- sync::{Arc, RwLock},
16+ sync::{Arc, RwLock, atomic::AtomicBool},
1717 time::Duration,
1818 };
1919
@@ -61,6 +61,9 @@ pub(crate) struct BackupClientState {
6161 /// on the server was changed by some other client, we will have a old
6262 /// value.
6363 pub(super) backup_exists_on_server: RwLock<Option<bool>>,
64+
65+ /// Whether a background fetch is filling `backup_exists_on_server`.
66+ pub(super) refreshing_exists_on_server: AtomicBool,
6467 }
6568
6669 impl BackupClientState {
@@ -96,6 +99,7 @@ impl Default for BackupClientState {
9699 global_state: Default::default(),
97100 room_keys_broadcaster: broadcast::Sender::new(100),
98101 backup_exists_on_server: RwLock::new(None),
102+ refreshing_exists_on_server: AtomicBool::new(false),
99103 }
100104 }
101105 }
Modified file: crates/matrix-sdk/src/room/mod.rs+1 additions−2 deletions
@@ -1146,8 +1146,7 @@ impl Room {
11461146 _ => true,
11471147 };
11481148
1149- let backup_exists_on_server =
1150- encryption.backups().exists_on_server().await.unwrap_or(false);
1149+ let backup_exists_on_server = encryption.backups().exists_on_server_without_waiting();
11511150
11521151 CryptoContextInfo {
11531152 device_creation_ts: encryption.device_creation_timestamp().await,