2024-09-04 21:37:35 +02:00
|
|
|
//! ### Buffer Controller
|
|
|
|
//! A [Controller] implementation for buffer actions
|
2023-08-20 00:46:55 +02:00
|
|
|
|
2023-11-09 05:21:24 +01:00
|
|
|
use std::sync::Arc;
|
|
|
|
|
2024-08-13 00:36:09 +02:00
|
|
|
use diamond_types::LocalVersion;
|
2024-08-16 12:58:43 +02:00
|
|
|
use tokio::sync::{mpsc, oneshot, watch};
|
2023-08-16 23:09:47 +02:00
|
|
|
use tonic::async_trait;
|
2023-08-11 15:33:40 +02:00
|
|
|
|
2024-09-01 02:46:03 +02:00
|
|
|
use crate::api::controller::{Controller, ControllerCallback};
|
2023-11-17 05:45:31 +01:00
|
|
|
use crate::api::TextChange;
|
2024-09-01 02:46:03 +02:00
|
|
|
use crate::errors::ControllerResult;
|
2024-08-10 16:13:16 +02:00
|
|
|
use crate::ext::InternallyMutable;
|
2024-08-08 00:27:24 +02:00
|
|
|
|
2024-08-17 00:17:01 +02:00
|
|
|
use super::worker::DeltaRequest;
|
|
|
|
|
2024-09-05 01:45:48 +02:00
|
|
|
/// A [Controller] to asynchronously interact with remote buffers.
|
2023-08-20 00:46:55 +02:00
|
|
|
///
|
2024-09-04 21:37:35 +02:00
|
|
|
/// Each buffer controller internally tracks the last acknowledged state, remaining always in sync
|
2024-09-05 01:45:48 +02:00
|
|
|
/// with the server while allowing to procedurally receive changes while still sending new ones.
|
2023-11-09 05:21:24 +01:00
|
|
|
#[derive(Debug, Clone)]
|
2024-08-05 22:44:46 +02:00
|
|
|
#[cfg_attr(feature = "python", pyo3::pyclass)]
|
2024-08-07 23:06:33 +02:00
|
|
|
#[cfg_attr(feature = "js", napi_derive::napi)]
|
2024-08-08 00:28:15 +02:00
|
|
|
pub struct BufferController(pub(crate) Arc<BufferControllerInner>);
|
|
|
|
|
|
|
|
impl BufferController {
|
2024-09-04 21:37:35 +02:00
|
|
|
/// Get the buffer path
|
|
|
|
pub fn path(&self) -> &str {
|
2024-08-08 00:28:15 +02:00
|
|
|
&self.0.name
|
|
|
|
}
|
|
|
|
|
2024-09-04 21:37:35 +02:00
|
|
|
/// Return buffer whole content, updating internal acknowledgement tracker
|
2024-09-01 02:46:03 +02:00
|
|
|
pub async fn content(&self) -> ControllerResult<String> {
|
2024-08-13 18:03:20 +02:00
|
|
|
let (tx, rx) = oneshot::channel();
|
|
|
|
self.0.content_request.send(tx).await?;
|
2024-08-14 15:55:18 +02:00
|
|
|
let content = rx.await?;
|
2024-08-16 12:58:43 +02:00
|
|
|
self.0
|
|
|
|
.last_update
|
|
|
|
.set(self.0.latest_version.borrow().clone());
|
2024-08-14 15:55:18 +02:00
|
|
|
Ok(content)
|
2024-08-08 00:28:15 +02:00
|
|
|
}
|
|
|
|
}
|
2024-08-05 19:13:48 +02:00
|
|
|
|
|
|
|
#[derive(Debug)]
|
2024-08-08 00:28:15 +02:00
|
|
|
pub(crate) struct BufferControllerInner {
|
2024-08-14 00:24:32 +02:00
|
|
|
pub(crate) name: String,
|
|
|
|
pub(crate) latest_version: watch::Receiver<diamond_types::LocalVersion>,
|
|
|
|
pub(crate) last_update: InternallyMutable<diamond_types::LocalVersion>,
|
2024-08-14 15:55:18 +02:00
|
|
|
pub(crate) ops_in: mpsc::UnboundedSender<(TextChange, oneshot::Sender<LocalVersion>)>,
|
2024-08-14 00:24:32 +02:00
|
|
|
pub(crate) poller: mpsc::UnboundedSender<oneshot::Sender<()>>,
|
|
|
|
pub(crate) stopper: mpsc::UnboundedSender<()>, // just exist
|
|
|
|
pub(crate) content_request: mpsc::Sender<oneshot::Sender<String>>,
|
2024-08-17 00:17:01 +02:00
|
|
|
pub(crate) delta_request: mpsc::Sender<DeltaRequest>,
|
2024-08-15 20:41:53 +02:00
|
|
|
pub(crate) callback: watch::Sender<Option<ControllerCallback<BufferController>>>,
|
2023-08-17 00:04:37 +02:00
|
|
|
}
|
|
|
|
|
2023-08-16 23:09:47 +02:00
|
|
|
#[async_trait]
|
2023-11-16 06:52:25 +01:00
|
|
|
impl Controller<TextChange> for BufferController {
|
2024-09-01 02:46:03 +02:00
|
|
|
async fn poll(&self) -> ControllerResult<()> {
|
2024-08-13 00:36:09 +02:00
|
|
|
if self.0.last_update.get() != *self.0.latest_version.borrow() {
|
|
|
|
return Ok(());
|
2023-11-30 03:03:09 +01:00
|
|
|
}
|
2024-08-13 00:36:09 +02:00
|
|
|
|
2023-11-23 15:52:36 +01:00
|
|
|
let (tx, rx) = oneshot::channel::<()>();
|
2024-08-05 19:13:48 +02:00
|
|
|
self.0.poller.send(tx)?;
|
2024-09-01 02:46:03 +02:00
|
|
|
rx.await?;
|
2023-11-30 03:03:09 +01:00
|
|
|
Ok(())
|
2023-08-21 02:35:56 +02:00
|
|
|
}
|
|
|
|
|
2024-09-01 02:46:03 +02:00
|
|
|
async fn try_recv(&self) -> ControllerResult<Option<TextChange>> {
|
2024-08-13 00:36:09 +02:00
|
|
|
let last_update = self.0.last_update.get();
|
|
|
|
let latest_version = self.0.latest_version.borrow().clone();
|
|
|
|
|
|
|
|
if last_update == latest_version {
|
2023-11-17 18:38:29 +01:00
|
|
|
return Ok(None);
|
2023-11-16 06:52:25 +01:00
|
|
|
}
|
2024-08-13 00:36:09 +02:00
|
|
|
|
2024-08-14 00:24:32 +02:00
|
|
|
let (tx, rx) = oneshot::channel();
|
|
|
|
self.0.delta_request.send((last_update, tx)).await?;
|
|
|
|
let (v, change) = rx.await?;
|
|
|
|
self.0.last_update.set(v);
|
2024-08-17 00:17:01 +02:00
|
|
|
Ok(change)
|
2023-07-09 03:44:27 +02:00
|
|
|
}
|
|
|
|
|
2024-09-01 02:46:03 +02:00
|
|
|
async fn send(&self, op: TextChange) -> ControllerResult<()> {
|
2024-08-13 00:36:09 +02:00
|
|
|
// we let the worker do the updating to the last version and send it back.
|
2024-08-14 15:55:18 +02:00
|
|
|
let (tx, rx) = oneshot::channel();
|
|
|
|
self.0.ops_in.send((op, tx))?;
|
|
|
|
self.0.last_update.set(rx.await?);
|
|
|
|
Ok(())
|
2023-07-09 03:44:27 +02:00
|
|
|
}
|
2023-11-30 03:03:09 +01:00
|
|
|
|
2024-08-15 22:47:49 +02:00
|
|
|
fn callback(&self, cb: impl Into<ControllerCallback<BufferController>>) {
|
|
|
|
if self.0.callback.send(Some(cb.into())).is_err() {
|
2024-08-15 19:32:01 +02:00
|
|
|
// TODO should we panic? we failed what we were supposed to do
|
|
|
|
tracing::error!("no active buffer worker to run registered callback!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn clear_callback(&self) {
|
|
|
|
if self.0.callback.send(None).is_err() {
|
|
|
|
tracing::warn!("no active buffer worker to clear callback");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-08 00:28:15 +02:00
|
|
|
fn stop(&self) -> bool {
|
|
|
|
self.0.stopper.send(()).is_ok()
|
2023-11-30 03:03:09 +01:00
|
|
|
}
|
|
|
|
}
|