2023-09-10 03:01:37 +02:00
|
|
|
use std::collections::VecDeque;
|
2023-08-11 15:33:40 +02:00
|
|
|
|
2023-09-07 20:39:45 +02:00
|
|
|
use operational_transform::OperationSeq;
|
2023-09-10 03:01:37 +02:00
|
|
|
use tokio::sync::{watch, mpsc, oneshot, 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;
|
2023-09-10 03:00:47 +02:00
|
|
|
use crate::api::controller::ControllerWorker;
|
|
|
|
use crate::api::factory::{leading_noop, tailing_noop};
|
2023-08-11 15:33:40 +02:00
|
|
|
|
2023-08-16 23:09:47 +02:00
|
|
|
use super::TextChange;
|
|
|
|
use super::controller::BufferController;
|
2023-08-11 15:33:40 +02:00
|
|
|
|
|
|
|
|
2023-08-16 23:09:47 +02:00
|
|
|
pub(crate) struct BufferControllerWorker {
|
2023-08-16 18:58:42 +02:00
|
|
|
uid: String,
|
2023-09-05 20:13:09 +02:00
|
|
|
content: watch::Sender<String>,
|
|
|
|
operations: mpsc::UnboundedReceiver<OperationSeq>,
|
2023-09-10 03:01:37 +02:00
|
|
|
stream: mpsc::UnboundedReceiver<oneshot::Sender<Option<TextChange>>>,
|
|
|
|
stream_requestor: mpsc::UnboundedSender<oneshot::Sender<Option<TextChange>>>,
|
2023-08-11 15:33:40 +02:00
|
|
|
receiver: watch::Receiver<String>,
|
2023-08-19 21:44:27 +02:00
|
|
|
sender: mpsc::UnboundedSender<OperationSeq>,
|
2023-08-11 15:33:40 +02:00
|
|
|
buffer: String,
|
|
|
|
path: String,
|
2023-08-19 04:02:21 +02:00
|
|
|
stop: mpsc::UnboundedReceiver<()>,
|
|
|
|
stop_control: mpsc::UnboundedSender<()>,
|
2023-09-10 03:01:37 +02:00
|
|
|
new_op_tx: watch::Sender<()>,
|
|
|
|
new_op_rx: watch::Receiver<()>,
|
2023-08-11 15:33:40 +02:00
|
|
|
}
|
|
|
|
|
2023-08-16 23:09:47 +02:00
|
|
|
impl BufferControllerWorker {
|
2023-08-16 18:58:42 +02:00
|
|
|
pub fn new(uid: String, buffer: &str, path: &str) -> Self {
|
|
|
|
let (txt_tx, txt_rx) = watch::channel(buffer.to_string());
|
2023-08-19 21:44:27 +02:00
|
|
|
let (op_tx, op_rx) = mpsc::unbounded_channel();
|
2023-09-10 03:01:37 +02:00
|
|
|
let (s_tx, s_rx) = mpsc::unbounded_channel();
|
2023-08-19 04:02:21 +02:00
|
|
|
let (end_tx, end_rx) = mpsc::unbounded_channel();
|
2023-09-10 03:01:37 +02:00
|
|
|
let (notx, norx) = watch::channel(());
|
2023-08-16 23:09:47 +02:00
|
|
|
BufferControllerWorker {
|
2023-08-16 18:58:42 +02:00
|
|
|
uid,
|
|
|
|
content: txt_tx,
|
|
|
|
operations: op_rx,
|
2023-09-10 03:01:37 +02:00
|
|
|
stream: s_rx,
|
|
|
|
stream_requestor: s_tx,
|
2023-08-16 18:58:42 +02:00
|
|
|
receiver: txt_rx,
|
|
|
|
sender: op_tx,
|
|
|
|
buffer: buffer.to_string(),
|
|
|
|
path: path.to_string(),
|
2023-08-19 04:02:21 +02:00
|
|
|
stop: end_rx,
|
|
|
|
stop_control: end_tx,
|
2023-09-10 03:01:37 +02:00
|
|
|
new_op_tx: notx,
|
|
|
|
new_op_rx: norx,
|
2023-08-16 18:58:42 +02:00
|
|
|
}
|
|
|
|
}
|
2023-09-10 03:01:37 +02:00
|
|
|
|
|
|
|
async fn send_op(&self, tx: &mut BufferClient<Channel>, outbound: &OperationSeq) -> crate::Result<()> {
|
|
|
|
let opseq = serde_json::to_string(outbound).expect("could not serialize opseq");
|
|
|
|
let req = OperationRequest {
|
|
|
|
path: self.path.clone(),
|
|
|
|
hash: format!("{:x}", md5::compute(&self.buffer)),
|
|
|
|
op: Some(RawOp {
|
|
|
|
opseq, user: self.uid.clone(),
|
|
|
|
}),
|
|
|
|
};
|
|
|
|
let _ = tx.edit(req).await?;
|
|
|
|
Ok(())
|
|
|
|
}
|
2023-08-16 18:58:42 +02:00
|
|
|
}
|
|
|
|
|
2023-08-11 15:33:40 +02:00
|
|
|
#[async_trait]
|
2023-08-16 23:09:47 +02:00
|
|
|
impl ControllerWorker<TextChange> for BufferControllerWorker {
|
|
|
|
type Controller = BufferController;
|
2023-08-16 18:58:42 +02:00
|
|
|
type Tx = BufferClient<Channel>;
|
|
|
|
type Rx = Streaming<RawOp>;
|
|
|
|
|
2023-08-16 23:09:47 +02:00
|
|
|
fn subscribe(&self) -> BufferController {
|
2023-08-17 00:04:37 +02:00
|
|
|
BufferController::new(
|
|
|
|
self.receiver.clone(),
|
|
|
|
self.sender.clone(),
|
2023-09-10 03:01:37 +02:00
|
|
|
self.stream_requestor.clone(),
|
2023-08-19 04:02:21 +02:00
|
|
|
self.stop_control.clone(),
|
2023-09-10 03:01:37 +02:00
|
|
|
Mutex::new(self.new_op_rx.clone()),
|
2023-08-17 00:04:37 +02:00
|
|
|
)
|
2023-08-11 15:33:40 +02:00
|
|
|
}
|
|
|
|
|
2023-08-16 18:58:42 +02:00
|
|
|
async fn work(mut self, mut tx: Self::Tx, mut rx: Self::Rx) {
|
2023-09-05 20:13:09 +02:00
|
|
|
let mut clientside : VecDeque<OperationSeq> = VecDeque::new();
|
|
|
|
let mut serverside : VecDeque<OperationSeq> = VecDeque::new();
|
2023-09-07 20:39:45 +02:00
|
|
|
|
2023-08-11 15:33:40 +02:00
|
|
|
loop {
|
2023-09-05 20:13:09 +02:00
|
|
|
|
|
|
|
// block until one of these is ready
|
2023-09-04 03:09:32 +02:00
|
|
|
tokio::select! {
|
2023-09-10 03:01:37 +02:00
|
|
|
biased;
|
|
|
|
|
|
|
|
// received a stop request (or channel got closed)
|
|
|
|
res = self.stop.recv() => {
|
|
|
|
tracing::info!("received stop signal");
|
|
|
|
match res {
|
|
|
|
None => return tracing::warn!("stop channel closed, stopping worker"),
|
|
|
|
Some(()) => return tracing::debug!("buffer worker stopping cleanly"),
|
|
|
|
}
|
|
|
|
}
|
2023-09-04 03:09:32 +02:00
|
|
|
|
2023-09-05 20:13:09 +02:00
|
|
|
// received a new message from server (or an error)
|
|
|
|
res = rx.message() => {
|
2023-09-10 03:01:37 +02:00
|
|
|
tracing::info!("received msg from server");
|
|
|
|
let inbound : OperationSeq = match res {
|
2023-09-05 20:13:09 +02:00
|
|
|
Err(e) => return tracing::error!("error receiving op from server: {}", e),
|
|
|
|
Ok(None) => return tracing::warn!("server closed operation stream"),
|
2023-09-10 03:01:37 +02:00
|
|
|
Ok(Some(msg)) => serde_json::from_str(&msg.opseq)
|
|
|
|
.expect("could not deserialize server opseq"),
|
|
|
|
};
|
|
|
|
self.buffer = inbound.apply(&self.buffer).expect("could not apply remote opseq???");
|
|
|
|
serverside.push_back(inbound);
|
|
|
|
while let Some(mut outbound) = clientside.get(0).cloned() {
|
|
|
|
let mut serverside_tmp = serverside.clone();
|
|
|
|
for server_op in serverside_tmp.iter_mut() {
|
|
|
|
tracing::info!("transforming {:?} <-> {:?}", outbound, server_op);
|
|
|
|
(outbound, *server_op) = outbound.transform(server_op)
|
|
|
|
.expect("could not transform enqueued out with just received");
|
|
|
|
}
|
|
|
|
match self.send_op(&mut tx, &outbound).await {
|
|
|
|
Err(e) => { tracing::warn!("could not send op even after transforming: {}", e); break; },
|
|
|
|
Ok(()) => {
|
|
|
|
tracing::info!("back in sync");
|
|
|
|
serverside = serverside_tmp;
|
|
|
|
self.buffer = outbound.apply(&self.buffer).expect("could not apply op after synching back");
|
|
|
|
clientside.pop_front();
|
|
|
|
},
|
|
|
|
}
|
2023-08-11 15:33:40 +02:00
|
|
|
}
|
2023-09-10 03:01:37 +02:00
|
|
|
self.content.send(self.buffer.clone()).expect("could not broadcast buffer update");
|
|
|
|
self.new_op_tx.send(()).expect("could not activate client after new server event");
|
2023-08-11 15:33:40 +02:00
|
|
|
},
|
2023-09-04 03:09:32 +02:00
|
|
|
|
2023-09-05 20:13:09 +02:00
|
|
|
// received a new operation from client (or channel got closed)
|
|
|
|
res = self.operations.recv() => {
|
2023-09-10 03:01:37 +02:00
|
|
|
tracing::info!("received op from client");
|
2023-09-05 20:13:09 +02:00
|
|
|
match res {
|
|
|
|
None => return tracing::warn!("client closed operation stream"),
|
|
|
|
Some(op) => {
|
2023-09-10 03:01:37 +02:00
|
|
|
if clientside.is_empty() {
|
|
|
|
match self.send_op(&mut tx, &op).await {
|
|
|
|
Ok(()) => {
|
|
|
|
self.buffer = op.apply(&self.buffer).expect("could not apply op");
|
|
|
|
self.content.send(self.buffer.clone()).expect("could not update buffer view");
|
|
|
|
},
|
|
|
|
Err(e) => {
|
|
|
|
tracing::warn!("server rejected op: {}", e);
|
|
|
|
clientside.push_back(op);
|
|
|
|
},
|
|
|
|
}
|
|
|
|
} else { // I GET STUCK IN THIS BRANCH AND NOTHING HAPPENS AAAAAAAAAA
|
|
|
|
clientside.push_back(op);
|
|
|
|
}
|
2023-09-05 20:13:09 +02:00
|
|
|
}
|
2023-09-04 03:09:32 +02:00
|
|
|
}
|
2023-08-11 15:33:40 +02:00
|
|
|
},
|
2023-09-10 03:01:37 +02:00
|
|
|
|
|
|
|
// client requested a server operation, transform it and send it
|
|
|
|
res = self.stream.recv() => {
|
|
|
|
tracing::info!("received op REQUEST from client");
|
2023-09-05 20:13:09 +02:00
|
|
|
match res {
|
2023-09-10 03:01:37 +02:00
|
|
|
None => return tracing::error!("client closed requestor stream"),
|
|
|
|
Some(tx) => tx.send(match serverside.pop_front() {
|
|
|
|
None => {
|
|
|
|
tracing::warn!("requested change but none is available");
|
|
|
|
None
|
|
|
|
},
|
|
|
|
Some(mut operation) => {
|
|
|
|
let mut after = self.buffer.clone();
|
|
|
|
for op in clientside.iter_mut() {
|
|
|
|
(*op, operation) = match op.transform(&operation) {
|
|
|
|
Err(e) => return tracing::warn!("could not transform enqueued operation: {}", e),
|
|
|
|
Ok((x, y)) => (x, y),
|
|
|
|
};
|
|
|
|
after = match op.apply(&after) {
|
|
|
|
Err(_) => return tracing::error!("could not apply outgoing enqueued opseq to current buffer?"),
|
|
|
|
Ok(x) => x,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
let skip = leading_noop(operation.ops()) as usize;
|
|
|
|
let tail = tailing_noop(operation.ops()) as usize;
|
|
|
|
let span = skip..(operation.base_len() - tail);
|
|
|
|
let content = if after.len() - tail < skip { "".into() } else { after[skip..after.len()-tail].to_string() };
|
|
|
|
let change = TextChange { span, content, after };
|
|
|
|
|
|
|
|
Some(change)
|
|
|
|
},
|
|
|
|
}).expect("client did not wait????"),
|
2023-09-05 20:13:09 +02:00
|
|
|
}
|
2023-09-10 03:01:37 +02:00
|
|
|
},
|
2023-09-05 20:13:09 +02:00
|
|
|
|
2023-08-11 15:33:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-08-16 18:58:42 +02:00
|
|
|
}
|