feat: both sync and async instance, sync feat

This commit is contained in:
əlemi 2023-08-19 18:28:27 +02:00
parent 4562c2732b
commit 87a1c17599
3 changed files with 157 additions and 59 deletions

View file

@ -29,3 +29,4 @@ tonic-build = "0.9"
default = ["proto", "global"] default = ["proto", "global"]
proto = ["dep:prost"] proto = ["dep:prost"]
global = ["dep:lazy_static"] global = ["dep:lazy_static"]
sync = []

View file

@ -42,6 +42,7 @@ impl Client {
} }
pub fn leave_workspace(&mut self) { pub fn leave_workspace(&mut self) {
// TODO need to stop tasks?
self.workspace = None self.workspace = None
} }

View file

@ -1,75 +1,171 @@
use std::sync::{Arc, Mutex};
use tokio::runtime::Runtime;
use crate::{
buffer::controller::BufferController,
errors::Error, client::Client, cursor::controller::CursorController,
};
#[cfg(feature = "global")] #[cfg(feature = "global")]
pub mod global { pub mod global {
#[cfg(not(feature = "sync"))]
lazy_static::lazy_static! { lazy_static::lazy_static! {
pub static ref INSTANCE : super::Instance = super::Instance::default(); pub static ref INSTANCE : super::a_sync::Instance = super::a_sync::Instance::default();
}
#[cfg(feature = "sync")]
lazy_static::lazy_static! {
pub static ref INSTANCE : super::sync::Instance = super::sync::Instance::default();
} }
} }
pub struct Instance { #[cfg(not(feature = "sync"))]
client: Mutex<Option<Client>>, pub mod a_sync {
runtime: Runtime, use std::sync::Arc;
}
impl Default for Instance { use tokio::sync::Mutex;
fn default() -> Self {
Instance { use crate::{
client: Mutex::new(None), buffer::controller::BufferController,
runtime: Runtime::new().expect("could not start tokio runtime"), errors::Error, client::Client, cursor::controller::CursorController,
};
#[derive(Default)]
pub struct Instance {
client: Mutex<Option<Client>>,
}
impl Instance {
pub async fn connect(&self, addr: &str) -> Result<(), Error> {
*self.client.lock().await = Some(Client::new(addr).await?);
Ok(())
}
pub async fn join(&self, session: &str) -> Result<Arc<CursorController>, Error> {
self.client
.lock().await
.as_mut()
.ok_or(Error::InvalidState { msg: "connect first".into() })?
.join(session)
.await
}
pub async fn create(&self, path: &str, content: Option<&str>) -> Result<(), Error> {
self.client
.lock().await
.as_mut()
.ok_or(Error::InvalidState { msg: "connect first".into() })?
.create(path, content)
.await
}
pub async fn attach(&self, path: &str) -> Result<Arc<BufferController>, Error> {
self.client
.lock().await
.as_mut()
.ok_or(Error::InvalidState { msg: "connect first".into() })?
.attach(path)
.await
}
pub async fn get_cursor(&self) -> Result<Arc<CursorController>, Error> {
self.client
.lock().await
.as_mut()
.ok_or(Error::InvalidState { msg: "connect first".into() })?
.get_cursor()
.ok_or(Error::InvalidState { msg: "join workspace first".into() })
}
pub async fn get_buffer(&self, path: &str) -> Result<Arc<BufferController>, Error> {
self.client
.lock().await
.as_mut()
.ok_or(Error::InvalidState { msg: "connect first".into() })?
.get_buffer(path)
.ok_or(Error::InvalidState { msg: "join workspace first".into() })
}
pub async fn leave_workspace(&self) -> Result<(), Error> {
self.client
.lock().await
.as_mut()
.ok_or(Error::InvalidState { msg: "connect first".into() })?
.leave_workspace();
Ok(())
}
pub async fn disconnect_buffer(&self, path: &str) -> Result<bool, Error> {
let res = self.client
.lock().await
.as_mut()
.ok_or(Error::InvalidState { msg: "connect first".into() })?
.disconnect_buffer(path);
Ok(res)
} }
} }
} }
impl Instance { #[cfg(feature = "sync")]
pub mod sync {
use std::sync::{Mutex, Arc};
fn if_client<T>(&self, op: impl FnOnce(&mut Client) -> T) -> Result<T, Error> { use tokio::runtime::Runtime;
if let Some(c) = self.client.lock().expect("client mutex poisoned").as_mut() {
Ok(op(c)) use crate::{
} else { client::Client, Error,
Err(Error::InvalidState { msg: "connect first".into() }) cursor::controller::CursorController,
buffer::controller::BufferController
};
pub struct Instance {
client: Mutex<Option<Client>>,
runtime: Runtime,
}
impl Default for Instance {
fn default() -> Self {
Instance {
client: Mutex::new(None),
runtime: Runtime::new().expect("could not start tokio runtime"),
}
} }
} }
pub fn rt(&self) -> &Runtime { &self.runtime } impl Instance {
fn if_client<T>(&self, op: impl FnOnce(&mut Client) -> T) -> Result<T, Error> {
if let Some(c) = self.client.lock().expect("client mutex poisoned").as_mut() {
Ok(op(c))
} else {
Err(Error::InvalidState { msg: "connect first".into() })
}
}
pub fn connect(&self, addr: &str) -> Result<(), Error> { pub fn rt(&self) -> &Runtime { &self.runtime }
*self.client.lock().expect("client mutex poisoned") = Some(self.rt().block_on(Client::new(addr))?);
Ok(())
}
pub fn join(&self, session: &str) -> Result<Arc<CursorController>, Error> { pub fn connect(&self, addr: &str) -> Result<(), Error> {
self.if_client(|c| self.rt().block_on(c.join(session)))? *self.client.lock().expect("client mutex poisoned") = Some(self.rt().block_on(Client::new(addr))?);
} Ok(())
}
pub fn create(&self, path: &str, content: Option<&str>) -> Result<(), Error> { pub fn join(&self, session: &str) -> Result<Arc<CursorController>, Error> {
self.if_client(|c| self.rt().block_on(c.create(path, content)))? self.if_client(|c| self.rt().block_on(c.join(session)))?
} }
pub fn attach(&self, path: &str) -> Result<Arc<BufferController>, Error> { pub fn create(&self, path: &str, content: Option<&str>) -> Result<(), Error> {
self.if_client(|c| self.rt().block_on(c.attach(path)))? self.if_client(|c| self.rt().block_on(c.create(path, content)))?
} }
pub fn get_cursor(&self) -> Result<Arc<CursorController>, Error> { pub fn attach(&self, path: &str) -> Result<Arc<BufferController>, Error> {
self.if_client(|c| c.get_cursor().ok_or(Error::InvalidState { msg: "join workspace first".into() }))? self.if_client(|c| self.rt().block_on(c.attach(path)))?
} }
pub fn get_buffer(&self, path: &str) -> Result<Arc<BufferController>, Error> { pub fn get_cursor(&self) -> Result<Arc<CursorController>, Error> {
self.if_client(|c| c.get_buffer(path).ok_or(Error::InvalidState { msg: "join workspace or create requested buffer first".into() }))? self.if_client(|c| c.get_cursor().ok_or(Error::InvalidState { msg: "join workspace first".into() }))?
} }
pub fn leave_workspace(&self) -> Result<(), Error> { pub fn get_buffer(&self, path: &str) -> Result<Arc<BufferController>, Error> {
self.if_client(|c| c.leave_workspace()) self.if_client(|c| c.get_buffer(path).ok_or(Error::InvalidState { msg: "join workspace or create requested buffer first".into() }))?
} }
pub fn disconnect_buffer(&self, path: &str) -> Result<bool, Error> { pub fn leave_workspace(&self) -> Result<(), Error> {
self.if_client(|c| c.disconnect_buffer(path)) self.if_client(|c| c.leave_workspace())
}
pub fn disconnect_buffer(&self, path: &str) -> Result<bool, Error> {
self.if_client(|c| c.disconnect_buffer(path))
}
} }
} }