|
@@ -1,18 +1,20 @@
|
|
use crate::{
|
|
use crate::{
|
|
services::doc::{
|
|
services::doc::{
|
|
- edit::edit_actor::{EditDocActor, EditMsg},
|
|
|
|
|
|
+ editor::{DocUser, ServerDocEditor},
|
|
read_doc,
|
|
read_doc,
|
|
ws_actor::{DocWsActor, DocWsMsg},
|
|
ws_actor::{DocWsActor, DocWsMsg},
|
|
},
|
|
},
|
|
web_socket::{entities::Socket, WsBizHandler, WsClientData, WsUser},
|
|
web_socket::{entities::Socket, WsBizHandler, WsClientData, WsUser},
|
|
};
|
|
};
|
|
use actix_web::web::Data;
|
|
use actix_web::web::Data;
|
|
|
|
+use async_stream::stream;
|
|
use backend_service::errors::{internal_error, Result as DocResult, ServerError};
|
|
use backend_service::errors::{internal_error, Result as DocResult, ServerError};
|
|
use dashmap::DashMap;
|
|
use dashmap::DashMap;
|
|
use flowy_collaboration::protobuf::{Doc, DocIdentifier};
|
|
use flowy_collaboration::protobuf::{Doc, DocIdentifier};
|
|
|
|
+use futures::stream::StreamExt;
|
|
use lib_ot::protobuf::Revision;
|
|
use lib_ot::protobuf::Revision;
|
|
use sqlx::PgPool;
|
|
use sqlx::PgPool;
|
|
-use std::sync::Arc;
|
|
|
|
|
|
+use std::sync::{atomic::Ordering::SeqCst, Arc};
|
|
use tokio::{
|
|
use tokio::{
|
|
sync::{mpsc, oneshot},
|
|
sync::{mpsc, oneshot},
|
|
task::spawn_blocking,
|
|
task::spawn_blocking,
|
|
@@ -43,13 +45,17 @@ impl DocumentCore {
|
|
}
|
|
}
|
|
|
|
|
|
impl WsBizHandler for DocumentCore {
|
|
impl WsBizHandler for DocumentCore {
|
|
- fn receive_data(&self, client_data: WsClientData) {
|
|
|
|
|
|
+ fn receive(&self, data: WsClientData) {
|
|
let (ret, rx) = oneshot::channel();
|
|
let (ret, rx) = oneshot::channel();
|
|
let sender = self.ws_sender.clone();
|
|
let sender = self.ws_sender.clone();
|
|
let pool = self.pg_pool.clone();
|
|
let pool = self.pg_pool.clone();
|
|
|
|
|
|
actix_rt::spawn(async move {
|
|
actix_rt::spawn(async move {
|
|
- let msg = DocWsMsg::ClientData { client_data, ret, pool };
|
|
|
|
|
|
+ let msg = DocWsMsg::ClientData {
|
|
|
|
+ client_data: data,
|
|
|
|
+ ret,
|
|
|
|
+ pool,
|
|
|
|
+ };
|
|
match sender.send(msg).await {
|
|
match sender.send(msg).await {
|
|
Ok(_) => {},
|
|
Ok(_) => {},
|
|
Err(e) => log::error!("{}", e),
|
|
Err(e) => log::error!("{}", e),
|
|
@@ -63,16 +69,9 @@ impl WsBizHandler for DocumentCore {
|
|
}
|
|
}
|
|
|
|
|
|
#[rustfmt::skip]
|
|
#[rustfmt::skip]
|
|
-// EditDocActor
|
|
|
|
-// ┌────────────────────────────────────┐
|
|
|
|
-// │ ServerDocEditor │
|
|
|
|
-// │ ┌──────────────────────────────┐ │
|
|
|
|
-// ┌────────────┐ 1 n ┌───────────────┐ │ │ ┌──────────┐ ┌──────────┐ │ │
|
|
|
|
-// │ DocManager │─────▶│ OpenDocHandle │──────▶│ │ │ Document │ │ Users │ │ │
|
|
|
|
-// └────────────┘ └───────────────┘ │ │ └──────────┘ └──────────┘ │ │
|
|
|
|
-// │ └──────────────────────────────┘ │
|
|
|
|
-// │ │
|
|
|
|
-// └────────────────────────────────────┘
|
|
|
|
|
|
+// ┌────────────┐ 1 n ┌───────────────┐ ┌──────────────────┐ ┌────────────────┐
|
|
|
|
+// │ DocManager │───────▶│ OpenDocHandle │────▶│ DocMessageQueue │───▶│ServerDocEditor │
|
|
|
|
+// └────────────┘ └───────────────┘ └──────────────────┘ └────────────────┘
|
|
pub struct DocManager {
|
|
pub struct DocManager {
|
|
open_doc_map: DashMap<String, Arc<OpenDocHandle>>,
|
|
open_doc_map: DashMap<String, Arc<OpenDocHandle>>,
|
|
}
|
|
}
|
|
@@ -109,20 +108,20 @@ impl DocManager {
|
|
}
|
|
}
|
|
|
|
|
|
pub struct OpenDocHandle {
|
|
pub struct OpenDocHandle {
|
|
- pub sender: mpsc::Sender<EditMsg>,
|
|
|
|
|
|
+ pub sender: mpsc::Sender<DocMessage>,
|
|
}
|
|
}
|
|
|
|
|
|
impl OpenDocHandle {
|
|
impl OpenDocHandle {
|
|
pub fn new(doc: Doc, pg_pool: Data<PgPool>) -> Result<Self, ServerError> {
|
|
pub fn new(doc: Doc, pg_pool: Data<PgPool>) -> Result<Self, ServerError> {
|
|
let (sender, receiver) = mpsc::channel(100);
|
|
let (sender, receiver) = mpsc::channel(100);
|
|
- let actor = EditDocActor::new(receiver, doc, pg_pool)?;
|
|
|
|
- tokio::task::spawn(actor.run());
|
|
|
|
|
|
+ let queue = DocMessageQueue::new(receiver, doc, pg_pool)?;
|
|
|
|
+ tokio::task::spawn(queue.run());
|
|
Ok(Self { sender })
|
|
Ok(Self { sender })
|
|
}
|
|
}
|
|
|
|
|
|
pub async fn add_user(&self, user: Arc<WsUser>, rev_id: i64, socket: Socket) -> Result<(), ServerError> {
|
|
pub async fn add_user(&self, user: Arc<WsUser>, rev_id: i64, socket: Socket) -> Result<(), ServerError> {
|
|
let (ret, rx) = oneshot::channel();
|
|
let (ret, rx) = oneshot::channel();
|
|
- let msg = EditMsg::NewDocUser {
|
|
|
|
|
|
+ let msg = DocMessage::NewConnectedUser {
|
|
user,
|
|
user,
|
|
socket,
|
|
socket,
|
|
rev_id,
|
|
rev_id,
|
|
@@ -139,7 +138,7 @@ impl OpenDocHandle {
|
|
revision: Revision,
|
|
revision: Revision,
|
|
) -> Result<(), ServerError> {
|
|
) -> Result<(), ServerError> {
|
|
let (ret, rx) = oneshot::channel();
|
|
let (ret, rx) = oneshot::channel();
|
|
- let msg = EditMsg::Revision {
|
|
|
|
|
|
+ let msg = DocMessage::ReceiveRevision {
|
|
user,
|
|
user,
|
|
socket,
|
|
socket,
|
|
revision,
|
|
revision,
|
|
@@ -151,19 +150,118 @@ impl OpenDocHandle {
|
|
|
|
|
|
pub async fn document_json(&self) -> DocResult<String> {
|
|
pub async fn document_json(&self) -> DocResult<String> {
|
|
let (ret, rx) = oneshot::channel();
|
|
let (ret, rx) = oneshot::channel();
|
|
- let msg = EditMsg::DocumentJson { ret };
|
|
|
|
|
|
+ let msg = DocMessage::GetDocJson { ret };
|
|
self.send(msg, rx).await?
|
|
self.send(msg, rx).await?
|
|
}
|
|
}
|
|
|
|
|
|
pub async fn rev_id(&self) -> DocResult<i64> {
|
|
pub async fn rev_id(&self) -> DocResult<i64> {
|
|
let (ret, rx) = oneshot::channel();
|
|
let (ret, rx) = oneshot::channel();
|
|
- let msg = EditMsg::DocumentRevId { ret };
|
|
|
|
|
|
+ let msg = DocMessage::GetDocRevId { ret };
|
|
self.send(msg, rx).await?
|
|
self.send(msg, rx).await?
|
|
}
|
|
}
|
|
|
|
|
|
- pub(crate) async fn send<T>(&self, msg: EditMsg, rx: oneshot::Receiver<T>) -> DocResult<T> {
|
|
|
|
|
|
+ pub(crate) async fn send<T>(&self, msg: DocMessage, rx: oneshot::Receiver<T>) -> DocResult<T> {
|
|
let _ = self.sender.send(msg).await.map_err(internal_error)?;
|
|
let _ = self.sender.send(msg).await.map_err(internal_error)?;
|
|
let result = rx.await?;
|
|
let result = rx.await?;
|
|
Ok(result)
|
|
Ok(result)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+#[derive(Debug)]
|
|
|
|
+pub enum DocMessage {
|
|
|
|
+ NewConnectedUser {
|
|
|
|
+ user: Arc<WsUser>,
|
|
|
|
+ socket: Socket,
|
|
|
|
+ rev_id: i64,
|
|
|
|
+ ret: oneshot::Sender<DocResult<()>>,
|
|
|
|
+ },
|
|
|
|
+ ReceiveRevision {
|
|
|
|
+ user: Arc<WsUser>,
|
|
|
|
+ socket: Socket,
|
|
|
|
+ revision: Revision,
|
|
|
|
+ ret: oneshot::Sender<DocResult<()>>,
|
|
|
|
+ },
|
|
|
|
+ GetDocJson {
|
|
|
|
+ ret: oneshot::Sender<DocResult<String>>,
|
|
|
|
+ },
|
|
|
|
+ GetDocRevId {
|
|
|
|
+ ret: oneshot::Sender<DocResult<i64>>,
|
|
|
|
+ },
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+struct DocMessageQueue {
|
|
|
|
+ receiver: Option<mpsc::Receiver<DocMessage>>,
|
|
|
|
+ edit_doc: Arc<ServerDocEditor>,
|
|
|
|
+ pg_pool: Data<PgPool>,
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl DocMessageQueue {
|
|
|
|
+ fn new(receiver: mpsc::Receiver<DocMessage>, doc: Doc, pg_pool: Data<PgPool>) -> Result<Self, ServerError> {
|
|
|
|
+ let edit_doc = Arc::new(ServerDocEditor::new(doc)?);
|
|
|
|
+ Ok(Self {
|
|
|
|
+ receiver: Some(receiver),
|
|
|
|
+ edit_doc,
|
|
|
|
+ pg_pool,
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ async fn run(mut self) {
|
|
|
|
+ let mut receiver = self
|
|
|
|
+ .receiver
|
|
|
|
+ .take()
|
|
|
|
+ .expect("DocActor's receiver should only take one time");
|
|
|
|
+
|
|
|
|
+ let stream = stream! {
|
|
|
|
+ loop {
|
|
|
|
+ match receiver.recv().await {
|
|
|
|
+ Some(msg) => yield msg,
|
|
|
|
+ None => break,
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ stream.for_each(|msg| self.handle_message(msg)).await;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ async fn handle_message(&self, msg: DocMessage) {
|
|
|
|
+ match msg {
|
|
|
|
+ DocMessage::NewConnectedUser {
|
|
|
|
+ user,
|
|
|
|
+ socket,
|
|
|
|
+ rev_id,
|
|
|
|
+ ret,
|
|
|
|
+ } => {
|
|
|
|
+ log::debug!("Receive new doc user: {:?}, rev_id: {}", user, rev_id);
|
|
|
|
+ let user = DocUser {
|
|
|
|
+ user: user.clone(),
|
|
|
|
+ socket: socket.clone(),
|
|
|
|
+ pg_pool: self.pg_pool.clone(),
|
|
|
|
+ };
|
|
|
|
+ let _ = ret.send(self.edit_doc.new_doc_user(user, rev_id).await);
|
|
|
|
+ },
|
|
|
|
+ DocMessage::ReceiveRevision {
|
|
|
|
+ user,
|
|
|
|
+ socket,
|
|
|
|
+ revision,
|
|
|
|
+ ret,
|
|
|
|
+ } => {
|
|
|
|
+ let user = DocUser {
|
|
|
|
+ user: user.clone(),
|
|
|
|
+ socket: socket.clone(),
|
|
|
|
+ pg_pool: self.pg_pool.clone(),
|
|
|
|
+ };
|
|
|
|
+ let _ = ret.send(self.edit_doc.apply_revision(user, revision).await);
|
|
|
|
+ },
|
|
|
|
+ DocMessage::GetDocJson { ret } => {
|
|
|
|
+ let edit_context = self.edit_doc.clone();
|
|
|
|
+ let json = spawn_blocking(move || edit_context.document_json())
|
|
|
|
+ .await
|
|
|
|
+ .map_err(internal_error);
|
|
|
|
+ let _ = ret.send(json);
|
|
|
|
+ },
|
|
|
|
+ DocMessage::GetDocRevId { ret } => {
|
|
|
|
+ let rev_id = self.edit_doc.rev_id.load(SeqCst);
|
|
|
|
+ let _ = ret.send(Ok(rev_id));
|
|
|
|
+ },
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|