2023-03-03 20:38:31 +08:00

101 lines
2.7 KiB
Rust

#![allow(clippy::while_let_loop)]
use crate::{RevIdCounter, RevisionMergeable, RevisionPersistence};
use async_stream::stream;
use bytes::Bytes;
use flowy_error::FlowyError;
use futures::stream::StreamExt;
use revision_model::Revision;
use std::sync::Arc;
use tokio::sync::mpsc::{Receiver, Sender};
use tokio::sync::oneshot;
#[derive(Debug)]
pub(crate) enum RevisionCommand {
RevisionData {
data: Bytes,
object_md5: String,
ret: Ret<i64>,
},
}
/// [RevisionQueue] is used to keep the [RevisionCommand] processing in order.
pub(crate) struct RevisionQueue<Connection> {
object_id: String,
rev_id_counter: Arc<RevIdCounter>,
rev_persistence: Arc<RevisionPersistence<Connection>>,
rev_compress: Arc<dyn RevisionMergeable>,
receiver: Option<RevCommandReceiver>,
}
impl<Connection> RevisionQueue<Connection>
where
Connection: 'static,
{
pub fn new(
object_id: String,
rev_id_counter: Arc<RevIdCounter>,
rev_persistence: Arc<RevisionPersistence<Connection>>,
rev_compress: Arc<dyn RevisionMergeable>,
receiver: RevCommandReceiver,
) -> Self {
Self {
object_id,
rev_id_counter,
rev_persistence,
rev_compress,
receiver: Some(receiver),
}
}
pub async fn run(mut self) {
let mut receiver = self.receiver.take().expect("Only take once");
let object_id = self.object_id.clone();
let stream = stream! {
loop {
match receiver.recv().await {
Some(msg) => yield msg,
None => {
tracing::trace!("{}'s RevQueue exist", &object_id);
break
},
}
}
};
stream
.for_each(|command| async {
match self.handle_command(command).await {
Ok(_) => {},
Err(e) => tracing::error!("[RevQueue]: {}", e),
}
})
.await;
}
async fn handle_command(&self, command: RevisionCommand) -> Result<(), FlowyError> {
match command {
RevisionCommand::RevisionData {
data,
object_md5: data_md5,
ret,
} => {
let base_rev_id = self.rev_id_counter.value();
let rev_id = self.rev_id_counter.next_id();
let revision = Revision::new(&self.object_id, base_rev_id, rev_id, data, data_md5);
let new_rev_id = self
.rev_persistence
.add_local_revision(revision, &self.rev_compress)
.await?;
self.rev_id_counter.set(new_rev_id);
let _ = ret.send(Ok(new_rev_id));
},
}
Ok(())
}
}
pub(crate) type RevCommandSender = Sender<RevisionCommand>;
pub(crate) type RevCommandReceiver = Receiver<RevisionCommand>;
pub(crate) type Ret<T> = oneshot::Sender<Result<T, FlowyError>>;