2021-12-06 21:47:21 +08:00
|
|
|
use crate::{
|
|
|
|
services::{
|
2021-12-10 11:05:23 +08:00
|
|
|
doc::manager::{DocManager, OpenDocHandle},
|
2021-12-06 21:47:21 +08:00
|
|
|
util::{md5, parse_from_bytes},
|
|
|
|
},
|
|
|
|
web_socket::{entities::Socket, WsClientData, WsUser},
|
2021-09-30 17:24:02 +08:00
|
|
|
};
|
2021-09-29 17:40:34 +08:00
|
|
|
use actix_rt::task::spawn_blocking;
|
|
|
|
use actix_web::web::Data;
|
|
|
|
use async_stream::stream;
|
2021-11-20 08:35:04 +08:00
|
|
|
use backend_service::errors::{internal_error, Result as DocResult, ServerError};
|
2021-12-11 13:47:16 +08:00
|
|
|
use flowy_collaboration::protobuf::{NewDocUser, WsDataType, WsDocumentData};
|
2021-09-29 17:40:34 +08:00
|
|
|
use futures::stream::StreamExt;
|
2021-12-07 22:32:34 +08:00
|
|
|
use lib_ot::protobuf::Revision;
|
2021-09-29 17:40:34 +08:00
|
|
|
use sqlx::PgPool;
|
|
|
|
use std::sync::Arc;
|
|
|
|
use tokio::sync::{mpsc, oneshot};
|
|
|
|
|
|
|
|
pub enum DocWsMsg {
|
|
|
|
ClientData {
|
2021-09-30 17:24:02 +08:00
|
|
|
client_data: WsClientData,
|
2021-09-29 17:40:34 +08:00
|
|
|
pool: Data<PgPool>,
|
|
|
|
ret: oneshot::Sender<DocResult<()>>,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2021-10-02 17:19:54 +08:00
|
|
|
pub struct DocWsActor {
|
2021-09-29 17:40:34 +08:00
|
|
|
receiver: Option<mpsc::Receiver<DocWsMsg>>,
|
|
|
|
doc_manager: Arc<DocManager>,
|
|
|
|
}
|
|
|
|
|
2021-10-02 17:19:54 +08:00
|
|
|
impl DocWsActor {
|
2021-09-29 17:40:34 +08:00
|
|
|
pub fn new(receiver: mpsc::Receiver<DocWsMsg>, manager: Arc<DocManager>) -> Self {
|
|
|
|
Self {
|
|
|
|
receiver: Some(receiver),
|
|
|
|
doc_manager: manager,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub 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: DocWsMsg) {
|
|
|
|
match msg {
|
2021-09-30 17:24:02 +08:00
|
|
|
DocWsMsg::ClientData { client_data, pool, ret } => {
|
|
|
|
let _ = ret.send(self.handle_client_data(client_data, pool).await);
|
2021-09-29 17:40:34 +08:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-30 17:24:02 +08:00
|
|
|
async fn handle_client_data(&self, client_data: WsClientData, pool: Data<PgPool>) -> DocResult<()> {
|
|
|
|
let WsClientData { user, socket, data } = client_data;
|
2021-09-29 17:40:34 +08:00
|
|
|
let document_data = spawn_blocking(move || {
|
2021-09-30 17:24:02 +08:00
|
|
|
let document_data: WsDocumentData = parse_from_bytes(&data)?;
|
2021-09-29 17:40:34 +08:00
|
|
|
DocResult::Ok(document_data)
|
|
|
|
})
|
|
|
|
.await
|
|
|
|
.map_err(internal_error)??;
|
|
|
|
|
2021-10-03 11:33:19 +08:00
|
|
|
let data = document_data.data;
|
|
|
|
|
2021-09-29 17:40:34 +08:00
|
|
|
match document_data.ty {
|
2021-09-30 17:24:02 +08:00
|
|
|
WsDataType::Acked => Ok(()),
|
2021-12-03 22:40:56 +08:00
|
|
|
WsDataType::PushRev => self.apply_pushed_rev(user, socket, data, pool).await,
|
|
|
|
WsDataType::NewDocUser => self.add_doc_user(user, socket, data, pool).await,
|
2021-09-30 17:24:02 +08:00
|
|
|
WsDataType::PullRev => Ok(()),
|
|
|
|
WsDataType::Conflict => Ok(()),
|
2021-09-29 17:40:34 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-03 22:40:56 +08:00
|
|
|
async fn add_doc_user(
|
2021-10-03 21:29:56 +08:00
|
|
|
&self,
|
|
|
|
user: Arc<WsUser>,
|
|
|
|
socket: Socket,
|
|
|
|
data: Vec<u8>,
|
|
|
|
pool: Data<PgPool>,
|
|
|
|
) -> DocResult<()> {
|
|
|
|
let doc_user = spawn_blocking(move || {
|
2021-10-03 11:33:19 +08:00
|
|
|
let user: NewDocUser = parse_from_bytes(&data)?;
|
|
|
|
DocResult::Ok(user)
|
|
|
|
})
|
|
|
|
.await
|
|
|
|
.map_err(internal_error)??;
|
2021-12-03 22:40:56 +08:00
|
|
|
if let Some(handle) = self.find_doc_handle(&doc_user.doc_id, pool).await {
|
|
|
|
handle.add_user(user, doc_user.rev_id, socket).await?;
|
2021-10-03 21:29:56 +08:00
|
|
|
}
|
|
|
|
Ok(())
|
2021-10-03 11:33:19 +08:00
|
|
|
}
|
|
|
|
|
2021-12-03 22:40:56 +08:00
|
|
|
async fn apply_pushed_rev(
|
2021-09-29 17:40:34 +08:00
|
|
|
&self,
|
2021-09-30 17:24:02 +08:00
|
|
|
user: Arc<WsUser>,
|
|
|
|
socket: Socket,
|
2021-10-03 11:33:19 +08:00
|
|
|
data: Vec<u8>,
|
2021-09-29 17:40:34 +08:00
|
|
|
pool: Data<PgPool>,
|
|
|
|
) -> DocResult<()> {
|
|
|
|
let revision = spawn_blocking(move || {
|
2021-10-03 11:33:19 +08:00
|
|
|
let revision: Revision = parse_from_bytes(&data)?;
|
2021-09-30 17:24:02 +08:00
|
|
|
let _ = verify_md5(&revision)?;
|
2021-09-29 17:40:34 +08:00
|
|
|
DocResult::Ok(revision)
|
|
|
|
})
|
|
|
|
.await
|
|
|
|
.map_err(internal_error)??;
|
2021-12-03 22:40:56 +08:00
|
|
|
if let Some(handle) = self.find_doc_handle(&revision.doc_id, pool).await {
|
2021-10-03 21:29:56 +08:00
|
|
|
handle.apply_revision(user, socket, revision).await?;
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
2021-09-29 17:40:34 +08:00
|
|
|
|
2021-12-10 11:05:23 +08:00
|
|
|
async fn find_doc_handle(&self, doc_id: &str, pool: Data<PgPool>) -> Option<Arc<OpenDocHandle>> {
|
2021-10-03 21:29:56 +08:00
|
|
|
match self.doc_manager.get(doc_id, pool).await {
|
|
|
|
Ok(Some(edit_doc)) => Some(edit_doc),
|
|
|
|
Ok(None) => {
|
|
|
|
log::error!("Document with id: {} not exist", doc_id);
|
|
|
|
None
|
2021-09-29 17:40:34 +08:00
|
|
|
},
|
2021-10-03 21:29:56 +08:00
|
|
|
Err(e) => {
|
|
|
|
log::error!("Get doc handle failed: {:?}", e);
|
|
|
|
None
|
2021-09-29 17:40:34 +08:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-09-30 17:24:02 +08:00
|
|
|
|
|
|
|
fn verify_md5(revision: &Revision) -> DocResult<()> {
|
|
|
|
if md5(&revision.delta_data) != revision.md5 {
|
|
|
|
return Err(ServerError::internal().context("Revision md5 not match"));
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|