state_store: add initial_use to let client know its safe to load state
parent
183fffe85e
commit
316295bb77
|
@ -610,7 +610,9 @@ impl AsyncClient {
|
||||||
#[instrument]
|
#[instrument]
|
||||||
pub async fn sync(&self, mut sync_settings: SyncSettings) -> Result<sync_events::Response> {
|
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 let Ok(synced) = self.sync_with_state_store().await {
|
||||||
if synced {
|
if synced {
|
||||||
// once synced, update the sync token to the last known state from `StateStore`.
|
// 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.
|
/// Returns `true` when a sync has successfully completed.
|
||||||
pub(crate) async fn sync_with_state_store(&mut self) -> Result<bool> {
|
pub(crate) async fn sync_with_state_store(&mut self) -> Result<bool> {
|
||||||
if let Some(store) = self.state_store.as_ref() {
|
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 {
|
let ClientState {
|
||||||
session,
|
session,
|
||||||
sync_token,
|
sync_token,
|
||||||
|
|
|
@ -60,6 +60,10 @@ impl ClientState {
|
||||||
/// Abstraction around the data store to avoid unnecessary request on client initialization.
|
/// Abstraction around the data store to avoid unnecessary request on client initialization.
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
pub trait StateStore: Send + Sync {
|
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.
|
/// Loads the state of `BaseClient` through `StateStore::Store` type.
|
||||||
async fn load_client_state(&self) -> Result<ClientState>;
|
async fn load_client_state(&self) -> Result<ClientState>;
|
||||||
/// Load the state of a single `Room` by `RoomId`.
|
/// Load the state of a single `Room` by `RoomId`.
|
||||||
|
|
|
@ -29,6 +29,12 @@ impl JsonStore {
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl StateStore for JsonStore {
|
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> {
|
async fn load_client_state(&self) -> Result<ClientState> {
|
||||||
let mut path = self.path.clone();
|
let mut path = self.path.clone();
|
||||||
path.push("client.json");
|
path.push("client.json");
|
||||||
|
@ -242,10 +248,8 @@ mod test {
|
||||||
AsyncClient::new_with_config(homeserver.clone(), Some(session.clone()), config)
|
AsyncClient::new_with_config(homeserver.clone(), Some(session.clone()), config)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let sync_settings = SyncSettings::new().timeout(std::time::Duration::from_millis(3000));
|
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_*`
|
// gather state to save to the db, the first time through loading will be skipped
|
||||||
assert!(client.sync_with_state_store().await.is_err());
|
|
||||||
// gather state to save to the db
|
|
||||||
let _ = client.sync(sync_settings.clone()).await.unwrap();
|
let _ = client.sync(sync_settings.clone()).await.unwrap();
|
||||||
|
|
||||||
// now syncing the client will update from the state store
|
// now syncing the client will update from the state store
|
||||||
|
|
Loading…
Reference in New Issue