Skip to content
Merged
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
4 changes: 4 additions & 0 deletions bindings/matrix-sdk-ffi/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ All notable changes to this project will be documented in this file.

## [Unreleased] - ReleaseDate

### Features

- Add `Client::get_store_sizes()` so to query the size of the existing stores, if available. ([#5911](https://github.com/matrix-org/matrix-rust-sdk/pull/5911))

### Breaking changes

- `TimelineConfiguration::track_read_receipts`'s type is now an enum to allow tracking to be enabled for all events
Expand Down
36 changes: 36 additions & 0 deletions bindings/matrix-sdk-ffi/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,17 @@ impl Client {

#[matrix_sdk_ffi_macros::export]
impl Client {
/// Perform database optimizations if any are available, i.e. vacuuming in
/// SQLite.
pub async fn optimize_stores(&self) -> Result<(), ClientError> {
Ok(self.inner.optimize_stores().await?)
}

/// Returns the sizes of the existing stores, if known.
pub async fn get_store_sizes(&self) -> Result<StoreSizes, ClientError> {
Copy link
Member

Choose a reason for hiding this comment

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

We usually don't have a get_ prefix, only a set_ prefix. It's not the end of the world, but so you know, it's more Rust idiomatic :-).

Ok(self.inner.get_store_sizes().await?.into())
}

/// Information about login options for the client's homeserver.
pub async fn homeserver_login_details(&self) -> Arc<HomeserverLoginDetails> {
let oauth = self.inner.oauth();
Expand Down Expand Up @@ -2851,3 +2862,28 @@ impl TryFrom<RumaAllowRule> for AllowRule {
}
}
}

/// Contains the disk size of the different stores, if known. It won't be
/// available for in-memory stores.
#[derive(Debug, Clone, uniffi::Record)]
pub struct StoreSizes {
/// The size of the CryptoStore.
crypto_store: Option<u64>,
/// The size of the StateStore.
state_store: Option<u64>,
/// The size of the EventCacheStore.
event_cache_store: Option<u64>,
/// The size of the MediaStore.
media_store: Option<u64>,
}

impl From<matrix_sdk::StoreSizes> for StoreSizes {
fn from(value: matrix_sdk::StoreSizes) -> Self {
Self {
crypto_store: value.crypto_store.map(|v| v as u64),
state_store: value.state_store.map(|v| v as u64),
event_cache_store: value.event_cache_store.map(|v| v as u64),
media_store: value.media_store.map(|v| v as u64),
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,14 @@ impl EventCacheStore for MemoryStore {
self.inner.write().unwrap().events.save_item(room_id.to_owned(), event);
Ok(())
}

async fn optimize(&self) -> Result<(), Self::Error> {
Ok(())
}

async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
Ok(None)
}
}

#[cfg(test)]
Expand Down
20 changes: 20 additions & 0 deletions crates/matrix-sdk-base/src/event_cache/store/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,17 @@ pub trait EventCacheStore: AsyncTraitDeps {
/// If the event was already stored with the same id, it must be replaced,
/// without causing an error.
async fn save_event(&self, room_id: &RoomId, event: Event) -> Result<(), Self::Error>;

/// Perform database optimizations if any are available, i.e. vacuuming in
/// SQLite.
///
/// **Warning:** this was added to check if SQLite fragmentation was the
/// source of performance issues, **DO NOT use in production**.
#[doc(hidden)]
async fn optimize(&self) -> Result<(), Self::Error>;

/// Returns the size of the store in bytes, if known.
async fn get_size(&self) -> Result<Option<usize>, Self::Error>;
}

#[repr(transparent)]
Expand Down Expand Up @@ -282,6 +293,15 @@ impl<T: EventCacheStore> EventCacheStore for EraseEventCacheStoreError<T> {
async fn save_event(&self, room_id: &RoomId, event: Event) -> Result<(), Self::Error> {
self.0.save_event(room_id, event).await.map_err(Into::into)
}

async fn optimize(&self) -> Result<(), Self::Error> {
self.0.optimize().await.map_err(Into::into)?;
Ok(())
}

async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
Ok(self.0.get_size().await.map_err(Into::into)?)
}
}

/// A type-erased [`EventCacheStore`].
Expand Down
8 changes: 8 additions & 0 deletions crates/matrix-sdk-base/src/media/store/memory_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,14 @@ impl MediaStore for MemoryMediaStore {
async fn clean(&self) -> Result<(), Self::Error> {
self.media_service.clean(self).await
}

async fn optimize(&self) -> Result<(), Self::Error> {
Ok(())
}

async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
Ok(None)
}
}

#[cfg_attr(target_family = "wasm", async_trait(?Send))]
Expand Down
19 changes: 19 additions & 0 deletions crates/matrix-sdk-base/src/media/store/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,17 @@ pub trait MediaStore: AsyncTraitDeps {
///
/// If there is already an ongoing cleanup, this is a noop.
async fn clean(&self) -> Result<(), Self::Error>;

/// Perform database optimizations if any are available, i.e. vacuuming in
/// SQLite.
///
/// **Warning:** this was added to check if SQLite fragmentation was the
/// source of performance issues, **DO NOT use in production**.
#[doc(hidden)]
async fn optimize(&self) -> Result<(), Self::Error>;

/// Returns the size of the store in bytes, if known.
async fn get_size(&self) -> Result<Option<usize>, Self::Error>;
}

/// An abstract trait that can be used to implement different store backends
Expand Down Expand Up @@ -381,6 +392,14 @@ impl<T: MediaStore> MediaStore for EraseMediaStoreError<T> {
async fn clean(&self) -> Result<(), Self::Error> {
self.0.clean().await.map_err(Into::into)
}

async fn optimize(&self) -> Result<(), Self::Error> {
self.0.optimize().await.map_err(Into::into)
}

async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
self.0.get_size().await.map_err(Into::into)
}
}

/// A type-erased [`MediaStore`].
Expand Down
8 changes: 8 additions & 0 deletions crates/matrix-sdk-base/src/store/memory_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,14 @@ impl StateStore for MemoryStore {

Ok(())
}

async fn optimize(&self) -> Result<(), Self::Error> {
Ok(())
}

async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
Ok(None)
}
}

