2023-11-10 04:29:50 +01:00
|
|
|
use std::collections::hash_map::DefaultHasher;
|
|
|
|
use std::hash::{Hash, Hasher};
|
2024-08-08 00:28:15 +02:00
|
|
|
use std::sync::Arc;
|
2023-11-10 04:29:50 +01:00
|
|
|
|
2024-08-13 00:36:09 +02:00
|
|
|
use diamond_types::LocalVersion;
|
|
|
|
use tokio::sync::{mpsc, oneshot, watch};
|
2023-08-16 18:58:42 +02:00
|
|
|
use tonic::{async_trait, Streaming};
|
2024-01-25 02:13:45 +01:00
|
|
|
use uuid::Uuid;
|
2023-08-11 15:33:40 +02:00
|
|
|
|
2023-09-10 03:00:47 +02:00
|
|
|
use crate::api::controller::ControllerWorker;
|
2024-08-13 00:36:09 +02:00
|
|
|
use crate::api::Op;
|
2023-11-17 05:45:31 +01:00
|
|
|
use crate::api::TextChange;
|
2024-08-13 00:36:09 +02:00
|
|
|
|
|
|
|
use crate::errors::IgnorableError;
|
2024-03-09 19:59:36 +01:00
|
|
|
use codemp_proto::buffer::{BufferEvent, Operation};
|
2023-08-11 15:33:40 +02:00
|
|
|
|
2024-08-08 00:28:15 +02:00
|
|
|
use super::controller::{BufferController, BufferControllerInner};
|
2023-08-11 15:33:40 +02:00
|
|
|
|
2024-01-25 02:13:45 +01:00
|
|
|
pub(crate) struct BufferWorker {
|
2024-08-13 00:36:09 +02:00
|
|
|
user_id: Uuid,
|
|
|
|
buffer: diamond_types::list::ListCRDT,
|
|
|
|
latest_version: watch::Sender<diamond_types::LocalVersion>,
|
|
|
|
ops_in: mpsc::UnboundedReceiver<TextChange>,
|
|
|
|
ops_out: mpsc::UnboundedSender<(LocalVersion, Option<Op>)>,
|
2023-11-30 03:03:09 +01:00
|
|
|
poller: mpsc::UnboundedReceiver<oneshot::Sender<()>>,
|
2023-11-23 15:52:36 +01:00
|
|
|
pollers: Vec<oneshot::Sender<()>>,
|
2023-11-27 14:55:46 +01:00
|
|
|
stop: mpsc::UnboundedReceiver<()>,
|
2024-08-08 02:27:06 +02:00
|
|
|
controller: BufferController,
|
2023-08-11 15:33:40 +02:00
|
|
|
}
|
|
|
|
|
2024-01-25 02:13:45 +01:00
|
|
|
impl BufferWorker {
|
|
|
|
pub fn new(user_id: Uuid, path: &str) -> Self {
|
2024-08-13 00:36:09 +02:00
|
|
|
//let (txt_tx, txt_rx) = watch::channel("".to_string());
|
|
|
|
let init = diamond_types::LocalVersion::default();
|
|
|
|
let buffer = diamond_types::list::ListCRDT::default();
|
|
|
|
|
|
|
|
let (latest_version_tx, latest_version_rx) = watch::channel(init.clone());
|
|
|
|
let (opin_tx, opin_rx) = mpsc::unbounded_channel();
|
|
|
|
let (opout_tx, opout_rx) = mpsc::unbounded_channel();
|
|
|
|
|
2023-11-30 03:03:09 +01:00
|
|
|
let (poller_tx, poller_rx) = mpsc::unbounded_channel();
|
2024-08-13 00:36:09 +02:00
|
|
|
|
2023-11-10 04:29:50 +01:00
|
|
|
let mut hasher = DefaultHasher::new();
|
2024-01-25 02:13:45 +01:00
|
|
|
user_id.hash(&mut hasher);
|
2024-08-13 00:36:09 +02:00
|
|
|
let _site_id = hasher.finish() as usize;
|
|
|
|
|
|
|
|
let (end_tx, end_rx) = mpsc::unbounded_channel();
|
|
|
|
|
2024-08-08 00:28:15 +02:00
|
|
|
let controller = BufferControllerInner::new(
|
|
|
|
path.to_string(),
|
2024-08-13 00:36:09 +02:00
|
|
|
latest_version_rx,
|
|
|
|
opin_tx,
|
|
|
|
opout_rx,
|
2024-08-08 00:28:15 +02:00
|
|
|
poller_tx,
|
|
|
|
end_tx,
|
|
|
|
);
|
2024-08-13 00:36:09 +02:00
|
|
|
|
2024-01-25 02:13:45 +01:00
|
|
|
BufferWorker {
|
2024-08-13 00:36:09 +02:00
|
|
|
user_id,
|
|
|
|
buffer,
|
|
|
|
latest_version: latest_version_tx,
|
|
|
|
ops_in: opin_rx,
|
|
|
|
ops_out: opout_tx,
|
2023-11-27 14:55:46 +01:00
|
|
|
poller: poller_rx,
|
|
|
|
pollers: Vec::new(),
|
2023-08-19 04:02:21 +02:00
|
|
|
stop: end_rx,
|
2024-08-08 02:27:06 +02:00
|
|
|
controller: BufferController(Arc::new(controller)),
|
2023-08-16 18:58:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-11 15:33:40 +02:00
|
|
|
#[async_trait]
|
2024-01-25 16:31:38 +01:00
|
|
|
impl ControllerWorker<TextChange> for BufferWorker {
|
2023-08-16 23:09:47 +02:00
|
|
|
type Controller = BufferController;
|
2024-01-25 02:13:45 +01:00
|
|
|
type Tx = mpsc::Sender<Operation>;
|
2024-02-07 01:09:28 +01:00
|
|
|
type Rx = Streaming<BufferEvent>;
|
2023-08-16 18:58:42 +02:00
|
|
|
|
2024-08-08 02:27:06 +02:00
|
|
|
fn controller(&self) -> BufferController {
|
|
|
|
self.controller.clone()
|
2023-08-11 15:33:40 +02:00
|
|
|
}
|
|
|
|
|
2024-01-25 02:13:45 +01:00
|
|
|
async fn work(mut self, tx: Self::Tx, mut rx: Self::Rx) {
|
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;
|
|
|
|
|
2023-11-09 05:21:24 +01:00
|
|
|
// received stop signal
|
|
|
|
_ = self.stop.recv() => break,
|
|
|
|
|
2023-11-23 15:52:36 +01:00
|
|
|
// received a new poller, add it to collection
|
2023-11-27 14:55:46 +01:00
|
|
|
res = self.poller.recv() => match res {
|
2023-11-23 15:52:36 +01:00
|
|
|
None => break tracing::error!("poller channel closed"),
|
|
|
|
Some(tx) => self.pollers.push(tx),
|
|
|
|
},
|
|
|
|
|
2023-11-09 05:21:24 +01:00
|
|
|
// received a text change from editor
|
2024-08-13 00:36:09 +02:00
|
|
|
res = self.ops_in.recv() => match res {
|
2024-02-09 00:35:08 +01:00
|
|
|
None => break tracing::debug!("stopping: editor closed channel"),
|
2024-08-13 00:36:09 +02:00
|
|
|
Some(change) => {
|
|
|
|
|
|
|
|
let agent_id = self.buffer.get_or_create_agent_id(&self.user_id.to_string());
|
|
|
|
let lastver = self.buffer.oplog.local_version_ref();
|
|
|
|
|
|
|
|
if change.is_insert() {
|
|
|
|
self.buffer.insert(agent_id, change.start as usize, &change.content) // TODO da vedere il cast
|
|
|
|
} else if change.is_delete() {
|
|
|
|
self.buffer.delete_without_content(1, change.span())
|
|
|
|
} else { continue; };
|
|
|
|
|
|
|
|
tx.send(Operation { data: self.buffer.oplog.encode_from(Default::default(), lastver) });
|
|
|
|
self.latest_version.send(self.buffer.oplog.local_version());
|
|
|
|
|
|
|
|
},
|
2023-08-11 15:33:40 +02:00
|
|
|
},
|
2023-09-10 03:01:37 +02:00
|
|
|
|
2023-11-23 15:52:36 +01:00
|
|
|
// received a message from server
|
2023-11-09 05:21:24 +01:00
|
|
|
res = rx.message() => match res {
|
|
|
|
Err(_e) => break,
|
|
|
|
Ok(None) => break,
|
2024-08-13 00:36:09 +02:00
|
|
|
Ok(Some(change)) => {
|
|
|
|
let lastver = self.buffer.oplog.local_version_ref();
|
|
|
|
|
|
|
|
match self.buffer.merge_data_and_ff(&change.op.data) {
|
|
|
|
Ok(local_version) => {
|
|
|
|
|
|
|
|
// give all the changes needed to the controller in a channel.
|
|
|
|
for (lv, Some(dtop)) in self.buffer.oplog.iter_xf_operations_from(lastver, &local_version) {
|
|
|
|
// x.0.start should always be after lastver!
|
|
|
|
// this step_ver will be the version after we apply the operation
|
|
|
|
// we give it to the controller so that he knows where it's at.
|
|
|
|
let step_ver = self.buffer.oplog.version_union(&[lv.start], lastver);
|
|
|
|
let opout = (step_ver, Some(Op(dtop)));
|
|
|
|
|
|
|
|
self.ops_out.send(opout).unwrap(); //TODO ERRORS
|
|
|
|
}
|
|
|
|
|
|
|
|
// finally we send the
|
|
|
|
self.latest_version.send(local_version);
|
|
|
|
for tx in self.pollers.drain(..) {
|
|
|
|
tx.send(()).unwrap_or_warn("could not wake up poller");
|
|
|
|
}
|
|
|
|
},
|
|
|
|
Err(e) => tracing::error!("could not deserialize operation from server: {}", e),
|
|
|
|
}
|
2023-11-09 05:21:24 +01:00
|
|
|
},
|
2024-08-13 00:36:09 +02:00
|
|
|
}
|
2023-08-11 15:33:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-08-16 18:58:42 +02:00
|
|
|
}
|