mirror of
https://github.com/matrix-org/matrix-rust-sdk.git
synced 2026-05-15 11:36:07 -04:00
doc: document the App API
This commit is contained in:
@@ -30,39 +30,61 @@ use crate::{
|
||||
room_list::{self, RoomListService},
|
||||
};
|
||||
|
||||
/// Current state of the application.
|
||||
///
|
||||
/// This is a high-level state indicating what's the status of the underlying syncs.
|
||||
/// The application starts in `Running` mode, and then hits a terminal state `Terminated` (if it
|
||||
/// gracefully exited) or `Error` (in case any of the underlying syncs ran into an error).
|
||||
///
|
||||
/// It is the responsibility of the caller to restart the application using the [`App::start`]
|
||||
/// method, in case it terminated, gracefully or not.
|
||||
///
|
||||
/// This can be observed with [`App::observe_state`].
|
||||
#[derive(Clone)]
|
||||
pub enum AppState {
|
||||
/// The underlying syncs are properly running in the background.
|
||||
Running,
|
||||
/// Any of the underlying syncs has terminated gracefully (i.e. be stopped).
|
||||
Terminated,
|
||||
/// Any of the underlying syncs has ran into an error.
|
||||
Error,
|
||||
}
|
||||
|
||||
pub struct App {
|
||||
room_list: Arc<RoomListService>,
|
||||
encryption_sync: Option<Arc<EncryptionSync>>,
|
||||
stream_task_handle: Arc<Mutex<Option<JoinHandle<()>>>>,
|
||||
task_handle: Arc<Mutex<Option<JoinHandle<()>>>>,
|
||||
state_observer: Observable<AppState>,
|
||||
}
|
||||
|
||||
impl App {
|
||||
/// Create a new builder for configuring an `App`.
|
||||
pub fn builder(client: Client) -> AppBuilder {
|
||||
AppBuilder::new(client)
|
||||
}
|
||||
|
||||
/// Get the underlying `RoomListService` instance for easier access to its methods.
|
||||
pub fn room_list_service(&self) -> &RoomListService {
|
||||
&*self.room_list
|
||||
}
|
||||
|
||||
/// Observe the current state of the application.
|
||||
///
|
||||
/// See also [`AppState`].
|
||||
pub fn observe_state(&self) -> impl Stream<Item = AppState> {
|
||||
self.state_observer.subscribe()
|
||||
}
|
||||
|
||||
/// Start (or restart) the underlying sliding syncs.
|
||||
///
|
||||
/// This can be called multiple times safely: if a previous task had been spawned to run the
|
||||
/// syncs, then it will be properly aborted and restarted.
|
||||
pub async fn start(&self) -> Result<(), Error> {
|
||||
let room_list = self.room_list.clone();
|
||||
let encryption_sync = self.encryption_sync.clone();
|
||||
let state_observer = self.state_observer.clone();
|
||||
|
||||
let mut task_handle_lock = self.stream_task_handle.lock().unwrap();
|
||||
let mut task_handle_lock = self.task_handle.lock().unwrap();
|
||||
|
||||
// If there was a task running already with the streams, stop it gently. In the case it was
|
||||
// already terminated, that's fine as it won't cause any harm to abort it.
|
||||
@@ -129,6 +151,10 @@ impl App {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Stop the underlying sliding syncs.
|
||||
///
|
||||
/// This must be called when the app goes into the background. It's better to call this API
|
||||
/// when the application exits, although not strictly necessary.
|
||||
pub fn pause(&self) -> Result<(), Error> {
|
||||
self.room_list.stop_sync()?;
|
||||
if let Some(ref encryption_sync) = self.encryption_sync {
|
||||
@@ -139,10 +165,18 @@ impl App {
|
||||
}
|
||||
|
||||
pub struct AppBuilder {
|
||||
/// SDK client.
|
||||
client: Client,
|
||||
identifier: String,
|
||||
with_cross_process_lock: bool,
|
||||
|
||||
/// Is the encryption sync running as a separate instance of sliding sync (true), or is it
|
||||
/// fused in the main `RoomList` sliding sync (false)?
|
||||
with_encryption_sync: bool,
|
||||
|
||||
/// Is the cross-process lock for the crypto store enabled?
|
||||
with_cross_process_lock: bool,
|
||||
|
||||
/// Application identifier, used the cross-process lock value, if applicable.
|
||||
identifier: String,
|
||||
}
|
||||
|
||||
impl AppBuilder {
|
||||
@@ -155,17 +189,37 @@ impl AppBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn identifier(mut self, name: String) -> Self {
|
||||
self.identifier = name;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_encryption_sync(mut self, with_cross_process_lock: bool) -> Self {
|
||||
/// Enables the encryption sync for this application.
|
||||
///
|
||||
/// This will run a second sliding sync instance, that can independently process encryption
|
||||
/// events, which can speed up some use cases.
|
||||
///
|
||||
/// It's also a prerequisite if another process can *also* process encryption events; in that
|
||||
/// case, the `with_cross_process_lock` boolean must be set to `true` to enable the
|
||||
/// cross-process crypto store lock. This is only applicable to very specific use cases, like
|
||||
/// an external process attempting to decrypt notifications. In general,
|
||||
/// `with_cross_process_lock` can remain `false`.
|
||||
///
|
||||
/// If the cross-process lock is enabled, then an app identifier can be provided too, to
|
||||
/// identify the current process; if it's not provided, a default value of "app" is used as the
|
||||
/// application identifier.
|
||||
pub fn with_encryption_sync(
|
||||
mut self,
|
||||
with_cross_process_lock: bool,
|
||||
app_identifier: Option<String>,
|
||||
) -> Self {
|
||||
self.with_encryption_sync = true;
|
||||
self.with_cross_process_lock = with_cross_process_lock;
|
||||
if let Some(app_identifier) = app_identifier {
|
||||
self.identifier = app_identifier;
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Finish setting up the `App`.
|
||||
///
|
||||
/// This creates the underlying sliding syncs, and will start them in the background. The
|
||||
/// resulting `App` must be kept alive as long as the sliding syncs are supposed to run.
|
||||
pub async fn build(self) -> Result<App, Error> {
|
||||
let (room_list, encryption_sync) = if self.with_encryption_sync {
|
||||
let room_list = RoomListService::new(self.client.clone()).await?;
|
||||
@@ -183,7 +237,7 @@ impl AppBuilder {
|
||||
room_list: Arc::new(room_list),
|
||||
encryption_sync,
|
||||
state_observer: Observable::new(AppState::Running),
|
||||
stream_task_handle: Default::default(),
|
||||
task_handle: Default::default(),
|
||||
};
|
||||
|
||||
app.start().await?;
|
||||
@@ -192,11 +246,14 @@ impl AppBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
/// Errors for the `App` API.
|
||||
#[derive(Debug, Error)]
|
||||
pub enum Error {
|
||||
/// An error received from the `RoomList` API.
|
||||
#[error(transparent)]
|
||||
RoomList(#[from] room_list::Error),
|
||||
|
||||
/// An error received from the `EncryptionSync` API.
|
||||
#[error(transparent)]
|
||||
EncryptionSync(#[from] encryption_sync::Error),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user