#[cfg(test)]
Expand Down
19 changes: 19 additions & 0 deletions crates/matrix-sdk-base/src/store/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,17 @@ pub trait StateStore: AsyncTraitDeps {
room: &RoomId,
thread_id: &EventId,
) -> Result<Option<StoredThreadSubscription>, Self::Error>;

/// Perform database optimizations if any are available, i.e. vacuuming in
/// SQLite.
///
/// /// **Warning:** this was added to check if SQLite fragmentation was the
/// source of performance issues, **DO NOT use in production**.
#[doc(hidden)]
async fn optimize(&self) -> Result<(), Self::Error>;

/// Returns the size of the store in bytes, if known.
async fn get_size(&self) -> Result<Option<usize>, Self::Error>;
}

#[repr(transparent)]
Expand Down Expand Up @@ -832,6 +843,14 @@ impl<T: StateStore> StateStore for EraseStateStoreError<T> {
) -> Result<(), Self::Error> {
self.0.remove_thread_subscription(room, thread_id).await.map_err(Into::into)
}

async fn optimize(&self) -> Result<(), Self::Error> {
self.0.optimize().await.map_err(Into::into)
}

async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
self.0.get_size().await.map_err(Into::into)
}
}

/// Convenience functionality for state stores.
Expand Down
8 changes: 8 additions & 0 deletions crates/matrix-sdk-crypto/src/store/memorystore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,10 @@ impl CryptoStore for MemoryStore {
) -> Result<Option<CrossProcessLockGeneration>> {
Ok(try_take_leased_lock(&mut self.leases.write(), lease_duration_ms, key, holder))
}

async fn get_size(&self) -> Result<Option<usize>> {
Ok(None)
}
}

#[cfg(test)]
Expand Down Expand Up @@ -1598,6 +1602,10 @@ mod integration_tests {
async fn next_batch_token(&self) -> Result<Option<String>, Self::Error> {
self.0.next_batch_token().await
}

async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
self.0.get_size().await
}
}

cryptostore_integration_tests!();
Expand Down
7 changes: 7 additions & 0 deletions crates/matrix-sdk-crypto/src/store/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,9 @@ pub trait CryptoStore: AsyncTraitDeps {

/// Load the next-batch token for a to-device query, if any.
async fn next_batch_token(&self) -> Result<Option<String>, Self::Error>;

/// Returns the size of the store in bytes, if known.
async fn get_size(&self) -> Result<Option<usize>, Self::Error>;
}

