diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4fb8cd866..8346f1d74 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,9 +34,9 @@ jobs: matrix: name: - no-encryption - - no-sled - - no-encryption-and-sled - - sled-cryptostore + - no-sqlite + - no-encryption-and-sqlite + - sqlite-cryptostore - rustls-tls - markdown - socks diff --git a/Cargo.lock b/Cargo.lock index f30e2ce13..4064c0bc1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2633,7 +2633,7 @@ dependencies = [ "matrix-sdk-base", "matrix-sdk-common", "matrix-sdk-indexeddb", - "matrix-sdk-sled", + "matrix-sdk-sqlite", "matrix-sdk-test", "mime", "mime2ext", diff --git a/crates/matrix-sdk-appservice/Cargo.toml b/crates/matrix-sdk-appservice/Cargo.toml index ad13da650..ea5f5f0c6 100644 --- a/crates/matrix-sdk-appservice/Cargo.toml +++ b/crates/matrix-sdk-appservice/Cargo.toml @@ -19,7 +19,7 @@ e2e-encryption = [ "matrix-sdk/e2e-encryption" ] eyre = ["matrix-sdk/eyre"] -sled = ["matrix-sdk/sled"] +sqlite = ["matrix-sdk/sqlite"] markdown = ["matrix-sdk/markdown"] native-tls = ["matrix-sdk/native-tls"] diff --git a/crates/matrix-sdk-crypto/src/store/mod.rs b/crates/matrix-sdk-crypto/src/store/mod.rs index 4a0e50842..0548a54a9 100644 --- a/crates/matrix-sdk-crypto/src/store/mod.rs +++ b/crates/matrix-sdk-crypto/src/store/mod.rs @@ -17,7 +17,7 @@ //! The storage layer for the [`OlmMachine`] can be customized using a trait. //! Implementing your own [`CryptoStore`] //! -//! An in-memory only store is provided as well as a Sled based one, depending +//! An in-memory only store is provided as well as a SQLite-based one, depending //! on your needs and targets a custom store may be implemented, e.g. for //! `wasm-unknown-unknown` an indexeddb store would be needed //! diff --git a/crates/matrix-sdk-sqlite/src/lib.rs b/crates/matrix-sdk-sqlite/src/lib.rs index 267dd4687..b2f64cf7b 100644 --- a/crates/matrix-sdk-sqlite/src/lib.rs +++ b/crates/matrix-sdk-sqlite/src/lib.rs @@ -16,7 +16,10 @@ allow(dead_code, unused_imports) )] +use std::path::Path; + use deadpool_sqlite::Object as SqliteConn; +use matrix_sdk_base::store::StoreConfig; use matrix_sdk_store_encryption::StoreCipher; #[cfg(feature = "crypto-store")] @@ -63,3 +66,26 @@ fn init_logging() { .with(tracing_subscriber::fmt::layer().with_test_writer()) .init(); } + +/// Create a [`StoreConfig`] with an opened [`SqliteStateStore`] in the given +/// directory and using the given passphrase. If the `crypto-store` feature is +/// enabled, a [`SqliteCryptoStore`] with the same parameters is also opened. +#[cfg(feature = "state-store")] +pub async fn make_store_config( + path: &Path, + passphrase: Option<&str>, +) -> Result { + let state_store = SqliteStateStore::open(path, passphrase).await?; + let config = StoreConfig::new().state_store(state_store); + + #[cfg(feature = "crypto-store")] + { + let crypto_store = SqliteCryptoStore::open(path, passphrase).await?; + Ok(config.crypto_store(crypto_store)) + } + + #[cfg(not(feature = "crypto-store"))] + { + Ok(config) + } +} diff --git a/crates/matrix-sdk/CHANGELOG.md b/crates/matrix-sdk/CHANGELOG.md index 9950ba377..b1bc4d286 100644 --- a/crates/matrix-sdk/CHANGELOG.md +++ b/crates/matrix-sdk/CHANGELOG.md @@ -3,6 +3,8 @@ - `Common::members` and `Common::members_no_sync` take a `RoomMemberships` to be able to filter the results by any membership state. - `Common::active_members(_no_sync)` and `Common::joined_members(_no_sync)` are deprecated. +- `matrix-sdk-sqlite` is the new default store implementation outside of WASM, behind the `sqlite` feature. + - The `sled` feature was removed. It is still possible to use `matrix-sdk-sled` as a custom store. # 0.6.2 diff --git a/crates/matrix-sdk/Cargo.toml b/crates/matrix-sdk/Cargo.toml index 5d6f9327b..0099cdc9d 100644 --- a/crates/matrix-sdk/Cargo.toml +++ b/crates/matrix-sdk/Cargo.toml @@ -19,7 +19,7 @@ rustdoc-args = ["--cfg", "docsrs"] default = [ "e2e-encryption", "automatic-room-key-forwarding", - "sled", + "sqlite", "native-tls", ] testing = [] @@ -27,12 +27,12 @@ testing = [] e2e-encryption = [ "matrix-sdk-base/e2e-encryption", "matrix-sdk-base/automatic-room-key-forwarding", - "matrix-sdk-sled?/crypto-store", # activate crypto-store on sled if given + "matrix-sdk-sqlite?/crypto-store", # activate crypto-store on sqlite if given "matrix-sdk-indexeddb?/e2e-encryption", # activate on indexeddb if given ] js = ["matrix-sdk-common/js", "matrix-sdk-base/js"] -sled = ["dep:matrix-sdk-sled", "matrix-sdk-sled?/state-store"] +sqlite = ["dep:matrix-sdk-sqlite", "matrix-sdk-sqlite?/state-store"] indexeddb = ["dep:matrix-sdk-indexeddb"] qrcode = ["e2e-encryption", "matrix-sdk-base/qrcode"] @@ -57,7 +57,7 @@ experimental-sliding-sync = [ docsrs = [ "e2e-encryption", - "sled", + "sqlite", "sso-login", "qrcode", "image-proc", @@ -85,7 +85,7 @@ hyper = { version = "0.14.20", features = ["http1", "http2", "server"], optional matrix-sdk-base = { version = "0.6.0", path = "../matrix-sdk-base", default_features = false } matrix-sdk-common = { version = "0.6.0", path = "../matrix-sdk-common" } matrix-sdk-indexeddb = { version = "0.2.0", path = "../matrix-sdk-indexeddb", default-features = false, optional = true } -matrix-sdk-sled = { version = "0.2.0", path = "../matrix-sdk-sled", default-features = false, optional = true } +matrix-sdk-sqlite = { version = "0.1.0", path = "../matrix-sdk-sqlite", default-features = false, optional = true } mime = "0.3.16" mime2ext = "0.1.52" once_cell = { workspace = true } diff --git a/crates/matrix-sdk/README.md b/crates/matrix-sdk/README.md index 450d789fa..0490ae5ad 100644 --- a/crates/matrix-sdk/README.md +++ b/crates/matrix-sdk/README.md @@ -65,7 +65,7 @@ The following crate feature flags are available: | `js` | No | Enables JavaScript API usage for things like the current system time on WASM (does nothing on other targets) | | `markdown` | No | Support for sending Markdown-formatted messages | | `qrcode` | Yes | QR code verification support | -| `sled` | Yes | Persistent storage of state and E2EE data (optionally, if feature `e2e-encryption` is enabled), via Sled | +| `sqlite` | Yes | Persistent storage of state and E2EE data (optionally, if feature `e2e-encryption` is enabled), via SQLite | | `indexeddb` | No | Persistent storage of state and E2EE data (optionally, if feature `e2e-encryption` is enabled) for browsers, via IndexedDB | | `socks` | No | SOCKS support in the default HTTP client, [`reqwest`] | | `sso-login` | No | Support for SSO login with a local HTTP server | diff --git a/crates/matrix-sdk/src/client/builder.rs b/crates/matrix-sdk/src/client/builder.rs index 83816431f..67bcc104a 100644 --- a/crates/matrix-sdk/src/client/builder.rs +++ b/crates/matrix-sdk/src/client/builder.rs @@ -118,19 +118,19 @@ impl ClientBuilder { self } - /// Set up the store configuration for a sled store. + /// Set up the store configuration for a SQLite store. /// /// This is the same as - /// .[store_config](Self::store_config)([matrix_sdk_sled]::[make_store_config](matrix_sdk_sled::make_store_config)(path, passphrase)?). + /// .[store_config](Self::store_config)([matrix_sdk_sqlite]::[make_store_config](matrix_sdk_sqlite::make_store_config)(path, passphrase)?). /// except it delegates the actual store config creation to when /// `.build().await` is called. - #[cfg(feature = "sled")] - pub fn sled_store( + #[cfg(feature = "sqlite")] + pub fn sqlite_store( mut self, path: impl AsRef, passphrase: Option<&str>, ) -> Self { - self.store_config = BuilderStoreConfig::Sled { + self.store_config = BuilderStoreConfig::Sqlite { path: path.as_ref().to_owned(), passphrase: passphrase.map(ToOwned::to_owned), }; @@ -342,9 +342,9 @@ impl ClientBuilder { #[allow(clippy::infallible_destructuring_match)] let store_config = match self.store_config { - #[cfg(feature = "sled")] - BuilderStoreConfig::Sled { path, passphrase } => { - matrix_sdk_sled::make_store_config(&path, passphrase.as_deref()).await? + #[cfg(feature = "sqlite")] + BuilderStoreConfig::Sqlite { path, passphrase } => { + matrix_sdk_sqlite::make_store_config(&path, passphrase.as_deref()).await? } #[cfg(feature = "indexeddb")] BuilderStoreConfig::IndexedDb { name, passphrase } => { @@ -480,8 +480,8 @@ impl Default for HttpConfig { #[derive(Clone)] enum BuilderStoreConfig { - #[cfg(feature = "sled")] - Sled { + #[cfg(feature = "sqlite")] + Sqlite { path: std::path::PathBuf, passphrase: Option, }, @@ -498,9 +498,9 @@ impl fmt::Debug for BuilderStoreConfig { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { #[allow(clippy::infallible_destructuring_match)] match self { - #[cfg(feature = "sled")] - Self::Sled { path, .. } => { - f.debug_struct("Sled").field("path", path).finish_non_exhaustive() + #[cfg(feature = "sqlite")] + Self::Sqlite { path, .. } => { + f.debug_struct("Sqlite").field("path", path).finish_non_exhaustive() } #[cfg(feature = "indexeddb")] Self::IndexedDb { name, .. } => { @@ -535,10 +535,10 @@ pub enum ClientBuildError { #[error(transparent)] IndexeddbStore(#[from] matrix_sdk_indexeddb::OpenStoreError), - /// Error opening the sled store. - #[cfg(feature = "sled")] + /// Error opening the sqlite store. + #[cfg(feature = "sqlite")] #[error(transparent)] - SledStore(#[from] matrix_sdk_sled::OpenStoreError), + SqliteStore(#[from] matrix_sdk_sqlite::OpenStoreError), } impl ClientBuildError { diff --git a/crates/matrix-sdk/src/docs/encryption.md b/crates/matrix-sdk/src/docs/encryption.md index 74438c2fb..39044c78f 100644 --- a/crates/matrix-sdk/src/docs/encryption.md +++ b/crates/matrix-sdk/src/docs/encryption.md @@ -216,7 +216,7 @@ is **not** supported using the default store. | Failure | Cause | Fix | | ------------------- | ----- | ----------- | | No messages get encrypted nor decrypted | The `e2e-encryption` feature is disabled | [Enable the feature in your `Cargo.toml` file] | -| Messages that were decryptable aren't after a restart | Storage isn't setup to be persistent | Ensure you've activated the persistent storage backend feature, e.g. `sled` | +| Messages that were decryptable aren't after a restart | Storage isn't setup to be persistent | Ensure you've activated the persistent storage backend feature, e.g. `sqlite` | | Messages are encrypted but can't be decrypted | The access token that the client is using is tied to another device | Clear storage to create a new device, read the [Restoring a Client] section | | Messages don't get encrypted but get decrypted | The `m.room.encryption` event is missing | Make sure encryption is [enabled] for the room and the event isn't [filtered] out, otherwise it might be a deserialization bug | diff --git a/examples/persist_session/src/main.rs b/examples/persist_session/src/main.rs index 88a04694f..41e037160 100644 --- a/examples/persist_session/src/main.rs +++ b/examples/persist_session/src/main.rs @@ -92,7 +92,7 @@ async fn restore_session(session_file: &Path) -> anyhow::Result<(Client, Option< // Build the client with the previous settings from the session. let client = Client::builder() .homeserver_url(client_session.homeserver) - .sled_store(client_session.db_path, Some(&client_session.passphrase)) + .sqlite_store(client_session.db_path, Some(&client_session.passphrase)) .build() .await?; @@ -165,7 +165,7 @@ async fn build_client(data_dir: &Path) -> anyhow::Result<(Client, ClientSession) // Generating a subfolder for the database is not mandatory, but it is useful if // you allow several clients to run at the same time. Each one must have a - // separate database, which is a different folder with the sled store. + // separate database, which is a different folder with the SQLite store. let db_subfolder: String = (&mut rng).sample_iter(Alphanumeric).take(7).map(char::from).collect(); let db_path = data_dir.join(db_subfolder); @@ -186,10 +186,10 @@ async fn build_client(data_dir: &Path) -> anyhow::Result<(Client, ClientSession) match Client::builder() .homeserver_url(&homeserver) - // We use the sled store, which is enabled by default. This is the crucial part to + // We use the SQLite store, which is enabled by default. This is the crucial part to // persist the encryption setup. - // Note that other store backends are available and you an even implement your own. - .sled_store(&db_path, Some(&passphrase)) + // Note that other store backends are available and you can even implement your own. + .sqlite_store(&db_path, Some(&passphrase)) .build() .await { diff --git a/examples/timeline/Cargo.toml b/examples/timeline/Cargo.toml index bc9c979e6..aa1b2e1c7 100644 --- a/examples/timeline/Cargo.toml +++ b/examples/timeline/Cargo.toml @@ -18,5 +18,5 @@ url = "2.2.2" [dependencies.matrix-sdk] path = "../../crates/matrix-sdk" -features = ["experimental-timeline", "sled"] +features = ["experimental-timeline"] version = "0.6.0" diff --git a/testing/matrix-sdk-integration-testing/src/helpers.rs b/testing/matrix-sdk-integration-testing/src/helpers.rs index dd534e339..8bb43431c 100644 --- a/testing/matrix-sdk-integration-testing/src/helpers.rs +++ b/testing/matrix-sdk-integration-testing/src/helpers.rs @@ -36,7 +36,7 @@ pub fn test_server_conf() -> (String, String) { ) } -pub async fn get_client_for_user(username: String, use_sled_store: bool) -> Result { +pub async fn get_client_for_user(username: String, use_sqlite_store: bool) -> Result { let mut users = USERS.lock().await; if let Some((client, _)) = users.get(&username) { return Ok(client.clone()); @@ -50,8 +50,8 @@ pub async fn get_client_for_user(username: String, use_sled_store: bool) -> Resu .user_agent("matrix-sdk-integation-tests") .homeserver_url(homeserver_url) .request_config(RequestConfig::short_retry()); - let client = if use_sled_store { - client_builder.sled_store(tmp_dir.path(), None).build().await? + let client = if use_sqlite_store { + client_builder.sqlite_store(tmp_dir.path(), None).build().await? } else { client_builder.build().await? }; diff --git a/testing/matrix-sdk-integration-testing/src/tests/repeated_join.rs b/testing/matrix-sdk-integration-testing/src/tests/repeated_join.rs index 37cb92aa8..d51589d46 100644 --- a/testing/matrix-sdk-integration-testing/src/tests/repeated_join.rs +++ b/testing/matrix-sdk-integration-testing/src/tests/repeated_join.rs @@ -18,7 +18,7 @@ use crate::helpers::get_client_for_user; #[tokio::test(flavor = "multi_thread", worker_threads = 4)] async fn test_repeated_join_leave() -> Result<()> { let peter = get_client_for_user("peter".to_owned(), true).await?; - // FIXME: Run once with memory, once with sled + // FIXME: Run once with memory, once with SQLite let karl = get_client_for_user("karl".to_owned(), false).await?; let karl_id = karl.user_id().expect("karl has a userid!").to_owned(); diff --git a/testing/sliding-sync-integration-test/src/lib.rs b/testing/sliding-sync-integration-test/src/lib.rs index 60cdd925e..b39be26d2 100644 --- a/testing/sliding-sync-integration-test/src/lib.rs +++ b/testing/sliding-sync-integration-test/src/lib.rs @@ -27,10 +27,13 @@ use matrix_sdk::{ }; use matrix_sdk_integration_testing::helpers::get_client_for_user; -async fn setup(name: String, use_sled_store: bool) -> anyhow::Result<(Client, SlidingSyncBuilder)> { +async fn setup( + name: String, + use_sqlite_store: bool, +) -> anyhow::Result<(Client, SlidingSyncBuilder)> { let sliding_sync_proxy_url = option_env!("SLIDING_SYNC_PROXY_URL").unwrap_or("http://localhost:8338").to_owned(); - let client = get_client_for_user(name, use_sled_store).await?; + let client = get_client_for_user(name, use_sqlite_store).await?; let sliding_sync_builder = client .sliding_sync() .await @@ -47,10 +50,10 @@ async fn random_setup_with_rooms( async fn random_setup_with_rooms_opt_store( number_of_rooms: usize, - use_sled_store: bool, + use_sqlite_store: bool, ) -> anyhow::Result<(Client, SlidingSyncBuilder)> { let namespace = uuid::Uuid::new_v4().to_string(); - let (client, sliding_sync_builder) = setup(namespace.clone(), use_sled_store).await?; + let (client, sliding_sync_builder) = setup(namespace.clone(), use_sqlite_store).await?; for room_num in 0..number_of_rooms { make_room(&client, format!("{namespace}-{room_num}")).await? diff --git a/xtask/src/ci.rs b/xtask/src/ci.rs index 1668101cd..8e9ea61a2 100644 --- a/xtask/src/ci.rs +++ b/xtask/src/ci.rs @@ -63,9 +63,9 @@ enum CiCommand { #[derive(Subcommand, PartialEq, Eq, PartialOrd, Ord)] enum FeatureSet { NoEncryption, - NoSled, - NoEncryptionAndSled, - SledCryptostore, + NoSqlite, + NoEncryptionAndSqlite, + SqliteCryptostore, RustlsTls, Markdown, Socks, @@ -194,13 +194,13 @@ fn run_feature_tests(cmd: Option) -> Result<()> { let args = BTreeMap::from([ ( FeatureSet::NoEncryption, - "--no-default-features --features sled,native-tls,experimental-sliding-sync", + "--no-default-features --features sqlite,native-tls,experimental-sliding-sync", ), - (FeatureSet::NoSled, "--no-default-features --features e2e-encryption,native-tls"), - (FeatureSet::NoEncryptionAndSled, "--no-default-features --features native-tls"), + (FeatureSet::NoSqlite, "--no-default-features --features e2e-encryption,native-tls"), + (FeatureSet::NoEncryptionAndSqlite, "--no-default-features --features native-tls"), ( - FeatureSet::SledCryptostore, - "--no-default-features --features e2e-encryption,sled,native-tls", + FeatureSet::SqliteCryptostore, + "--no-default-features --features e2e-encryption,sqlite,native-tls", ), (FeatureSet::RustlsTls, "--no-default-features --features rustls-tls"), (FeatureSet::Markdown, "--features markdown"),