fix init folder manager bugs

This commit is contained in:
appflowy 2022-01-23 22:33:47 +08:00
parent 23c4924532
commit 10d99bdd8b
36 changed files with 205 additions and 157 deletions

View File

@ -11,7 +11,7 @@ use crate::services::kv::revision_kv::RevisionKVPersistence;
use std::sync::Arc; use std::sync::Arc;
use uuid::Uuid; use uuid::Uuid;
#[tracing::instrument(level = "debug", skip(document_store, params), err)] #[tracing::instrument(level = "trace", skip(document_store, params), err)]
pub(crate) async fn create_document( pub(crate) async fn create_document(
document_store: &Arc<RevisionKVPersistence>, document_store: &Arc<RevisionKVPersistence>,
mut params: CreateDocParams, mut params: CreateDocParams,
@ -21,7 +21,7 @@ pub(crate) async fn create_document(
Ok(()) Ok(())
} }
#[tracing::instrument(level = "debug", skip(document_store), err)] #[tracing::instrument(level = "trace", skip(document_store), err)]
pub async fn read_document( pub async fn read_document(
document_store: &Arc<RevisionKVPersistence>, document_store: &Arc<RevisionKVPersistence>,
params: DocumentId, params: DocumentId,
@ -52,7 +52,7 @@ pub async fn reset_document(
Ok(()) Ok(())
} }
#[tracing::instrument(level = "debug", skip(document_store), err)] #[tracing::instrument(level = "trace", skip(document_store), err)]
pub(crate) async fn delete_document( pub(crate) async fn delete_document(
document_store: &Arc<RevisionKVPersistence>, document_store: &Arc<RevisionKVPersistence>,
doc_id: Uuid, doc_id: Uuid,

View File

@ -31,27 +31,27 @@ pub enum DocumentWSActorMessage {
} }
pub struct DocumentWebSocketActor { pub struct DocumentWebSocketActor {
receiver: Option<mpsc::Receiver<DocumentWSActorMessage>>, actor_msg_receiver: Option<mpsc::Receiver<DocumentWSActorMessage>>,
doc_manager: Arc<ServerDocumentManager>, doc_manager: Arc<ServerDocumentManager>,
} }
impl DocumentWebSocketActor { impl DocumentWebSocketActor {
pub fn new(receiver: mpsc::Receiver<DocumentWSActorMessage>, manager: Arc<ServerDocumentManager>) -> Self { pub fn new(receiver: mpsc::Receiver<DocumentWSActorMessage>, manager: Arc<ServerDocumentManager>) -> Self {
Self { Self {
receiver: Some(receiver), actor_msg_receiver: Some(receiver),
doc_manager: manager, doc_manager: manager,
} }
} }
pub async fn run(mut self) { pub async fn run(mut self) {
let mut receiver = self let mut actor_msg_receiver = self
.receiver .actor_msg_receiver
.take() .take()
.expect("DocumentWebSocketActor's receiver should only take one time"); .expect("DocumentWebSocketActor's receiver should only take one time");
let stream = stream! { let stream = stream! {
loop { loop {
match receiver.recv().await { match actor_msg_receiver.recv().await {
Some(msg) => yield msg, Some(msg) => yield msg,
None => break, None => break,
} }
@ -79,7 +79,7 @@ impl DocumentWebSocketActor {
.await .await
.map_err(internal_error)??; .map_err(internal_error)??;
tracing::debug!( tracing::trace!(
"[DocumentWebSocketActor]: receive: {}:{}, {:?}", "[DocumentWebSocketActor]: receive: {}:{}, {:?}",
document_client_data.object_id, document_client_data.object_id,
document_client_data.data_id, document_client_data.data_id,

View File

@ -34,28 +34,31 @@ pub fn make_document_ws_receiver(
persistence: Arc<FlowyPersistence>, persistence: Arc<FlowyPersistence>,
document_manager: Arc<ServerDocumentManager>, document_manager: Arc<ServerDocumentManager>,
) -> Arc<DocumentWebSocketReceiver> { ) -> Arc<DocumentWebSocketReceiver> {
let (ws_sender, rx) = tokio::sync::mpsc::channel(1000); let (actor_msg_sender, rx) = tokio::sync::mpsc::channel(1000);
let actor = DocumentWebSocketActor::new(rx, document_manager); let actor = DocumentWebSocketActor::new(rx, document_manager);
tokio::task::spawn(actor.run()); tokio::task::spawn(actor.run());
Arc::new(DocumentWebSocketReceiver::new(persistence, ws_sender)) Arc::new(DocumentWebSocketReceiver::new(persistence, actor_msg_sender))
} }
pub struct DocumentWebSocketReceiver { pub struct DocumentWebSocketReceiver {
ws_sender: mpsc::Sender<DocumentWSActorMessage>, actor_msg_sender: mpsc::Sender<DocumentWSActorMessage>,
persistence: Arc<FlowyPersistence>, persistence: Arc<FlowyPersistence>,
} }
impl DocumentWebSocketReceiver { impl DocumentWebSocketReceiver {
pub fn new(persistence: Arc<FlowyPersistence>, ws_sender: mpsc::Sender<DocumentWSActorMessage>) -> Self { pub fn new(persistence: Arc<FlowyPersistence>, actor_msg_sender: mpsc::Sender<DocumentWSActorMessage>) -> Self {
Self { ws_sender, persistence } Self {
actor_msg_sender,
persistence,
}
} }
} }
impl WebSocketReceiver for DocumentWebSocketReceiver { impl WebSocketReceiver for DocumentWebSocketReceiver {
fn receive(&self, data: WSClientData) { fn receive(&self, data: WSClientData) {
let (ret, rx) = oneshot::channel(); let (ret, rx) = oneshot::channel();
let sender = self.ws_sender.clone(); let actor_msg_sender = self.actor_msg_sender.clone();
let persistence = self.persistence.clone(); let persistence = self.persistence.clone();
actix_rt::spawn(async move { actix_rt::spawn(async move {
@ -65,13 +68,13 @@ impl WebSocketReceiver for DocumentWebSocketReceiver {
ret, ret,
}; };
match sender.send(msg).await { match actor_msg_sender.send(msg).await {
Ok(_) => {}, Ok(_) => {},
Err(e) => log::error!("{}", e), Err(e) => log::error!("[DocumentWebSocketReceiver]: send message to actor failed: {}", e),
} }
match rx.await { match rx.await {
Ok(_) => {}, Ok(_) => {},
Err(e) => log::error!("{:?}", e), Err(e) => log::error!("[DocumentWebSocketReceiver]: message ret failed {:?}", e),
}; };
}); });
} }

View File

@ -29,28 +29,30 @@ pub enum FolderWSActorMessage {
} }
pub struct FolderWebSocketActor { pub struct FolderWebSocketActor {
receiver: Option<mpsc::Receiver<FolderWSActorMessage>>, actor_msg_receiver: Option<mpsc::Receiver<FolderWSActorMessage>>,
folder_manager: Arc<ServerFolderManager>, folder_manager: Arc<ServerFolderManager>,
} }
impl FolderWebSocketActor { impl FolderWebSocketActor {
pub fn new(receiver: mpsc::Receiver<FolderWSActorMessage>, folder_manager: Arc<ServerFolderManager>) -> Self { pub fn new(receiver: mpsc::Receiver<FolderWSActorMessage>, folder_manager: Arc<ServerFolderManager>) -> Self {
Self { Self {
receiver: Some(receiver), actor_msg_receiver: Some(receiver),
folder_manager, folder_manager,
} }
} }
pub async fn run(mut self) { pub async fn run(mut self) {
let mut receiver = self let mut actor_msg_receiver = self
.receiver .actor_msg_receiver
.take() .take()
.expect("FolderWebSocketActor's receiver should only take one time"); .expect("FolderWebSocketActor's receiver should only take one time");
let stream = stream! { let stream = stream! {
loop { loop {
match receiver.recv().await { match actor_msg_receiver.recv().await {
Some(msg) => yield msg, Some(msg) => yield msg,
None => break, None => {
break
},
} }
} }
}; };
@ -76,7 +78,7 @@ impl FolderWebSocketActor {
.map_err(internal_error)??; .map_err(internal_error)??;
tracing::debug!( tracing::debug!(
"[DocumentWebSocketActor]: receive: {}:{}, {:?}", "[FolderWebSocketActor]: receive: {}:{}, {:?}",
folder_client_data.object_id, folder_client_data.object_id,
folder_client_data.data_id, folder_client_data.data_id,
folder_client_data.ty folder_client_data.ty

View File

@ -23,27 +23,30 @@ pub fn make_folder_ws_receiver(
persistence: Arc<FlowyPersistence>, persistence: Arc<FlowyPersistence>,
folder_manager: Arc<ServerFolderManager>, folder_manager: Arc<ServerFolderManager>,
) -> Arc<FolderWebSocketReceiver> { ) -> Arc<FolderWebSocketReceiver> {
let (ws_sender, rx) = tokio::sync::mpsc::channel(1000); let (actor_msg_sender, rx) = tokio::sync::mpsc::channel(1000);
let actor = FolderWebSocketActor::new(rx, folder_manager); let actor = FolderWebSocketActor::new(rx, folder_manager);
tokio::task::spawn(actor.run()); tokio::task::spawn(actor.run());
Arc::new(FolderWebSocketReceiver::new(persistence, ws_sender)) Arc::new(FolderWebSocketReceiver::new(persistence, actor_msg_sender))
} }
pub struct FolderWebSocketReceiver { pub struct FolderWebSocketReceiver {
ws_sender: mpsc::Sender<FolderWSActorMessage>, actor_msg_sender: mpsc::Sender<FolderWSActorMessage>,
persistence: Arc<FlowyPersistence>, persistence: Arc<FlowyPersistence>,
} }
impl FolderWebSocketReceiver { impl FolderWebSocketReceiver {
pub fn new(persistence: Arc<FlowyPersistence>, ws_sender: mpsc::Sender<FolderWSActorMessage>) -> Self { pub fn new(persistence: Arc<FlowyPersistence>, actor_msg_sender: mpsc::Sender<FolderWSActorMessage>) -> Self {
Self { ws_sender, persistence } Self {
actor_msg_sender,
persistence,
}
} }
} }
impl WebSocketReceiver for FolderWebSocketReceiver { impl WebSocketReceiver for FolderWebSocketReceiver {
fn receive(&self, data: WSClientData) { fn receive(&self, data: WSClientData) {
let (ret, rx) = oneshot::channel(); let (ret, rx) = oneshot::channel();
let sender = self.ws_sender.clone(); let actor_msg_sender = self.actor_msg_sender.clone();
let persistence = self.persistence.clone(); let persistence = self.persistence.clone();
actix_rt::spawn(async move { actix_rt::spawn(async move {
@ -53,13 +56,15 @@ impl WebSocketReceiver for FolderWebSocketReceiver {
ret, ret,
}; };
match sender.send(msg).await { match actor_msg_sender.send(msg).await {
Ok(_) => {}, Ok(_) => {},
Err(e) => log::error!("{}", e), Err(e) => {
log::error!("[FolderWebSocketReceiver]: send message to actor failed: {}", e);
},
} }
match rx.await { match rx.await {
Ok(_) => {}, Ok(_) => {},
Err(e) => log::error!("{:?}", e), Err(e) => log::error!("[FolderWebSocketReceiver]: message ret failed {:?}", e),
}; };
}); });
} }

View File

@ -28,7 +28,7 @@ impl Builder {
let env_filter = EnvFilter::new(self.env_filter); let env_filter = EnvFilter::new(self.env_filter);
let subscriber = tracing_subscriber::fmt() let subscriber = tracing_subscriber::fmt()
.with_target(true) .with_target(true)
.with_max_level(tracing::Level::DEBUG) .with_max_level(tracing::Level::TRACE)
.with_writer(std::io::stderr) .with_writer(std::io::stderr)
.with_thread_ids(true) .with_thread_ids(true)
.compact() .compact()

View File

@ -29,8 +29,9 @@ impl std::default::Default for WebSocketReceivers {
impl WebSocketReceivers { impl WebSocketReceivers {
pub fn new() -> Self { WebSocketReceivers::default() } pub fn new() -> Self { WebSocketReceivers::default() }
pub fn set(&mut self, source: WSChannel, receiver: Arc<dyn WebSocketReceiver>) { pub fn set(&mut self, channel: WSChannel, receiver: Arc<dyn WebSocketReceiver>) {
self.inner.insert(source, receiver); tracing::trace!("Add {:?} receiver", channel);
self.inner.insert(channel, receiver);
} }
pub fn get(&self, source: &WSChannel) -> Option<Arc<dyn WebSocketReceiver>> { self.inner.get(source).cloned() } pub fn get(&self, source: &WSChannel) -> Option<Arc<dyn WebSocketReceiver>> { self.inner.get(source).cloned() }

View File

@ -15,7 +15,7 @@ CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
CARGO_MAKE_CRATE_FS_NAME = "dart_ffi" CARGO_MAKE_CRATE_FS_NAME = "dart_ffi"
CARGO_MAKE_CRATE_NAME = "dart-ffi" CARGO_MAKE_CRATE_NAME = "dart-ffi"
VERSION = "0.0.2" VERSION = "0.0.2"
FEATURES = "flutter" FEATURES = "flutter, http_server"
PRODUCT_NAME = "AppFlowy" PRODUCT_NAME = "AppFlowy"
#CRATE_TYPE: https://doc.rust-lang.org/reference/linkage.html #CRATE_TYPE: https://doc.rust-lang.org/reference/linkage.html
CRATE_TYPE = "staticlib" CRATE_TYPE = "staticlib"

View File

@ -2,6 +2,7 @@ import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/user/application/splash_bloc.dart'; import 'package:app_flowy/user/application/splash_bloc.dart';
import 'package:app_flowy/user/domain/auth_state.dart'; import 'package:app_flowy/user/domain/auth_state.dart';
import 'package:app_flowy/user/domain/i_splash.dart'; import 'package:app_flowy/user/domain/i_splash.dart';
import 'package:flowy_log/flowy_log.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-core-data-model/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core-data-model/errors.pb.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -48,6 +49,7 @@ class SplashScreen extends StatelessWidget {
return result.fold( return result.fold(
(workspaceSetting) => getIt<ISplashRoute>().pushHomeScreen(context, userProfile, workspaceSetting), (workspaceSetting) => getIt<ISplashRoute>().pushHomeScreen(context, userProfile, workspaceSetting),
(error) async { (error) async {
Log.error(error);
assert(error.code == ErrorCode.RecordNotFound.value); assert(error.code == ErrorCode.RecordNotFound.value);
getIt<ISplashRoute>().pushWelcomeScreen(context, userProfile); getIt<ISplashRoute>().pushWelcomeScreen(context, userProfile);
}, },

View File

@ -7,7 +7,7 @@ use lazy_static::lazy_static;
use flowy_collaboration::{entities::ws_data::ServerRevisionWSData, folder::FolderPad}; use flowy_collaboration::{entities::ws_data::ServerRevisionWSData, folder::FolderPad};
use flowy_document::FlowyDocumentManager; use flowy_document::FlowyDocumentManager;
use parking_lot::RwLock;
use std::{collections::HashMap, convert::TryInto, fmt::Formatter, sync::Arc}; use std::{collections::HashMap, convert::TryInto, fmt::Formatter, sync::Arc};
use tokio::sync::RwLock as TokioRwLock; use tokio::sync::RwLock as TokioRwLock;
@ -28,10 +28,10 @@ use crate::{
}; };
lazy_static! { lazy_static! {
static ref INIT_FOLDER_FLAG: RwLock<HashMap<String, bool>> = RwLock::new(HashMap::new()); static ref INIT_FOLDER_FLAG: TokioRwLock<HashMap<String, bool>> = TokioRwLock::new(HashMap::new());
} }
const FOLDER_ID: &str = "user_folder"; const FOLDER_ID: &str = "folder";
const FOLDER_ID_SPLIT: &str = ":"; const FOLDER_ID_SPLIT: &str = ":";
#[derive(Clone)] #[derive(Clone)]
pub struct FolderId(String); pub struct FolderId(String);
@ -64,17 +64,13 @@ pub struct FolderManager {
} }
impl FolderManager { impl FolderManager {
pub fn new( pub async fn new(
user: Arc<dyn WorkspaceUser>, user: Arc<dyn WorkspaceUser>,
cloud_service: Arc<dyn FolderCouldServiceV1>, cloud_service: Arc<dyn FolderCouldServiceV1>,
database: Arc<dyn WorkspaceDatabase>, database: Arc<dyn WorkspaceDatabase>,
document_manager: Arc<FlowyDocumentManager>, document_manager: Arc<FlowyDocumentManager>,
web_socket: Arc<dyn RevisionWebSocket>, web_socket: Arc<dyn RevisionWebSocket>,
) -> Self { ) -> Self {
if let Ok(token) = user.token() {
INIT_FOLDER_FLAG.write().insert(token, false);
}
let folder_editor = Arc::new(TokioRwLock::new(None)); let folder_editor = Arc::new(TokioRwLock::new(None));
let persistence = Arc::new(FolderPersistence::new(database.clone(), folder_editor.clone())); let persistence = Arc::new(FolderPersistence::new(database.clone(), folder_editor.clone()));
@ -145,7 +141,8 @@ impl FolderManager {
} }
pub async fn initialize(&self, user_id: &str) -> FlowyResult<()> { pub async fn initialize(&self, user_id: &str) -> FlowyResult<()> {
if let Some(is_init) = INIT_FOLDER_FLAG.read().get(user_id) { let mut write_guard = INIT_FOLDER_FLAG.write().await;
if let Some(is_init) = write_guard.get(user_id) {
if *is_init { if *is_init {
return Ok(()); return Ok(());
} }
@ -160,7 +157,7 @@ impl FolderManager {
let _ = self.app_controller.initialize()?; let _ = self.app_controller.initialize()?;
let _ = self.view_controller.initialize()?; let _ = self.view_controller.initialize()?;
INIT_FOLDER_FLAG.write().insert(user_id.to_owned(), true); write_guard.insert(user_id.to_owned(), true);
Ok(()) Ok(())
} }

View File

@ -27,12 +27,12 @@ impl std::convert::From<WorkspaceNotification> for i32 {
fn from(notification: WorkspaceNotification) -> Self { notification as i32 } fn from(notification: WorkspaceNotification) -> Self { notification as i32 }
} }
#[tracing::instrument(level = "debug")] #[tracing::instrument(level = "trace")]
pub(crate) fn send_dart_notification(id: &str, ty: WorkspaceNotification) -> DartNotifyBuilder { pub(crate) fn send_dart_notification(id: &str, ty: WorkspaceNotification) -> DartNotifyBuilder {
DartNotifyBuilder::new(id, ty, OBSERVABLE_CATEGORY) DartNotifyBuilder::new(id, ty, OBSERVABLE_CATEGORY)
} }
#[tracing::instrument(level = "debug")] #[tracing::instrument(level = "trace")]
pub(crate) fn send_anonymous_dart_notification(ty: WorkspaceNotification) -> DartNotifyBuilder { pub(crate) fn send_anonymous_dart_notification(ty: WorkspaceNotification) -> DartNotifyBuilder {
DartNotifyBuilder::new("", ty, OBSERVABLE_CATEGORY) DartNotifyBuilder::new("", ty, OBSERVABLE_CATEGORY)
} }

View File

@ -112,14 +112,14 @@ impl AppController {
} }
impl AppController { impl AppController {
#[tracing::instrument(level = "debug", skip(self), err)] #[tracing::instrument(level = "trace", skip(self), err)]
async fn create_app_on_server(&self, params: CreateAppParams) -> Result<App, FlowyError> { async fn create_app_on_server(&self, params: CreateAppParams) -> Result<App, FlowyError> {
let token = self.user.token()?; let token = self.user.token()?;
let app = self.cloud_service.create_app(&token, params).await?; let app = self.cloud_service.create_app(&token, params).await?;
Ok(app) Ok(app)
} }
#[tracing::instrument(level = "debug", skip(self), err)] #[tracing::instrument(level = "trace", skip(self), err)]
fn update_app_on_server(&self, params: UpdateAppParams) -> Result<(), FlowyError> { fn update_app_on_server(&self, params: UpdateAppParams) -> Result<(), FlowyError> {
let token = self.user.token()?; let token = self.user.token()?;
let server = self.cloud_service.clone(); let server = self.cloud_service.clone();
@ -135,7 +135,7 @@ impl AppController {
Ok(()) Ok(())
} }
#[tracing::instrument(level = "debug", skip(self), err)] #[tracing::instrument(level = "trace", skip(self), err)]
fn read_app_on_server(&self, params: AppId) -> Result<(), FlowyError> { fn read_app_on_server(&self, params: AppId) -> Result<(), FlowyError> {
let token = self.user.token()?; let token = self.user.token()?;
let server = self.cloud_service.clone(); let server = self.cloud_service.clone();

View File

@ -104,7 +104,7 @@ struct FolderRevisionCloudServiceImpl {
} }
impl RevisionCloudService for FolderRevisionCloudServiceImpl { impl RevisionCloudService for FolderRevisionCloudServiceImpl {
#[tracing::instrument(level = "debug", skip(self))] #[tracing::instrument(level = "trace", skip(self))]
fn fetch_object(&self, _user_id: &str, _object_id: &str) -> FutureResult<Vec<Revision>, FlowyError> { fn fetch_object(&self, _user_id: &str, _object_id: &str) -> FutureResult<Vec<Revision>, FlowyError> {
FutureResult::new(async move { Ok(vec![]) }) FutureResult::new(async move { Ok(vec![]) })
} }

View File

@ -11,4 +11,4 @@ pub(crate) mod view;
mod web_socket; mod web_socket;
pub(crate) mod workspace; pub(crate) mod workspace;
pub const FOLDER_SYNC_INTERVAL_IN_MILLIS: u64 = 1000; pub const FOLDER_SYNC_INTERVAL_IN_MILLIS: u64 = 5000;

View File

@ -205,7 +205,7 @@ impl TrashController {
} }
impl TrashController { impl TrashController {
#[tracing::instrument(level = "debug", skip(self, trash), err)] #[tracing::instrument(level = "trace", skip(self, trash), err)]
fn create_trash_on_server<T: Into<RepeatedTrashId>>(&self, trash: T) -> FlowyResult<()> { fn create_trash_on_server<T: Into<RepeatedTrashId>>(&self, trash: T) -> FlowyResult<()> {
let token = self.user.token()?; let token = self.user.token()?;
let trash_identifiers = trash.into(); let trash_identifiers = trash.into();
@ -220,7 +220,7 @@ impl TrashController {
Ok(()) Ok(())
} }
#[tracing::instrument(level = "debug", skip(self, trash), err)] #[tracing::instrument(level = "trace", skip(self, trash), err)]
fn delete_trash_on_server<T: Into<RepeatedTrashId>>(&self, trash: T) -> FlowyResult<()> { fn delete_trash_on_server<T: Into<RepeatedTrashId>>(&self, trash: T) -> FlowyResult<()> {
let token = self.user.token()?; let token = self.user.token()?;
let trash_identifiers = trash.into(); let trash_identifiers = trash.into();
@ -234,7 +234,7 @@ impl TrashController {
Ok(()) Ok(())
} }
#[tracing::instrument(level = "debug", skip(self), err)] #[tracing::instrument(level = "trace", skip(self), err)]
fn read_trash_on_server(&self) -> FlowyResult<()> { fn read_trash_on_server(&self) -> FlowyResult<()> {
let token = self.user.token()?; let token = self.user.token()?;
let server = self.cloud_service.clone(); let server = self.cloud_service.clone();
@ -264,7 +264,7 @@ impl TrashController {
Ok(()) Ok(())
} }
#[tracing::instrument(level = "debug", skip(self), err)] #[tracing::instrument(level = "trace", skip(self), err)]
async fn delete_all_trash_on_server(&self) -> FlowyResult<()> { async fn delete_all_trash_on_server(&self) -> FlowyResult<()> {
let token = self.user.token()?; let token = self.user.token()?;
let server = self.cloud_service.clone(); let server = self.cloud_service.clone();

View File

@ -60,7 +60,7 @@ impl ViewController {
Ok(()) Ok(())
} }
#[tracing::instrument(level = "debug", skip(self, params), fields(name = %params.name), err)] #[tracing::instrument(level = "trace", skip(self, params), fields(name = %params.name), err)]
pub(crate) async fn create_view_from_params(&self, params: CreateViewParams) -> Result<View, FlowyError> { pub(crate) async fn create_view_from_params(&self, params: CreateViewParams) -> Result<View, FlowyError> {
let view_data = if params.view_data.is_empty() { let view_data = if params.view_data.is_empty() {
initial_delta_string() initial_delta_string()

View File

@ -37,6 +37,7 @@ pub(crate) async fn make_folder_ws_manager(
let sink_provider = Arc::new(FolderWSSinkDataProviderAdapter(composite_sink_provider)); let sink_provider = Arc::new(FolderWSSinkDataProviderAdapter(composite_sink_provider));
let ping_duration = Duration::from_millis(FOLDER_SYNC_INTERVAL_IN_MILLIS); let ping_duration = Duration::from_millis(FOLDER_SYNC_INTERVAL_IN_MILLIS);
Arc::new(RevisionWebSocketManager::new( Arc::new(RevisionWebSocketManager::new(
"Folder",
folder_id, folder_id,
web_socket, web_socket,
sink_provider, sink_provider,

View File

@ -150,14 +150,14 @@ impl WorkspaceController {
} }
impl WorkspaceController { impl WorkspaceController {
#[tracing::instrument(level = "debug", skip(self), err)] #[tracing::instrument(level = "trace", skip(self), err)]
async fn create_workspace_on_server(&self, params: CreateWorkspaceParams) -> Result<Workspace, FlowyError> { async fn create_workspace_on_server(&self, params: CreateWorkspaceParams) -> Result<Workspace, FlowyError> {
let token = self.user.token()?; let token = self.user.token()?;
let workspace = self.cloud_service.create_workspace(&token, params).await?; let workspace = self.cloud_service.create_workspace(&token, params).await?;
Ok(workspace) Ok(workspace)
} }
#[tracing::instrument(level = "debug", skip(self), err)] #[tracing::instrument(level = "trace", skip(self), err)]
fn update_workspace_on_server(&self, params: UpdateWorkspaceParams) -> Result<(), FlowyError> { fn update_workspace_on_server(&self, params: UpdateWorkspaceParams) -> Result<(), FlowyError> {
let (token, server) = (self.user.token()?, self.cloud_service.clone()); let (token, server) = (self.user.token()?, self.cloud_service.clone());
tokio::spawn(async move { tokio::spawn(async move {
@ -172,7 +172,7 @@ impl WorkspaceController {
Ok(()) Ok(())
} }
#[tracing::instrument(level = "debug", skip(self), err)] #[tracing::instrument(level = "trace", skip(self), err)]
fn delete_workspace_on_server(&self, workspace_id: &str) -> Result<(), FlowyError> { fn delete_workspace_on_server(&self, workspace_id: &str) -> Result<(), FlowyError> {
let params = WorkspaceId { let params = WorkspaceId {
workspace_id: Some(workspace_id.to_string()), workspace_id: Some(workspace_id.to_string()),

View File

@ -94,7 +94,7 @@ pub async fn read_cur_workspace_handler(
data_result(setting) data_result(setting)
} }
#[tracing::instrument(level = "debug", skip(folder_manager), err)] #[tracing::instrument(level = "trace", skip(folder_manager), err)]
fn read_workspaces_on_server( fn read_workspaces_on_server(
folder_manager: Unit<Arc<FolderManager>>, folder_manager: Unit<Arc<FolderManager>>,
user_id: String, user_id: String,

View File

@ -21,7 +21,6 @@ pub trait DocumentUser: Send + Sync {
fn db_pool(&self) -> Result<Arc<ConnectionPool>, FlowyError>; fn db_pool(&self) -> Result<Arc<ConnectionPool>, FlowyError>;
} }
#[async_trait] #[async_trait]
pub(crate) trait DocumentWSReceiver: Send + Sync { pub(crate) trait DocumentWSReceiver: Send + Sync {
async fn receive_ws_data(&self, data: ServerRevisionWSData) -> Result<(), FlowyError>; async fn receive_ws_data(&self, data: ServerRevisionWSData) -> Result<(), FlowyError>;
@ -67,7 +66,7 @@ impl FlowyDocumentManager {
self.get_editor(doc_id).await self.get_editor(doc_id).await
} }
#[tracing::instrument(level = "debug", skip(self, doc_id), fields(doc_id), err)] #[tracing::instrument(level = "trace", skip(self, doc_id), fields(doc_id), err)]
pub fn close_document<T: AsRef<str>>(&self, doc_id: T) -> Result<(), FlowyError> { pub fn close_document<T: AsRef<str>>(&self, doc_id: T) -> Result<(), FlowyError> {
let doc_id = doc_id.as_ref(); let doc_id = doc_id.as_ref();
tracing::Span::current().record("doc_id", &doc_id); tracing::Span::current().record("doc_id", &doc_id);
@ -178,7 +177,7 @@ struct DocumentRevisionCloudServiceImpl {
} }
impl RevisionCloudService for DocumentRevisionCloudServiceImpl { impl RevisionCloudService for DocumentRevisionCloudServiceImpl {
#[tracing::instrument(level = "debug", skip(self))] #[tracing::instrument(level = "trace", skip(self))]
fn fetch_object(&self, user_id: &str, doc_id: &str) -> FutureResult<Vec<Revision>, FlowyError> { fn fetch_object(&self, user_id: &str, doc_id: &str) -> FutureResult<Vec<Revision>, FlowyError> {
let params = DocumentId { let params = DocumentId {
doc_id: doc_id.to_string(), doc_id: doc_id.to_string(),
@ -235,7 +234,7 @@ impl OpenDocCache {
} }
} }
#[tracing::instrument(level = "debug", skip(state_receiver, receivers))] #[tracing::instrument(level = "trace", skip(state_receiver, receivers))]
fn listen_ws_state_changed(mut state_receiver: WSStateReceiver, receivers: WebSocketDataReceivers) { fn listen_ws_state_changed(mut state_receiver: WSStateReceiver, receivers: WebSocketDataReceivers) {
tokio::spawn(async move { tokio::spawn(async move {
while let Ok(state) = state_receiver.recv().await { while let Ok(state) = state_receiver.recv().await {

View File

@ -147,7 +147,7 @@ impl ClientDocumentEditor {
Ok(json) Ok(json)
} }
#[tracing::instrument(level = "debug", skip(self, data), err)] #[tracing::instrument(level = "trace", skip(self, data), err)]
pub(crate) async fn compose_local_delta(&self, data: Bytes) -> Result<(), FlowyError> { pub(crate) async fn compose_local_delta(&self, data: Bytes) -> Result<(), FlowyError> {
let delta = RichTextDelta::from_bytes(&data)?; let delta = RichTextDelta::from_bytes(&data)?;
let (ret, rx) = oneshot::channel::<CollaborateResult<()>>(); let (ret, rx) = oneshot::channel::<CollaborateResult<()>>();

View File

@ -48,6 +48,7 @@ pub(crate) async fn make_document_ws_manager(
let sink_provider = Arc::new(DocumentWSSinkDataProviderAdapter(composite_sink_provider)); let sink_provider = Arc::new(DocumentWSSinkDataProviderAdapter(composite_sink_provider));
let ping_duration = Duration::from_millis(DOCUMENT_SYNC_INTERVAL_IN_MILLIS); let ping_duration = Duration::from_millis(DOCUMENT_SYNC_INTERVAL_IN_MILLIS);
let ws_manager = Arc::new(RevisionWebSocketManager::new( let ws_manager = Arc::new(RevisionWebSocketManager::new(
"Document",
&doc_id, &doc_id,
web_socket, web_socket,
sink_provider, sink_provider,

View File

@ -60,15 +60,14 @@ impl FlowyRawWebSocket for LocalWebSocket {
fn reconnect(&self, _count: usize) -> FutureResult<(), FlowyError> { FutureResult::new(async { Ok(()) }) } fn reconnect(&self, _count: usize) -> FutureResult<(), FlowyError> { FutureResult::new(async { Ok(()) }) }
fn add_receiver(&self, receiver: Arc<dyn WSMessageReceiver>) -> Result<(), FlowyError> { fn add_msg_receiver(&self, receiver: Arc<dyn WSMessageReceiver>) -> Result<(), FlowyError> {
tracing::trace!("Local web socket add ws receiver: {:?}", receiver.source()); tracing::trace!("Local web socket add ws receiver: {:?}", receiver.source());
self.receivers.insert(receiver.source(), receiver); self.receivers.insert(receiver.source(), receiver);
Ok(()) Ok(())
} }
fn sender(&self) -> Result<Arc<dyn FlowyWebSocket>, FlowyError> { fn ws_msg_sender(&self) -> Result<Arc<dyn FlowyWebSocket>, FlowyError> {
let ws = LocalWebSocketAdaptor(self.server_ws_sender.clone()); Ok(Arc::new(LocalWebSocketAdaptor(self.server_ws_sender.clone())))
Ok(Arc::new(ws))
} }
} }

View File

@ -15,8 +15,8 @@ pub trait FlowyRawWebSocket: Send + Sync {
fn stop_connect(&self) -> FutureResult<(), FlowyError>; fn stop_connect(&self) -> FutureResult<(), FlowyError>;
fn subscribe_connect_state(&self) -> broadcast::Receiver<WSConnectState>; fn subscribe_connect_state(&self) -> broadcast::Receiver<WSConnectState>;
fn reconnect(&self, count: usize) -> FutureResult<(), FlowyError>; fn reconnect(&self, count: usize) -> FutureResult<(), FlowyError>;
fn add_receiver(&self, receiver: Arc<dyn WSMessageReceiver>) -> Result<(), FlowyError>; fn add_msg_receiver(&self, receiver: Arc<dyn WSMessageReceiver>) -> Result<(), FlowyError>;
fn sender(&self) -> Result<Arc<dyn FlowyWebSocket>, FlowyError>; fn ws_msg_sender(&self) -> Result<Arc<dyn FlowyWebSocket>, FlowyError>;
} }
pub trait FlowyWebSocket: Send + Sync { pub trait FlowyWebSocket: Send + Sync {
@ -97,11 +97,11 @@ impl FlowyWebSocketConnect {
pub fn subscribe_network_ty(&self) -> broadcast::Receiver<NetworkType> { self.status_notifier.subscribe() } pub fn subscribe_network_ty(&self) -> broadcast::Receiver<NetworkType> { self.status_notifier.subscribe() }
pub fn add_ws_message_receiver(&self, receiver: Arc<dyn WSMessageReceiver>) -> Result<(), FlowyError> { pub fn add_ws_message_receiver(&self, receiver: Arc<dyn WSMessageReceiver>) -> Result<(), FlowyError> {
let _ = self.inner.add_receiver(receiver)?; let _ = self.inner.add_msg_receiver(receiver)?;
Ok(()) Ok(())
} }
pub fn web_socket(&self) -> Result<Arc<dyn FlowyWebSocket>, FlowyError> { self.inner.sender() } pub fn web_socket(&self) -> Result<Arc<dyn FlowyWebSocket>, FlowyError> { self.inner.ws_msg_sender() }
} }
#[tracing::instrument(level = "debug", skip(ws_conn))] #[tracing::instrument(level = "debug", skip(ws_conn))]

View File

@ -37,12 +37,12 @@ impl FlowyRawWebSocket for Arc<WSController> {
}) })
} }
fn add_receiver(&self, receiver: Arc<dyn WSMessageReceiver>) -> Result<(), FlowyError> { fn add_msg_receiver(&self, receiver: Arc<dyn WSMessageReceiver>) -> Result<(), FlowyError> {
let _ = self.add_ws_message_receiver(receiver).map_err(internal_error)?; let _ = self.add_ws_message_receiver(receiver).map_err(internal_error)?;
Ok(()) Ok(())
} }
fn sender(&self) -> Result<Arc<dyn FlowyWebSocket>, FlowyError> { fn ws_msg_sender(&self) -> Result<Arc<dyn FlowyWebSocket>, FlowyError> {
let sender = self.ws_message_sender().map_err(internal_error)?; let sender = self.ws_message_sender().map_err(internal_error)?;
Ok(sender) Ok(sender)
} }

View File

@ -20,7 +20,7 @@ use std::{convert::TryInto, sync::Arc};
pub struct FolderDepsResolver(); pub struct FolderDepsResolver();
impl FolderDepsResolver { impl FolderDepsResolver {
pub fn resolve( pub async fn resolve(
local_server: Option<Arc<LocalServer>>, local_server: Option<Arc<LocalServer>>,
user_session: Arc<UserSession>, user_session: Arc<UserSession>,
server_config: &ClientServerConfiguration, server_config: &ClientServerConfiguration,
@ -35,13 +35,8 @@ impl FolderDepsResolver {
Some(local_server) => local_server, Some(local_server) => local_server,
}; };
let folder_manager = Arc::new(FolderManager::new( let folder_manager =
user, Arc::new(FolderManager::new(user, cloud_service, database, document_manager.clone(), web_socket).await);
cloud_service,
database,
document_manager.clone(),
web_socket,
));
let receiver = Arc::new(FolderWSMessageReceiverImpl(folder_manager.clone())); let receiver = Arc::new(FolderWSMessageReceiverImpl(folder_manager.clone()));
ws_conn.add_ws_message_receiver(receiver).unwrap(); ws_conn.add_ws_message_receiver(receiver).unwrap();

View File

@ -12,6 +12,7 @@ use flowy_user::services::{notifier::UserStatus, UserSession, UserSessionConfig}
use lib_dispatch::prelude::*; use lib_dispatch::prelude::*;
use flowy_document::FlowyDocumentManager; use flowy_document::FlowyDocumentManager;
use lib_dispatch::util::tokio_default_runtime;
use module::mk_modules; use module::mk_modules;
pub use module::*; pub use module::*;
use std::{ use std::{
@ -21,7 +22,7 @@ use std::{
Arc, Arc,
}, },
}; };
use tokio::sync::broadcast; use tokio::{runtime::Runtime, sync::broadcast};
static INIT_LOG: AtomicBool = AtomicBool::new(false); static INIT_LOG: AtomicBool = AtomicBool::new(false);
@ -95,7 +96,7 @@ impl FlowySDK {
init_log(&config); init_log(&config);
init_kv(&config.root); init_kv(&config.root);
tracing::debug!("🔥 {:?}", config); tracing::debug!("🔥 {:?}", config);
let runtime = tokio_default_runtime().unwrap();
let ws_addr = config.server_config.ws_addr(); let ws_addr = config.server_config.ws_addr();
let (local_server, ws_conn) = if cfg!(feature = "http_server") { let (local_server, ws_conn) = if cfg!(feature = "http_server") {
let ws_conn = Arc::new(FlowyWebSocketConnect::new(ws_addr)); let ws_conn = Arc::new(FlowyWebSocketConnect::new(ws_addr));
@ -110,6 +111,7 @@ impl FlowySDK {
let user_session = mk_user_session(&config, &local_server, &config.server_config); let user_session = mk_user_session(&config, &local_server, &config.server_config);
let document_manager = mk_document(&local_server, &ws_conn, &user_session, &config.server_config); let document_manager = mk_document(&local_server, &ws_conn, &user_session, &config.server_config);
let folder_manager = mk_folder_manager( let folder_manager = mk_folder_manager(
&runtime,
&local_server, &local_server,
&user_session, &user_session,
&document_manager, &document_manager,
@ -117,9 +119,9 @@ impl FlowySDK {
&ws_conn, &ws_conn,
); );
// let dispatcher = Arc::new(EventDispatcher::construct(runtime, || {
let modules = mk_modules(&ws_conn, &folder_manager, &user_session); mk_modules(&ws_conn, &folder_manager, &user_session)
let dispatcher = Arc::new(EventDispatcher::construct(|| modules)); }));
_init(&local_server, &dispatcher, &ws_conn, &user_session, &folder_manager); _init(&local_server, &dispatcher, &ws_conn, &user_session, &folder_manager);
Self { Self {
@ -244,12 +246,14 @@ fn mk_user_session(
} }
fn mk_folder_manager( fn mk_folder_manager(
runtime: &Runtime,
local_server: &Option<Arc<LocalServer>>, local_server: &Option<Arc<LocalServer>>,
user_session: &Arc<UserSession>, user_session: &Arc<UserSession>,
document_manager: &Arc<FlowyDocumentManager>, document_manager: &Arc<FlowyDocumentManager>,
server_config: &ClientServerConfiguration, server_config: &ClientServerConfiguration,
ws_conn: &Arc<FlowyWebSocketConnect>, ws_conn: &Arc<FlowyWebSocketConnect>,
) -> Arc<FolderManager> { ) -> Arc<FolderManager> {
runtime.block_on(async {
FolderDepsResolver::resolve( FolderDepsResolver::resolve(
local_server.clone(), local_server.clone(),
user_session.clone(), user_session.clone(),
@ -257,6 +261,8 @@ fn mk_folder_manager(
document_manager, document_manager,
ws_conn.clone(), ws_conn.clone(),
) )
.await
})
} }
pub fn mk_document( pub fn mk_document(

View File

@ -10,13 +10,13 @@ pub fn mk_modules(
user_session: &Arc<UserSession>, user_session: &Arc<UserSession>,
) -> Vec<Module> { ) -> Vec<Module> {
let user_module = mk_user_module(user_session.clone()); let user_module = mk_user_module(user_session.clone());
let core_module = mk_core_module(folder_manager.clone()); let folder_module = mk_folder_module(folder_manager.clone());
let network_module = mk_network_module(ws_conn.clone()); let network_module = mk_network_module(ws_conn.clone());
vec![user_module, core_module, network_module] vec![user_module, folder_module, network_module]
} }
fn mk_user_module(user_session: Arc<UserSession>) -> Module { flowy_user::module::create(user_session) } fn mk_user_module(user_session: Arc<UserSession>) -> Module { flowy_user::module::create(user_session) }
fn mk_core_module(core: Arc<FolderManager>) -> Module { flowy_core::module::create(core) } fn mk_folder_module(core: Arc<FolderManager>) -> Module { flowy_core::module::create(core) }
fn mk_network_module(ws_conn: Arc<FlowyWebSocketConnect>) -> Module { flowy_net::module::create(ws_conn) } fn mk_network_module(ws_conn: Arc<FlowyWebSocketConnect>) -> Module { flowy_net::module::create(ws_conn) }

View File

@ -5,10 +5,8 @@ use flowy_collaboration::{
util::{pair_rev_id_from_revisions, RevIdCounter}, util::{pair_rev_id_from_revisions, RevIdCounter},
}; };
use flowy_error::{FlowyError, FlowyResult}; use flowy_error::{FlowyError, FlowyResult};
use futures_util::{future, stream, stream::StreamExt};
use lib_infra::future::FutureResult; use lib_infra::future::FutureResult;
use std::{collections::VecDeque, sync::Arc}; use std::{collections::VecDeque, sync::Arc};
use tokio::sync::{broadcast, RwLock}; use tokio::sync::{broadcast, RwLock};
pub trait RevisionCloudService: Send + Sync { pub trait RevisionCloudService: Send + Sync {
@ -54,7 +52,7 @@ impl RevisionManager {
where where
Builder: RevisionObjectBuilder, Builder: RevisionObjectBuilder,
{ {
let revisions = RevisionLoader { let (revisions, rev_id) = RevisionLoader {
object_id: self.object_id.clone(), object_id: self.object_id.clone(),
user_id: self.user_id.clone(), user_id: self.user_id.clone(),
cloud, cloud,
@ -63,6 +61,7 @@ impl RevisionManager {
} }
.load() .load()
.await?; .await?;
self.rev_id_counter.set(rev_id);
Builder::build_with_revisions(&self.object_id, revisions) Builder::build_with_revisions(&self.object_id, revisions)
} }
@ -117,8 +116,6 @@ impl RevisionManager {
pub fn rev_id(&self) -> i64 { self.rev_id_counter.value() } pub fn rev_id(&self) -> i64 { self.rev_id_counter.value() }
pub fn set_rev_id(&self, rev_id: i64) { self.rev_id_counter.set(rev_id); }
pub fn next_rev_id_pair(&self) -> (i64, i64) { pub fn next_rev_id_pair(&self) -> (i64, i64) {
let cur = self.rev_id_counter.value(); let cur = self.rev_id_counter.value();
let next = self.rev_id_counter.next(); let next = self.rev_id_counter.next();
@ -223,12 +220,14 @@ struct RevisionLoader {
} }
impl RevisionLoader { impl RevisionLoader {
async fn load(&self) -> Result<Vec<Revision>, FlowyError> { async fn load(&self) -> Result<(Vec<Revision>, i64), FlowyError> {
let records = self.revision_cache.batch_get(&self.object_id)?; let records = self.revision_cache.batch_get(&self.object_id)?;
let revisions: Vec<Revision>; let revisions: Vec<Revision>;
let mut rev_id = 0;
if records.is_empty() { if records.is_empty() {
let remote_revisions = self.cloud.fetch_object(&self.user_id, &self.object_id).await?; let remote_revisions = self.cloud.fetch_object(&self.user_id, &self.object_id).await?;
for revision in &remote_revisions { for revision in &remote_revisions {
rev_id = revision.rev_id;
let _ = self let _ = self
.revision_cache .revision_cache
.add(revision.clone(), RevisionState::Ack, true) .add(revision.clone(), RevisionState::Ack, true)
@ -236,25 +235,30 @@ impl RevisionLoader {
} }
revisions = remote_revisions; revisions = remote_revisions;
} else { } else {
stream::iter(records.clone()) for record in records.clone() {
.filter(|record| future::ready(record.state == RevisionState::Sync))
.for_each(|record| async move {
let f = || async { let f = || async {
// Sync the records if their state is RevisionState::Local. rev_id = record.revision.rev_id;
if record.state == RevisionState::Sync {
// Sync the records if their state is RevisionState::Sync.
let _ = self.revision_sync_seq.add_revision_record(record.clone()).await?; let _ = self.revision_sync_seq.add_revision_record(record.clone()).await?;
let _ = self.revision_cache.add(record.revision, record.state, false).await?; let _ = self.revision_cache.add(record.revision, record.state, false).await?;
}
Ok::<(), FlowyError>(()) Ok::<(), FlowyError>(())
}; };
match f().await { match f().await {
Ok(_) => {}, Ok(_) => {},
Err(e) => tracing::error!("[RevisionLoader]: {}", e), Err(e) => tracing::error!("[RevisionLoader]: {}", e),
} }
}) }
.await;
revisions = records.into_iter().map(|record| record.revision).collect::<_>(); revisions = records.into_iter().map(|record| record.revision).collect::<_>();
} }
Ok(revisions) if let Some(revision) = revisions.last() {
debug_assert_eq!(rev_id, revision.rev_id);
}
Ok((revisions, rev_id))
} }
} }

View File

@ -9,7 +9,7 @@ use flowy_error::{FlowyError, FlowyResult};
use futures_util::stream::StreamExt; use futures_util::stream::StreamExt;
use lib_infra::future::{BoxResultFuture, FutureResult}; use lib_infra::future::{BoxResultFuture, FutureResult};
use lib_ws::WSConnectState; use lib_ws::WSConnectState;
use std::{collections::VecDeque, convert::TryFrom, sync::Arc}; use std::{collections::VecDeque, convert::TryFrom, fmt::Formatter, sync::Arc};
use tokio::{ use tokio::{
sync::{ sync::{
broadcast, broadcast,
@ -41,6 +41,7 @@ pub trait RevisionWebSocket: Send + Sync + 'static {
} }
pub struct RevisionWebSocketManager { pub struct RevisionWebSocketManager {
pub object_name: String,
pub object_id: String, pub object_id: String,
sink_provider: Arc<dyn RevisionWSSinkDataProvider>, sink_provider: Arc<dyn RevisionWSSinkDataProvider>,
stream_consumer: Arc<dyn RevisionWSSteamConsumer>, stream_consumer: Arc<dyn RevisionWSSteamConsumer>,
@ -51,8 +52,14 @@ pub struct RevisionWebSocketManager {
stop_sync_tx: SinkStopTx, stop_sync_tx: SinkStopTx,
} }
impl std::fmt::Display for RevisionWebSocketManager {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{}RevisionWebSocketManager", self.object_name))
}
}
impl RevisionWebSocketManager { impl RevisionWebSocketManager {
pub fn new( pub fn new(
object_name: &str,
object_id: &str, object_id: &str,
web_socket: Arc<dyn RevisionWebSocket>, web_socket: Arc<dyn RevisionWebSocket>,
sink_provider: Arc<dyn RevisionWSSinkDataProvider>, sink_provider: Arc<dyn RevisionWSSinkDataProvider>,
@ -62,9 +69,11 @@ impl RevisionWebSocketManager {
let (ws_passthrough_tx, ws_passthrough_rx) = mpsc::channel(1000); let (ws_passthrough_tx, ws_passthrough_rx) = mpsc::channel(1000);
let (stop_sync_tx, _) = tokio::sync::broadcast::channel(2); let (stop_sync_tx, _) = tokio::sync::broadcast::channel(2);
let object_id = object_id.to_string(); let object_id = object_id.to_string();
let object_name = object_name.to_string();
let (state_passthrough_tx, _) = broadcast::channel(2); let (state_passthrough_tx, _) = broadcast::channel(2);
let mut manager = RevisionWebSocketManager { let mut manager = RevisionWebSocketManager {
object_id, object_id,
object_name,
sink_provider, sink_provider,
stream_consumer, stream_consumer,
web_socket, web_socket,
@ -81,12 +90,14 @@ impl RevisionWebSocketManager {
let ws_msg_rx = self.ws_passthrough_rx.take().expect("Only take once"); let ws_msg_rx = self.ws_passthrough_rx.take().expect("Only take once");
let sink = RevisionWSSink::new( let sink = RevisionWSSink::new(
&self.object_id, &self.object_id,
&self.object_name,
self.sink_provider.clone(), self.sink_provider.clone(),
self.web_socket.clone(), self.web_socket.clone(),
self.stop_sync_tx.subscribe(), self.stop_sync_tx.subscribe(),
ping_duration, ping_duration,
); );
let stream = RevisionWSStream::new( let stream = RevisionWSStream::new(
&self.object_name,
&self.object_id, &self.object_id,
self.stream_consumer.clone(), self.stream_consumer.clone(),
ws_msg_rx, ws_msg_rx,
@ -106,28 +117,37 @@ impl RevisionWebSocketManager {
} }
impl std::ops::Drop for RevisionWebSocketManager { impl std::ops::Drop for RevisionWebSocketManager {
fn drop(&mut self) { tracing::trace!("{} RevisionWebSocketManager was dropped", self.object_id) } fn drop(&mut self) { tracing::trace!("{} was dropped", self) }
} }
pub struct RevisionWSStream { pub struct RevisionWSStream {
object_name: String,
object_id: String, object_id: String,
consumer: Arc<dyn RevisionWSSteamConsumer>, consumer: Arc<dyn RevisionWSSteamConsumer>,
ws_msg_rx: Option<mpsc::Receiver<ServerRevisionWSData>>, ws_msg_rx: Option<mpsc::Receiver<ServerRevisionWSData>>,
stop_rx: Option<SinkStopRx>, stop_rx: Option<SinkStopRx>,
} }
impl std::fmt::Display for RevisionWSStream {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{}RevisionWSStream", self.object_name))
}
}
impl std::ops::Drop for RevisionWSStream { impl std::ops::Drop for RevisionWSStream {
fn drop(&mut self) { tracing::trace!("{} RevisionWSStream was dropped", self.object_id) } fn drop(&mut self) { tracing::trace!("{} was dropped", self) }
} }
impl RevisionWSStream { impl RevisionWSStream {
pub fn new( pub fn new(
object_name: &str,
object_id: &str, object_id: &str,
consumer: Arc<dyn RevisionWSSteamConsumer>, consumer: Arc<dyn RevisionWSSteamConsumer>,
ws_msg_rx: mpsc::Receiver<ServerRevisionWSData>, ws_msg_rx: mpsc::Receiver<ServerRevisionWSData>,
stop_rx: SinkStopRx, stop_rx: SinkStopRx,
) -> Self { ) -> Self {
RevisionWSStream { RevisionWSStream {
object_name: object_name.to_string(),
object_id: object_id.to_owned(), object_id: object_id.to_owned(),
consumer, consumer,
ws_msg_rx: Some(ws_msg_rx), ws_msg_rx: Some(ws_msg_rx),
@ -139,6 +159,7 @@ impl RevisionWSStream {
let mut receiver = self.ws_msg_rx.take().expect("Only take once"); let mut receiver = self.ws_msg_rx.take().expect("Only take once");
let mut stop_rx = self.stop_rx.take().expect("Only take once"); let mut stop_rx = self.stop_rx.take().expect("Only take once");
let object_id = self.object_id.clone(); let object_id = self.object_id.clone();
let name = format!("{}", &self);
let stream = stream! { let stream = stream! {
loop { loop {
tokio::select! { tokio::select! {
@ -148,13 +169,13 @@ impl RevisionWSStream {
yield msg yield msg
}, },
None => { None => {
tracing::debug!("[RevisionWSStream]:{} loop exit", object_id); tracing::debug!("[{}]:{} loop exit", name, object_id);
break; break;
}, },
} }
}, },
_ = stop_rx.recv() => { _ = stop_rx.recv() => {
tracing::debug!("[RevisionWSStream]:{} loop exit", object_id); tracing::debug!("[{}]:{} loop exit", name, object_id);
break break
}, },
}; };
@ -165,7 +186,7 @@ impl RevisionWSStream {
.for_each(|msg| async { .for_each(|msg| async {
match self.handle_message(msg).await { match self.handle_message(msg).await {
Ok(_) => {}, Ok(_) => {},
Err(e) => tracing::error!("[RevisionWSStream]:{} error: {}", self.object_id, e), Err(e) => tracing::error!("[{}]:{} error: {}", &self, self.object_id, e),
} }
}) })
.await; .await;
@ -174,7 +195,7 @@ impl RevisionWSStream {
async fn handle_message(&self, msg: ServerRevisionWSData) -> FlowyResult<()> { async fn handle_message(&self, msg: ServerRevisionWSData) -> FlowyResult<()> {
let ServerRevisionWSData { object_id, ty, data } = msg; let ServerRevisionWSData { object_id, ty, data } = msg;
let bytes = Bytes::from(data); let bytes = Bytes::from(data);
tracing::trace!("[RevisionWSStream]: new message: {}:{:?}", object_id, ty); tracing::trace!("[{}]: new message: {}:{:?}", self, object_id, ty);
match ty { match ty {
ServerRevisionWSDataType::ServerPushRev => { ServerRevisionWSDataType::ServerPushRev => {
let _ = self.consumer.receive_push_revision(bytes).await?; let _ = self.consumer.receive_push_revision(bytes).await?;
@ -199,26 +220,29 @@ impl RevisionWSStream {
type SinkStopRx = broadcast::Receiver<()>; type SinkStopRx = broadcast::Receiver<()>;
type SinkStopTx = broadcast::Sender<()>; type SinkStopTx = broadcast::Sender<()>;
pub struct RevisionWSSink { pub struct RevisionWSSink {
object_id: String,
object_name: String,
provider: Arc<dyn RevisionWSSinkDataProvider>, provider: Arc<dyn RevisionWSSinkDataProvider>,
ws_sender: Arc<dyn RevisionWebSocket>, ws_sender: Arc<dyn RevisionWebSocket>,
stop_rx: Option<SinkStopRx>, stop_rx: Option<SinkStopRx>,
object_id: String,
ping_duration: Duration, ping_duration: Duration,
} }
impl RevisionWSSink { impl RevisionWSSink {
pub fn new( pub fn new(
object_id: &str, object_id: &str,
object_name: &str,
provider: Arc<dyn RevisionWSSinkDataProvider>, provider: Arc<dyn RevisionWSSinkDataProvider>,
ws_sender: Arc<dyn RevisionWebSocket>, ws_sender: Arc<dyn RevisionWebSocket>,
stop_rx: SinkStopRx, stop_rx: SinkStopRx,
ping_duration: Duration, ping_duration: Duration,
) -> Self { ) -> Self {
Self { Self {
object_id: object_id.to_owned(),
object_name: object_name.to_owned(),
provider, provider,
ws_sender, ws_sender,
stop_rx: Some(stop_rx), stop_rx: Some(stop_rx),
object_id: object_id.to_owned(),
ping_duration, ping_duration,
} }
} }
@ -228,6 +252,7 @@ impl RevisionWSSink {
let mut stop_rx = self.stop_rx.take().expect("Only take once"); let mut stop_rx = self.stop_rx.take().expect("Only take once");
let object_id = self.object_id.clone(); let object_id = self.object_id.clone();
tokio::spawn(tick(tx, self.ping_duration)); tokio::spawn(tick(tx, self.ping_duration));
let name = format!("{}", self);
let stream = stream! { let stream = stream! {
loop { loop {
tokio::select! { tokio::select! {
@ -238,7 +263,7 @@ impl RevisionWSSink {
} }
}, },
_ = stop_rx.recv() => { _ = stop_rx.recv() => {
tracing::trace!("[RevisionWSSink:{}] loop exit", object_id); tracing::trace!("[{}]:{} loop exit", name, object_id);
break break
}, },
}; };
@ -248,7 +273,7 @@ impl RevisionWSSink {
.for_each(|_| async { .for_each(|_| async {
match self.send_next_revision().await { match self.send_next_revision().await {
Ok(_) => {}, Ok(_) => {},
Err(e) => tracing::error!("[RevisionWSSink] send failed, {:?}", e), Err(e) => tracing::error!("[{}] send failed, {:?}", self, e),
} }
}) })
.await; .await;
@ -257,19 +282,25 @@ impl RevisionWSSink {
async fn send_next_revision(&self) -> FlowyResult<()> { async fn send_next_revision(&self) -> FlowyResult<()> {
match self.provider.next().await? { match self.provider.next().await? {
None => { None => {
tracing::trace!("Finish synchronizing revisions"); tracing::trace!("[{}]: Finish synchronizing revisions", self);
Ok(()) Ok(())
}, },
Some(data) => { Some(data) => {
tracing::trace!("[RevisionWSSink] send: {}:{}-{:?}", data.object_id, data.id(), data.ty); tracing::trace!("[{}]: send {}:{}-{:?}", self, data.object_id, data.id(), data.ty);
self.ws_sender.send(data) self.ws_sender.send(data)
}, },
} }
} }
} }
impl std::fmt::Display for RevisionWSSink {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{}RevisionWSSink", self.object_name))
}
}
impl std::ops::Drop for RevisionWSSink { impl std::ops::Drop for RevisionWSSink {
fn drop(&mut self) { tracing::trace!("{} RevisionWSSink was dropped", self.object_id) } fn drop(&mut self) { tracing::trace!("{} was dropped", self) }
} }
async fn tick(sender: mpsc::Sender<()>, duration: Duration) { async fn tick(sender: mpsc::Sender<()>, duration: Duration) {
@ -330,11 +361,6 @@ impl CompositeWSSinkDataProvider {
} }
}, },
}; };
if let Ok(Some(data)) = &data {
tracing::trace!("[CompositeWSSinkDataProvider]: {}:{:?}", data.object_id, data.ty);
}
data data
} }

View File

@ -3,7 +3,6 @@ use crate::{
module::{as_module_map, Module, ModuleMap, ModuleRequest}, module::{as_module_map, Module, ModuleMap, ModuleRequest},
response::EventResponse, response::EventResponse,
service::{Service, ServiceFactory}, service::{Service, ServiceFactory},
util::tokio_default_runtime,
}; };
use derivative::*; use derivative::*;
use futures_core::future::BoxFuture; use futures_core::future::BoxFuture;
@ -17,11 +16,10 @@ pub struct EventDispatcher {
} }
impl EventDispatcher { impl EventDispatcher {
pub fn construct<F>(module_factory: F) -> EventDispatcher pub fn construct<F>(runtime: tokio::runtime::Runtime, module_factory: F) -> EventDispatcher
where where
F: FnOnce() -> Vec<Module>, F: FnOnce() -> Vec<Module>,
{ {
let runtime = tokio_default_runtime().unwrap();
let modules = module_factory(); let modules = module_factory();
tracing::trace!("{}", module_info(&modules)); tracing::trace!("{}", module_info(&modules));
let module_map = as_module_map(modules); let module_map = as_module_map(modules);

View File

@ -3,7 +3,7 @@ mod module;
mod request; mod request;
mod response; mod response;
mod service; mod service;
mod util; pub mod util;
mod byte_trait; mod byte_trait;
mod data; mod data;

View File

@ -1,4 +1,4 @@
use lib_dispatch::prelude::*; use lib_dispatch::{prelude::*, util::tokio_default_runtime};
use std::sync::Arc; use std::sync::Arc;
pub async fn hello() -> String { "say hello".to_string() } pub async fn hello() -> String { "say hello".to_string() }
@ -8,7 +8,10 @@ async fn test() {
env_logger::init(); env_logger::init();
let event = "1"; let event = "1";
let dispatch = Arc::new(EventDispatcher::construct(|| vec![Module::new().event(event, hello)])); let runtime = tokio_default_runtime().unwrap();
let dispatch = Arc::new(EventDispatcher::construct(runtime, || {
vec![Module::new().event(event, hello)]
}));
let request = ModuleRequest::new(event); let request = ModuleRequest::new(event);
let _ = EventDispatcher::async_send_with_callback(dispatch.clone(), request, |resp| { let _ = EventDispatcher::async_send_with_callback(dispatch.clone(), request, |resp| {
Box::pin(async move { Box::pin(async move {

View File

@ -88,6 +88,7 @@ impl ServerDocumentManager {
let result = match self.get_document_handler(&object_id).await { let result = match self.get_document_handler(&object_id).await {
None => { None => {
tracing::trace!("Can't find the document. Creating the document {}", object_id);
let _ = self.create_document(&object_id, repeated_revision).await.map_err(|e| { let _ = self.create_document(&object_id, repeated_revision).await.map_err(|e| {
CollaborateError::internal().context(format!("Server create document failed: {}", e)) CollaborateError::internal().context(format!("Server create document failed: {}", e))
})?; })?;

View File

@ -61,15 +61,19 @@ impl Future for WSConnectionFuture {
loop { loop {
return match ready!(self.as_mut().project().fut.poll(cx)) { return match ready!(self.as_mut().project().fut.poll(cx)) {
Ok((stream, _)) => { Ok((stream, _)) => {
tracing::debug!("🐴 ws connect success"); tracing::debug!("[WebSocket]: connect success");
let (msg_tx, ws_rx) = ( let (msg_tx, ws_rx) = (
self.msg_tx.take().expect("WsConnection should be call once "), self.msg_tx
self.ws_rx.take().expect("WsConnection should be call once "), .take()
.expect("[WebSocket]: WSConnection should be call once "),
self.ws_rx
.take()
.expect("[WebSocket]: WSConnection should be call once "),
); );
Poll::Ready(Ok(WSStream::new(msg_tx, ws_rx, stream))) Poll::Ready(Ok(WSStream::new(msg_tx, ws_rx, stream)))
}, },
Err(error) => { Err(error) => {
tracing::debug!("🐴 ws connect failed: {:?}", error); tracing::debug!("[WebSocket]: ❌ connect failed: {:?}", error);
Poll::Ready(Err(error.into())) Poll::Ready(Err(error.into()))
}, },
}; };
@ -99,7 +103,7 @@ impl WSStream {
.for_each(|message| async { .for_each(|message| async {
match tx.send(send_message(msg_tx.clone(), message)) { match tx.send(send_message(msg_tx.clone(), message)) {
Ok(_) => {}, Ok(_) => {},
Err(e) => log::error!("WsStream tx closed unexpectedly: {} ", e), Err(e) => log::error!("[WebSocket]: WSStream sender closed unexpectedly: {} ", e),
} }
}) })
.await; .await;
@ -110,7 +114,8 @@ impl WSStream {
loop { loop {
match rx.recv().await { match rx.recv().await {
None => { None => {
return Err(WSError::internal().context("WsStream rx closed unexpectedly")); return Err(WSError::internal()
.context("[WebSocket]: WSStream receiver closed unexpectedly"));
}, },
Some(result) => { Some(result) => {
if result.is_err() { if result.is_err() {

View File

@ -116,7 +116,7 @@ impl WSController {
} }
pub async fn retry(&self, count: usize) -> Result<(), ServerError> { pub async fn retry(&self, count: usize) -> Result<(), ServerError> {
if self.sender_ctrl.read().is_connecting() { if !self.sender_ctrl.read().is_disconnected() {
return Ok(()); return Ok(());
} }
@ -125,7 +125,7 @@ impl WSController {
.addr .addr
.read() .read()
.as_ref() .as_ref()
.expect("must call start_connect first") .expect("Retry web socket connection failed, should call start_connect first")
.clone(); .clone();
self.connect(addr, strategy).await self.connect(addr, strategy).await
@ -135,7 +135,7 @@ impl WSController {
pub fn ws_message_sender(&self) -> Result<Arc<WSSender>, WSError> { pub fn ws_message_sender(&self) -> Result<Arc<WSSender>, WSError> {
match self.sender_ctrl.read().sender() { match self.sender_ctrl.read().sender() {
None => Err(WSError::internal().context("WsSender is not initialized, should call connect first")), None => Err(WSError::internal().context("WebSocket is not initialized, should call connect first")),
Some(sender) => Ok(sender), Some(sender) => Ok(sender),
} }
} }
@ -370,10 +370,10 @@ impl WSSenderController {
fn sender(&self) -> Option<Arc<WSSender>> { self.sender.clone() } fn sender(&self) -> Option<Arc<WSSender>> { self.sender.clone() }
#[allow(dead_code)]
fn is_connecting(&self) -> bool { self.state == WSConnectState::Connecting } fn is_connecting(&self) -> bool { self.state == WSConnectState::Connecting }
#[allow(dead_code)] fn is_disconnected(&self) -> bool { self.state == WSConnectState::Disconnected }
fn is_connected(&self) -> bool { self.state == WSConnectState::Connected }
} }
impl std::default::Default for WSSenderController { impl std::default::Default for WSSenderController {