#[repr(transparent)]
Expand Down Expand Up @@ -648,6 +651,10 @@ impl<T: CryptoStore> CryptoStore for EraseCryptoStoreError<T> {
async fn next_batch_token(&self) -> Result<Option<String>, Self::Error> {
self.0.next_batch_token().await.map_err(Into::into)
}

async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
self.0.get_size().await.map_err(Into::into)
}
}

/// A type-erased [`CryptoStore`].
Expand Down
5 changes: 5 additions & 0 deletions crates/matrix-sdk-indexeddb/src/crypto_store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1657,6 +1657,11 @@ impl_crypto_store! {
None
})
}

#[allow(clippy::unused_async)]
async fn get_size(&self) -> Result<Option<usize>> {
Ok(None)
}
}

impl Drop for IndexeddbCryptoStore {
Expand Down
8 changes: 8 additions & 0 deletions crates/matrix-sdk-indexeddb/src/event_cache_store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,14 @@ impl EventCacheStore for IndexeddbEventCacheStore {
transaction.commit().await?;
Ok(())
}

async fn optimize(&self) -> Result<(), Self::Error> {
Ok(())
}

async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
Ok(None)
}
}

#[cfg(all(test, target_family = "wasm"))]
Expand Down
8 changes: 8 additions & 0 deletions crates/matrix-sdk-indexeddb/src/media_store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,14 @@ impl MediaStore for IndexeddbMediaStore {
let _timer = timer!("method");
self.media_service.clean(self).await
}

async fn optimize(&self) -> Result<(), Self::Error> {
Ok(())
}

async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
Ok(None)
}
}

#[cfg(target_family = "wasm")]
Expand Down
10 changes: 10 additions & 0 deletions crates/matrix-sdk-indexeddb/src/state_store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2026,6 +2026,16 @@ impl_state_store!({

Ok(())
}

#[allow(clippy::unused_async)]
async fn optimize(&self) -> Result<()> {
Ok(())
}

#[allow(clippy::unused_async)]
async fn get_size(&self) -> Result<Option<usize>> {
Ok(None)
}
});

/// A room member.
Expand Down
4 changes: 4 additions & 0 deletions crates/matrix-sdk-sqlite/src/crypto_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1549,6 +1549,10 @@ impl CryptoStore for SqliteCryptoStore {
Ok(None)
}
}

async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
Ok(Some(self.pool.get().await?.get_db_size().await?))
}
}

#[cfg(test)]
Expand Down
16 changes: 16 additions & 0 deletions crates/matrix-sdk-sqlite/src/event_cache_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,14 @@ impl SqliteEventCacheStore {
relates_to: relates_to.map(|relates_to| relates_to.to_string()),
})
}

pub async fn vacuum(&self) -> Result<()> {
self.write_connection.lock().await.vacuum().await
}

async fn get_db_size(&self) -> Result<Option<usize>> {
Ok(Some(self.pool.get().await?.get_db_size().await?))
}
}

struct EncodedEvent {
Expand Down Expand Up @@ -1426,6 +1434,14 @@ impl EventCacheStore for SqliteEventCacheStore {
})
.await
}

async fn optimize(&self) -> Result<(), Self::Error> {
Ok(self.vacuum().await?)
}

async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
self.get_db_size().await
}
}

fn find_event_relations_transaction(
Expand Down
16 changes: 16 additions & 0 deletions crates/matrix-sdk-sqlite/src/media_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,14 @@ impl SqliteMediaStore {

Ok(connection)
}

pub async fn vacuum(&self) -> Result<()> {
self.write_connection.lock().await.vacuum().await
}

async fn get_db_size(&self) -> Result<Option<usize>> {
Ok(Some(self.pool.get().await?.get_db_size().await?))
}
}

/// Run migrations for the given version of the database.
Expand Down Expand Up @@ -389,6 +397,14 @@ impl MediaStore for SqliteMediaStore {

self.media_service.clean(self).await
}

async fn optimize(&self) -> Result<(), Self::Error> {
Ok(self.vacuum().await?)
}

async fn get_size(&self) -> Result<Option<usize>, Self::Error> {
self.get_db_size().await
}
}

#[cfg_attr(target_family = "wasm", async_trait(?Send))]
Expand Down
Loading
Loading