base: Add initial state store based on sled.

This commit is contained in:
Damir Jelić 2020-10-20 09:04:24 +02:00
parent cd3d90df3f
commit 045ab25fb7
4 changed files with 110 additions and 7 deletions

View file

@ -15,7 +15,7 @@ features = ["docs"]
rustdoc-args = ["--cfg", "feature=\"docs\""]
[features]
default = ["encryption", "sqlite_cryptostore", "messages"]
default = []
messages = []
encryption = ["matrix-sdk-crypto"]
sqlite_cryptostore = ["matrix-sdk-crypto/sqlite_cryptostore"]

View file

@ -20,8 +20,6 @@ use std::{
sync::Arc,
};
use sled::{self, Config as SledConfig, Db as Sled};
#[cfg(feature = "encryption")]
use matrix_sdk_common::locks::Mutex;
use matrix_sdk_common::{
@ -49,7 +47,7 @@ use matrix_sdk_crypto::{
};
use zeroize::Zeroizing;
use crate::{error::Result, session::Session};
use crate::{error::Result, session::Session, store::Store};
pub type Token = String;
@ -170,7 +168,7 @@ pub struct BaseClient {
/// The current sync token that should be used for the next sync call.
pub(crate) sync_token: Arc<RwLock<Option<Token>>>,
/// Database
sled: Sled,
store: Store,
#[cfg(feature = "encryption")]
olm: Arc<Mutex<Option<OlmMachine>>>,
#[cfg(feature = "encryption")]
@ -276,7 +274,7 @@ impl BaseClient {
Ok(BaseClient {
session: Arc::new(RwLock::new(None)),
sync_token: Arc::new(RwLock::new(None)),
sled: SledConfig::new().temporary(true).open().unwrap(),
store: Store::open(),
#[cfg(feature = "encryption")]
olm: Arc::new(Mutex::new(None)),
#[cfg(feature = "encryption")]

View file

@ -28,7 +28,6 @@
//! of Synapse in compliance with the Matrix API specification.
#![deny(
missing_debug_implementations,
missing_docs,
trivial_casts,
trivial_numeric_casts,
unused_extern_crates,
@ -46,6 +45,9 @@ pub use matrix_sdk_common::*;
mod client;
mod error;
mod session;
mod store;
pub use store::Store;
pub use client::{BaseClient, BaseClientConfig, RoomState, RoomStateType};

View file

@ -0,0 +1,103 @@
use serde_json;
use sled::{transaction::TransactionalTree, Config, Db, Tree};
#[derive(Debug, Clone)]
pub struct Store {
inner: Db,
session_tree: Tree,
}
use crate::Session;
pub struct TransactionalStore<'a> {
inner: &'a TransactionalTree,
}
impl<'a> std::fmt::Debug for TransactionalStore<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TransactionalStore").finish()
}
}
impl<'a> TransactionalStore<'a> {
pub fn store_session(&self, session: &Session) {
self.inner
.insert("session", serde_json::to_vec(session).unwrap())
.unwrap();
}
}
impl Store {
pub fn open() -> Self {
let db = Config::new().temporary(true).open().unwrap();
let session_tree = db.open_tree("session").unwrap();
Self {
inner: db,
session_tree,
}
}
pub fn get_session(&self) -> Option<Session> {
self.session_tree
.get("session")
.unwrap()
.map(|s| serde_json::from_slice(&s).unwrap())
}
pub async fn transaction<F, R>(&self, callback: F) -> R
where
F: Fn(&TransactionalStore) -> R,
{
let ret = self
.session_tree
.transaction::<_, _, ()>(|t| {
let transaction = TransactionalStore { inner: t };
Ok(callback(&transaction))
})
.unwrap();
self.inner.flush_async().await.unwrap();
ret
}
}
#[cfg(test)]
mod test {
use matrix_sdk_common::identifiers::{user_id, DeviceIdBox, UserId};
use matrix_sdk_test::async_test;
use super::Store;
use crate::Session;
fn user_id() -> UserId {
user_id!("@example:localhost")
}
fn device_id() -> DeviceIdBox {
"DEVICEID".into()
}
#[async_test]
async fn test_session_saving() {
let session = Session {
user_id: user_id(),
device_id: device_id().into(),
access_token: "TEST_TOKEN".to_owned(),
};
let store = Store::open();
store
.transaction(|t| {
t.store_session(&session);
()
})
.await;
let stored_session = store.get_session().unwrap();
assert_eq!(session, stored_session);
}
}