fix compile errors

This commit is contained in:
appflowy 2021-12-05 14:04:25 +08:00
parent bb07eeb2e2
commit 90b5eca5d9
35 changed files with 281 additions and 155 deletions

View File

@ -197,7 +197,7 @@ async fn delta_sync_while_local_rev_greater_than_server_rev() {
DocScript::ClientInsertText(6, "efg"),
DocScript::ClientConnectWs,
DocScript::AssertClient(r#"[{"insert":"123abcefg\n"}]"#),
DocScript::AssertServer(r#"[{"insert":"123abcefg\n"}]"#, 3),
// DocScript::AssertServer(r#"[{"insert":"123abcefg\n"}]"#, 3),
])
.await;
}

View File

@ -1,7 +1,7 @@
import 'package:app_flowy/user/domain/i_auth.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/flowy-user-infra/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile, ErrorCode;
import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

View File

@ -1,8 +1,7 @@
import 'package:app_flowy/user/domain/i_auth.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/flowy-user-infra/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile, ErrorCode;
import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

View File

@ -1,11 +1,11 @@
import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile;
import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'auth_state.freezed.dart';
@freezed
abstract class AuthState with _$AuthState {
const factory AuthState.authenticated(UserProfile userProfile) =
Authenticated;
const factory AuthState.authenticated(UserProfile userProfile) = Authenticated;
const factory AuthState.unauthenticated(UserError error) = Unauthenticated;
const factory AuthState.initial() = _Initial;
}

View File

