feat: initial features splitting, added singleton

This commit is contained in:
əlemi 2023-07-30 22:58:24 +02:00
parent 02b2588073
commit 5cddb27b98
6 changed files with 54 additions and 14 deletions

View file

@ -13,7 +13,7 @@ name = "codemp"
# core # core
tracing = "0.1" tracing = "0.1"
tonic = { version = "0.9", features = ["tls", "tls-roots"] } tonic = { version = "0.9", features = ["tls", "tls-roots"] }
prost = "0.11.8" prost = { version = "0.11.8", optional = true }
md5 = "0.7.0" md5 = "0.7.0"
uuid = { version = "1.3.1", features = ["v4"] } uuid = { version = "1.3.1", features = ["v4"] }
operational-transform = { version = "0.6", features = ["serde"] } operational-transform = { version = "0.6", features = ["serde"] }
@ -23,6 +23,12 @@ serde = { version = "1", optional = false }
serde_json = { version = "1", optional = false } serde_json = { version = "1", optional = false }
tracing-subscriber = { version = "0.3", optional = true } tracing-subscriber = { version = "0.3", optional = true }
similar = { version = "2.2", features = ["inline"] } similar = { version = "2.2", features = ["inline"] }
lazy_static = { version = "1.4", optional = true }
[build-dependencies] [build-dependencies]
tonic-build = "0.9" tonic-build = "0.9"
[features]
default = ["proto", "static"]
proto = ["dep:prost"]
static = ["dep:lazy_static"]

View file

@ -14,17 +14,28 @@ pub struct TextChange {
} }
#[async_trait] #[async_trait]
pub trait OperationControllerSubscriber { pub trait OperationControllerSubscriber : OperationFactory {
async fn poll(&self) -> Option<TextChange>; async fn poll(&self) -> Option<TextChange>;
async fn apply(&self, op: OperationSeq); async fn apply(&self, op: OperationSeq);
} }
#[derive(Clone)]
pub struct OperationControllerHandle { pub struct OperationControllerHandle {
content: watch::Receiver<String>, content: watch::Receiver<String>,
operations: mpsc::Sender<OperationSeq>, operations: mpsc::Sender<OperationSeq>,
original: Arc<broadcast::Sender<OperationSeq>>, original: Arc<broadcast::Sender<OperationSeq>>,
stream: Arc<Mutex<broadcast::Receiver<OperationSeq>>>, stream: Mutex<broadcast::Receiver<OperationSeq>>,
}
impl Clone for OperationControllerHandle {
fn clone(&self) -> Self {
OperationControllerHandle {
content: self.content.clone(),
operations: self.operations.clone(),
original: self.original.clone(),
stream: Mutex::new(self.original.subscribe()),
}
}
} }
#[async_trait] #[async_trait]
@ -87,7 +98,7 @@ impl<C : OperationControllerEditor + Send> ControllerWorker<OperationControllerH
content: self.receiver.clone(), content: self.receiver.clone(),
operations: self.sender.clone(), operations: self.sender.clone(),
original: self.stream.clone(), original: self.stream.clone(),
stream: Arc::new(Mutex::new(self.stream.subscribe())), stream: Mutex::new(self.stream.subscribe()),
} }
} }

1
src/cursor/client.rs Normal file
View file

@ -0,0 +1 @@
// TODO separate cursor movement from buffer operations in protocol!

View file

@ -1,20 +1,28 @@
pub mod workspace;
pub mod cursor; pub mod cursor;
pub mod errors; pub mod errors;
pub mod buffer; pub mod buffer;
pub mod state;
pub use tonic; pub use tonic;
pub use tokio; pub use tokio;
pub use operational_transform as ot; pub use operational_transform as ot;
use tonic::async_trait; #[cfg(feature = "proto")]
pub mod proto {
tonic::include_proto!("buffer");
}
#[async_trait] // TODO move this somewhere? pub use errors::CodempError;
pub trait ControllerWorker<T> {
#[tonic::async_trait] // TODO move this somewhere?
pub(crate) trait ControllerWorker<T> {
fn subscribe(&self) -> T; fn subscribe(&self) -> T;
async fn work(self); async fn work(self);
} }
pub mod proto { #[tonic::async_trait]
tonic::include_proto!("buffer"); pub trait Controller<T> {
async fn recv(&self) -> Result<T, CodempError>;
async fn send(&self, x: T) -> Result<(), CodempError>;
} }

View file

@ -8,6 +8,21 @@ use crate::{
cursor::controller::CursorSubscriber, errors::CodempError, cursor::controller::CursorSubscriber, errors::CodempError,
}; };
#[cfg(feature = "static")]
pub mod instance {
use tokio::runtime::Runtime;
use super::Workspace;
const CODEMP_DEFAULT_HOST : &str = "http://fantabos.co:50051";
lazy_static::lazy_static! {
static ref RUNTIME : Runtime = Runtime::new().expect("could not create tokio runtime");
static ref WORKSPACE : Workspace = RUNTIME.block_on(
Workspace::new(&std::env::var("CODEMP_HOST").unwrap_or(CODEMP_DEFAULT_HOST.into()))
).expect("could not create codemp workspace");
}
}
pub struct Workspace { pub struct Workspace {
client: CodempClient, client: CodempClient,
buffers: RwLock<BTreeMap<Box<str>, BufferController>>, buffers: RwLock<BTreeMap<Box<str>, BufferController>>,
@ -19,7 +34,7 @@ pub type BufferController = Arc<dyn OperationControllerSubscriber + Send + Sync>
#[async_trait] #[async_trait]
pub trait WorkspaceHandle { pub trait WorkspaceHandle {
fn cursor(&self) -> CursorController; async fn cursor(&self) -> CursorController;
async fn buffer(&self, path: &str) -> Option<BufferController>; async fn buffer(&self, path: &str) -> Option<BufferController>;
async fn attach(&self, path: &str) -> Result<(), CodempError>; async fn attach(&self, path: &str) -> Result<(), CodempError>;
async fn create(&self, path: &str, content: Option<&str>) -> Result<bool, CodempError>; async fn create(&self, path: &str, content: Option<&str>) -> Result<bool, CodempError>;
@ -42,7 +57,7 @@ impl Workspace {
#[async_trait] #[async_trait]
impl WorkspaceHandle for Workspace { impl WorkspaceHandle for Workspace {
// Cursor // Cursor
fn cursor(&self) -> CursorController { async fn cursor(&self) -> CursorController {
self.cursor.clone() self.cursor.clone()
} }

View file

@ -1 +0,0 @@
pub mod controller;