Commit a5865326c81b
tarball5 files changed+62-22
@@ -69,6 +69,9 @@ web-sys = { version = "0.3.105", optional = true, features = [
6969
"WorkerGlobalScope",7070
] }7171
72
+[target.'cfg(not(target_family = "wasm"))'.dependencies]73
+tokio = { version = "1.47.1", features = ["rt"] }74
+7275
[target.'cfg(not(target_family = "wasm"))'.dev-dependencies]7376
matrix-sdk = { git = "ssh://brewery@pls.lobotomise.me:33/atagen/matrix-rust-sdk", rev = "0f2f982989765b79c39efdc30e86eaafccf69e4a", default-features = false, features = ["testing"] }7477
matrix-sdk-test = { git = "ssh://brewery@pls.lobotomise.me:33/atagen/matrix-rust-sdk", rev = "0f2f982989765b79c39efdc30e86eaafccf69e4a" }@@ -865,15 +865,16 @@ impl Session {
865865
.ok_or(AccountError::MissingSession)?866866
.to_owned(),867867
};868
- let search =869
- crate::search::store::SearchStore::open(self.tracking.store.store(), account.clone())870
- .await;871868
let opener = crate::mentions::store::Opener::new(872869
self.tracking.store.store(),873
- account,870
+ account.clone(),874871
config.max_mentions_bytes,875872
);876
- let mentions = match opener.open().await {873
+ let (search, mentions) = futures_util::join!(874
+ crate::search::store::SearchStore::open(self.tracking.store.store(), account),875
+ opener.open(),876
+ );877
+ let mentions = match mentions {877878
Ok(store) => Ok(store),878879
Err(crate::mentions::store::OpenError::Unavailable(error)) => {879880
Err(crate::mentions::service::Unopened {@@ -80,3 +80,17 @@ impl<T: 'static> Drop for TaskSet<T> {
8080
self.abort_all();8181
}8282
}83
+84
+/// a store cipher's pbkdf2 holds its thread for over a second in a debug build, so natively it85
+/// runs beside the runtime and two stores can derive at once86
+#[cfg(not(target_family = "wasm"))]87
+pub(crate) async fn derive<T: Send + 'static>(work: impl FnOnce() -> T + Send + 'static) -> T {88
+ tokio::task::spawn_blocking(work)89
+ .await90
+ .unwrap_or_else(|error| std::panic::resume_unwind(error.into_panic()))91
+}92
+93
+#[cfg(target_family = "wasm")]94
+pub(crate) async fn derive<T>(work: impl FnOnce() -> T) -> T {95
+ work()96
+}@@ -6,7 +6,7 @@ use ruma::OwnedUserId;
66
use serde::{Deserialize, Serialize, de::DeserializeOwned};77
use serde_json::{Value, value::RawValue};88
9
-use crate::{Error, ErrorKind, StoreConfig};9
+use crate::{Error, ErrorKind, StoreConfig, engine::executor::derive};1010
1111
#[cfg(feature = "sqlite")]1212
mod sqlite;@@ -155,7 +155,7 @@ impl MentionsStore {
155155
.await156156
.map_err(OpenError::Unavailable)?;157157
let restored = match backend.load().await {158
- Ok(Some(snapshot)) => match restore(opener, snapshot) {158
+ Ok(Some(snapshot)) => match restore(opener, snapshot).await {159159
Ok(restored) => Some(restored),160160
Err(Rejected::Newer(error)) => return Err(OpenError::Newer(error)),161161
Err(Rejected::Content(error)) => {@@ -363,8 +363,14 @@ struct Schema {
363363
schema: u32,364364
}365365
366
-fn restore(opener: &Opener, snapshot: Snapshot) -> Result<(StoreCipher, Snapshot, u64), Rejected> {367
- let cipher = StoreCipher::import(&opener.passphrase, &snapshot.exported)366
+async fn restore(367
+ opener: &Opener,368
+ snapshot: Snapshot,369
+) -> Result<(StoreCipher, Snapshot, u64), Rejected> {370
+ let passphrase = opener.passphrase.clone();371
+ let exported = snapshot.exported.clone();372
+ let cipher = derive(move || StoreCipher::import(&passphrase, &exported))373
+ .await368374
.map_err(|error| storage_error("opening the mentions cipher", error))?;369375
let schema: Schema = cipher370376
.decrypt_value(&snapshot.head)@@ -395,11 +401,16 @@ fn restore(opener: &Opener, snapshot: Snapshot) -> Result<(StoreCipher, Snapshot
395401
}396402
397403
async fn create(backend: &Backend, opener: &Opener) -> Result<(StoreCipher, Snapshot, u64), Error> {398
- let cipher =399
- StoreCipher::new().map_err(|error| storage_error("creating the mentions cipher", error))?;400
- let exported = cipher401
- .export(&opener.passphrase)402
- .map_err(|error| storage_error("sealing the mentions cipher", error))?;404
+ let passphrase = opener.passphrase.clone();405
+ let (cipher, exported) = derive(move || {406
+ let cipher = StoreCipher::new()407
+ .map_err(|error| storage_error("creating the mentions cipher", error))?;408
+ let exported = cipher409
+ .export(&passphrase)410
+ .map_err(|error| storage_error("sealing the mentions cipher", error))?;411
+ Ok::<_, Error>((cipher, exported))412
+ })413
+ .await?;403414
let head = seal_head(&cipher, &opener.account, 0, 0, 0)?;404415
let snapshot = Snapshot {405416
exported,@@ -4,7 +4,7 @@ use matrix_sdk::{SendOutsideWasm, SyncOutsideWasm};
44
use matrix_sdk_store_encryption::{EncryptedValueBase64, StoreCipher};55
use serde::{Deserialize, Serialize};66
7
-use crate::{Error, ErrorKind, StoreConfig, mentions::store::Account};7
+use crate::{Error, ErrorKind, StoreConfig, engine::executor::derive, mentions::store::Account};88
99
#[cfg(feature = "indexeddb")]1010
mod indexeddb;@@ -65,8 +65,14 @@ impl SearchStore {
6565
user_id: account.user_id.to_string(),6666
};6767
let mut blobs = backend.load(&[CIPHER, ACCOUNT]).await?;68
- let opened = blobs.remove(CIPHER).and_then(|exported| {69
- let cipher = StoreCipher::import(config.passphrase(), &exported).ok()?;68
+ let imported = match blobs.remove(CIPHER) {69
+ Some(exported) => {70
+ let passphrase = config.passphrase().to_owned();71
+ derive(move || StoreCipher::import(&passphrase, &exported).ok()).await72
+ }73
+ None => None,74
+ };75
+ let opened = imported.and_then(|cipher| {7076
let stored: Owner =7177
serde_json::from_slice(&unseal(&cipher, ACCOUNT, blobs.remove(ACCOUNT)?)?).ok()?;7278
(stored.homeserver == owner.homeserver && stored.user_id == owner.user_id)@@ -75,11 +81,16 @@ impl SearchStore {
7581
if let Some(cipher) = opened {7682
return Ok(Self { backend, cipher });7783
}78
- let cipher = StoreCipher::new()79
- .map_err(|error| storage_error("creating the search cipher", error))?;80
- let exported = cipher81
- .export(config.passphrase())82
- .map_err(|error| storage_error("sealing the search cipher", error))?;84
+ let passphrase = config.passphrase().to_owned();85
+ let (cipher, exported) = derive(move || {86
+ let cipher = StoreCipher::new()87
+ .map_err(|error| storage_error("creating the search cipher", error))?;88
+ let exported = cipher89
+ .export(&passphrase)90
+ .map_err(|error| storage_error("sealing the search cipher", error))?;91
+ Ok::<_, Error>((cipher, exported))92
+ })93
+ .await?;8394
let owner = serde_json::to_vec(&owner)8495
.map_err(|error| storage_error("encoding the search owner", error))?;8596
let sealed = seal(&cipher, ACCOUNT, owner)?;