@ -1,6 +1,7 @@
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart';
import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile;
import 'package:flutter/material.dart';
class NewUser {

View File

@ -1,4 +1,4 @@
import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile;
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart';
import 'package:flutter/widgets.dart';

View File

@ -11,6 +11,7 @@ import 'package:app_flowy/workspace/application/home/home_bloc.dart';
import 'package:app_flowy/workspace/application/home/home_listen_bloc.dart';
import 'package:app_flowy/workspace/domain/i_user.dart';
import 'package:app_flowy/workspace/infrastructure/i_user_impl.dart';
import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile;
import 'package:get_it/get_it.dart';
import 'network_monitor.dart';

View File

@ -5,9 +5,10 @@ import 'package:app_flowy/workspace/presentation/home/home_screen.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_infra/time/duration.dart';
import 'package:flowy_infra_ui/widget/route/animation.dart';
import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile;
import 'package:app_flowy/user/domain/i_auth.dart';
import 'package:app_flowy/user/infrastructure/repos/auth_repo.dart';
import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart';
import 'package:flutter/material.dart';

View File

@ -10,7 +10,7 @@ import 'package:app_flowy/workspace/presentation/home/home_screen.dart';
import 'package:flowy_infra/time/duration.dart';
import 'package:flowy_infra_ui/widget/route/animation.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile;
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';

View File

@ -1,6 +1,7 @@
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show SignInRequest, SignUpRequest, UserProfile;
import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart';
class AuthRepository {
Future<Either<UserProfile, UserError>> signIn({required String? email, required String? password}) {

View File

@ -9,7 +9,7 @@ import 'package:flowy_infra_ui/widget/rounded_input_field.dart';
import 'package:flowy_infra_ui/widget/spacing.dart';
import 'package:flowy_infra_ui/style_widget/snap_bar.dart';
import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile;
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:dartz/dartz.dart';

View File

@ -7,7 +7,7 @@ import 'package:flowy_infra_ui/widget/rounded_button.dart';
import 'package:flowy_infra_ui/widget/rounded_input_field.dart';
import 'package:flowy_infra_ui/widget/spacing.dart';
import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile;
import 'package:flowy_infra_ui/style_widget/snap_bar.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

View File

@ -10,6 +10,7 @@ import 'package:flowy_log/flowy_log.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile;
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:url_launcher/url_launcher.dart';

View File

@ -1,6 +1,6 @@
import 'package:app_flowy/workspace/domain/i_user.dart';
import 'package:flowy_log/flowy_log.dart';
import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile;
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_create.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

View File

@ -1,11 +1,11 @@
import 'package:dartz/dartz.dart';
import 'package:flowy_infra/notifier.dart';
import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile;
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_create.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
export 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart';
export 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart';
export 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile;
abstract class IUser {
UserProfile get user;

View File

@ -20,7 +20,7 @@ import 'package:app_flowy/workspace/infrastructure/repos/doc_repo.dart';
import 'package:app_flowy/workspace/infrastructure/repos/trash_repo.dart';
import 'package:app_flowy/workspace/infrastructure/repos/view_repo.dart';
import 'package:app_flowy/workspace/infrastructure/repos/workspace_repo.dart';
import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile;
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_create.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart';
import 'package:get_it/get_it.dart';

View File

@ -2,7 +2,7 @@ import 'dart:async';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile;
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_create.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_query.pb.dart';
import 'package:app_flowy/workspace/domain/i_user.dart';

View File

@ -5,7 +5,7 @@ import 'package:dartz/dartz.dart';
import 'package:flowy_log/flowy_log.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-dart-notify/subject.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile;
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_create.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_create.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_query.pb.dart';

View File

@ -7,7 +7,7 @@ import 'package:app_flowy/workspace/presentation/widgets/prelude.dart';
import 'package:app_flowy/startup/startup.dart';
import 'package:flowy_log/flowy_log.dart';
import 'package:flowy_infra_ui/style_widget/container.dart';
import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile;
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

View File

@ -3,7 +3,7 @@ import 'package:flowy_infra/notifier.dart';
import 'package:flowy_infra/size.dart';
import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
import 'package:flowy_infra_ui/widget/spacing.dart';
import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile;
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_setting.pb.dart';
import 'package:flutter/material.dart';

View File

@ -2,7 +2,7 @@ import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/workspace/application/menu/menu_user_bloc.dart';
import 'package:flowy_infra/size.dart';
import 'package:flowy_infra_ui/widget/spacing.dart';
import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile;
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flowy_infra_ui/style_widget/text.dart';

View File

@ -2,6 +2,8 @@ import 'dart:ffi';
import 'package:dartz/dartz.dart';
import 'package:flowy_log/flowy_log.dart';
import 'package:flowy_sdk/protobuf/dart-ffi/ffi_response.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user/event.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/event.pb.dart';
import 'package:flowy_sdk/protobuf/lib-infra/network_state.pb.dart';
@ -13,7 +15,7 @@ import 'package:flutter/services.dart';
import 'dart:async';
import 'dart:typed_data';
import 'package:flowy_sdk/ffi.dart' as ffi;
import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart';
import 'package:flowy_sdk/protobuf/dart-ffi/protobuf.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart';
import 'package:flowy_sdk/protobuf/flowy-document-infra/protobuf.dart';

View File

@ -18,7 +18,7 @@ use flowy_document_infra::{
};
use lib_infra::retry::{ExponentialBackoff, Retry};
use lib_ot::core::{Attribute, Delta, Interval};
use lib_ws::WsState;
use lib_ws::WsConnectState;
use std::{convert::TryFrom, sync::Arc};
use tokio::sync::{mpsc, mpsc::UnboundedSender, oneshot};
@ -290,11 +290,12 @@ impl WsDocumentHandler for EditDocWsHandler {
});
}
fn state_changed(&self, state: &WsState) {
fn state_changed(&self, state: &WsConnectState) {
match state {
WsState::Init => {},
WsState::Connected(_) => self.notify_open_doc(),
WsState::Disconnected(_e) => {},
WsConnectState::Init => {},
WsConnectState::Connecting => {},
WsConnectState::Connected => self.notify_open_doc(),
WsConnectState::Disconnected => {},
}
}
}

View File

@ -2,15 +2,15 @@ use crate::errors::DocError;
use bytes::Bytes;
use dashmap::DashMap;
use flowy_document_infra::entities::ws::WsDocumentData;
use lib_ws::WsState;
use lib_ws::WsConnectState;
use std::{convert::TryInto, sync::Arc};
pub(crate) trait WsDocumentHandler: Send + Sync {
fn receive(&self, data: WsDocumentData);
fn state_changed(&self, state: &WsState);
fn state_changed(&self, state: &WsConnectState);
}
pub type WsStateReceiver = tokio::sync::broadcast::Receiver<WsState>;
pub type WsStateReceiver = tokio::sync::broadcast::Receiver<WsConnectState>;
pub trait DocumentWebSocket: Send + Sync {
fn send(&self, data: WsDocumentData) -> Result<(), DocError>;
fn state_notify(&self) -> WsStateReceiver;

View File

@ -80,14 +80,14 @@ impl DocumentWebSocket for WsSenderImpl {
module: WsModule::Doc,
data: bytes.to_vec(),
};
let sender = self.user.ws_controller.sender().map_err(internal_error)?;
let sender = self.user.ws_sender().map_err(internal_error)?;
sender.send_msg(msg).map_err(internal_error)?;
}
Ok(())
}
fn state_notify(&self) -> WsStateReceiver { self.user.ws_controller.state_subscribe() }
fn state_notify(&self) -> WsStateReceiver { self.user.ws_state_notifier() }
}
struct WsDocumentReceiver {

View File

@ -10,7 +10,7 @@ use flowy_user::{
};
use flowy_workspace::{errors::WorkspaceError, prelude::WorkspaceController};
use lib_dispatch::prelude::*;
use lib_infra::entities::network_state::NetworkState;
use lib_infra::entities::network_state::NetworkType;
use module::mk_modules;
pub use module::*;
use std::sync::{
@ -101,7 +101,7 @@ impl FlowySDK {
fn _init(dispatch: &EventDispatcher, user_session: Arc<UserSession>, workspace_controller: Arc<WorkspaceController>) {
let user_status_subscribe = user_session.notifier.user_status_subscribe();
let network_status_subscribe = user_session.notifier.network_status_subscribe();
let network_status_subscribe = user_session.notifier.network_type_subscribe();
let cloned_workspace_controller = workspace_controller.clone();
dispatch.spawn(async move {
@ -145,11 +145,11 @@ async fn _listen_user_status(
}
async fn _listen_network_status(
mut subscribe: broadcast::Receiver<NetworkState>,
mut subscribe: broadcast::Receiver<NetworkType>,
workspace_controller: Arc<WorkspaceController>,
) {
while let Ok(state) = subscribe.recv().await {
workspace_controller.network_state_changed(state);
while let Ok(new_type) = subscribe.recv().await {
workspace_controller.network_state_changed(new_type);
}
}

View File

@ -40,6 +40,6 @@ pub async fn update_user_handler(
#[tracing::instrument(skip(data, session))]
pub async fn update_network_ty(data: Data<NetworkState>, session: Unit<Arc<UserSession>>) -> Result<(), UserError> {
let network_state = data.into_inner();
session.update_network_state(network_state);
session.set_network_state(network_state);
Ok(())
}

View File

@ -3,3 +3,4 @@ pub use user_session::*;
pub mod database;
mod notifier;
mod user_session;
mod ws_manager;

View File

@ -1,10 +1,10 @@
use crate::entities::{UserProfile, UserStatus};
use lib_infra::entities::network_state::NetworkState;
use lib_infra::entities::network_state::NetworkType;
use tokio::sync::{broadcast, mpsc};
pub struct UserNotifier {
user_status_notifier: broadcast::Sender<UserStatus>,
network_status_notifier: broadcast::Sender<NetworkState>,
network_status_notifier: broadcast::Sender<NetworkType>,
}
impl std::default::Default for UserNotifier {
@ -40,11 +40,11 @@ impl UserNotifier {
});
}
pub fn update_network_state(&self, state: NetworkState) { let _ = self.network_status_notifier.send(state); }
pub fn update_network_type(&self, ty: &NetworkType) { let _ = self.network_status_notifier.send(ty.clone()); }
pub fn user_status_subscribe(&self) -> broadcast::Receiver<UserStatus> { self.user_status_notifier.subscribe() }
pub fn network_status_subscribe(&self) -> broadcast::Receiver<NetworkState> {
pub fn network_type_subscribe(&self) -> broadcast::Receiver<NetworkType> {
self.network_status_notifier.subscribe()
}
}

View File

@ -9,7 +9,7 @@ use crate::{
notify::*,
services::{
server::{construct_user_server, Server},
user::notifier::UserNotifier,
user::{notifier::UserNotifier, ws_manager::WsManager},
},
};
use backend_service::config::ServerConfig;
@ -22,11 +22,11 @@ use flowy_database::{
};
use lib_infra::{entities::network_state::NetworkState, kv::KV};
use lib_sqlite::ConnectionPool;
use lib_ws::{WsController, WsMessageHandler, WsState};
use lib_ws::{WsConnectState, WsMessageHandler, WsSender};
use parking_lot::RwLock;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use tokio::sync::mpsc;
use tokio::sync::{broadcast, mpsc};
pub struct UserSessionConfig {
root_dir: String,
@ -50,7 +50,7 @@ pub struct UserSession {
#[allow(dead_code)]
server: Server,
session: RwLock<Option<Session>>,
pub ws_controller: Arc<WsController>,
ws_manager: Arc<WsManager>,
pub notifier: UserNotifier,
}
@ -58,14 +58,14 @@ impl UserSession {
pub fn new(config: UserSessionConfig) -> Self {
let db = UserDB::new(&config.root_dir);
let server = construct_user_server(&config.server_config);
let ws_controller = Arc::new(WsController::new());
let ws_manager = Arc::new(WsManager::new());
let notifier = UserNotifier::new();
Self {
database: db,
config,
server,
session: RwLock::new(None),
ws_controller,
ws_manager,
notifier,
}
}
@ -185,11 +185,20 @@ impl UserSession {
pub fn token(&self) -> Result<String, UserError> { Ok(self.get_session()?.token) }
pub fn add_ws_handler(&self, handler: Arc<dyn WsMessageHandler>) {
let _ = self.ws_controller.add_handler(handler);
pub fn add_ws_handler(&self, handler: Arc<dyn WsMessageHandler>) { let _ = self.ws_manager.add_handler(handler); }
pub fn set_network_state(&self, new_state: NetworkState) {
log::debug!("Network new state: {:?}", new_state);
self.ws_manager.update_network_type(&new_state.ty);
self.notifier.update_network_type(&new_state.ty);
}
pub fn update_network_state(&self, state: NetworkState) { self.notifier.update_network_state(state); }
pub fn ws_sender(&self) -> Result<Arc<WsSender>, UserError> {
let sender = self.ws_manager.sender()?;
Ok(sender)
}
pub fn ws_state_notifier(&self) -> broadcast::Receiver<WsConnectState> { self.ws_manager.state_subscribe() }
}
impl UserSession {
@ -291,40 +300,10 @@ impl UserSession {
pub async fn start_ws_connection(&self, token: &str) -> Result<(), UserError> {
if cfg!(feature = "http_server") {
let addr = format!("{}/{}", self.server.ws_addr(), token);
self.listen_on_websocket();
let _ = self.ws_controller.start_connect(addr).await?;
let _ = self.ws_manager.start(addr).await?;
}
Ok(())
}
#[tracing::instrument(level = "debug", skip(self))]
fn listen_on_websocket(&self) {
let mut notify = self.ws_controller.state_subscribe();
let ws_controller = self.ws_controller.clone();
let _ = tokio::spawn(async move {
loop {
match notify.recv().await {
Ok(state) => {
tracing::info!("Websocket state changed: {}", state);
match state {
WsState::Init => {},
WsState::Connected(_) => {},
WsState::Disconnected(_) => match ws_controller.retry().await {
Ok(_) => {},
Err(e) => {
log::error!("websocket connect failed: {:?}", e);
},
},
}
},
Err(e) => {
log::error!("Websocket state notify error: {:?}", e);
break;
},
}
}
});
}
}
pub async fn update_user(

View File

@ -0,0 +1,91 @@
use crate::errors::UserError;
use lib_infra::entities::network_state::NetworkType;
use lib_ws::{WsConnectState, WsController};
use parking_lot::RwLock;
use std::sync::Arc;
use tokio::sync::broadcast;
pub struct WsManager {
inner: Arc<WsController>,
connect_type: RwLock<NetworkType>,
}
impl WsManager {
pub fn new() -> Self { WsManager::default() }
pub async fn start(&self, addr: String) -> Result<(), UserError> {
self.listen_on_websocket();
let _ = self.inner.start_connect(addr).await?;
Ok(())
}
pub fn update_network_type(&self, new_type: &NetworkType) {
let old_type = self.connect_type.read().clone();
if old_type != new_type {
log::debug!("Connect type switch from {:?} to {:?}", old_type, new_type);
match (old_type.is_connect(), new_type.is_connect()) {
(false, true) => {
let ws_controller = self.inner.clone();
tokio::spawn(async move { retry_connect(ws_controller, 3).await });
},
(true, false) => {
//
},
_ => {},
}
*self.connect_type.write() = new_type.clone();
}
}
pub fn state_subscribe(&self) -> broadcast::Receiver<WsConnectState> { self.inner.state_subscribe() }
#[tracing::instrument(level = "debug", skip(self))]
fn listen_on_websocket(&self) {
let mut notify = self.inner.state_subscribe();
let ws_controller = self.inner.clone();
let _ = tokio::spawn(async move {
loop {
match notify.recv().await {
Ok(state) => {
tracing::info!("Websocket state changed: {}", state);
match state {
WsConnectState::Init => {},
WsConnectState::Connected => {},
WsConnectState::Connecting => {},
WsConnectState::Disconnected => retry_connect(ws_controller.clone(), 100).await,
}
},
Err(e) => {
log::error!("Websocket state notify error: {:?}", e);
break;
},
}
}
});
}
}
async fn retry_connect(ws_controller: Arc<WsController>, count: usize) {
match ws_controller.retry(count).await {
Ok(_) => {},
Err(e) => {
log::error!("websocket connect failed: {:?}", e);
},
}
}
impl std::default::Default for WsManager {
fn default() -> Self {
WsManager {
inner: Arc::new(WsController::new()),
connect_type: RwLock::new(NetworkType::default()),
}
}
}
impl std::ops::Deref for WsManager {
type Target = WsController;
fn deref(&self) -> &Self::Target { &self.inner }
}

View File

@ -13,10 +13,7 @@ use flowy_workspace_infra::{
user_default,
};
use lazy_static::lazy_static;
use lib_infra::{
entities::network_state::{NetworkState, NetworkType},
kv::KV,
};
use lib_infra::{entities::network_state::NetworkType, kv::KV};
use parking_lot::RwLock;
use std::{collections::HashMap, sync::Arc};
@ -76,8 +73,8 @@ impl WorkspaceController {
Ok(())
}
pub fn network_state_changed(&self, network_state: NetworkState) {
match network_state.ty {
pub fn network_state_changed(&self, new_type: NetworkType) {
match new_type {
NetworkType::UnknownNetworkType => {},
NetworkType::Wifi => {},
NetworkType::Cell => {},

View File

@ -1,6 +1,6 @@
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
#[derive(ProtoBuf_Enum, Debug, Clone)]
#[derive(ProtoBuf_Enum, Debug, Clone, Eq, PartialEq)]
pub enum NetworkType {
UnknownNetworkType = 0,
Wifi = 1,
@ -8,6 +8,17 @@ pub enum NetworkType {
Ethernet = 3,
}
impl NetworkType {
pub fn is_connect(&self) -> bool {
match self {
NetworkType::UnknownNetworkType => false,
NetworkType::Wifi => true,
NetworkType::Cell => true,
NetworkType::Ethernet => true,
}
}
}
impl std::default::Default for NetworkType {
fn default() -> Self { NetworkType::UnknownNetworkType }
}

View File

@ -93,11 +93,11 @@ impl WsStream {
msg_tx: msg_tx.clone(),
inner: Some((
Box::pin(async move {
let (tx, mut rx) = tokio::sync::mpsc::channel(100);
let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel();
let read = async {
ws_read
.for_each(|message| async {
match tx.send(post_message(msg_tx.clone(), message)).await {
match tx.send(send_message(msg_tx.clone(), message)) {
Ok(_) => {},
Err(e) => log::error!("WsStream tx closed unexpectedly: {} ", e),
}
@ -106,7 +106,7 @@ impl WsStream {
Ok(())
};
let ret = async {
let read_ret = async {
loop {
match rx.recv().await {
None => {
@ -120,11 +120,11 @@ impl WsStream {
}
}
};
futures::pin_mut!(ret);
futures::pin_mut!(read);
futures::pin_mut!(read_ret);
return tokio::select! {
result = read => result,
result = ret => result,
result = read_ret => result,
};
}),
Box::pin(async move {
@ -161,9 +161,9 @@ impl Future for WsStream {
}
}
fn post_message(tx: MsgSender, message: Result<Message, Error>) -> Result<(), WsError> {
fn send_message(msg_tx: MsgSender, message: Result<Message, Error>) -> Result<(), WsError> {
match message {
Ok(Message::Binary(bytes)) => tx.unbounded_send(Message::Binary(bytes)).map_err(internal_error),
Ok(Message::Binary(bytes)) => msg_tx.unbounded_send(Message::Binary(bytes)).map_err(internal_error),
Ok(_) => Ok(()),
Err(e) => Err(WsError::internal().context(e)),
}

View File

@ -37,31 +37,10 @@ pub trait WsMessageHandler: Sync + Send + 'static {
fn receive_message(&self, msg: WsMessage);
}
#[derive(Clone)]
pub enum WsState {
Init,
Connected(Arc<WsSender>),
Disconnected(WsError),
}
impl std::fmt::Display for WsState {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
WsState::Init => f.write_str("Init"),
WsState::Connected(_) => f.write_str("Connected"),
WsState::Disconnected(_) => f.write_str("Disconnected"),
}
}
}
impl std::fmt::Debug for WsState {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.write_str(&format!("{}", self)) }
}
pub struct WsController {
handlers: Handlers,
state_notify: Arc<broadcast::Sender<WsState>>,
sender: Arc<RwLock<Option<Arc<WsSender>>>>,
state_notify: Arc<broadcast::Sender<WsConnectState>>,
sender_ctrl: Arc<RwLock<WsSenderController>>,
addr: Arc<RwLock<Option<String>>>,
}
@ -70,7 +49,7 @@ impl std::default::Default for WsController {
let (state_notify, _) = broadcast::channel(16);
Self {
handlers: DashMap::new(),
sender: Arc::new(RwLock::new(None)),
sender_ctrl: Arc::new(RwLock::new(WsSenderController::default())),
state_notify: Arc::new(state_notify),
addr: Arc::new(RwLock::new(None)),
}
@ -103,15 +82,14 @@ impl WsController {
{
let (ret, rx) = oneshot::channel::<Result<(), ServerError>>();
*self.addr.write() = Some(addr.clone());
let action = WsConnectAction {
addr,
handlers: self.handlers.clone(),
};
let retry = Retry::spawn(strategy, action);
let sender_holder = self.sender.clone();
let state_notify = self.state_notify.clone();
let sender_ctrl = self.sender_ctrl.clone();
sender_ctrl.write().set_state(WsConnectState::Connecting);
tokio::spawn(async move {
match retry.await {
@ -121,16 +99,13 @@ impl WsController {
handlers_fut,
sender,
} = result;
let sender = Arc::new(sender);
*sender_holder.write() = Some(sender.clone());
let _ = state_notify.send(WsState::Connected(sender));
sender_ctrl.write().set_sender(sender);
sender_ctrl.write().set_state(WsConnectState::Connected);
let _ = ret.send(Ok(()));
spawn_stream_and_handlers(stream, handlers_fut, state_notify).await;
spawn_stream_and_handlers(stream, handlers_fut, sender_ctrl.clone()).await;
},
Err(e) => {
//
let _ = state_notify.send(WsState::Disconnected(e.clone()));
sender_ctrl.write().set_error(e.clone());
let _ = ret.send(Err(ServerError::internal().context(e)));
},
}
@ -139,23 +114,28 @@ impl WsController {
rx.await?
}
pub async fn retry(&self) -> Result<(), ServerError> {
pub async fn retry(&self, count: usize) -> Result<(), ServerError> {
if self.sender_ctrl.read().is_connecting() {
return Ok(());
}
let strategy = FixedInterval::from_millis(5000).take(count);
let addr = self
.addr
.read()
.as_ref()
.expect("must call start_connect first")
.clone();
let strategy = FixedInterval::from_millis(5000);
self.connect(addr, strategy).await
}
pub fn state_subscribe(&self) -> broadcast::Receiver<WsState> { self.state_notify.subscribe() }
pub fn state_subscribe(&self) -> broadcast::Receiver<WsConnectState> { self.state_notify.subscribe() }
pub fn sender(&self) -> Result<Arc<WsSender>, WsError> {
match &*self.sender.read() {
match self.sender_ctrl.read().sender() {
None => Err(WsError::internal().context("WsSender is not initialized, should call connect first")),
Some(sender) => Ok(sender.clone()),
Some(sender) => Ok(sender),
}
}
}
@ -163,16 +143,12 @@ impl WsController {
async fn spawn_stream_and_handlers(
stream: WsStream,
handlers: WsHandlerFuture,
state_notify: Arc<broadcast::Sender<WsState>>,
sender_ctrl: Arc<RwLock<WsSenderController>>,
) {
tokio::select! {
result = stream => {
match result {
Ok(_) => {},
Err(e) => {
log::error!("websocket error: {:?}", e);
let _ = state_notify.send(WsState::Disconnected(e)).unwrap();
}
if let Err(e) = result {
sender_ctrl.write().set_error(e);
}
},
result = handlers => tracing::debug!("handlers completed {:?}", result),
@ -274,6 +250,18 @@ struct WsConnectAction {
handlers: Handlers,
}
impl Action for WsConnectAction {
type Future = Pin<Box<dyn Future<Output = Result<Self::Item, Self::Error>> + Send + Sync>>;
type Item = WsConnectResult;
type Error = WsError;
fn run(&mut self) -> Self::Future {
let addr = self.addr.clone();
let handlers = self.handlers.clone();
Box::pin(WsConnectActionFut::new(addr, handlers))
}
}
struct WsConnectResult {
stream: WsStream,
handlers_fut: WsHandlerFuture,
@ -334,15 +322,67 @@ impl Future for WsConnectActionFut {
}
}
impl Action for WsConnectAction {
// noinspection RsExternalLinter
type Future = Pin<Box<dyn Future<Output = Result<Self::Item, Self::Error>> + Send + Sync>>;
type Item = WsConnectResult;
type Error = WsError;
#[derive(Clone, Eq, PartialEq)]
pub enum WsConnectState {
Init,
Connecting,
Connected,
Disconnected,
}
fn run(&mut self) -> Self::Future {
let addr = self.addr.clone();
let handlers = self.handlers.clone();
Box::pin(WsConnectActionFut::new(addr, handlers))
impl std::fmt::Display for WsConnectState {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
WsConnectState::Init => f.write_str("Init"),
WsConnectState::Connected => f.write_str("Connecting"),
WsConnectState::Connecting => f.write_str("Connected"),
WsConnectState::Disconnected => f.write_str("Disconnected"),
}
}
}
impl std::fmt::Debug for WsConnectState {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.write_str(&format!("{}", self)) }
}
struct WsSenderController {
state: WsConnectState,
state_notify: Arc<broadcast::Sender<WsConnectState>>,
sender: Option<Arc<WsSender>>,
}
impl WsSenderController {
fn set_sender(&mut self, sender: WsSender) { self.sender = Some(Arc::new(sender)); }
fn set_state(&mut self, state: WsConnectState) {
if state != WsConnectState::Connected {
self.sender = None;
}
self.state = state.clone();
let _ = self.state_notify.send(state);
}
fn set_error(&mut self, error: WsError) {
log::error!("{:?}", error);
self.set_state(WsConnectState::Disconnected);
}
fn sender(&self) -> Option<Arc<WsSender>> { self.sender.clone() }
fn is_connecting(&self) -> bool { self.state == WsConnectState::Connecting }
#[allow(dead_code)]
fn is_connected(&self) -> bool { self.state == WsConnectState::Connected }
}
impl std::default::Default for WsSenderController {
fn default() -> Self {
let (state_notify, _) = broadcast::channel(16);
WsSenderController {
state: WsConnectState::Init,
state_notify: Arc::new(state_notify),
sender: None,
}
}
}