2023-08-11 15:33:40 +02:00
|
|
|
use std::{sync::Arc, collections::VecDeque, ops::Range};
|
|
|
|
|
|
|
|
use operational_transform::OperationSeq;
|
|
|
|
use tokio::sync::{watch, mpsc, broadcast, Mutex};
|
2023-08-16 18:58:42 +02:00
|
|
|
use tonic::transport::Channel;
|
|
|
|
use tonic::{async_trait, Streaming};
|
2023-08-11 15:33:40 +02:00
|
|
|
|
2023-08-16 18:58:42 +02:00
|
|
|
use crate::proto::{OperationRequest, RawOp};
|
|
|
|
use crate::proto::buffer_client::BufferClient;
|
|
|
|
use crate::{ControllerWorker, Controller, CodempError};
|
2023-08-11 15:33:40 +02:00
|
|
|
use crate::buffer::factory::{leading_noop, tailing_noop, OperationFactory};
|
|
|
|
|
|
|
|
pub struct TextChange {
|
|
|
|
pub span: Range<usize>,
|
|
|
|
pub content: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct BufferHandle {
|
|
|
|
content: watch::Receiver<String>,
|
|
|
|
operations: mpsc::Sender<OperationSeq>,
|
|
|
|
stream: Mutex<broadcast::Receiver<OperationSeq>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[async_trait]
|
|
|
|
impl OperationFactory for BufferHandle {
|
|
|
|
fn content(&self) -> String {
|
|
|
|
self.content.borrow().clone()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-16 18:58:42 +02:00
|
|
|
#[async_trait]
|
|
|
|
impl Controller<TextChange> for BufferHandle {
|
|
|
|
type Input = OperationSeq;
|
|
|
|
|
|
|
|
async fn recv(&self) -> Result<TextChange, CodempError> {
|
|
|
|
let op = self.stream.lock().await.recv().await?;
|
2023-08-11 15:33:40 +02:00
|
|
|
let after = self.content.borrow().clone();
|
|
|
|
let skip = leading_noop(op.ops()) as usize;
|
|
|
|
let before_len = op.base_len();
|
|
|
|
let tail = tailing_noop(op.ops()) as usize;
|
|
|
|
let span = skip..before_len-tail;
|
|
|
|
let content = after[skip..after.len()-tail].to_string();
|
2023-08-16 18:58:42 +02:00
|
|
|
Ok(TextChange { span, content })
|
2023-08-11 15:33:40 +02:00
|
|
|
}
|
|
|
|
|
2023-08-16 18:58:42 +02:00
|
|
|
async fn send(&self, op: OperationSeq) -> Result<(), CodempError> {
|
|
|
|
Ok(self.operations.send(op).await?)
|
2023-08-11 15:33:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-16 18:58:42 +02:00
|
|
|
pub(crate) struct OperationControllerWorker {
|
|
|
|
uid: String,
|
2023-08-11 15:33:40 +02:00
|
|
|
pub(crate) content: watch::Sender<String>,
|
|
|
|
pub(crate) operations: mpsc::Receiver<OperationSeq>,
|
|
|
|
pub(crate) stream: Arc<broadcast::Sender<OperationSeq>>,
|
|
|
|
pub(crate) queue: VecDeque<OperationSeq>,
|
|
|
|
receiver: watch::Receiver<String>,
|
|
|
|
sender: mpsc::Sender<OperationSeq>,
|
|
|
|
buffer: String,
|
|
|
|
path: String,
|
|
|
|
}
|
|
|
|
|
2023-08-16 18:58:42 +02:00
|
|
|
impl OperationControllerWorker {
|
|
|
|
pub fn new(uid: String, buffer: &str, path: &str) -> Self {
|
|
|
|
let (txt_tx, txt_rx) = watch::channel(buffer.to_string());
|
|
|
|
let (op_tx, op_rx) = mpsc::channel(64);
|
|
|
|
let (s_tx, _s_rx) = broadcast::channel(64);
|
|
|
|
OperationControllerWorker {
|
|
|
|
uid,
|
|
|
|
content: txt_tx,
|
|
|
|
operations: op_rx,
|
|
|
|
stream: Arc::new(s_tx),
|
|
|
|
receiver: txt_rx,
|
|
|
|
sender: op_tx,
|
|
|
|
queue: VecDeque::new(),
|
|
|
|
buffer: buffer.to_string(),
|
|
|
|
path: path.to_string(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-11 15:33:40 +02:00
|
|
|
#[async_trait]
|
2023-08-16 18:58:42 +02:00
|
|
|
impl ControllerWorker<TextChange> for OperationControllerWorker {
|
|
|
|
type Controller = BufferHandle;
|
|
|
|
type Tx = BufferClient<Channel>;
|
|
|
|
type Rx = Streaming<RawOp>;
|
|
|
|
|
2023-08-11 15:33:40 +02:00
|
|
|
fn subscribe(&self) -> BufferHandle {
|
|
|
|
BufferHandle {
|
|
|
|
content: self.receiver.clone(),
|
|
|
|
operations: self.sender.clone(),
|
|
|
|
stream: Mutex::new(self.stream.subscribe()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-16 18:58:42 +02:00
|
|
|
async fn work(mut self, mut tx: Self::Tx, mut rx: Self::Rx) {
|
2023-08-11 15:33:40 +02:00
|
|
|
loop {
|
|
|
|
let op = tokio::select! {
|
2023-08-16 18:58:42 +02:00
|
|
|
Some(operation) = recv_opseq(&mut rx) => {
|
2023-08-11 15:33:40 +02:00
|
|
|
let mut out = operation;
|
|
|
|
for op in self.queue.iter_mut() {
|
|
|
|
(*op, out) = op.transform(&out).unwrap();
|
|
|
|
}
|
|
|
|
self.stream.send(out.clone()).unwrap();
|
|
|
|
out
|
|
|
|
},
|
|
|
|
Some(op) = self.operations.recv() => {
|
|
|
|
self.queue.push_back(op.clone());
|
|
|
|
op
|
|
|
|
},
|
|
|
|
else => break
|
|
|
|
};
|
|
|
|
self.buffer = op.apply(&self.buffer).unwrap();
|
|
|
|
self.content.send(self.buffer.clone()).unwrap();
|
|
|
|
|
|
|
|
while let Some(op) = self.queue.get(0) {
|
2023-08-16 18:58:42 +02:00
|
|
|
if !send_opseq(&mut tx, self.uid.clone(), self.path.clone(), op.clone()).await { break }
|
2023-08-11 15:33:40 +02:00
|
|
|
self.queue.pop_front();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-08-16 18:58:42 +02:00
|
|
|
}
|
2023-08-11 15:33:40 +02:00
|
|
|
|
2023-08-16 18:58:42 +02:00
|
|
|
async fn send_opseq(tx: &mut BufferClient<Channel>, uid: String, path: String, op: OperationSeq) -> bool {
|
|
|
|
let req = OperationRequest {
|
|
|
|
hash: "".into(),
|
|
|
|
opseq: serde_json::to_string(&op).unwrap(),
|
|
|
|
path,
|
|
|
|
user: uid,
|
|
|
|
};
|
|
|
|
match tx.edit(req).await {
|
|
|
|
Ok(_) => true,
|
|
|
|
Err(e) => {
|
|
|
|
tracing::error!("error sending edit: {}", e);
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
2023-08-11 15:33:40 +02:00
|
|
|
}
|
|
|
|
|
2023-08-16 18:58:42 +02:00
|
|
|
async fn recv_opseq(rx: &mut Streaming<RawOp>) -> Option<OperationSeq> {
|
|
|
|
match rx.message().await {
|
|
|
|
Ok(Some(op)) => Some(serde_json::from_str(&op.opseq).unwrap()),
|
|
|
|
Ok(None) => None,
|
|
|
|
Err(e) => {
|
|
|
|
tracing::error!("could not receive edit from server: {}", e);
|
|
|
|
None
|
2023-08-11 15:33:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|