state_store: add initial_use to let client know its safe to load state
This commit is contained in:
parent
183fffe85e
commit
316295bb77
4 changed files with 20 additions and 5 deletions
|
@ -610,7 +610,9 @@ impl AsyncClient {
|
|||
#[instrument]
|
||||
pub async fn sync(&self, mut sync_settings: SyncSettings) -> Result<sync_events::Response> {
|
||||
{
|
||||
if self.base_client.read().await.is_state_store_synced() {
|
||||
// if the client hasn't been synced from the state store don't sync again
|
||||
if !self.base_client.read().await.is_state_store_synced() {
|
||||
// this will bail out returning false if the store has not been set up
|
||||
if let Ok(synced) = self.sync_with_state_store().await {
|
||||
if synced {
|
||||
// once synced, update the sync token to the last known state from `StateStore`.
|
||||
|
|
|
@ -148,6 +148,11 @@ impl Client {
|
|||
/// Returns `true` when a sync has successfully completed.
|
||||
pub(crate) async fn sync_with_state_store(&mut self) -> Result<bool> {
|
||||
if let Some(store) = self.state_store.as_ref() {
|
||||
// return false and continues with a sync request then saves the state and creates
|
||||
// and populates the files during the sync
|
||||
if !store.initial_use().await? {
|
||||
return Ok(false);
|
||||
}
|
||||
let ClientState {
|
||||
session,
|
||||
sync_token,
|
||||
|
|
|
@ -60,6 +60,10 @@ impl ClientState {
|
|||
/// Abstraction around the data store to avoid unnecessary request on client initialization.
|
||||
#[async_trait::async_trait]
|
||||
pub trait StateStore: Send + Sync {
|
||||
/// Signals to the `AsyncClient` if this is the first time a StateStore` has been used.
|
||||
///
|
||||
/// Returns true if `StateStore` has been set up and ready to be loaded from.
|
||||
async fn initial_use(&self) -> Result<bool>;
|
||||
/// Loads the state of `BaseClient` through `StateStore::Store` type.
|
||||
async fn load_client_state(&self) -> Result<ClientState>;
|
||||
/// Load the state of a single `Room` by `RoomId`.
|
||||
|
|
|
@ -29,6 +29,12 @@ impl JsonStore {
|
|||
|
||||
#[async_trait::async_trait]
|
||||
impl StateStore for JsonStore {
|
||||
async fn initial_use(&self) -> Result<bool> {
|
||||
let mut path = self.path.clone();
|
||||
path.push("client.json");
|
||||
Ok(fs::read_to_string(path).map_or(false, |s| !s.is_empty()))
|
||||
}
|
||||
|
||||
async fn load_client_state(&self) -> Result<ClientState> {
|
||||
let mut path = self.path.clone();
|
||||
path.push("client.json");
|
||||
|
@ -242,10 +248,8 @@ mod test {
|
|||
AsyncClient::new_with_config(homeserver.clone(), Some(session.clone()), config)
|
||||
.unwrap();
|
||||
let sync_settings = SyncSettings::new().timeout(std::time::Duration::from_millis(3000));
|
||||
// fake a sync to skip the load with the state store, this will fail as the files won't exist
|
||||
// but the `AsyncClient::sync` will skip `StateStore::load_*`
|
||||
assert!(client.sync_with_state_store().await.is_err());
|
||||
// gather state to save to the db
|
||||
|
||||
// gather state to save to the db, the first time through loading will be skipped
|
||||
let _ = client.sync(sync_settings.clone()).await.unwrap();
|
||||
|
||||
// now syncing the client will update from the state store
|
||||
|
|
Loading…
Reference in a new issue