refactor errors

This commit is contained in:
appflowy
2021-12-14 18:04:51 +08:00
parent 72a8f7a9e3
commit 013d8f753a
177 changed files with 1657 additions and 2740 deletions

View File

@ -16,6 +16,7 @@ lib-infra = { path = "../../../shared-lib/lib-infra" }
flowy-document = { path = "../flowy-document" }
flowy-database = { path = "../flowy-database" }
flowy-error = { path = "../flowy-error", features = ["db", "backend"]}
flowy-net = { path = "../flowy-net" }
dart-notify = { path = "../dart-notify" }
lib-dispatch = { path = "../lib-dispatch" }

View File

@ -1,6 +1,6 @@
use crate::{
core::CoreContext,
errors::WorkspaceError,
errors::FlowyError,
notify::{send_dart_notification, WorkspaceNotification},
services::workspace::sql::{WorkspaceTable, WorkspaceTableSql},
};
@ -13,7 +13,7 @@ pub fn read_workspaces_on_server(
core: Unit<Arc<CoreContext>>,
user_id: String,
params: WorkspaceIdentifier,
) -> Result<(), WorkspaceError> {
) -> Result<(), FlowyError> {
let (token, server) = (core.user.token()?, core.server.clone());
let app_ctrl = core.app_controller.clone();
let view_ctrl = core.view_controller.clone();
@ -22,7 +22,7 @@ pub fn read_workspaces_on_server(
tokio::spawn(async move {
// Opti: handle the error and retry?
let workspaces = server.read_workspace(&token, params).await?;
let _ = (&*conn).immediate_transaction::<_, WorkspaceError, _>(|| {
let _ = (&*conn).immediate_transaction::<_, FlowyError, _>(|| {
tracing::debug!("Save {} workspace", workspaces.len());
for workspace in &workspaces.items {
let m_workspace = workspace.clone();
@ -53,7 +53,7 @@ pub fn read_workspaces_on_server(
send_dart_notification(&token, WorkspaceNotification::WorkspaceListUpdated)
.payload(workspaces)
.send();
Result::<(), WorkspaceError>::Ok(())
Result::<(), FlowyError>::Ok(())
});
Ok(())

View File

@ -10,7 +10,7 @@ use flowy_net::entities::NetworkType;
use crate::{
entities::workspace::RepeatedWorkspace,
errors::{WorkspaceError, WorkspaceResult},
errors::{FlowyError, FlowyResult},
module::{WorkspaceDatabase, WorkspaceUser},
notify::{send_dart_notification, WorkspaceNotification},
services::{server::Server, AppController, TrashController, ViewController, WorkspaceController},
@ -64,7 +64,7 @@ impl CoreContext {
}
}
pub async fn user_did_sign_in(&self, token: &str) -> WorkspaceResult<()> {
pub async fn user_did_sign_in(&self, token: &str) -> FlowyResult<()> {
log::debug!("workspace initialize after sign in");
let _ = self.init(token).await?;
Ok(())
@ -78,7 +78,7 @@ impl CoreContext {
// TODO: (nathan) do something here
}
pub async fn user_did_sign_up(&self, _token: &str) -> WorkspaceResult<()> {
pub async fn user_did_sign_up(&self, _token: &str) -> FlowyResult<()> {
log::debug!("Create user default workspace");
let time = Utc::now();
let mut workspace = user_default::create_default_workspace(time);
@ -120,7 +120,7 @@ impl CoreContext {
Ok(())
}
async fn init(&self, token: &str) -> Result<(), WorkspaceError> {
async fn init(&self, token: &str) -> Result<(), FlowyError> {
if let Some(is_init) = INIT_WORKSPACE.read().get(token) {
if *is_init {
return Ok(());

View File

@ -1,6 +1,6 @@
use crate::{
core::{aggregate_tasks::read_workspaces_on_server, CoreContext},
errors::WorkspaceError,
errors::FlowyError,
services::{get_current_workspace, read_local_workspace_apps},
};
use flowy_core_infra::entities::{
@ -14,14 +14,14 @@ use std::{convert::TryInto, sync::Arc};
pub(crate) async fn read_workspaces_handler(
data: Data<QueryWorkspaceRequest>,
core: Unit<Arc<CoreContext>>,
) -> DataResult<RepeatedWorkspace, WorkspaceError> {
) -> DataResult<RepeatedWorkspace, FlowyError> {
let params: WorkspaceIdentifier = data.into_inner().try_into()?;
let user_id = core.user.user_id()?;
let conn = &*core.database.db_connection()?;
let workspace_controller = core.workspace_controller.clone();
let trash_controller = core.trash_controller.clone();
let workspaces = conn.immediate_transaction::<_, WorkspaceError, _>(|| {
let workspaces = conn.immediate_transaction::<_, FlowyError, _>(|| {
let mut workspaces = workspace_controller.read_local_workspaces(params.workspace_id.clone(), &user_id, conn)?;
for workspace in workspaces.iter_mut() {
let apps = read_local_workspace_apps(&workspace.id, trash_controller.clone(), conn)?.into_inner();
@ -38,7 +38,7 @@ pub(crate) async fn read_workspaces_handler(
#[tracing::instrument(skip(core), err)]
pub async fn read_cur_workspace_handler(
core: Unit<Arc<CoreContext>>,
) -> DataResult<CurrentWorkspaceSetting, WorkspaceError> {
) -> DataResult<CurrentWorkspaceSetting, FlowyError> {
let workspace_id = get_current_workspace()?;
let user_id = core.user.user_id()?;
let params = WorkspaceIdentifier {

View File

@ -1,106 +0,0 @@
use bytes::Bytes;
use backend_service::errors::ErrorCode as ServerErrorCode;
pub use flowy_core_infra::errors::ErrorCode;
use flowy_derive::ProtoBuf;
use flowy_document::errors::DocError;
use lib_dispatch::prelude::{EventResponse, ResponseBuilder};
use std::{convert::TryInto, fmt, fmt::Debug};
pub type WorkspaceResult<T> = std::result::Result<T, WorkspaceError>;
#[derive(Debug, Default, Clone, ProtoBuf)]
pub struct WorkspaceError {
#[pb(index = 1)]
pub code: i32,
#[pb(index = 2)]
pub msg: String,
}
macro_rules! static_workspace_error {
($name:ident, $code:expr) => {
#[allow(non_snake_case, missing_docs)]
pub fn $name() -> WorkspaceError { $code.into() }
};
}
impl WorkspaceError {
pub fn new(code: ErrorCode, msg: &str) -> Self {
Self {
code: code.value(),
msg: msg.to_owned(),
}
}
static_workspace_error!(workspace_name, ErrorCode::WorkspaceNameInvalid);
static_workspace_error!(workspace_id, ErrorCode::WorkspaceIdInvalid);
static_workspace_error!(color_style, ErrorCode::AppColorStyleInvalid);
static_workspace_error!(workspace_desc, ErrorCode::WorkspaceDescTooLong);
static_workspace_error!(app_name, ErrorCode::AppNameInvalid);
static_workspace_error!(invalid_app_id, ErrorCode::AppIdInvalid);
static_workspace_error!(view_name, ErrorCode::ViewNameInvalid);
static_workspace_error!(view_thumbnail, ErrorCode::ViewThumbnailInvalid);
static_workspace_error!(invalid_view_id, ErrorCode::ViewIdInvalid);
static_workspace_error!(view_desc, ErrorCode::ViewDescTooLong);
static_workspace_error!(view_data, ErrorCode::ViewDataInvalid);
static_workspace_error!(unauthorized, ErrorCode::UserUnauthorized);
static_workspace_error!(internal, ErrorCode::InternalError);
static_workspace_error!(record_not_found, ErrorCode::RecordNotFound);
static_workspace_error!(ws, ErrorCode::WsConnectError);
pub fn context<T: Debug>(mut self, error: T) -> Self {
self.msg = format!("{:?}", error);
self
}
}
pub fn internal_error<T>(e: T) -> WorkspaceError
where
T: std::fmt::Debug,
{
WorkspaceError::internal().context(e)
}
impl std::convert::From<ErrorCode> for WorkspaceError {
fn from(code: ErrorCode) -> Self {
WorkspaceError {
code: code.value(),
msg: format!("{}", code),
}
}
}
impl std::convert::From<flowy_document::errors::DocError> for WorkspaceError {
fn from(error: DocError) -> Self { WorkspaceError::internal().context(error) }
}
impl std::convert::From<backend_service::errors::ServerError> for WorkspaceError {
fn from(error: backend_service::errors::ServerError) -> Self {
let code = server_error_to_workspace_error(error.code);
WorkspaceError::new(code, &error.msg)
}
}
impl std::convert::From<flowy_database::Error> for WorkspaceError {
fn from(error: flowy_database::Error) -> Self { WorkspaceError::internal().context(error) }
}
impl lib_dispatch::Error for WorkspaceError {
fn as_response(&self) -> EventResponse {
let bytes: Bytes = self.clone().try_into().unwrap();
ResponseBuilder::Err().data(bytes).build()
}
}
impl fmt::Display for WorkspaceError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}: {}", &self.code, &self.msg) }
}
fn server_error_to_workspace_error(code: ServerErrorCode) -> ErrorCode {
match code {
ServerErrorCode::UserUnauthorized => ErrorCode::UserUnauthorized,
ServerErrorCode::RecordNotFound => ErrorCode::RecordNotFound,
_ => ErrorCode::InternalError,
}
}

View File

@ -2,7 +2,7 @@ use flowy_derive::{Flowy_Event, ProtoBuf_Enum};
use strum_macros::Display;
#[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)]
#[event_err = "WorkspaceError"]
#[event_err = "FlowyError"]
pub enum WorkspaceEvent {
#[event(input = "CreateWorkspaceRequest", output = "Workspace")]
CreateWorkspace = 0,

View File

@ -11,7 +11,7 @@ mod macros;
extern crate flowy_database;
pub mod core;
pub mod errors;
mod notify;
pub mod protobuf;
mod util;
@ -21,3 +21,7 @@ pub mod prelude {
pub use crate::{core::*, errors::*, module::*};
}
pub mod errors {
pub use flowy_error::{internal_error, ErrorCode, FlowyError, FlowyResult};
}

View File

@ -1,7 +1,7 @@
// #[macro_export]
// macro_rules! impl_save_func {
// ($func_name:ident, $target:ident, $table_name:expr, $conn:ident) => {
// fn $func_name(object: $target) -> Result<(), WorkspaceError> {
// fn $func_name(object: $target) -> Result<(), FlowyError> {
// let _ = diesel::insert_into($table_name)
// .values($target)
// .execute(&*($conn))?;

View File

@ -8,7 +8,7 @@ use lib_sqlite::ConnectionPool;
use crate::{
core::{event_handler::*, CoreContext},
errors::WorkspaceError,
errors::FlowyError,
event::WorkspaceEvent,
services::{
app::event_handler::*,
@ -26,16 +26,16 @@ use crate::{
pub trait WorkspaceDeps: WorkspaceUser + WorkspaceDatabase {}
pub trait WorkspaceUser: Send + Sync {
fn user_id(&self) -> Result<String, WorkspaceError>;
fn token(&self) -> Result<String, WorkspaceError>;
fn user_id(&self) -> Result<String, FlowyError>;
fn token(&self) -> Result<String, FlowyError>;
}
pub trait WorkspaceDatabase: Send + Sync {
fn db_pool(&self) -> Result<Arc<ConnectionPool>, WorkspaceError>;
fn db_pool(&self) -> Result<Arc<ConnectionPool>, FlowyError>;
fn db_connection(&self) -> Result<DBConnection, WorkspaceError> {
fn db_connection(&self) -> Result<DBConnection, FlowyError> {
let pool = self.db_pool()?;
let conn = pool.get().map_err(|e| WorkspaceError::internal().context(e))?;
let conn = pool.get().map_err(|e| FlowyError::internal().context(e))?;
Ok(conn)
}
}

View File

@ -1,243 +0,0 @@
// This file is generated by rust-protobuf 2.22.1. Do not edit
// @generated
// https://github.com/rust-lang/rust-clippy/issues/702
#![allow(unknown_lints)]
#![allow(clippy::all)]
#![allow(unused_attributes)]
#![cfg_attr(rustfmt, rustfmt::skip)]
#![allow(box_pointers)]
#![allow(dead_code)]
#![allow(missing_docs)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(trivial_casts)]
#![allow(unused_imports)]
#![allow(unused_results)]
//! Generated file from `errors.proto`
/// Generated files are compatible only with the same version
/// of protobuf runtime.
// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_22_1;
#[derive(PartialEq,Clone,Default)]
pub struct WorkspaceError {
// message fields
pub code: i32,
pub msg: ::std::string::String,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize,
}
impl<'a> ::std::default::Default for &'a WorkspaceError {
fn default() -> &'a WorkspaceError {
<WorkspaceError as ::protobuf::Message>::default_instance()
}
}
impl WorkspaceError {
pub fn new() -> WorkspaceError {
::std::default::Default::default()
}
// int32 code = 1;
pub fn get_code(&self) -> i32 {
self.code
}
pub fn clear_code(&mut self) {
self.code = 0;
}
// Param is passed by value, moved
pub fn set_code(&mut self, v: i32) {
self.code = v;
}
// string msg = 2;
pub fn get_msg(&self) -> &str {
&self.msg
}
pub fn clear_msg(&mut self) {
self.msg.clear();
}
// Param is passed by value, moved
pub fn set_msg(&mut self, v: ::std::string::String) {
self.msg = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_msg(&mut self) -> &mut ::std::string::String {
&mut self.msg
}
// Take field
pub fn take_msg(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.msg, ::std::string::String::new())
}
}
impl ::protobuf::Message for WorkspaceError {
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
while !is.eof()? {
let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number {
1 => {
if wire_type != ::protobuf::wire_format::WireTypeVarint {
return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
}
let tmp = is.read_int32()?;
self.code = tmp;
},
2 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.msg)?;
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
if self.code != 0 {
my_size += ::protobuf::rt::value_size(1, self.code, ::protobuf::wire_format::WireTypeVarint);
}
if !self.msg.is_empty() {
my_size += ::protobuf::rt::string_size(2, &self.msg);
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
if self.code != 0 {
os.write_int32(1, self.code)?;
}
if !self.msg.is_empty() {
os.write_string(2, &self.msg)?;
}
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
}
fn get_cached_size(&self) -> u32 {
self.cached_size.get()
}
fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
&self.unknown_fields
}
fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
&mut self.unknown_fields
}
fn as_any(&self) -> &dyn (::std::any::Any) {
self as &dyn (::std::any::Any)
}
fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
self as &mut dyn (::std::any::Any)
}
fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
self
}
fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
Self::descriptor_static()
}
fn new() -> WorkspaceError {
WorkspaceError::new()
}
fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
descriptor.get(|| {
let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeInt32>(
"code",
|m: &WorkspaceError| { &m.code },
|m: &mut WorkspaceError| { &mut m.code },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"msg",
|m: &WorkspaceError| { &m.msg },
|m: &mut WorkspaceError| { &mut m.msg },
));
::protobuf::reflect::MessageDescriptor::new_pb_name::<WorkspaceError>(
"WorkspaceError",
fields,
file_descriptor_proto()
)
})
}
fn default_instance() -> &'static WorkspaceError {
static instance: ::protobuf::rt::LazyV2<WorkspaceError> = ::protobuf::rt::LazyV2::INIT;
instance.get(WorkspaceError::new)
}
}
impl ::protobuf::Clear for WorkspaceError {
fn clear(&mut self) {
self.code = 0;
self.msg.clear();
self.unknown_fields.clear();
}
}
impl ::std::fmt::Debug for WorkspaceError {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for WorkspaceError {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Message(self)
}
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x0cerrors.proto\"6\n\x0eWorkspaceError\x12\x12\n\x04code\x18\x01\x20\
\x01(\x05R\x04code\x12\x10\n\x03msg\x18\x02\x20\x01(\tR\x03msgJ\x98\x01\
\n\x06\x12\x04\0\0\x05\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\
\0\x12\x04\x02\0\x05\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x16\n\x0b\n\
\x04\x04\0\x02\0\x12\x03\x03\x04\x13\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\
\x03\x04\t\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\n\x0e\n\x0c\n\x05\x04\
\0\x02\0\x03\x12\x03\x03\x11\x12\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x04\
\x04\x13\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\x04\n\n\x0c\n\x05\x04\
\0\x02\x01\x01\x12\x03\x04\x0b\x0e\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\
\x04\x11\x12b\x06proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap()
}
pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
file_descriptor_proto_lazy.get(|| {
parse_descriptor_proto()
})
}

View File

@ -4,8 +4,5 @@
mod observable;
pub use observable::*;
mod errors;
pub use errors::*;
mod event;
pub use event::*;

View File

@ -1,6 +0,0 @@
syntax = "proto3";
message WorkspaceError {
int32 code = 1;
string msg = 2;
}

View File

@ -39,20 +39,20 @@ impl AppController {
}
}
pub fn init(&self) -> Result<(), WorkspaceError> {
pub fn init(&self) -> Result<(), FlowyError> {
self.listen_trash_can_event();
Ok(())
}
#[tracing::instrument(level = "debug", skip(self, params), fields(name = %params.name) err)]
pub(crate) async fn create_app_from_params(&self, params: CreateAppParams) -> Result<App, WorkspaceError> {
pub(crate) async fn create_app_from_params(&self, params: CreateAppParams) -> Result<App, FlowyError> {
let app = self.create_app_on_server(params).await?;
self.create_app(app).await
}
pub(crate) async fn create_app(&self, app: App) -> Result<App, WorkspaceError> {
pub(crate) async fn create_app(&self, app: App) -> Result<App, FlowyError> {
let conn = &*self.database.db_connection()?;
conn.immediate_transaction::<_, WorkspaceError, _>(|| {
conn.immediate_transaction::<_, FlowyError, _>(|| {
let _ = self.save_app(app.clone(), &*conn)?;
let _ = notify_apps_changed(&app.workspace_id, self.trash_can.clone(), conn)?;
Ok(())
@ -61,30 +61,30 @@ impl AppController {
Ok(app)
}
pub(crate) fn save_app(&self, app: App, conn: &SqliteConnection) -> Result<(), WorkspaceError> {
pub(crate) fn save_app(&self, app: App, conn: &SqliteConnection) -> Result<(), FlowyError> {
let app_table = AppTable::new(app);
let _ = AppTableSql::create_app(app_table, &*conn)?;
Ok(())
}
pub(crate) async fn read_app(&self, params: AppIdentifier) -> Result<App, WorkspaceError> {
pub(crate) async fn read_app(&self, params: AppIdentifier) -> Result<App, FlowyError> {
let conn = self.database.db_connection()?;
let app_table = AppTableSql::read_app(&params.app_id, &*conn)?;
let trash_ids = self.trash_can.trash_ids(&conn)?;
if trash_ids.contains(&app_table.id) {
return Err(WorkspaceError::record_not_found());
return Err(FlowyError::record_not_found());
}
let _ = self.read_app_on_server(params)?;
Ok(app_table.into())
}
pub(crate) async fn update_app(&self, params: UpdateAppParams) -> Result<(), WorkspaceError> {
pub(crate) async fn update_app(&self, params: UpdateAppParams) -> Result<(), FlowyError> {
let changeset = AppTableChangeset::new(params.clone());
let app_id = changeset.id.clone();
let conn = &*self.database.db_connection()?;
conn.immediate_transaction::<_, WorkspaceError, _>(|| {
conn.immediate_transaction::<_, FlowyError, _>(|| {
let _ = AppTableSql::update_app(changeset, conn)?;
let app: App = AppTableSql::read_app(&app_id, conn)?.into();
send_dart_notification(&app_id, WorkspaceNotification::AppUpdated)
@ -97,10 +97,10 @@ impl AppController {
Ok(())
}
pub(crate) fn read_app_tables(&self, ids: Vec<String>) -> Result<Vec<AppTable>, WorkspaceError> {
pub(crate) fn read_app_tables(&self, ids: Vec<String>) -> Result<Vec<AppTable>, FlowyError> {
let conn = &*self.database.db_connection()?;
let mut app_tables = vec![];
conn.immediate_transaction::<_, WorkspaceError, _>(|| {
conn.immediate_transaction::<_, FlowyError, _>(|| {
for app_id in ids {
app_tables.push(AppTableSql::read_app(&app_id, conn)?);
}
@ -113,14 +113,14 @@ impl AppController {
impl AppController {
#[tracing::instrument(level = "debug", skip(self), err)]
async fn create_app_on_server(&self, params: CreateAppParams) -> Result<App, WorkspaceError> {
async fn create_app_on_server(&self, params: CreateAppParams) -> Result<App, FlowyError> {
let token = self.user.token()?;
let app = self.server.create_app(&token, params).await?;
Ok(app)
}
#[tracing::instrument(level = "debug", skip(self), err)]
fn update_app_on_server(&self, params: UpdateAppParams) -> Result<(), WorkspaceError> {
fn update_app_on_server(&self, params: UpdateAppParams) -> Result<(), FlowyError> {
let token = self.user.token()?;
let server = self.server.clone();
tokio::spawn(async move {
@ -136,7 +136,7 @@ impl AppController {
}
#[tracing::instrument(level = "debug", skip(self), err)]
fn read_app_on_server(&self, params: AppIdentifier) -> Result<(), WorkspaceError> {
fn read_app_on_server(&self, params: AppIdentifier) -> Result<(), FlowyError> {
let token = self.user.token()?;
let server = self.server.clone();
let pool = self.database.db_pool()?;
@ -192,21 +192,21 @@ async fn handle_trash_event(database: Arc<dyn WorkspaceDatabase>, trash_can: Arc
TrashEvent::NewTrash(identifiers, ret) | TrashEvent::Putback(identifiers, ret) => {
let result = || {
let conn = &*db_result?;
let _ = conn.immediate_transaction::<_, WorkspaceError, _>(|| {
let _ = conn.immediate_transaction::<_, FlowyError, _>(|| {
for identifier in identifiers.items {
let app_table = AppTableSql::read_app(&identifier.id, conn)?;
let _ = notify_apps_changed(&app_table.workspace_id, trash_can.clone(), conn)?;
}
Ok(())
})?;
Ok::<(), WorkspaceError>(())
Ok::<(), FlowyError>(())
};
let _ = ret.send(result()).await;
},
TrashEvent::Delete(identifiers, ret) => {
let result = || {
let conn = &*db_result?;
let _ = conn.immediate_transaction::<_, WorkspaceError, _>(|| {
let _ = conn.immediate_transaction::<_, FlowyError, _>(|| {
let mut notify_ids = HashSet::new();
for identifier in identifiers.items {
let app_table = AppTableSql::read_app(&identifier.id, conn)?;
@ -219,7 +219,7 @@ async fn handle_trash_event(database: Arc<dyn WorkspaceDatabase>, trash_can: Arc
}
Ok(())
})?;
Ok::<(), WorkspaceError>(())
Ok::<(), FlowyError>(())
};
let _ = ret.send(result()).await;
},
@ -231,7 +231,7 @@ fn notify_apps_changed(
workspace_id: &str,
trash_can: Arc<TrashController>,
conn: &SqliteConnection,
) -> WorkspaceResult<()> {
) -> FlowyResult<()> {
let repeated_app = read_local_workspace_apps(workspace_id, trash_can, conn)?;
send_dart_notification(workspace_id, WorkspaceNotification::WorkspaceAppsChanged)
.payload(repeated_app)
@ -243,7 +243,7 @@ pub fn read_local_workspace_apps(
workspace_id: &str,
trash_controller: Arc<TrashController>,
conn: &SqliteConnection,
) -> Result<RepeatedApp, WorkspaceError> {
) -> Result<RepeatedApp, FlowyError> {
let mut app_tables = AppTableSql::read_workspace_apps(workspace_id, false, conn)?;
let trash_ids = trash_controller.trash_ids(conn)?;
app_tables.retain(|app_table| !trash_ids.contains(&app_table.id));
@ -254,8 +254,8 @@ pub fn read_local_workspace_apps(
// #[tracing::instrument(level = "debug", skip(self), err)]
// pub(crate) async fn delete_app(&self, app_id: &str) -> Result<(),
// WorkspaceError> { let conn = &*self.database.db_connection()?;
// conn.immediate_transaction::<_, WorkspaceError, _>(|| {
// FlowyError> { let conn = &*self.database.db_connection()?;
// conn.immediate_transaction::<_, FlowyError, _>(|| {
// let app = AppTableSql::delete_app(app_id, &*conn)?;
// let apps = self.read_local_apps(&app.workspace_id, &*conn)?;
// send_dart_notification(&app.workspace_id,
@ -269,7 +269,7 @@ pub fn read_local_workspace_apps(
// }
//
// #[tracing::instrument(level = "debug", skip(self), err)]
// fn delete_app_on_server(&self, app_id: &str) -> Result<(), WorkspaceError> {
// fn delete_app_on_server(&self, app_id: &str) -> Result<(), FlowyError> {
// let token = self.user.token()?;
// let server = self.server.clone();
// let params = DeleteAppParams {
@ -291,7 +291,7 @@ pub fn read_local_workspace_apps(
// // Ok(_) => {},
// // Err(e) => log::error!("Delete app failed: {:?}", e),
// // }
// // Ok::<(), WorkspaceError>(())
// // Ok::<(), FlowyError>(())
// // }
// // });
// //

View File

@ -11,7 +11,7 @@ use crate::{
},
trash::Trash,
},
errors::WorkspaceError,
errors::FlowyError,
services::{AppController, TrashController, ViewController},
};
use lib_dispatch::prelude::{data_result, Data, DataResult, Unit};
@ -20,7 +20,7 @@ use std::{convert::TryInto, sync::Arc};
pub(crate) async fn create_app_handler(
data: Data<CreateAppRequest>,
controller: Unit<Arc<AppController>>,
) -> DataResult<App, WorkspaceError> {
) -> DataResult<App, FlowyError> {
let params: CreateAppParams = data.into_inner().try_into()?;
let detail = controller.create_app_from_params(params).await?;
@ -31,7 +31,7 @@ pub(crate) async fn delete_app_handler(
data: Data<QueryAppRequest>,
controller: Unit<Arc<AppController>>,
trash_can: Unit<Arc<TrashController>>,
) -> Result<(), WorkspaceError> {
) -> Result<(), FlowyError> {
let params: AppIdentifier = data.into_inner().try_into()?;
let trash = controller
.read_app_tables(vec![params.app_id])?
@ -47,7 +47,7 @@ pub(crate) async fn delete_app_handler(
pub(crate) async fn update_app_handler(
data: Data<UpdateAppRequest>,
controller: Unit<Arc<AppController>>,
) -> Result<(), WorkspaceError> {
) -> Result<(), FlowyError> {
let params: UpdateAppParams = data.into_inner().try_into()?;
let _ = controller.update_app(params).await?;
Ok(())
@ -58,7 +58,7 @@ pub(crate) async fn read_app_handler(
data: Data<QueryAppRequest>,
app_controller: Unit<Arc<AppController>>,
view_controller: Unit<Arc<ViewController>>,
) -> DataResult<App, WorkspaceError> {
) -> DataResult<App, FlowyError> {
let params: AppIdentifier = data.into_inner().try_into()?;
let mut app = app_controller.read_app(params.clone()).await?;
app.belongings = view_controller.read_views_belong_to(&params.app_id).await?;

View File

@ -15,12 +15,12 @@ use flowy_database::{
use serde::{Deserialize, Serialize, __private::TryFrom};
use std::convert::TryInto;
use crate::errors::WorkspaceError;
use crate::errors::FlowyError;
pub struct AppTableSql {}
impl AppTableSql {
pub(crate) fn create_app(app_table: AppTable, conn: &SqliteConnection) -> Result<(), WorkspaceError> {
pub(crate) fn create_app(app_table: AppTable, conn: &SqliteConnection) -> Result<(), FlowyError> {
match diesel_record_count!(app_table, &app_table.id, conn) {
0 => diesel_insert_table!(app_table, &app_table, conn),
_ => {
@ -31,12 +31,12 @@ impl AppTableSql {
Ok(())
}
pub(crate) fn update_app(changeset: AppTableChangeset, conn: &SqliteConnection) -> Result<(), WorkspaceError> {
pub(crate) fn update_app(changeset: AppTableChangeset, conn: &SqliteConnection) -> Result<(), FlowyError> {
diesel_update_table!(app_table, changeset, conn);
Ok(())
}
pub(crate) fn read_app(app_id: &str, conn: &SqliteConnection) -> Result<AppTable, WorkspaceError> {
pub(crate) fn read_app(app_id: &str, conn: &SqliteConnection) -> Result<AppTable, FlowyError> {
let filter = dsl::app_table.filter(app_table::id.eq(app_id)).into_boxed();
let app_table = filter.first::<AppTable>(conn)?;
Ok(app_table)
@ -46,7 +46,7 @@ impl AppTableSql {
workspace_id: &str,
is_trash: bool,
conn: &SqliteConnection,
) -> Result<Vec<AppTable>, WorkspaceError> {
) -> Result<Vec<AppTable>, FlowyError> {
let app_table = dsl::app_table
.filter(app_table::workspace_id.eq(workspace_id))
.filter(app_table::is_trash.eq(is_trash))
@ -56,7 +56,7 @@ impl AppTableSql {
Ok(app_table)
}
pub(crate) fn delete_app(app_id: &str, conn: &SqliteConnection) -> Result<AppTable, WorkspaceError> {
pub(crate) fn delete_app(app_id: &str, conn: &SqliteConnection) -> Result<AppTable, FlowyError> {
let app_table = dsl::app_table
.filter(app_table::id.eq(app_id))
.first::<AppTable>(conn)?;
@ -67,10 +67,10 @@ impl AppTableSql {
// pub(crate) fn read_views_belong_to_app(
// &self,
// app_id: &str,
// ) -> Result<Vec<ViewTable>, WorkspaceError> {
// ) -> Result<Vec<ViewTable>, FlowyError> {
// let conn = self.database.db_connection()?;
//
// let views = conn.immediate_transaction::<_, WorkspaceError, _>(|| {
// let views = conn.immediate_transaction::<_, FlowyError, _>(|| {
// let app_table: AppTable = dsl::app_table
// .filter(app_table::id.eq(app_id))
// .first::<AppTable>(&*(conn))?;

View File

@ -12,7 +12,7 @@ use crate::{
view::{CreateViewParams, UpdateViewParams, View, ViewIdentifier, ViewIdentifiers},
workspace::{CreateWorkspaceParams, RepeatedWorkspace, UpdateWorkspaceParams, Workspace, WorkspaceIdentifier},
},
errors::WorkspaceError,
errors::FlowyError,
};
use backend_service::configuration::ClientServerConfiguration;
use lib_infra::future::FutureResult;
@ -24,42 +24,38 @@ pub trait WorkspaceServerAPI {
fn init(&self);
// Workspace
fn create_workspace(&self, token: &str, params: CreateWorkspaceParams) -> FutureResult<Workspace, WorkspaceError>;
fn create_workspace(&self, token: &str, params: CreateWorkspaceParams) -> FutureResult<Workspace, FlowyError>;
fn read_workspace(
&self,
token: &str,
params: WorkspaceIdentifier,
) -> FutureResult<RepeatedWorkspace, WorkspaceError>;
fn read_workspace(&self, token: &str, params: WorkspaceIdentifier) -> FutureResult<RepeatedWorkspace, FlowyError>;
fn update_workspace(&self, token: &str, params: UpdateWorkspaceParams) -> FutureResult<(), WorkspaceError>;
fn update_workspace(&self, token: &str, params: UpdateWorkspaceParams) -> FutureResult<(), FlowyError>;
fn delete_workspace(&self, token: &str, params: WorkspaceIdentifier) -> FutureResult<(), WorkspaceError>;
fn delete_workspace(&self, token: &str, params: WorkspaceIdentifier) -> FutureResult<(), FlowyError>;
// View
fn create_view(&self, token: &str, params: CreateViewParams) -> FutureResult<View, WorkspaceError>;
fn create_view(&self, token: &str, params: CreateViewParams) -> FutureResult<View, FlowyError>;
fn read_view(&self, token: &str, params: ViewIdentifier) -> FutureResult<Option<View>, WorkspaceError>;
fn read_view(&self, token: &str, params: ViewIdentifier) -> FutureResult<Option<View>, FlowyError>;
fn delete_view(&self, token: &str, params: ViewIdentifiers) -> FutureResult<(), WorkspaceError>;
fn delete_view(&self, token: &str, params: ViewIdentifiers) -> FutureResult<(), FlowyError>;
fn update_view(&self, token: &str, params: UpdateViewParams) -> FutureResult<(), WorkspaceError>;
fn update_view(&self, token: &str, params: UpdateViewParams) -> FutureResult<(), FlowyError>;
// App
fn create_app(&self, token: &str, params: CreateAppParams) -> FutureResult<App, WorkspaceError>;
fn create_app(&self, token: &str, params: CreateAppParams) -> FutureResult<App, FlowyError>;
fn read_app(&self, token: &str, params: AppIdentifier) -> FutureResult<Option<App>, WorkspaceError>;
fn read_app(&self, token: &str, params: AppIdentifier) -> FutureResult<Option<App>, FlowyError>;
fn update_app(&self, token: &str, params: UpdateAppParams) -> FutureResult<(), WorkspaceError>;
fn update_app(&self, token: &str, params: UpdateAppParams) -> FutureResult<(), FlowyError>;
fn delete_app(&self, token: &str, params: AppIdentifier) -> FutureResult<(), WorkspaceError>;
fn delete_app(&self, token: &str, params: AppIdentifier) -> FutureResult<(), FlowyError>;
// Trash
fn create_trash(&self, token: &str, params: TrashIdentifiers) -> FutureResult<(), WorkspaceError>;
fn create_trash(&self, token: &str, params: TrashIdentifiers) -> FutureResult<(), FlowyError>;
fn delete_trash(&self, token: &str, params: TrashIdentifiers) -> FutureResult<(), WorkspaceError>;
fn delete_trash(&self, token: &str, params: TrashIdentifiers) -> FutureResult<(), FlowyError>;
fn read_trash(&self, token: &str) -> FutureResult<RepeatedTrash, WorkspaceError>;
fn read_trash(&self, token: &str) -> FutureResult<RepeatedTrash, FlowyError>;
}
pub(crate) fn construct_workspace_server(

View File

@ -5,12 +5,11 @@ use crate::{
view::{CreateViewParams, UpdateViewParams, View, ViewIdentifier, ViewIdentifiers},
workspace::{CreateWorkspaceParams, RepeatedWorkspace, UpdateWorkspaceParams, Workspace, WorkspaceIdentifier},
},
errors::WorkspaceError,
errors::{ErrorCode, FlowyError},
notify::{send_dart_notification, WorkspaceNotification},
services::server::WorkspaceServerAPI,
};
use backend_service::{configuration::ClientServerConfiguration, middleware::*, workspace_request::*};
use flowy_core_infra::errors::ErrorCode;
use lib_infra::future::FutureResult;
pub struct WorkspaceHttpServer {
@ -26,7 +25,7 @@ impl WorkspaceServerAPI for WorkspaceHttpServer {
let mut rx = BACKEND_API_MIDDLEWARE.invalid_token_subscribe();
tokio::spawn(async move {
while let Ok(invalid_token) = rx.recv().await {
let error = WorkspaceError::new(ErrorCode::UserUnauthorized, "");
let error = FlowyError::new(ErrorCode::UserUnauthorized, "");
send_dart_notification(&invalid_token, WorkspaceNotification::UserUnauthorized)
.error(error)
.send()
@ -34,7 +33,7 @@ impl WorkspaceServerAPI for WorkspaceHttpServer {
});
}
fn create_workspace(&self, token: &str, params: CreateWorkspaceParams) -> FutureResult<Workspace, WorkspaceError> {
fn create_workspace(&self, token: &str, params: CreateWorkspaceParams) -> FutureResult<Workspace, FlowyError> {
let token = token.to_owned();
let url = self.config.workspace_url();
FutureResult::new(async move {
@ -43,11 +42,7 @@ impl WorkspaceServerAPI for WorkspaceHttpServer {
})
}
fn read_workspace(
&self,
token: &str,
params: WorkspaceIdentifier,
) -> FutureResult<RepeatedWorkspace, WorkspaceError> {
fn read_workspace(&self, token: &str, params: WorkspaceIdentifier) -> FutureResult<RepeatedWorkspace, FlowyError> {
let token = token.to_owned();
let url = self.config.workspace_url();
FutureResult::new(async move {
@ -56,7 +51,7 @@ impl WorkspaceServerAPI for WorkspaceHttpServer {
})
}
fn update_workspace(&self, token: &str, params: UpdateWorkspaceParams) -> FutureResult<(), WorkspaceError> {
fn update_workspace(&self, token: &str, params: UpdateWorkspaceParams) -> FutureResult<(), FlowyError> {
let token = token.to_owned();
let url = self.config.workspace_url();
FutureResult::new(async move {
@ -65,7 +60,7 @@ impl WorkspaceServerAPI for WorkspaceHttpServer {
})
}
fn delete_workspace(&self, token: &str, params: WorkspaceIdentifier) -> FutureResult<(), WorkspaceError> {
fn delete_workspace(&self, token: &str, params: WorkspaceIdentifier) -> FutureResult<(), FlowyError> {
let token = token.to_owned();
let url = self.config.workspace_url();
FutureResult::new(async move {
@ -74,7 +69,7 @@ impl WorkspaceServerAPI for WorkspaceHttpServer {
})
}
fn create_view(&self, token: &str, params: CreateViewParams) -> FutureResult<View, WorkspaceError> {
fn create_view(&self, token: &str, params: CreateViewParams) -> FutureResult<View, FlowyError> {
let token = token.to_owned();
let url = self.config.view_url();
FutureResult::new(async move {
@ -83,7 +78,7 @@ impl WorkspaceServerAPI for WorkspaceHttpServer {
})
}
fn read_view(&self, token: &str, params: ViewIdentifier) -> FutureResult<Option<View>, WorkspaceError> {
fn read_view(&self, token: &str, params: ViewIdentifier) -> FutureResult<Option<View>, FlowyError> {
let token = token.to_owned();
let url = self.config.view_url();
FutureResult::new(async move {
@ -92,7 +87,7 @@ impl WorkspaceServerAPI for WorkspaceHttpServer {
})
}
fn delete_view(&self, token: &str, params: ViewIdentifiers) -> FutureResult<(), WorkspaceError> {
fn delete_view(&self, token: &str, params: ViewIdentifiers) -> FutureResult<(), FlowyError> {
let token = token.to_owned();
let url = self.config.view_url();
FutureResult::new(async move {
@ -101,7 +96,7 @@ impl WorkspaceServerAPI for WorkspaceHttpServer {
})
}
fn update_view(&self, token: &str, params: UpdateViewParams) -> FutureResult<(), WorkspaceError> {
fn update_view(&self, token: &str, params: UpdateViewParams) -> FutureResult<(), FlowyError> {
let token = token.to_owned();
let url = self.config.view_url();
FutureResult::new(async move {
@ -110,7 +105,7 @@ impl WorkspaceServerAPI for WorkspaceHttpServer {
})
}
fn create_app(&self, token: &str, params: CreateAppParams) -> FutureResult<App, WorkspaceError> {
fn create_app(&self, token: &str, params: CreateAppParams) -> FutureResult<App, FlowyError> {
let token = token.to_owned();
let url = self.config.app_url();
FutureResult::new(async move {
@ -119,7 +114,7 @@ impl WorkspaceServerAPI for WorkspaceHttpServer {
})
}
fn read_app(&self, token: &str, params: AppIdentifier) -> FutureResult<Option<App>, WorkspaceError> {
fn read_app(&self, token: &str, params: AppIdentifier) -> FutureResult<Option<App>, FlowyError> {
let token = token.to_owned();
let url = self.config.app_url();
FutureResult::new(async move {
@ -128,7 +123,7 @@ impl WorkspaceServerAPI for WorkspaceHttpServer {
})
}
fn update_app(&self, token: &str, params: UpdateAppParams) -> FutureResult<(), WorkspaceError> {
fn update_app(&self, token: &str, params: UpdateAppParams) -> FutureResult<(), FlowyError> {
let token = token.to_owned();
let url = self.config.app_url();
FutureResult::new(async move {
@ -137,7 +132,7 @@ impl WorkspaceServerAPI for WorkspaceHttpServer {
})
}
fn delete_app(&self, token: &str, params: AppIdentifier) -> FutureResult<(), WorkspaceError> {
fn delete_app(&self, token: &str, params: AppIdentifier) -> FutureResult<(), FlowyError> {
let token = token.to_owned();
let url = self.config.app_url();
FutureResult::new(async move {
@ -146,7 +141,7 @@ impl WorkspaceServerAPI for WorkspaceHttpServer {
})
}
fn create_trash(&self, token: &str, params: TrashIdentifiers) -> FutureResult<(), WorkspaceError> {
fn create_trash(&self, token: &str, params: TrashIdentifiers) -> FutureResult<(), FlowyError> {
let token = token.to_owned();
let url = self.config.trash_url();
FutureResult::new(async move {
@ -155,7 +150,7 @@ impl WorkspaceServerAPI for WorkspaceHttpServer {
})
}
fn delete_trash(&self, token: &str, params: TrashIdentifiers) -> FutureResult<(), WorkspaceError> {
fn delete_trash(&self, token: &str, params: TrashIdentifiers) -> FutureResult<(), FlowyError> {
let token = token.to_owned();
let url = self.config.trash_url();
FutureResult::new(async move {
@ -164,7 +159,7 @@ impl WorkspaceServerAPI for WorkspaceHttpServer {
})
}
fn read_trash(&self, token: &str) -> FutureResult<RepeatedTrash, WorkspaceError> {
fn read_trash(&self, token: &str) -> FutureResult<RepeatedTrash, FlowyError> {
let token = token.to_owned();
let url = self.config.trash_url();
FutureResult::new(async move {

View File

@ -5,7 +5,7 @@ use crate::{
view::{CreateViewParams, RepeatedView, UpdateViewParams, View, ViewIdentifier, ViewIdentifiers},
workspace::{CreateWorkspaceParams, RepeatedWorkspace, UpdateWorkspaceParams, Workspace, WorkspaceIdentifier},
},
errors::WorkspaceError,
errors::FlowyError,
services::server::WorkspaceServerAPI,
};
use lib_infra::{future::FutureResult, timestamp, uuid};
@ -15,7 +15,7 @@ pub struct WorkspaceServerMock {}
impl WorkspaceServerAPI for WorkspaceServerMock {
fn init(&self) {}
fn create_workspace(&self, _token: &str, params: CreateWorkspaceParams) -> FutureResult<Workspace, WorkspaceError> {
fn create_workspace(&self, _token: &str, params: CreateWorkspaceParams) -> FutureResult<Workspace, FlowyError> {
let time = timestamp();
let workspace = Workspace {
id: uuid(),
@ -33,22 +33,22 @@ impl WorkspaceServerAPI for WorkspaceServerMock {
&self,
_token: &str,
_params: WorkspaceIdentifier,
) -> FutureResult<RepeatedWorkspace, WorkspaceError> {
) -> FutureResult<RepeatedWorkspace, FlowyError> {
FutureResult::new(async {
let repeated_workspace = RepeatedWorkspace { items: vec![] };
Ok(repeated_workspace)
})
}
fn update_workspace(&self, _token: &str, _params: UpdateWorkspaceParams) -> FutureResult<(), WorkspaceError> {
fn update_workspace(&self, _token: &str, _params: UpdateWorkspaceParams) -> FutureResult<(), FlowyError> {
FutureResult::new(async { Ok(()) })
}
fn delete_workspace(&self, _token: &str, _params: WorkspaceIdentifier) -> FutureResult<(), WorkspaceError> {
fn delete_workspace(&self, _token: &str, _params: WorkspaceIdentifier) -> FutureResult<(), FlowyError> {
FutureResult::new(async { Ok(()) })
}
fn create_view(&self, _token: &str, params: CreateViewParams) -> FutureResult<View, WorkspaceError> {
fn create_view(&self, _token: &str, params: CreateViewParams) -> FutureResult<View, FlowyError> {
let time = timestamp();
let view = View {
id: uuid(),
@ -64,19 +64,19 @@ impl WorkspaceServerAPI for WorkspaceServerMock {
FutureResult::new(async { Ok(view) })
}
fn read_view(&self, _token: &str, _params: ViewIdentifier) -> FutureResult<Option<View>, WorkspaceError> {
fn read_view(&self, _token: &str, _params: ViewIdentifier) -> FutureResult<Option<View>, FlowyError> {
FutureResult::new(async { Ok(None) })
}
fn delete_view(&self, _token: &str, _params: ViewIdentifiers) -> FutureResult<(), WorkspaceError> {
fn delete_view(&self, _token: &str, _params: ViewIdentifiers) -> FutureResult<(), FlowyError> {
FutureResult::new(async { Ok(()) })
}
fn update_view(&self, _token: &str, _params: UpdateViewParams) -> FutureResult<(), WorkspaceError> {
fn update_view(&self, _token: &str, _params: UpdateViewParams) -> FutureResult<(), FlowyError> {
FutureResult::new(async { Ok(()) })
}
fn create_app(&self, _token: &str, params: CreateAppParams) -> FutureResult<App, WorkspaceError> {
fn create_app(&self, _token: &str, params: CreateAppParams) -> FutureResult<App, FlowyError> {
let time = timestamp();
let app = App {
id: uuid(),
@ -91,27 +91,27 @@ impl WorkspaceServerAPI for WorkspaceServerMock {
FutureResult::new(async { Ok(app) })
}
fn read_app(&self, _token: &str, _params: AppIdentifier) -> FutureResult<Option<App>, WorkspaceError> {
fn read_app(&self, _token: &str, _params: AppIdentifier) -> FutureResult<Option<App>, FlowyError> {
FutureResult::new(async { Ok(None) })
}
fn update_app(&self, _token: &str, _params: UpdateAppParams) -> FutureResult<(), WorkspaceError> {
fn update_app(&self, _token: &str, _params: UpdateAppParams) -> FutureResult<(), FlowyError> {
FutureResult::new(async { Ok(()) })
}
fn delete_app(&self, _token: &str, _params: AppIdentifier) -> FutureResult<(), WorkspaceError> {
fn delete_app(&self, _token: &str, _params: AppIdentifier) -> FutureResult<(), FlowyError> {
FutureResult::new(async { Ok(()) })
}
fn create_trash(&self, _token: &str, _params: TrashIdentifiers) -> FutureResult<(), WorkspaceError> {
fn create_trash(&self, _token: &str, _params: TrashIdentifiers) -> FutureResult<(), FlowyError> {
FutureResult::new(async { Ok(()) })
}
fn delete_trash(&self, _token: &str, _params: TrashIdentifiers) -> FutureResult<(), WorkspaceError> {
fn delete_trash(&self, _token: &str, _params: TrashIdentifiers) -> FutureResult<(), FlowyError> {
FutureResult::new(async { Ok(()) })
}
fn read_trash(&self, _token: &str) -> FutureResult<RepeatedTrash, WorkspaceError> {
fn read_trash(&self, _token: &str) -> FutureResult<RepeatedTrash, FlowyError> {
FutureResult::new(async {
let repeated_trash = RepeatedTrash { items: vec![] };
Ok(repeated_trash)

View File

@ -1,6 +1,6 @@
use crate::{
entities::trash::{RepeatedTrash, Trash, TrashIdentifier, TrashIdentifiers, TrashType},
errors::{WorkspaceError, WorkspaceResult},
errors::{FlowyError, FlowyResult},
module::{WorkspaceDatabase, WorkspaceUser},
notify::{send_anonymous_dart_notification, WorkspaceNotification},
services::{server::Server, trash::sql::TrashTableSql},
@ -29,21 +29,21 @@ impl TrashController {
}
}
pub(crate) fn init(&self) -> Result<(), WorkspaceError> { Ok(()) }
pub(crate) fn init(&self) -> Result<(), FlowyError> { Ok(()) }
#[tracing::instrument(level = "debug", skip(self), fields(putback) err)]
pub async fn putback(&self, trash_id: &str) -> WorkspaceResult<()> {
let (tx, mut rx) = mpsc::channel::<WorkspaceResult<()>>(1);
pub async fn putback(&self, trash_id: &str) -> FlowyResult<()> {
let (tx, mut rx) = mpsc::channel::<FlowyResult<()>>(1);
let trash_table = TrashTableSql::read(trash_id, &*self.database.db_connection()?)?;
let _ = thread::scope(|_s| {
let conn = self.database.db_connection()?;
conn.immediate_transaction::<_, WorkspaceError, _>(|| {
conn.immediate_transaction::<_, FlowyError, _>(|| {
let _ = TrashTableSql::delete_trash(trash_id, &*conn)?;
notify_trash_changed(TrashTableSql::read_all(&conn)?);
Ok(())
})?;
Ok::<(), WorkspaceError>(())
Ok::<(), FlowyError>(())
})
.unwrap()?;
@ -64,10 +64,10 @@ impl TrashController {
}
#[tracing::instrument(level = "debug", skip(self) err)]
pub async fn restore_all(&self) -> WorkspaceResult<()> {
pub async fn restore_all(&self) -> FlowyResult<()> {
let repeated_trash = thread::scope(|_s| {
let conn = self.database.db_connection()?;
conn.immediate_transaction::<_, WorkspaceError, _>(|| {
conn.immediate_transaction::<_, FlowyError, _>(|| {
let repeated_trash = TrashTableSql::read_all(&*conn)?;
let _ = TrashTableSql::delete_all(&*conn)?;
Ok(repeated_trash)
@ -76,7 +76,7 @@ impl TrashController {
.unwrap()?;
let identifiers: TrashIdentifiers = repeated_trash.items.clone().into();
let (tx, mut rx) = mpsc::channel::<WorkspaceResult<()>>(1);
let (tx, mut rx) = mpsc::channel::<FlowyResult<()>>(1);
let _ = self.notify.send(TrashEvent::Putback(identifiers, tx));
let _ = rx.recv().await;
@ -86,7 +86,7 @@ impl TrashController {
}
#[tracing::instrument(level = "debug", skip(self), err)]
pub async fn delete_all(&self) -> WorkspaceResult<()> {
pub async fn delete_all(&self) -> FlowyResult<()> {
let repeated_trash = TrashTableSql::read_all(&*(self.database.db_connection()?))?;
let trash_identifiers: TrashIdentifiers = repeated_trash.items.clone().into();
let _ = self.delete_with_identifiers(trash_identifiers.clone()).await?;
@ -97,7 +97,7 @@ impl TrashController {
}
#[tracing::instrument(level = "debug", skip(self), err)]
pub async fn delete(&self, trash_identifiers: TrashIdentifiers) -> WorkspaceResult<()> {
pub async fn delete(&self, trash_identifiers: TrashIdentifiers) -> FlowyResult<()> {
let _ = self.delete_with_identifiers(trash_identifiers.clone()).await?;
notify_trash_changed(TrashTableSql::read_all(&*(self.database.db_connection()?))?);
let _ = self.delete_trash_on_server(trash_identifiers)?;
@ -106,8 +106,8 @@ impl TrashController {
}
#[tracing::instrument(level = "debug", skip(self), fields(delete_trash_ids), err)]
pub async fn delete_with_identifiers(&self, trash_identifiers: TrashIdentifiers) -> WorkspaceResult<()> {
let (tx, mut rx) = mpsc::channel::<WorkspaceResult<()>>(1);
pub async fn delete_with_identifiers(&self, trash_identifiers: TrashIdentifiers) -> FlowyResult<()> {
let (tx, mut rx) = mpsc::channel::<FlowyResult<()>>(1);
tracing::Span::current().record("delete_trash_ids", &format!("{}", trash_identifiers).as_str());
let _ = self.notify.send(TrashEvent::Delete(trash_identifiers.clone(), tx));
@ -120,7 +120,7 @@ impl TrashController {
}
let conn = self.database.db_connection()?;
conn.immediate_transaction::<_, WorkspaceError, _>(|| {
conn.immediate_transaction::<_, FlowyError, _>(|| {
for trash_identifier in &trash_identifiers.items {
let _ = TrashTableSql::delete_trash(&trash_identifier.id, &conn)?;
}
@ -136,8 +136,8 @@ impl TrashController {
// CREATE and DROP tables operations because those are auto-commit in the
// database.
#[tracing::instrument(name = "add_trash", level = "debug", skip(self, trash), fields(trash_ids), err)]
pub async fn add<T: Into<Trash>>(&self, trash: Vec<T>) -> Result<(), WorkspaceError> {
let (tx, mut rx) = mpsc::channel::<WorkspaceResult<()>>(1);
pub async fn add<T: Into<Trash>>(&self, trash: Vec<T>) -> Result<(), FlowyError> {
let (tx, mut rx) = mpsc::channel::<FlowyResult<()>>(1);
let repeated_trash = trash.into_iter().map(|t| t.into()).collect::<Vec<Trash>>();
let identifiers = repeated_trash
.iter()
@ -157,14 +157,14 @@ impl TrashController {
);
let _ = thread::scope(|_s| {
let conn = self.database.db_connection()?;
conn.immediate_transaction::<_, WorkspaceError, _>(|| {
conn.immediate_transaction::<_, FlowyError, _>(|| {
let _ = TrashTableSql::create_trash(repeated_trash.clone(), &*conn)?;
let _ = self.create_trash_on_server(repeated_trash);
notify_trash_changed(TrashTableSql::read_all(&conn)?);
Ok(())
})?;
Ok::<(), WorkspaceError>(())
Ok::<(), FlowyError>(())
})
.unwrap()?;
@ -176,13 +176,13 @@ impl TrashController {
pub fn subscribe(&self) -> broadcast::Receiver<TrashEvent> { self.notify.subscribe() }
pub fn read_trash(&self, conn: &SqliteConnection) -> Result<RepeatedTrash, WorkspaceError> {
pub fn read_trash(&self, conn: &SqliteConnection) -> Result<RepeatedTrash, FlowyError> {
let repeated_trash = TrashTableSql::read_all(&*conn)?;
let _ = self.read_trash_on_server()?;
Ok(repeated_trash)
}
pub fn trash_ids(&self, conn: &SqliteConnection) -> Result<Vec<String>, WorkspaceError> {
pub fn trash_ids(&self, conn: &SqliteConnection) -> Result<Vec<String>, FlowyError> {
let ids = TrashTableSql::read_all(&*conn)?
.into_inner()
.into_iter()
@ -194,7 +194,7 @@ impl TrashController {
impl TrashController {
#[tracing::instrument(level = "debug", skip(self, trash), err)]
fn create_trash_on_server<T: Into<TrashIdentifiers>>(&self, trash: T) -> WorkspaceResult<()> {
fn create_trash_on_server<T: Into<TrashIdentifiers>>(&self, trash: T) -> FlowyResult<()> {
let token = self.user.token()?;
let trash_identifiers = trash.into();
let server = self.server.clone();
@ -209,7 +209,7 @@ impl TrashController {
}
#[tracing::instrument(level = "debug", skip(self, trash), err)]
fn delete_trash_on_server<T: Into<TrashIdentifiers>>(&self, trash: T) -> WorkspaceResult<()> {
fn delete_trash_on_server<T: Into<TrashIdentifiers>>(&self, trash: T) -> FlowyResult<()> {
let token = self.user.token()?;
let trash_identifiers = trash.into();
let server = self.server.clone();
@ -223,7 +223,7 @@ impl TrashController {
}
#[tracing::instrument(level = "debug", skip(self), err)]
fn read_trash_on_server(&self) -> WorkspaceResult<()> {
fn read_trash_on_server(&self) -> FlowyResult<()> {
let token = self.user.token()?;
let server = self.server.clone();
let pool = self.database.db_pool()?;
@ -234,7 +234,7 @@ impl TrashController {
tracing::debug!("Remote trash count: {}", repeated_trash.items.len());
match pool.get() {
Ok(conn) => {
let result = conn.immediate_transaction::<_, WorkspaceError, _>(|| {
let result = conn.immediate_transaction::<_, FlowyError, _>(|| {
let _ = TrashTableSql::create_trash(repeated_trash.items.clone(), &*conn)?;
TrashTableSql::read_all(&conn)
});
@ -256,7 +256,7 @@ impl TrashController {
}
#[tracing::instrument(level = "debug", skip(self), err)]
async fn delete_all_trash_on_server(&self) -> WorkspaceResult<()> {
async fn delete_all_trash_on_server(&self) -> FlowyResult<()> {
let token = self.user.token()?;
let server = self.server.clone();
server.delete_trash(&token, TrashIdentifiers::all()).await
@ -273,9 +273,9 @@ fn notify_trash_changed(repeated_trash: RepeatedTrash) {
#[derive(Clone)]
pub enum TrashEvent {
NewTrash(TrashIdentifiers, mpsc::Sender<WorkspaceResult<()>>),
Putback(TrashIdentifiers, mpsc::Sender<WorkspaceResult<()>>),
Delete(TrashIdentifiers, mpsc::Sender<WorkspaceResult<()>>),
NewTrash(TrashIdentifiers, mpsc::Sender<FlowyResult<()>>),
Putback(TrashIdentifiers, mpsc::Sender<FlowyResult<()>>),
Delete(TrashIdentifiers, mpsc::Sender<FlowyResult<()>>),
}
impl std::fmt::Debug for TrashEvent {

View File

@ -1,6 +1,6 @@
use crate::{
entities::trash::{RepeatedTrash, TrashIdentifier, TrashIdentifiers},
errors::WorkspaceError,
errors::FlowyError,
services::TrashController,
};
use lib_dispatch::prelude::{data_result, Data, DataResult, Unit};
@ -9,7 +9,7 @@ use std::sync::Arc;
#[tracing::instrument(skip(controller), err)]
pub(crate) async fn read_trash_handler(
controller: Unit<Arc<TrashController>>,
) -> DataResult<RepeatedTrash, WorkspaceError> {
) -> DataResult<RepeatedTrash, FlowyError> {
let conn = controller.database.db_connection()?;
let repeated_trash = controller.read_trash(&conn)?;
data_result(repeated_trash)
@ -19,7 +19,7 @@ pub(crate) async fn read_trash_handler(
pub(crate) async fn putback_trash_handler(
identifier: Data<TrashIdentifier>,
controller: Unit<Arc<TrashController>>,
) -> Result<(), WorkspaceError> {
) -> Result<(), FlowyError> {
let _ = controller.putback(&identifier.id).await?;
Ok(())
}
@ -28,19 +28,19 @@ pub(crate) async fn putback_trash_handler(
pub(crate) async fn delete_trash_handler(
identifiers: Data<TrashIdentifiers>,
controller: Unit<Arc<TrashController>>,
) -> Result<(), WorkspaceError> {
) -> Result<(), FlowyError> {
let _ = controller.delete(identifiers.into_inner()).await?;
Ok(())
}
#[tracing::instrument(skip(controller), err)]
pub(crate) async fn restore_all_handler(controller: Unit<Arc<TrashController>>) -> Result<(), WorkspaceError> {
pub(crate) async fn restore_all_handler(controller: Unit<Arc<TrashController>>) -> Result<(), FlowyError> {
let _ = controller.restore_all().await?;
Ok(())
}
#[tracing::instrument(skip(controller), err)]
pub(crate) async fn delete_all_handler(controller: Unit<Arc<TrashController>>) -> Result<(), WorkspaceError> {
pub(crate) async fn delete_all_handler(controller: Unit<Arc<TrashController>>) -> Result<(), FlowyError> {
let _ = controller.delete_all().await?;
Ok(())
}

View File

@ -1,6 +1,6 @@
use crate::{
entities::trash::{RepeatedTrash, Trash, TrashType},
errors::WorkspaceError,
errors::FlowyError,
};
use diesel::sql_types::Integer;
use flowy_database::{
@ -12,7 +12,7 @@ use flowy_database::{
pub struct TrashTableSql {}
impl TrashTableSql {
pub(crate) fn create_trash(repeated_trash: Vec<Trash>, conn: &SqliteConnection) -> Result<(), WorkspaceError> {
pub(crate) fn create_trash(repeated_trash: Vec<Trash>, conn: &SqliteConnection) -> Result<(), FlowyError> {
for trash in repeated_trash {
let trash_table: TrashTable = trash.into();
match diesel_record_count!(trash_table, &trash_table.id, conn) {
@ -27,25 +27,25 @@ impl TrashTableSql {
Ok(())
}
pub(crate) fn read_all(conn: &SqliteConnection) -> Result<RepeatedTrash, WorkspaceError> {
pub(crate) fn read_all(conn: &SqliteConnection) -> Result<RepeatedTrash, FlowyError> {
let trash_tables = dsl::trash_table.load::<TrashTable>(conn)?;
let items = trash_tables.into_iter().map(|t| t.into()).collect::<Vec<Trash>>();
Ok(RepeatedTrash { items })
}
pub(crate) fn delete_all(conn: &SqliteConnection) -> Result<(), WorkspaceError> {
pub(crate) fn delete_all(conn: &SqliteConnection) -> Result<(), FlowyError> {
let _ = diesel::delete(dsl::trash_table).execute(conn)?;
Ok(())
}
pub(crate) fn read(trash_id: &str, conn: &SqliteConnection) -> Result<TrashTable, WorkspaceError> {
pub(crate) fn read(trash_id: &str, conn: &SqliteConnection) -> Result<TrashTable, FlowyError> {
let trash_table = dsl::trash_table
.filter(trash_table::id.eq(trash_id))
.first::<TrashTable>(conn)?;
Ok(trash_table)
}
pub(crate) fn delete_trash(trash_id: &str, conn: &SqliteConnection) -> Result<(), WorkspaceError> {
pub(crate) fn delete_trash(trash_id: &str, conn: &SqliteConnection) -> Result<(), FlowyError> {
diesel_delete_table!(trash_table, trash_id, conn);
Ok(())
}

View File

@ -8,7 +8,7 @@ use crate::{
trash::{TrashIdentifiers, TrashType},
view::{CreateViewParams, RepeatedView, UpdateViewParams, View, ViewIdentifier},
},
errors::{internal_error, WorkspaceError, WorkspaceResult},
errors::{internal_error, FlowyError, FlowyResult},
module::{WorkspaceDatabase, WorkspaceUser},
notify::{send_dart_notification, WorkspaceNotification},
services::{
@ -49,23 +49,23 @@ impl ViewController {
}
}
pub(crate) fn init(&self) -> Result<(), WorkspaceError> {
pub(crate) fn init(&self) -> Result<(), FlowyError> {
let _ = self.document.init()?;
self.listen_trash_can_event();
Ok(())
}
#[tracing::instrument(level = "debug", skip(self, params), fields(name = %params.name), err)]
pub(crate) async fn create_view_from_params(&self, params: CreateViewParams) -> Result<View, WorkspaceError> {
pub(crate) async fn create_view_from_params(&self, params: CreateViewParams) -> Result<View, FlowyError> {
let view = self.create_view_on_server(params.clone()).await?;
self.create_view(view).await
}
pub(crate) async fn create_view(&self, view: View) -> Result<View, WorkspaceError> {
pub(crate) async fn create_view(&self, view: View) -> Result<View, FlowyError> {
let conn = &*self.database.db_connection()?;
let trash_can = self.trash_can.clone();
conn.immediate_transaction::<_, WorkspaceError, _>(|| {
conn.immediate_transaction::<_, FlowyError, _>(|| {
let _ = self.save_view(view.clone(), conn)?;
let _ = notify_views_changed(&view.belong_to_id, trash_can, &conn)?;
@ -75,20 +75,20 @@ impl ViewController {
Ok(view)
}
pub(crate) fn save_view(&self, view: View, conn: &SqliteConnection) -> Result<(), WorkspaceError> {
pub(crate) fn save_view(&self, view: View, conn: &SqliteConnection) -> Result<(), FlowyError> {
let view_table = ViewTable::new(view);
let _ = ViewTableSql::create_view(view_table, conn)?;
Ok(())
}
#[tracing::instrument(skip(self, params), fields(view_id = %params.view_id), err)]
pub(crate) async fn read_view(&self, params: ViewIdentifier) -> Result<View, WorkspaceError> {
pub(crate) async fn read_view(&self, params: ViewIdentifier) -> Result<View, FlowyError> {
let conn = self.database.db_connection()?;
let view_table = ViewTableSql::read_view(&params.view_id, &*conn)?;
let trash_ids = self.trash_can.trash_ids(&conn)?;
if trash_ids.contains(&view_table.id) {
return Err(WorkspaceError::record_not_found());
return Err(FlowyError::record_not_found());
}
let view: View = view_table.into();
@ -96,10 +96,10 @@ impl ViewController {
Ok(view)
}
pub(crate) fn read_view_tables(&self, ids: Vec<String>) -> Result<Vec<ViewTable>, WorkspaceError> {
pub(crate) fn read_view_tables(&self, ids: Vec<String>) -> Result<Vec<ViewTable>, FlowyError> {
let conn = &*self.database.db_connection()?;
let mut view_tables = vec![];
conn.immediate_transaction::<_, WorkspaceError, _>(|| {
conn.immediate_transaction::<_, FlowyError, _>(|| {
for view_id in ids {
view_tables.push(ViewTableSql::read_view(&view_id, conn)?);
}
@ -110,7 +110,7 @@ impl ViewController {
}
#[tracing::instrument(level = "debug", skip(self, params), fields(doc_id = %params.doc_id), err)]
pub(crate) async fn open_view(&self, params: DocIdentifier) -> Result<DocDelta, WorkspaceError> {
pub(crate) async fn open_view(&self, params: DocIdentifier) -> Result<DocDelta, FlowyError> {
let doc_id = params.doc_id.clone();
let edit_context = self.document.open(params).await?;
@ -119,13 +119,13 @@ impl ViewController {
}
#[tracing::instrument(level = "debug", skip(self,params), fields(doc_id = %params.doc_id), err)]
pub(crate) async fn close_view(&self, params: DocIdentifier) -> Result<(), WorkspaceError> {
pub(crate) async fn close_view(&self, params: DocIdentifier) -> Result<(), FlowyError> {
let _ = self.document.close(params).await?;
Ok(())
}
#[tracing::instrument(level = "debug", skip(self,params), fields(doc_id = %params.doc_id), err)]
pub(crate) async fn delete_view(&self, params: DocIdentifier) -> Result<(), WorkspaceError> {
pub(crate) async fn delete_view(&self, params: DocIdentifier) -> Result<(), FlowyError> {
if let Some(view_id) = KV::get_str(LATEST_VIEW_ID) {
if view_id == params.doc_id {
let _ = KV::remove(LATEST_VIEW_ID);
@ -136,7 +136,7 @@ impl ViewController {
}
#[tracing::instrument(level = "debug", skip(self, params), fields(doc_id = %params.doc_id), err)]
pub(crate) async fn duplicate_view(&self, params: DocIdentifier) -> Result<(), WorkspaceError> {
pub(crate) async fn duplicate_view(&self, params: DocIdentifier) -> Result<(), FlowyError> {
let view: View = ViewTableSql::read_view(&params.doc_id, &*self.database.db_connection()?)?.into();
let delta_data = self
.document
@ -157,7 +157,7 @@ impl ViewController {
}
#[tracing::instrument(level = "debug", skip(self, params), err)]
pub(crate) async fn export_doc(&self, params: ExportParams) -> Result<ExportData, WorkspaceError> {
pub(crate) async fn export_doc(&self, params: ExportParams) -> Result<ExportData, FlowyError> {
let doc_identifier: DocIdentifier = params.doc_id.into();
let doc = self
.document
@ -172,7 +172,7 @@ impl ViewController {
// belong_to_id will be the app_id or view_id.
#[tracing::instrument(level = "debug", skip(self), err)]
pub(crate) async fn read_views_belong_to(&self, belong_to_id: &str) -> Result<RepeatedView, WorkspaceError> {
pub(crate) async fn read_views_belong_to(&self, belong_to_id: &str) -> Result<RepeatedView, FlowyError> {
// TODO: read from server
let conn = self.database.db_connection()?;
let repeated_view = read_local_belonging_view(belong_to_id, self.trash_can.clone(), &conn)?;
@ -180,12 +180,12 @@ impl ViewController {
}
#[tracing::instrument(level = "debug", skip(self, params), err)]
pub(crate) async fn update_view(&self, params: UpdateViewParams) -> Result<View, WorkspaceError> {
pub(crate) async fn update_view(&self, params: UpdateViewParams) -> Result<View, FlowyError> {
let conn = &*self.database.db_connection()?;
let changeset = ViewTableChangeset::new(params.clone());
let view_id = changeset.id.clone();
let updated_view = conn.immediate_transaction::<_, WorkspaceError, _>(|| {
let updated_view = conn.immediate_transaction::<_, FlowyError, _>(|| {
let _ = ViewTableSql::update_view(changeset, conn)?;
let view: View = ViewTableSql::read_view(&view_id, conn)?.into();
Ok(view)
@ -201,12 +201,12 @@ impl ViewController {
Ok(updated_view)
}
pub(crate) async fn apply_doc_delta(&self, params: DocDelta) -> Result<DocDelta, WorkspaceError> {
pub(crate) async fn apply_doc_delta(&self, params: DocDelta) -> Result<DocDelta, FlowyError> {
let doc = self.document.apply_doc_delta(params).await?;
Ok(doc)
}
pub(crate) fn latest_visit_view(&self) -> WorkspaceResult<Option<View>> {
pub(crate) fn latest_visit_view(&self) -> FlowyResult<Option<View>> {
match KV::get_str(LATEST_VIEW_ID) {
None => Ok(None),
Some(view_id) => {
@ -222,14 +222,14 @@ impl ViewController {
impl ViewController {
#[tracing::instrument(skip(self), err)]
async fn create_view_on_server(&self, params: CreateViewParams) -> Result<View, WorkspaceError> {
async fn create_view_on_server(&self, params: CreateViewParams) -> Result<View, FlowyError> {
let token = self.user.token()?;
let view = self.server.create_view(&token, params).await?;
Ok(view)
}
#[tracing::instrument(skip(self), err)]
fn update_view_on_server(&self, params: UpdateViewParams) -> Result<(), WorkspaceError> {
fn update_view_on_server(&self, params: UpdateViewParams) -> Result<(), FlowyError> {
let token = self.user.token()?;
let server = self.server.clone();
tokio::spawn(async move {
@ -245,7 +245,7 @@ impl ViewController {
}
#[tracing::instrument(skip(self), err)]
fn read_view_on_server(&self, params: ViewIdentifier) -> Result<(), WorkspaceError> {
fn read_view_on_server(&self, params: ViewIdentifier) -> Result<(), FlowyError> {
let token = self.user.token()?;
let server = self.server.clone();
let pool = self.database.db_pool()?;
@ -314,7 +314,7 @@ async fn handle_trash_event(
let _ = notify_views_changed(&view_table.belong_to_id, trash_can.clone(), conn)?;
notify_dart(view_table, WorkspaceNotification::ViewDeleted);
}
Ok::<(), WorkspaceError>(())
Ok::<(), FlowyError>(())
};
let _ = ret.send(result()).await;
},
@ -326,14 +326,14 @@ async fn handle_trash_event(
let _ = notify_views_changed(&view_table.belong_to_id, trash_can.clone(), conn)?;
notify_dart(view_table, WorkspaceNotification::ViewRestored);
}
Ok::<(), WorkspaceError>(())
Ok::<(), FlowyError>(())
};
let _ = ret.send(result()).await;
},
TrashEvent::Delete(identifiers, ret) => {
let result = || {
let conn = &*db_result?;
let _ = conn.immediate_transaction::<_, WorkspaceError, _>(|| {
let _ = conn.immediate_transaction::<_, FlowyError, _>(|| {
let mut notify_ids = HashSet::new();
for identifier in identifiers.items {
let view_table = ViewTableSql::read_view(&identifier.id, conn)?;
@ -348,19 +348,16 @@ async fn handle_trash_event(
Ok(())
})?;
Ok::<(), WorkspaceError>(())
Ok::<(), FlowyError>(())
};
let _ = ret.send(result()).await;
},
}
}
fn get_view_table_from(
identifiers: TrashIdentifiers,
conn: &SqliteConnection,
) -> Result<Vec<ViewTable>, WorkspaceError> {
fn get_view_table_from(identifiers: TrashIdentifiers, conn: &SqliteConnection) -> Result<Vec<ViewTable>, FlowyError> {
let mut view_tables = vec![];
let _ = conn.immediate_transaction::<_, WorkspaceError, _>(|| {
let _ = conn.immediate_transaction::<_, FlowyError, _>(|| {
for identifier in identifiers.items {
let view_table = ViewTableSql::read_view(&identifier.id, conn)?;
view_tables.push(view_table);
@ -380,7 +377,7 @@ fn notify_views_changed(
belong_to_id: &str,
trash_can: Arc<TrashController>,
conn: &SqliteConnection,
) -> WorkspaceResult<()> {
) -> FlowyResult<()> {
let repeated_view = read_local_belonging_view(belong_to_id, trash_can.clone(), conn)?;
tracing::Span::current().record("view_count", &format!("{}", repeated_view.len()).as_str());
send_dart_notification(&belong_to_id, WorkspaceNotification::AppViewsChanged)
@ -393,7 +390,7 @@ fn read_local_belonging_view(
belong_to_id: &str,
trash_can: Arc<TrashController>,
conn: &SqliteConnection,
) -> WorkspaceResult<RepeatedView> {
) -> FlowyResult<RepeatedView> {
let mut view_tables = ViewTableSql::read_views(belong_to_id, conn)?;
let trash_ids = trash_can.trash_ids(conn)?;
view_tables.retain(|view_table| !trash_ids.contains(&view_table.id));

View File

@ -12,7 +12,7 @@ use crate::{
ViewIdentifiers,
},
},
errors::WorkspaceError,
errors::FlowyError,
services::{TrashController, ViewController},
};
use flowy_collaboration::entities::doc::DocDelta;
@ -23,7 +23,7 @@ use std::{convert::TryInto, sync::Arc};
pub(crate) async fn create_view_handler(
data: Data<CreateViewRequest>,
controller: Unit<Arc<ViewController>>,
) -> DataResult<View, WorkspaceError> {
) -> DataResult<View, FlowyError> {
let params: CreateViewParams = data.into_inner().try_into()?;
let view = controller.create_view_from_params(params).await?;
data_result(view)
@ -32,7 +32,7 @@ pub(crate) async fn create_view_handler(
pub(crate) async fn read_view_handler(
data: Data<QueryViewRequest>,
controller: Unit<Arc<ViewController>>,
) -> DataResult<View, WorkspaceError> {
) -> DataResult<View, FlowyError> {
let params: ViewIdentifier = data.into_inner().try_into()?;
let mut view = controller.read_view(params.clone()).await?;
view.belongings = controller.read_views_belong_to(&params.view_id).await?;
@ -44,7 +44,7 @@ pub(crate) async fn read_view_handler(
pub(crate) async fn update_view_handler(
data: Data<UpdateViewRequest>,
controller: Unit<Arc<ViewController>>,
) -> Result<(), WorkspaceError> {
) -> Result<(), FlowyError> {
let params: UpdateViewParams = data.into_inner().try_into()?;
let _ = controller.update_view(params).await?;
@ -54,7 +54,7 @@ pub(crate) async fn update_view_handler(
pub(crate) async fn apply_doc_delta_handler(
data: Data<DocDelta>,
controller: Unit<Arc<ViewController>>,
) -> DataResult<DocDelta, WorkspaceError> {
) -> DataResult<DocDelta, FlowyError> {
// let params: DocDelta = data.into_inner().try_into()?;
let doc = controller.apply_doc_delta(data.into_inner()).await?;
data_result(doc)
@ -64,7 +64,7 @@ pub(crate) async fn delete_view_handler(
data: Data<QueryViewRequest>,
controller: Unit<Arc<ViewController>>,
trash_can: Unit<Arc<TrashController>>,
) -> Result<(), WorkspaceError> {
) -> Result<(), FlowyError> {
let params: ViewIdentifiers = data.into_inner().try_into()?;
for view_id in &params.view_ids {
let _ = controller.delete_view(view_id.into()).await;
@ -83,7 +83,7 @@ pub(crate) async fn delete_view_handler(
pub(crate) async fn open_view_handler(
data: Data<QueryViewRequest>,
controller: Unit<Arc<ViewController>>,
) -> DataResult<DocDelta, WorkspaceError> {
) -> DataResult<DocDelta, FlowyError> {
let params: ViewIdentifier = data.into_inner().try_into()?;
let doc = controller.open_view(params.into()).await?;
data_result(doc)
@ -92,7 +92,7 @@ pub(crate) async fn open_view_handler(
pub(crate) async fn close_view_handler(
data: Data<QueryViewRequest>,
controller: Unit<Arc<ViewController>>,
) -> Result<(), WorkspaceError> {
) -> Result<(), FlowyError> {
let params: ViewIdentifier = data.into_inner().try_into()?;
let _ = controller.close_view(params.into()).await?;
Ok(())
@ -102,7 +102,7 @@ pub(crate) async fn close_view_handler(
pub(crate) async fn duplicate_view_handler(
data: Data<QueryViewRequest>,
controller: Unit<Arc<ViewController>>,
) -> Result<(), WorkspaceError> {
) -> Result<(), FlowyError> {
let params: ViewIdentifier = data.into_inner().try_into()?;
let _ = controller.duplicate_view(params.into()).await?;
Ok(())
@ -112,7 +112,7 @@ pub(crate) async fn duplicate_view_handler(
pub(crate) async fn export_handler(
data: Data<ExportRequest>,
controller: Unit<Arc<ViewController>>,
) -> DataResult<ExportData, WorkspaceError> {
) -> DataResult<ExportData, FlowyError> {
let params: ExportParams = data.into_inner().try_into()?;
let data = controller.export_doc(params).await?;
data_result(data)

View File

@ -3,7 +3,7 @@ use crate::{
trash::{Trash, TrashType},
view::{RepeatedView, UpdateViewParams, View, ViewType},
},
errors::WorkspaceError,
errors::FlowyError,
services::app::sql::AppTable,
};
use diesel::sql_types::Integer;
@ -17,7 +17,7 @@ use lib_infra::timestamp;
pub struct ViewTableSql {}
impl ViewTableSql {
pub(crate) fn create_view(view_table: ViewTable, conn: &SqliteConnection) -> Result<(), WorkspaceError> {
pub(crate) fn create_view(view_table: ViewTable, conn: &SqliteConnection) -> Result<(), FlowyError> {
match diesel_record_count!(view_table, &view_table.id, conn) {
0 => diesel_insert_table!(view_table, &view_table, conn),
_ => {
@ -28,7 +28,7 @@ impl ViewTableSql {
Ok(())
}
pub(crate) fn read_view(view_id: &str, conn: &SqliteConnection) -> Result<ViewTable, WorkspaceError> {
pub(crate) fn read_view(view_id: &str, conn: &SqliteConnection) -> Result<ViewTable, FlowyError> {
// https://docs.diesel.rs/diesel/query_builder/struct.UpdateStatement.html
// let mut filter =
// dsl::view_table.filter(view_table::id.eq(view_id)).into_boxed();
@ -44,7 +44,7 @@ impl ViewTableSql {
}
// belong_to_id will be the app_id or view_id.
pub(crate) fn read_views(belong_to_id: &str, conn: &SqliteConnection) -> Result<Vec<ViewTable>, WorkspaceError> {
pub(crate) fn read_views(belong_to_id: &str, conn: &SqliteConnection) -> Result<Vec<ViewTable>, FlowyError> {
let view_tables = dsl::view_table
.filter(view_table::belong_to_id.eq(belong_to_id))
.order(view_table::create_time.asc())
@ -54,12 +54,12 @@ impl ViewTableSql {
Ok(view_tables)
}
pub(crate) fn update_view(changeset: ViewTableChangeset, conn: &SqliteConnection) -> Result<(), WorkspaceError> {
pub(crate) fn update_view(changeset: ViewTableChangeset, conn: &SqliteConnection) -> Result<(), FlowyError> {
diesel_update_table!(view_table, changeset, conn);
Ok(())
}
pub(crate) fn delete_view(view_id: &str, conn: &SqliteConnection) -> Result<(), WorkspaceError> {
pub(crate) fn delete_view(view_id: &str, conn: &SqliteConnection) -> Result<(), FlowyError> {
diesel_delete_table!(view_table, view_id, conn);
Ok(())
}
@ -69,7 +69,7 @@ impl ViewTableSql {
// belong_to_id: &str,
// is_trash: Option<bool>,
// conn: &SqliteConnection,
// ) -> Result<RepeatedView, WorkspaceError> {
// ) -> Result<RepeatedView, FlowyError> {
// let views = dsl::view_table
// .inner_join(trash_table::dsl::trash_table.on(trash_id.ne(view_table::
// id))) .filter(view_table::belong_to_id.eq(belong_to_id))

View File

@ -35,17 +35,17 @@ impl WorkspaceController {
}
}
pub(crate) fn init(&self) -> Result<(), WorkspaceError> { Ok(()) }
pub(crate) fn init(&self) -> Result<(), FlowyError> { Ok(()) }
pub(crate) async fn create_workspace_from_params(
&self,
params: CreateWorkspaceParams,
) -> Result<Workspace, WorkspaceError> {
) -> Result<Workspace, FlowyError> {
let workspace = self.create_workspace_on_server(params.clone()).await?;
self.create_workspace(workspace).await
}
pub(crate) async fn create_workspace(&self, workspace: Workspace) -> Result<Workspace, WorkspaceError> {
pub(crate) async fn create_workspace(&self, workspace: Workspace) -> Result<Workspace, FlowyError> {
let user_id = self.user.user_id()?;
let token = self.user.token()?;
let workspace_table = WorkspaceTable::new(workspace.clone(), &user_id);
@ -61,7 +61,7 @@ impl WorkspaceController {
// immediately. EXCLUSIVE and IMMEDIATE are the same in WAL mode, but in
// other journaling modes, EXCLUSIVE prevents other database connections from
// reading the database while the transaction is underway.
conn.immediate_transaction::<_, WorkspaceError, _>(|| {
conn.immediate_transaction::<_, FlowyError, _>(|| {
WorkspaceTableSql::create_workspace(workspace_table, conn)?;
let repeated_workspace = self.read_local_workspaces(None, &user_id, conn)?;
send_dart_notification(&token, WorkspaceNotification::UserCreateWorkspace)
@ -77,11 +77,11 @@ impl WorkspaceController {
}
#[allow(dead_code)]
pub(crate) async fn update_workspace(&self, params: UpdateWorkspaceParams) -> Result<(), WorkspaceError> {
pub(crate) async fn update_workspace(&self, params: UpdateWorkspaceParams) -> Result<(), FlowyError> {
let changeset = WorkspaceTableChangeset::new(params.clone());
let workspace_id = changeset.id.clone();
let conn = &*self.database.db_connection()?;
conn.immediate_transaction::<_, WorkspaceError, _>(|| {
conn.immediate_transaction::<_, FlowyError, _>(|| {
let _ = WorkspaceTableSql::update_workspace(changeset, conn)?;
let user_id = self.user.user_id()?;
let workspace = self.read_local_workspace(workspace_id.clone(), &user_id, conn)?;
@ -98,11 +98,11 @@ impl WorkspaceController {
}
#[allow(dead_code)]
pub(crate) async fn delete_workspace(&self, workspace_id: &str) -> Result<(), WorkspaceError> {
pub(crate) async fn delete_workspace(&self, workspace_id: &str) -> Result<(), FlowyError> {
let user_id = self.user.user_id()?;
let token = self.user.token()?;
let conn = &*self.database.db_connection()?;
conn.immediate_transaction::<_, WorkspaceError, _>(|| {
conn.immediate_transaction::<_, FlowyError, _>(|| {
let _ = WorkspaceTableSql::delete_workspace(workspace_id, conn)?;
let repeated_workspace = self.read_local_workspaces(None, &user_id, conn)?;
send_dart_notification(&token, WorkspaceNotification::UserDeleteWorkspace)
@ -116,7 +116,7 @@ impl WorkspaceController {
Ok(())
}
pub(crate) async fn open_workspace(&self, params: WorkspaceIdentifier) -> Result<Workspace, WorkspaceError> {
pub(crate) async fn open_workspace(&self, params: WorkspaceIdentifier) -> Result<Workspace, FlowyError> {
let user_id = self.user.user_id()?;
let conn = self.database.db_connection()?;
if let Some(workspace_id) = params.workspace_id {
@ -124,11 +124,11 @@ impl WorkspaceController {
set_current_workspace(&workspace.id);
Ok(workspace)
} else {
return Err(WorkspaceError::workspace_id().context("Opened workspace id should not be empty"));
return Err(FlowyError::workspace_id().context("Opened workspace id should not be empty"));
}
}
pub(crate) async fn read_current_workspace_apps(&self) -> Result<RepeatedApp, WorkspaceError> {
pub(crate) async fn read_current_workspace_apps(&self) -> Result<RepeatedApp, FlowyError> {
let workspace_id = get_current_workspace()?;
let conn = self.database.db_connection()?;
let repeated_app = self.read_local_apps(&workspace_id, &*conn)?;
@ -142,7 +142,7 @@ impl WorkspaceController {
workspace_id: Option<String>,
user_id: &str,
conn: &SqliteConnection,
) -> Result<RepeatedWorkspace, WorkspaceError> {
) -> Result<RepeatedWorkspace, FlowyError> {
let workspace_id = workspace_id.to_owned();
let workspace_tables = WorkspaceTableSql::read_workspaces(workspace_id, user_id, conn)?;
@ -159,11 +159,11 @@ impl WorkspaceController {
workspace_id: String,
user_id: &str,
conn: &SqliteConnection,
) -> Result<Workspace, WorkspaceError> {
) -> Result<Workspace, FlowyError> {
// Opti: fetch single workspace from local db
let mut repeated_workspace = self.read_local_workspaces(Some(workspace_id.clone()), user_id, conn)?;
if repeated_workspace.is_empty() {
return Err(WorkspaceError::record_not_found().context(format!("{} workspace not found", workspace_id)));
return Err(FlowyError::record_not_found().context(format!("{} workspace not found", workspace_id)));
}
debug_assert_eq!(repeated_workspace.len(), 1);
@ -172,7 +172,7 @@ impl WorkspaceController {
}
#[tracing::instrument(level = "debug", skip(self, conn), err)]
fn read_local_apps(&self, workspace_id: &str, conn: &SqliteConnection) -> Result<RepeatedApp, WorkspaceError> {
fn read_local_apps(&self, workspace_id: &str, conn: &SqliteConnection) -> Result<RepeatedApp, FlowyError> {
let repeated_app = read_local_workspace_apps(workspace_id, self.trash_controller.clone(), conn)?;
Ok(repeated_app)
}
@ -180,14 +180,14 @@ impl WorkspaceController {
impl WorkspaceController {
#[tracing::instrument(level = "debug", skip(self), err)]
async fn create_workspace_on_server(&self, params: CreateWorkspaceParams) -> Result<Workspace, WorkspaceError> {
async fn create_workspace_on_server(&self, params: CreateWorkspaceParams) -> Result<Workspace, FlowyError> {
let token = self.user.token()?;
let workspace = self.server.create_workspace(&token, params).await?;
Ok(workspace)
}
#[tracing::instrument(level = "debug", skip(self), err)]
fn update_workspace_on_server(&self, params: UpdateWorkspaceParams) -> Result<(), WorkspaceError> {
fn update_workspace_on_server(&self, params: UpdateWorkspaceParams) -> Result<(), FlowyError> {
let (token, server) = (self.user.token()?, self.server.clone());
tokio::spawn(async move {
match server.update_workspace(&token, params).await {
@ -202,7 +202,7 @@ impl WorkspaceController {
}
#[tracing::instrument(level = "debug", skip(self), err)]
fn delete_workspace_on_server(&self, workspace_id: &str) -> Result<(), WorkspaceError> {
fn delete_workspace_on_server(&self, workspace_id: &str) -> Result<(), FlowyError> {
let params = WorkspaceIdentifier {
workspace_id: Some(workspace_id.to_string()),
};
@ -224,10 +224,12 @@ const CURRENT_WORKSPACE_ID: &str = "current_workspace_id";
fn set_current_workspace(workspace_id: &str) { KV::set_str(CURRENT_WORKSPACE_ID, workspace_id.to_owned()); }
pub fn get_current_workspace() -> Result<String, WorkspaceError> {
pub fn get_current_workspace() -> Result<String, FlowyError> {
match KV::get_str(CURRENT_WORKSPACE_ID) {
None => Err(WorkspaceError::record_not_found()
.context("Current workspace not found or should call open workspace first")),
None => {
Err(FlowyError::record_not_found()
.context("Current workspace not found or should call open workspace first"))
},
Some(workspace_id) => Ok(workspace_id),
}
}

View File

@ -1,4 +1,4 @@
use crate::{errors::WorkspaceError, services::WorkspaceController};
use crate::{errors::FlowyError, services::WorkspaceController};
use flowy_core_infra::entities::{app::RepeatedApp, workspace::*};
use lib_dispatch::prelude::{data_result, Data, DataResult, Unit};
@ -8,7 +8,7 @@ use std::{convert::TryInto, sync::Arc};
pub(crate) async fn create_workspace_handler(
data: Data<CreateWorkspaceRequest>,
controller: Unit<Arc<WorkspaceController>>,
) -> DataResult<Workspace, WorkspaceError> {
) -> DataResult<Workspace, FlowyError> {
let controller = controller.get_ref().clone();
let params: CreateWorkspaceParams = data.into_inner().try_into()?;
let detail = controller.create_workspace_from_params(params).await?;
@ -18,7 +18,7 @@ pub(crate) async fn create_workspace_handler(
#[tracing::instrument(skip(controller), err)]
pub(crate) async fn read_workspace_apps_handler(
controller: Unit<Arc<WorkspaceController>>,
) -> DataResult<RepeatedApp, WorkspaceError> {
) -> DataResult<RepeatedApp, FlowyError> {
let repeated_app = controller.read_current_workspace_apps().await?;
data_result(repeated_app)
}
@ -27,7 +27,7 @@ pub(crate) async fn read_workspace_apps_handler(
pub(crate) async fn open_workspace_handler(
data: Data<QueryWorkspaceRequest>,
controller: Unit<Arc<WorkspaceController>>,
) -> DataResult<Workspace, WorkspaceError> {
) -> DataResult<Workspace, FlowyError> {
let params: WorkspaceIdentifier = data.into_inner().try_into()?;
let workspaces = controller.open_workspace(params).await?;
data_result(workspaces)

View File

@ -3,7 +3,7 @@ use crate::{
app::RepeatedApp,
workspace::{UpdateWorkspaceParams, Workspace},
},
errors::WorkspaceError,
errors::FlowyError,
};
use diesel::SqliteConnection;
use flowy_database::{
@ -13,7 +13,7 @@ use flowy_database::{
pub(crate) struct WorkspaceTableSql {}
impl WorkspaceTableSql {
pub(crate) fn create_workspace(table: WorkspaceTable, conn: &SqliteConnection) -> Result<(), WorkspaceError> {
pub(crate) fn create_workspace(table: WorkspaceTable, conn: &SqliteConnection) -> Result<(), FlowyError> {
match diesel_record_count!(workspace_table, &table.id, conn) {
0 => diesel_insert_table!(workspace_table, &table, conn),
_ => {
@ -28,7 +28,7 @@ impl WorkspaceTableSql {
workspace_id: Option<String>,
user_id: &str,
conn: &SqliteConnection,
) -> Result<Vec<WorkspaceTable>, WorkspaceError> {
) -> Result<Vec<WorkspaceTable>, FlowyError> {
let mut filter = dsl::workspace_table
.filter(workspace_table::user_id.eq(user_id))
.order(workspace_table::create_time.asc())
@ -47,13 +47,13 @@ impl WorkspaceTableSql {
pub(crate) fn update_workspace(
changeset: WorkspaceTableChangeset,
conn: &SqliteConnection,
) -> Result<(), WorkspaceError> {
) -> Result<(), FlowyError> {
diesel_update_table!(workspace_table, changeset, conn);
Ok(())
}
#[allow(dead_code)]
pub(crate) fn delete_workspace(workspace_id: &str, conn: &SqliteConnection) -> Result<(), WorkspaceError> {
pub(crate) fn delete_workspace(workspace_id: &str, conn: &SqliteConnection) -> Result<(), FlowyError> {
diesel_delete_table!(workspace_table, workspace_id, conn);
Ok(())
}

View File

@ -9,17 +9,17 @@ edition = "2018"
[dependencies]
flowy-collaboration = { path = "../../../shared-lib/flowy-collaboration" }
flowy-derive = { path = "../../../shared-lib/flowy-derive" }
backend-service = { path = "../../../shared-lib/backend-service" }
lib-ot = { path = "../../../shared-lib/lib-ot" }
lib-ws = { path = "../../../shared-lib/lib-ws" }
backend-service = { path = "../../../shared-lib/backend-service" }
lib-infra = { path = "../../../shared-lib/lib-infra" }
derive_more = {version = "0.99", features = ["display"]}
lib-dispatch = { path = "../lib-dispatch" }
flowy-database = { path = "../flowy-database" }
flowy-error = { path = "../flowy-error", features = ["collaboration", "ot", "backend", "serde", "db"] }
dart-notify = { path = "../dart-notify" }
diesel = {version = "1.4.8", features = ["sqlite"]}
diesel_derives = {version = "1.4.1", features = ["sqlite"]}
protobuf = {version = "2.18.0"}

View File

@ -1,138 +0,0 @@
use backend_service::errors::ServerError;
use bytes::Bytes;
use derive_more::Display;
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
use lib_dispatch::prelude::{EventResponse, ResponseBuilder};
use std::{convert::TryInto, fmt};
pub type DocResult<T> = std::result::Result<T, DocError>;
#[derive(Debug, Default, Clone, ProtoBuf)]
pub struct DocError {
#[pb(index = 1)]
pub code: ErrorCode,
#[pb(index = 2)]
pub msg: String,
}
macro_rules! static_doc_error {
($name:ident, $status:expr) => {
#[allow(non_snake_case, missing_docs)]
pub fn $name() -> DocError {
DocError {
code: $status,
msg: format!("{}", $status),
}
}
};
}
impl DocError {
fn new(code: ErrorCode, msg: &str) -> Self {
Self {
code,
msg: msg.to_owned(),
}
}
pub fn context<T: Debug>(mut self, error: T) -> Self {
self.msg = format!("{:?}", error);
self
}
pub fn is_record_not_found(&self) -> bool { self.code == ErrorCode::DocNotfound }
static_doc_error!(ws, ErrorCode::WsConnectError);
static_doc_error!(internal, ErrorCode::InternalError);
static_doc_error!(unauthorized, ErrorCode::UserUnauthorized);
static_doc_error!(doc_not_found, ErrorCode::DocNotfound);
static_doc_error!(duplicate_rev, ErrorCode::DuplicateRevision);
}
pub fn internal_error<T>(e: T) -> DocError
where
T: std::fmt::Debug,
{
DocError::internal().context(e)
}
#[derive(Debug, Clone, ProtoBuf_Enum, Display, PartialEq, Eq)]
pub enum ErrorCode {
#[display(fmt = "Document websocket error")]
WsConnectError = 0,
#[display(fmt = "DocNotfound")]
DocNotfound = 1,
#[display(fmt = "Duplicate revision")]
DuplicateRevision = 2,
#[display(fmt = "UserUnauthorized")]
UserUnauthorized = 10,
#[display(fmt = "InternalError")]
InternalError = 1000,
}
impl std::default::Default for ErrorCode {
fn default() -> Self { ErrorCode::InternalError }
}
impl std::convert::From<flowy_database::Error> for DocError {
fn from(error: flowy_database::Error) -> Self {
match error {
flowy_database::Error::NotFound => DocError::doc_not_found().context(error),
_ => DocError::internal().context(error),
}
}
}
impl std::convert::From<lib_ot::errors::OTError> for DocError {
fn from(error: lib_ot::errors::OTError) -> Self { DocError::internal().context(error) }
}
impl std::convert::From<flowy_collaboration::errors::CollaborateError> for DocError {
fn from(error: flowy_collaboration::errors::CollaborateError) -> Self { DocError::internal().context(error) }
}
impl std::convert::From<std::io::Error> for DocError {
fn from(error: std::io::Error) -> Self { DocError::internal().context(error) }
}
impl std::convert::From<serde_json::Error> for DocError {
fn from(error: serde_json::Error) -> Self { DocError::internal().context(error) }
}
impl std::convert::From<protobuf::ProtobufError> for DocError {
fn from(e: protobuf::ProtobufError) -> Self { DocError::internal().context(e) }
}
impl std::convert::From<backend_service::errors::ServerError> for DocError {
fn from(error: ServerError) -> Self {
let code = server_error_to_doc_error(error.code);
DocError::new(code, &error.msg)
}
}
use backend_service::errors::ErrorCode as ServerErrorCode;
use std::fmt::Debug;
fn server_error_to_doc_error(code: ServerErrorCode) -> ErrorCode {
match code {
ServerErrorCode::UserUnauthorized => ErrorCode::UserUnauthorized,
ServerErrorCode::RecordNotFound => ErrorCode::DocNotfound,
_ => ErrorCode::InternalError,
}
}
impl lib_dispatch::Error for DocError {
fn as_response(&self) -> EventResponse {
let bytes: Bytes = self.clone().try_into().unwrap();
ResponseBuilder::Err().data(bytes).build()
}
}
impl fmt::Display for DocError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}: {}", &self.code, &self.msg) }
}

View File

@ -1,4 +1,3 @@
pub mod errors;
pub mod module;
mod notify;
pub mod protobuf;
@ -7,3 +6,7 @@ mod sql_tables;
#[macro_use]
extern crate flowy_database;
pub mod errors {
pub use flowy_error::{internal_error, ErrorCode, FlowyError};
}

View File

@ -1,5 +1,5 @@
use crate::{
errors::DocError,
errors::FlowyError,
services::{
doc::{controller::DocController, edit::ClientDocEditor},
server::construct_doc_server,
@ -12,10 +12,10 @@ use flowy_database::ConnectionPool;
use std::sync::Arc;
pub trait DocumentUser: Send + Sync {
fn user_dir(&self) -> Result<String, DocError>;
fn user_id(&self) -> Result<String, DocError>;
fn token(&self) -> Result<String, DocError>;
fn db_pool(&self) -> Result<Arc<ConnectionPool>, DocError>;
fn user_dir(&self) -> Result<String, FlowyError>;
fn user_id(&self) -> Result<String, FlowyError>;
fn token(&self) -> Result<String, FlowyError>;
fn db_pool(&self) -> Result<Arc<ConnectionPool>, FlowyError>;
}
pub struct FlowyDocument {
@ -34,22 +34,22 @@ impl FlowyDocument {
Self { doc_ctrl, user }
}
pub fn init(&self) -> Result<(), DocError> {
pub fn init(&self) -> Result<(), FlowyError> {
let _ = self.doc_ctrl.init()?;
Ok(())
}
pub fn delete(&self, params: DocIdentifier) -> Result<(), DocError> {
pub fn delete(&self, params: DocIdentifier) -> Result<(), FlowyError> {
let _ = self.doc_ctrl.delete(params)?;
Ok(())
}
pub async fn open(&self, params: DocIdentifier) -> Result<Arc<ClientDocEditor>, DocError> {
pub async fn open(&self, params: DocIdentifier) -> Result<Arc<ClientDocEditor>, FlowyError> {
let edit_context = self.doc_ctrl.open(params, self.user.db_pool()?).await?;
Ok(edit_context)
}
pub async fn close(&self, params: DocIdentifier) -> Result<(), DocError> {
pub async fn close(&self, params: DocIdentifier) -> Result<(), FlowyError> {
let _ = self.doc_ctrl.close(&params.doc_id)?;
Ok(())
}
@ -58,13 +58,13 @@ impl FlowyDocument {
&self,
params: DocIdentifier,
pool: Arc<ConnectionPool>,
) -> Result<DocDelta, DocError> {
) -> Result<DocDelta, FlowyError> {
let edit_context = self.doc_ctrl.open(params, pool).await?;
let delta = edit_context.delta().await?;
Ok(delta)
}
pub async fn apply_doc_delta(&self, params: DocDelta) -> Result<DocDelta, DocError> {
pub async fn apply_doc_delta(&self, params: DocDelta) -> Result<DocDelta, FlowyError> {
// workaround: compare the rust's delta with flutter's delta. Will be removed
// very soon
let doc = self

View File

@ -1,312 +0,0 @@
// This file is generated by rust-protobuf 2.22.1. Do not edit
// @generated
// https://github.com/rust-lang/rust-clippy/issues/702
#![allow(unknown_lints)]
#![allow(clippy::all)]
#![allow(unused_attributes)]
#![cfg_attr(rustfmt, rustfmt::skip)]
#![allow(box_pointers)]
#![allow(dead_code)]
#![allow(missing_docs)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(trivial_casts)]
#![allow(unused_imports)]
#![allow(unused_results)]
//! Generated file from `errors.proto`
/// Generated files are compatible only with the same version
/// of protobuf runtime.
// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_22_1;
#[derive(PartialEq,Clone,Default)]
pub struct DocError {
// message fields
pub code: ErrorCode,
pub msg: ::std::string::String,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize,
}
impl<'a> ::std::default::Default for &'a DocError {
fn default() -> &'a DocError {
<DocError as ::protobuf::Message>::default_instance()
}
}
impl DocError {
pub fn new() -> DocError {
::std::default::Default::default()
}
// .ErrorCode code = 1;
pub fn get_code(&self) -> ErrorCode {
self.code
}
pub fn clear_code(&mut self) {
self.code = ErrorCode::WsConnectError;
}
// Param is passed by value, moved
pub fn set_code(&mut self, v: ErrorCode) {
self.code = v;
}
// string msg = 2;
pub fn get_msg(&self) -> &str {
&self.msg
}
pub fn clear_msg(&mut self) {
self.msg.clear();
}
// Param is passed by value, moved
pub fn set_msg(&mut self, v: ::std::string::String) {
self.msg = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_msg(&mut self) -> &mut ::std::string::String {
&mut self.msg
}
// Take field
pub fn take_msg(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.msg, ::std::string::String::new())
}
}
impl ::protobuf::Message for DocError {
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
while !is.eof()? {
let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number {
1 => {
::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.code, 1, &mut self.unknown_fields)?
},
2 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.msg)?;
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
if self.code != ErrorCode::WsConnectError {
my_size += ::protobuf::rt::enum_size(1, self.code);
}
if !self.msg.is_empty() {
my_size += ::protobuf::rt::string_size(2, &self.msg);
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
if self.code != ErrorCode::WsConnectError {
os.write_enum(1, ::protobuf::ProtobufEnum::value(&self.code))?;
}
if !self.msg.is_empty() {
os.write_string(2, &self.msg)?;
}
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
}
fn get_cached_size(&self) -> u32 {
self.cached_size.get()
}
fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
&self.unknown_fields
}
fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
&mut self.unknown_fields
}
fn as_any(&self) -> &dyn (::std::any::Any) {
self as &dyn (::std::any::Any)
}
fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
self as &mut dyn (::std::any::Any)
}
fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
self
}
fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
Self::descriptor_static()
}
fn new() -> DocError {
DocError::new()
}
fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
descriptor.get(|| {
let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum<ErrorCode>>(
"code",
|m: &DocError| { &m.code },
|m: &mut DocError| { &mut m.code },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"msg",
|m: &DocError| { &m.msg },
|m: &mut DocError| { &mut m.msg },
));
::protobuf::reflect::MessageDescriptor::new_pb_name::<DocError>(
"DocError",
fields,
file_descriptor_proto()
)
})
}
fn default_instance() -> &'static DocError {
static instance: ::protobuf::rt::LazyV2<DocError> = ::protobuf::rt::LazyV2::INIT;
instance.get(DocError::new)
}
}
impl ::protobuf::Clear for DocError {
fn clear(&mut self) {
self.code = ErrorCode::WsConnectError;
self.msg.clear();
self.unknown_fields.clear();
}
}
impl ::std::fmt::Debug for DocError {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for DocError {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Message(self)
}
}
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
pub enum ErrorCode {
WsConnectError = 0,
DocNotfound = 1,
DuplicateRevision = 2,
UserUnauthorized = 10,
InternalError = 1000,
}
impl ::protobuf::ProtobufEnum for ErrorCode {
fn value(&self) -> i32 {
*self as i32
}
fn from_i32(value: i32) -> ::std::option::Option<ErrorCode> {
match value {
0 => ::std::option::Option::Some(ErrorCode::WsConnectError),
1 => ::std::option::Option::Some(ErrorCode::DocNotfound),
2 => ::std::option::Option::Some(ErrorCode::DuplicateRevision),
10 => ::std::option::Option::Some(ErrorCode::UserUnauthorized),
1000 => ::std::option::Option::Some(ErrorCode::InternalError),
_ => ::std::option::Option::None
}
}
fn values() -> &'static [Self] {
static values: &'static [ErrorCode] = &[
ErrorCode::WsConnectError,
ErrorCode::DocNotfound,
ErrorCode::DuplicateRevision,
ErrorCode::UserUnauthorized,
ErrorCode::InternalError,
];
values
}
fn enum_descriptor_static() -> &'static ::protobuf::reflect::EnumDescriptor {
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::EnumDescriptor> = ::protobuf::rt::LazyV2::INIT;
descriptor.get(|| {
::protobuf::reflect::EnumDescriptor::new_pb_name::<ErrorCode>("ErrorCode", file_descriptor_proto())
})
}
}
impl ::std::marker::Copy for ErrorCode {
}
impl ::std::default::Default for ErrorCode {
fn default() -> Self {
ErrorCode::WsConnectError
}
}
impl ::protobuf::reflect::ProtobufValue for ErrorCode {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self))
}
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x0cerrors.proto\"<\n\x08DocError\x12\x1e\n\x04code\x18\x01\x20\x01(\
\x0e2\n.ErrorCodeR\x04code\x12\x10\n\x03msg\x18\x02\x20\x01(\tR\x03msg*q\
\n\tErrorCode\x12\x12\n\x0eWsConnectError\x10\0\x12\x0f\n\x0bDocNotfound\
\x10\x01\x12\x15\n\x11DuplicateRevision\x10\x02\x12\x14\n\x10UserUnautho\
rized\x10\n\x12\x12\n\rInternalError\x10\xe8\x07J\xfd\x02\n\x06\x12\x04\
\0\0\x0c\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\
\0\x05\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x10\n\x0b\n\x04\x04\0\x02\
\0\x12\x03\x03\x04\x17\n\x0c\n\x05\x04\0\x02\0\x06\x12\x03\x03\x04\r\n\
\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\x0e\x12\n\x0c\n\x05\x04\0\x02\0\
\x03\x12\x03\x03\x15\x16\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x04\x04\x13\n\
\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\x04\n\n\x0c\n\x05\x04\0\x02\x01\
\x01\x12\x03\x04\x0b\x0e\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x04\x11\
\x12\n\n\n\x02\x05\0\x12\x04\x06\0\x0c\x01\n\n\n\x03\x05\0\x01\x12\x03\
\x06\x05\x0e\n\x0b\n\x04\x05\0\x02\0\x12\x03\x07\x04\x17\n\x0c\n\x05\x05\
\0\x02\0\x01\x12\x03\x07\x04\x12\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x07\
\x15\x16\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x08\x04\x14\n\x0c\n\x05\x05\0\
\x02\x01\x01\x12\x03\x08\x04\x0f\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\
\x08\x12\x13\n\x0b\n\x04\x05\0\x02\x02\x12\x03\t\x04\x1a\n\x0c\n\x05\x05\
\0\x02\x02\x01\x12\x03\t\x04\x15\n\x0c\n\x05\x05\0\x02\x02\x02\x12\x03\t\
\x18\x19\n\x0b\n\x04\x05\0\x02\x03\x12\x03\n\x04\x1a\n\x0c\n\x05\x05\0\
\x02\x03\x01\x12\x03\n\x04\x14\n\x0c\n\x05\x05\0\x02\x03\x02\x12\x03\n\
\x17\x19\n\x0b\n\x04\x05\0\x02\x04\x12\x03\x0b\x04\x19\n\x0c\n\x05\x05\0\
\x02\x04\x01\x12\x03\x0b\x04\x11\n\x0c\n\x05\x05\0\x02\x04\x02\x12\x03\
\x0b\x14\x18b\x06proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap()
}
pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
file_descriptor_proto_lazy.get(|| {
parse_descriptor_proto()
})
}

View File

@ -3,6 +3,3 @@
mod observable;
pub use observable::*;
mod errors;
pub use errors::*;

View File

@ -1,13 +0,0 @@
syntax = "proto3";
message DocError {
ErrorCode code = 1;
string msg = 2;
}
enum ErrorCode {
WsConnectError = 0;
DocNotfound = 1;
DuplicateRevision = 2;
UserUnauthorized = 10;
InternalError = 1000;
}

View File

@ -1,5 +1,5 @@
use crate::{
errors::{DocError, DocResult},
errors::FlowyError,
module::DocumentUser,
services::{
doc::{
@ -14,6 +14,7 @@ use bytes::Bytes;
use dashmap::DashMap;
use flowy_collaboration::entities::doc::{Doc, DocDelta, DocIdentifier};
use flowy_database::ConnectionPool;
use flowy_error::FlowyResult;
use lib_infra::future::FutureResult;
use std::sync::Arc;
@ -35,7 +36,7 @@ impl DocController {
}
}
pub(crate) fn init(&self) -> DocResult<()> {
pub(crate) fn init(&self) -> FlowyResult<()> {
self.ws_manager.init();
Ok(())
}
@ -44,7 +45,7 @@ impl DocController {
&self,
params: DocIdentifier,
pool: Arc<ConnectionPool>,
) -> Result<Arc<ClientDocEditor>, DocError> {
) -> Result<Arc<ClientDocEditor>, FlowyError> {
if !self.open_cache.contains(&params.doc_id) {
let edit_ctx = self.make_edit_context(&params.doc_id, pool.clone()).await?;
return Ok(edit_ctx);
@ -54,7 +55,7 @@ impl DocController {
Ok(edit_doc_ctx)
}
pub(crate) fn close(&self, doc_id: &str) -> Result<(), DocError> {
pub(crate) fn close(&self, doc_id: &str) -> Result<(), FlowyError> {
tracing::debug!("Close doc {}", doc_id);
self.open_cache.remove(doc_id);
self.ws_manager.remove_handler(doc_id);
@ -62,7 +63,7 @@ impl DocController {
}
#[tracing::instrument(level = "debug", skip(self), err)]
pub(crate) fn delete(&self, params: DocIdentifier) -> Result<(), DocError> {
pub(crate) fn delete(&self, params: DocIdentifier) -> Result<(), FlowyError> {
let doc_id = &params.doc_id;
self.open_cache.remove(doc_id);
self.ws_manager.remove_handler(doc_id);
@ -78,7 +79,7 @@ impl DocController {
&self,
delta: DocDelta,
db_pool: Arc<ConnectionPool>,
) -> Result<DocDelta, DocError> {
) -> Result<DocDelta, FlowyError> {
if !self.open_cache.contains(&delta.doc_id) {
let doc_identifier: DocIdentifier = delta.doc_id.clone().into();
let _ = self.open(doc_identifier, db_pool).await?;
@ -95,7 +96,7 @@ impl DocController {
&self,
doc_id: &str,
pool: Arc<ConnectionPool>,
) -> Result<Arc<ClientDocEditor>, DocError> {
) -> Result<Arc<ClientDocEditor>, FlowyError> {
let user = self.user.clone();
let rev_manager = self.make_rev_manager(doc_id, pool.clone())?;
let edit_ctx = ClientDocEditor::new(doc_id, user, pool, rev_manager, self.ws_manager.ws()).await?;
@ -105,7 +106,7 @@ impl DocController {
Ok(edit_ctx)
}
fn make_rev_manager(&self, doc_id: &str, pool: Arc<ConnectionPool>) -> Result<RevisionManager, DocError> {
fn make_rev_manager(&self, doc_id: &str, pool: Arc<ConnectionPool>) -> Result<RevisionManager, FlowyError> {
// Opti: require upgradable_read lock and then upgrade to write lock using
// RwLockUpgradableReadGuard::upgrade(xx) of ws
// let doc = self.read_doc(doc_id, pool.clone()).await?;
@ -128,7 +129,7 @@ struct RevisionServerImpl {
impl RevisionServer for RevisionServerImpl {
#[tracing::instrument(level = "debug", skip(self))]
fn fetch_document(&self, doc_id: &str) -> FutureResult<Doc, DocError> {
fn fetch_document(&self, doc_id: &str) -> FutureResult<Doc, FlowyError> {
let params = DocIdentifier {
doc_id: doc_id.to_string(),
};
@ -137,7 +138,7 @@ impl RevisionServer for RevisionServerImpl {
FutureResult::new(async move {
match server.read_doc(&token, params).await? {
None => Err(DocError::doc_not_found().context("Remote doesn't have this document")),
None => Err(FlowyError::record_not_found().context("Remote doesn't have this document")),
Some(doc) => Ok(doc),
}
})
@ -161,7 +162,7 @@ impl OpenDocCache {
pub(crate) fn contains(&self, doc_id: &str) -> bool { self.inner.get(doc_id).is_some() }
pub(crate) fn get(&self, doc_id: &str) -> Result<Arc<ClientDocEditor>, DocError> {
pub(crate) fn get(&self, doc_id: &str) -> Result<Arc<ClientDocEditor>, FlowyError> {
if !self.contains(&doc_id) {
return Err(doc_not_found());
}
@ -179,4 +180,6 @@ impl OpenDocCache {
}
}
fn doc_not_found() -> DocError { DocError::doc_not_found().context("Doc is close or you should call open first") }
fn doc_not_found() -> FlowyError {
FlowyError::record_not_found().context("Doc is close or you should call open first")
}

View File

@ -1,5 +1,5 @@
use crate::{
errors::{internal_error, DocError, DocResult},
errors::FlowyError,
module::DocumentUser,
services::{
doc::{
@ -16,6 +16,7 @@ use flowy_collaboration::{
errors::CollaborateResult,
};
use flowy_database::ConnectionPool;
use flowy_error::{internal_error, FlowyResult};
use lib_infra::retry::{ExponentialBackoff, Retry};
use lib_ot::{
core::Interval,
@ -45,7 +46,7 @@ impl ClientDocEditor {
pool: Arc<ConnectionPool>,
mut rev_manager: RevisionManager,
ws_sender: Arc<dyn DocumentWebSocket>,
) -> DocResult<Arc<Self>> {
) -> FlowyResult<Arc<Self>> {
let delta = rev_manager.load_document().await?;
let edit_cmd_tx = spawn_edit_queue(doc_id, delta, pool.clone());
let doc_id = doc_id.to_string();
@ -69,7 +70,7 @@ impl ClientDocEditor {
Ok(edit_doc)
}
pub async fn insert<T: ToString>(&self, index: usize, data: T) -> Result<(), DocError> {
pub async fn insert<T: ToString>(&self, index: usize, data: T) -> Result<(), FlowyError> {
let (ret, rx) = oneshot::channel::<CollaborateResult<RichTextDelta>>();
let msg = EditCommand::Insert {
index,
@ -82,7 +83,7 @@ impl ClientDocEditor {
Ok(())
}
pub async fn delete(&self, interval: Interval) -> Result<(), DocError> {
pub async fn delete(&self, interval: Interval) -> Result<(), FlowyError> {
let (ret, rx) = oneshot::channel::<CollaborateResult<RichTextDelta>>();
let msg = EditCommand::Delete { interval, ret };
let _ = self.edit_cmd_tx.send(msg);
@ -91,7 +92,7 @@ impl ClientDocEditor {
Ok(())
}
pub async fn format(&self, interval: Interval, attribute: RichTextAttribute) -> Result<(), DocError> {
pub async fn format(&self, interval: Interval, attribute: RichTextAttribute) -> Result<(), FlowyError> {
let (ret, rx) = oneshot::channel::<CollaborateResult<RichTextDelta>>();
let msg = EditCommand::Format {
interval,
@ -104,7 +105,7 @@ impl ClientDocEditor {
Ok(())
}
pub async fn replace<T: ToString>(&self, interval: Interval, data: T) -> Result<(), DocError> {
pub async fn replace<T: ToString>(&self, interval: Interval, data: T) -> Result<(), FlowyError> {
let (ret, rx) = oneshot::channel::<CollaborateResult<RichTextDelta>>();
let msg = EditCommand::Replace {
interval,
@ -131,7 +132,7 @@ impl ClientDocEditor {
rx.await.unwrap_or(false)
}
pub async fn undo(&self) -> Result<UndoResult, DocError> {
pub async fn undo(&self) -> Result<UndoResult, FlowyError> {
let (ret, rx) = oneshot::channel::<CollaborateResult<UndoResult>>();
let msg = EditCommand::Undo { ret };
let _ = self.edit_cmd_tx.send(msg);
@ -139,7 +140,7 @@ impl ClientDocEditor {
Ok(r)
}
pub async fn redo(&self) -> Result<UndoResult, DocError> {
pub async fn redo(&self) -> Result<UndoResult, FlowyError> {
let (ret, rx) = oneshot::channel::<CollaborateResult<UndoResult>>();
let msg = EditCommand::Redo { ret };
let _ = self.edit_cmd_tx.send(msg);
@ -147,7 +148,7 @@ impl ClientDocEditor {
Ok(r)
}
pub async fn delta(&self) -> DocResult<DocDelta> {
pub async fn delta(&self) -> FlowyResult<DocDelta> {
let (ret, rx) = oneshot::channel::<CollaborateResult<String>>();
let msg = EditCommand::ReadDoc { ret };
let _ = self.edit_cmd_tx.send(msg);
@ -159,7 +160,7 @@ impl ClientDocEditor {
})
}
async fn save_local_delta(&self, delta: RichTextDelta) -> Result<RevId, DocError> {
async fn save_local_delta(&self, delta: RichTextDelta) -> Result<RevId, FlowyError> {
let delta_data = delta.to_bytes();
let (base_rev_id, rev_id) = self.rev_manager.next_rev_id();
let delta_data = delta_data.to_vec();
@ -170,7 +171,7 @@ impl ClientDocEditor {
}
#[tracing::instrument(level = "debug", skip(self, data), err)]
pub(crate) async fn composing_local_delta(&self, data: Bytes) -> Result<(), DocError> {
pub(crate) async fn composing_local_delta(&self, data: Bytes) -> Result<(), FlowyError> {
let delta = RichTextDelta::from_bytes(&data)?;
let (ret, rx) = oneshot::channel::<CollaborateResult<()>>();
let msg = EditCommand::ComposeDelta {
@ -207,7 +208,7 @@ impl ClientDocEditor {
}
#[tracing::instrument(level = "debug", skip(self))]
pub(crate) async fn handle_push_rev(&self, bytes: Bytes) -> DocResult<()> {
pub(crate) async fn handle_push_rev(&self, bytes: Bytes) -> FlowyResult<()> {
// Transform the revision
let (ret, rx) = oneshot::channel::<CollaborateResult<TransformDeltas>>();
let _ = self.edit_cmd_tx.send(EditCommand::ProcessRemoteRevision { bytes, ret });
@ -262,7 +263,7 @@ impl ClientDocEditor {
Ok(())
}
pub async fn handle_ws_message(&self, doc_data: WsDocumentData) -> DocResult<()> {
pub async fn handle_ws_message(&self, doc_data: WsDocumentData) -> FlowyResult<()> {
match self.ws_msg_tx.send(doc_data) {
Ok(_) => {},
Err(e) => tracing::error!("❌Propagate ws message failed. {}", e),
@ -323,7 +324,7 @@ fn start_sync(
#[cfg(feature = "flowy_unit_test")]
impl ClientDocEditor {
pub async fn doc_json(&self) -> DocResult<String> {
pub async fn doc_json(&self) -> FlowyResult<String> {
let (ret, rx) = oneshot::channel::<CollaborateResult<String>>();
let msg = EditCommand::ReadDoc { ret };
let _ = self.edit_cmd_tx.send(msg);
@ -331,7 +332,7 @@ impl ClientDocEditor {
Ok(s)
}
pub async fn doc_delta(&self) -> DocResult<RichTextDelta> {
pub async fn doc_delta(&self) -> FlowyResult<RichTextDelta> {
let (ret, rx) = oneshot::channel::<CollaborateResult<RichTextDelta>>();
let msg = EditCommand::ReadDocDelta { ret };
let _ = self.edit_cmd_tx.send(msg);

View File

@ -1,6 +1,6 @@
#![allow(clippy::all)]
#![cfg_attr(rustfmt, rustfmt::skip)]
use crate::{errors::DocError, services::ws::DocumentWebSocket};
use crate::{errors::FlowyError, services::ws::DocumentWebSocket};
use futures::future::BoxFuture;
use lib_infra::retry::Action;
@ -29,7 +29,7 @@ impl OpenDocAction {
impl Action for OpenDocAction {
type Future = BoxFuture<'static, Result<Self::Item, Self::Error>>;
type Item = ();
type Error = DocError;
type Error = FlowyError;
fn run(&mut self) -> Self::Future {
// let new_doc_user = NewDocUser {
@ -42,6 +42,6 @@ impl Action for OpenDocAction {
// Ok(_) => Box::pin(future::ready(Ok::<(), DocError>(()))),
// Err(e) => Box::pin(future::ready(Err::<(), DocError>(e))),
// }
Box::pin(future::ready(Ok::<(), DocError>(())))
Box::pin(future::ready(Ok::<(), FlowyError>(())))
}
}

View File

@ -1,5 +1,5 @@
use crate::{
errors::{internal_error, DocError, DocResult},
errors::FlowyError,
services::doc::revision::{
cache::{disk::RevisionDiskCache, memory::RevisionMemoryCache},
RevisionRecord,
@ -9,6 +9,7 @@ use crate::{
};
use flowy_collaboration::entities::doc::Doc;
use flowy_database::ConnectionPool;
use flowy_error::{internal_error, FlowyResult};
use lib_infra::future::FutureResult;
use lib_ot::{
core::{Operation, OperationTransformable},
@ -22,10 +23,10 @@ use tokio::{
};
pub trait RevisionIterator: Send + Sync {
fn next(&self) -> FutureResult<Option<RevisionRecord>, DocError>;
fn next(&self) -> FutureResult<Option<RevisionRecord>, FlowyError>;
}
type DocRevisionDeskCache = dyn RevisionDiskCache<Error = DocError>;
type DocRevisionDeskCache = dyn RevisionDiskCache<Error = FlowyError>;
pub struct RevisionCache {
user_id: String,
@ -57,9 +58,9 @@ impl RevisionCache {
}
#[tracing::instrument(level = "debug", skip(self, revision))]
pub async fn add_local_revision(&self, revision: Revision) -> DocResult<()> {
pub async fn add_local_revision(&self, revision: Revision) -> FlowyResult<()> {
if self.memory_cache.contains(&revision.rev_id) {
return Err(DocError::duplicate_rev().context(format!("Duplicate revision id: {}", revision.rev_id)));
return Err(FlowyError::internal().context(format!("Duplicate revision id: {}", revision.rev_id)));
}
let record = RevisionRecord {
revision,
@ -71,9 +72,9 @@ impl RevisionCache {
}
#[tracing::instrument(level = "debug", skip(self, revision))]
pub async fn add_remote_revision(&self, revision: Revision) -> DocResult<()> {
pub async fn add_remote_revision(&self, revision: Revision) -> FlowyResult<()> {
if self.memory_cache.contains(&revision.rev_id) {
return Err(DocError::duplicate_rev().context(format!("Duplicate revision id: {}", revision.rev_id)));
return Err(FlowyError::internal().context(format!("Duplicate revision id: {}", revision.rev_id)));
}
let record = RevisionRecord {
revision,
@ -126,7 +127,7 @@ impl RevisionCache {
}));
}
pub async fn revisions_in_range(&self, range: RevisionRange) -> DocResult<Vec<Revision>> {
pub async fn revisions_in_range(&self, range: RevisionRange) -> FlowyResult<Vec<Revision>> {
let revs = self.memory_cache.revisions_in_range(&range).await?;
if revs.len() == range.len() as usize {
Ok(revs)
@ -145,7 +146,7 @@ impl RevisionCache {
}
}
pub async fn load_document(&self) -> DocResult<Doc> {
pub async fn load_document(&self) -> FlowyResult<Doc> {
// Loading the document from disk and it will be sync with server.
let result = load_from_disk(&self.doc_id, self.memory_cache.clone(), self.dish_cache.clone()).await;
if result.is_ok() {
@ -170,7 +171,7 @@ impl RevisionCache {
}
impl RevisionIterator for RevisionCache {
fn next(&self) -> FutureResult<Option<RevisionRecord>, DocError> {
fn next(&self) -> FutureResult<Option<RevisionRecord>, FlowyError> {
let memory_cache = self.memory_cache.clone();
let disk_cache = self.dish_cache.clone();
let doc_id = self.doc_id.clone();
@ -196,13 +197,13 @@ async fn load_from_disk(
doc_id: &str,
memory_cache: Arc<RevisionMemoryCache>,
disk_cache: Arc<DocRevisionDeskCache>,
) -> DocResult<Doc> {
) -> FlowyResult<Doc> {
let doc_id = doc_id.to_owned();
let (tx, mut rx) = mpsc::channel(2);
let doc = spawn_blocking(move || {
let records = disk_cache.read_revisions(&doc_id)?;
if records.is_empty() {
return Err(DocError::doc_not_found().context("Local doesn't have this document"));
return Err(FlowyError::record_not_found().context("Local doesn't have this document"));
}
let (base_rev_id, rev_id) = records.last().unwrap().revision.pair_rev_id();
@ -224,7 +225,7 @@ async fn load_from_disk(
}
correct_delta_if_need(&mut delta);
Result::<Doc, DocError>::Ok(Doc {
Result::<Doc, FlowyError>::Ok(Doc {
id: doc_id,
data: delta.to_json(),
rev_id,
@ -261,11 +262,11 @@ pub(crate) struct Persistence {
}
impl RevisionDiskCache for Persistence {
type Error = DocError;
type Error = FlowyError;
fn create_revisions(&self, revisions: Vec<RevisionRecord>) -> Result<(), Self::Error> {
let conn = &*self.pool.get().map_err(internal_error)?;
conn.immediate_transaction::<_, DocError, _>(|| {
conn.immediate_transaction::<_, FlowyError, _>(|| {
let _ = RevTableSql::create_rev_table(revisions, conn)?;
Ok(())
})

View File

@ -1,11 +1,12 @@
use crate::{
errors::{DocError, DocResult},
errors::FlowyError,
services::{
doc::revision::{RevisionCache, RevisionUpStream, SteamStopRx},
ws::DocumentWebSocket,
},
};
use flowy_collaboration::{entities::doc::Doc, util::RevIdCounter};
use flowy_error::FlowyResult;
use lib_infra::future::FutureResult;
use lib_ot::{
core::OperationTransformable,
@ -15,7 +16,7 @@ use lib_ot::{
use std::sync::Arc;
pub trait RevisionServer: Send + Sync {
fn fetch_document(&self, doc_id: &str) -> FutureResult<Doc, DocError>;
fn fetch_document(&self, doc_id: &str) -> FutureResult<Doc, FlowyError>;
}
pub struct RevisionManager {
@ -38,23 +39,23 @@ impl RevisionManager {
}
}
pub async fn load_document(&mut self) -> DocResult<RichTextDelta> {
pub async fn load_document(&mut self) -> FlowyResult<RichTextDelta> {
let doc = self.cache.load_document().await?;
self.update_rev_id_counter_value(doc.rev_id);
Ok(doc.delta()?)
}
pub async fn add_remote_revision(&self, revision: &Revision) -> Result<(), DocError> {
pub async fn add_remote_revision(&self, revision: &Revision) -> Result<(), FlowyError> {
let _ = self.cache.add_remote_revision(revision.clone()).await?;
Ok(())
}
pub async fn add_local_revision(&self, revision: &Revision) -> Result<(), DocError> {
pub async fn add_local_revision(&self, revision: &Revision) -> Result<(), FlowyError> {
let _ = self.cache.add_local_revision(revision.clone()).await?;
Ok(())
}
pub async fn ack_revision(&self, rev_id: RevId) -> Result<(), DocError> {
pub async fn ack_revision(&self, rev_id: RevId) -> Result<(), FlowyError> {
self.cache.ack_revision(rev_id.into()).await;
Ok(())
}
@ -69,7 +70,7 @@ impl RevisionManager {
pub fn update_rev_id_counter_value(&self, rev_id: i64) { self.rev_id_counter.set(rev_id); }
pub async fn mk_revisions(&self, range: RevisionRange) -> Result<Revision, DocError> {
pub async fn mk_revisions(&self, range: RevisionRange) -> Result<Revision, FlowyError> {
debug_assert!(range.doc_id == self.doc_id);
let revisions = self.cache.revisions_in_range(range.clone()).await?;
let mut new_delta = RichTextDelta::new();

View File

@ -1,16 +1,14 @@
use crate::{
errors::{internal_error, DocResult},
services::{
doc::{
edit::ClientDocEditor,
revision::{RevisionIterator, RevisionManager},
},
ws::DocumentWebSocket,
use crate::services::{
doc::{
edit::ClientDocEditor,
revision::{RevisionIterator, RevisionManager},
},
ws::DocumentWebSocket,
};
use async_stream::stream;
use bytes::Bytes;
use flowy_collaboration::entities::ws::{WsDataType, WsDocumentData};
use flowy_error::{internal_error, FlowyResult};
use futures::stream::StreamExt;
use lib_ot::revision::{RevId, RevisionRange};
use std::{convert::TryFrom, sync::Arc};
@ -81,7 +79,7 @@ impl RevisionDownStream {
.await;
}
async fn handle_message(&self, msg: WsDocumentData) -> DocResult<()> {
async fn handle_message(&self, msg: WsDocumentData) -> FlowyResult<()> {
let WsDocumentData { doc_id: _, ty, data } = msg;
let bytes = spawn_blocking(move || Bytes::from(data))
.await
@ -169,13 +167,13 @@ impl RevisionUpStream {
.await;
}
async fn handle_msg(&self, msg: UpStreamMsg) -> DocResult<()> {
async fn handle_msg(&self, msg: UpStreamMsg) -> FlowyResult<()> {
match msg {
UpStreamMsg::Tick => self.send_next_revision().await,
}
}
async fn send_next_revision(&self) -> DocResult<()> {
async fn send_next_revision(&self) -> FlowyResult<()> {
match self.revisions.next().await? {
None => Ok(()),
Some(record) => {

View File

@ -17,7 +17,7 @@ impl ResponseMiddleware for DocMiddleware {
None => {},
Some(_token) => {
// let error =
// WorkspaceError::new(ErrorCode::UserUnauthorized, "");
// FlowyError::new(ErrorCode::UserUnauthorized, "");
// observable(token,
// WorkspaceObservable::UserUnauthorized).error(error).
// build()

View File

@ -4,7 +4,7 @@ mod server_api_mock;
pub use server_api::*;
// TODO: ignore mock files in production
use crate::errors::DocError;
use crate::errors::FlowyError;
use backend_service::configuration::ClientServerConfiguration;
use flowy_collaboration::entities::doc::{CreateDocParams, Doc, DocIdentifier, UpdateDocParams};
use lib_infra::future::FutureResult;
@ -13,11 +13,11 @@ use std::sync::Arc;
pub(crate) type Server = Arc<dyn DocumentServerAPI + Send + Sync>;
pub trait DocumentServerAPI {
fn create_doc(&self, token: &str, params: CreateDocParams) -> FutureResult<(), DocError>;
fn create_doc(&self, token: &str, params: CreateDocParams) -> FutureResult<(), FlowyError>;
fn read_doc(&self, token: &str, params: DocIdentifier) -> FutureResult<Option<Doc>, DocError>;
fn read_doc(&self, token: &str, params: DocIdentifier) -> FutureResult<Option<Doc>, FlowyError>;
fn update_doc(&self, token: &str, params: UpdateDocParams) -> FutureResult<(), DocError>;
fn update_doc(&self, token: &str, params: UpdateDocParams) -> FutureResult<(), FlowyError>;
}
pub(crate) fn construct_doc_server(

View File

@ -1,4 +1,4 @@
use crate::{errors::DocError, services::server::DocumentServerAPI};
use crate::{errors::FlowyError, services::server::DocumentServerAPI};
use backend_service::{configuration::*, request::HttpRequestBuilder};
use flowy_collaboration::entities::doc::{CreateDocParams, Doc, DocIdentifier, UpdateDocParams};
use lib_infra::future::FutureResult;
@ -12,19 +12,19 @@ impl DocServer {
}
impl DocumentServerAPI for DocServer {
fn create_doc(&self, token: &str, params: CreateDocParams) -> FutureResult<(), DocError> {
fn create_doc(&self, token: &str, params: CreateDocParams) -> FutureResult<(), FlowyError> {
let token = token.to_owned();
let url = self.config.doc_url();
FutureResult::new(async move { create_doc_request(&token, params, &url).await })
}
fn read_doc(&self, token: &str, params: DocIdentifier) -> FutureResult<Option<Doc>, DocError> {
fn read_doc(&self, token: &str, params: DocIdentifier) -> FutureResult<Option<Doc>, FlowyError> {
let token = token.to_owned();
let url = self.config.doc_url();
FutureResult::new(async move { read_doc_request(&token, params, &url).await })
}
fn update_doc(&self, token: &str, params: UpdateDocParams) -> FutureResult<(), DocError> {
fn update_doc(&self, token: &str, params: UpdateDocParams) -> FutureResult<(), FlowyError> {
let token = token.to_owned();
let url = self.config.doc_url();
FutureResult::new(async move { update_doc_request(&token, params, &url).await })
@ -35,7 +35,7 @@ pub(crate) fn request_builder() -> HttpRequestBuilder {
HttpRequestBuilder::new().middleware(super::middleware::MIDDLEWARE.clone())
}
pub async fn create_doc_request(token: &str, params: CreateDocParams, url: &str) -> Result<(), DocError> {
pub async fn create_doc_request(token: &str, params: CreateDocParams, url: &str) -> Result<(), FlowyError> {
let _ = request_builder()
.post(&url.to_owned())
.header(HEADER_TOKEN, token)
@ -45,7 +45,7 @@ pub async fn create_doc_request(token: &str, params: CreateDocParams, url: &str)
Ok(())
}
pub async fn read_doc_request(token: &str, params: DocIdentifier, url: &str) -> Result<Option<Doc>, DocError> {
pub async fn read_doc_request(token: &str, params: DocIdentifier, url: &str) -> Result<Option<Doc>, FlowyError> {
let doc = request_builder()
.get(&url.to_owned())
.header(HEADER_TOKEN, token)
@ -56,7 +56,7 @@ pub async fn read_doc_request(token: &str, params: DocIdentifier, url: &str) ->
Ok(doc)
}
pub async fn update_doc_request(token: &str, params: UpdateDocParams, url: &str) -> Result<(), DocError> {
pub async fn update_doc_request(token: &str, params: UpdateDocParams, url: &str) -> Result<(), FlowyError> {
let _ = request_builder()
.patch(&url.to_owned())
.header(HEADER_TOKEN, token)

View File

@ -4,16 +4,16 @@ use flowy_collaboration::{
};
use lib_infra::future::FutureResult;
use crate::{errors::DocError, services::server::DocumentServerAPI};
use crate::{errors::FlowyError, services::server::DocumentServerAPI};
pub struct DocServerMock {}
impl DocumentServerAPI for DocServerMock {
fn create_doc(&self, _token: &str, _params: CreateDocParams) -> FutureResult<(), DocError> {
fn create_doc(&self, _token: &str, _params: CreateDocParams) -> FutureResult<(), FlowyError> {
FutureResult::new(async { Ok(()) })
}
fn read_doc(&self, _token: &str, params: DocIdentifier) -> FutureResult<Option<Doc>, DocError> {
fn read_doc(&self, _token: &str, params: DocIdentifier) -> FutureResult<Option<Doc>, FlowyError> {
let doc = Doc {
id: params.doc_id,
data: initial_string(),
@ -23,7 +23,7 @@ impl DocumentServerAPI for DocServerMock {
FutureResult::new(async { Ok(Some(doc)) })
}
fn update_doc(&self, _token: &str, _params: UpdateDocParams) -> FutureResult<(), DocError> {
fn update_doc(&self, _token: &str, _params: UpdateDocParams) -> FutureResult<(), FlowyError> {
FutureResult::new(async { Ok(()) })
}
}

View File

@ -1,4 +1,4 @@
use crate::errors::DocError;
use crate::errors::FlowyError;
use bytes::Bytes;
use dashmap::DashMap;
use flowy_collaboration::entities::ws::WsDocumentData;
@ -12,7 +12,7 @@ pub(crate) trait WsDocumentHandler: Send + Sync {
pub type WsStateReceiver = tokio::sync::broadcast::Receiver<WsConnectState>;
pub trait DocumentWebSocket: Send + Sync {
fn send(&self, data: WsDocumentData) -> Result<(), DocError>;
fn send(&self, data: WsDocumentData) -> Result<(), FlowyError>;
fn subscribe_state_changed(&self) -> WsStateReceiver;
}

View File

@ -1,5 +1,5 @@
use crate::{
errors::DocError,
errors::FlowyError,
services::doc::revision::RevisionRecord,
sql_tables::{doc::RevTable, mk_revision_record_from_table, RevChangeset, RevTableState, RevTableType},
};
@ -10,7 +10,7 @@ use lib_ot::revision::RevisionRange;
pub struct RevTableSql {}
impl RevTableSql {
pub(crate) fn create_rev_table(revisions: Vec<RevisionRecord>, conn: &SqliteConnection) -> Result<(), DocError> {
pub(crate) fn create_rev_table(revisions: Vec<RevisionRecord>, conn: &SqliteConnection) -> Result<(), FlowyError> {
// Batch insert: https://diesel.rs/guides/all-about-inserts.html
let records = revisions
.into_iter()
@ -33,7 +33,7 @@ impl RevTableSql {
}
#[allow(dead_code)]
pub(crate) fn update_rev_table(changeset: RevChangeset, conn: &SqliteConnection) -> Result<(), DocError> {
pub(crate) fn update_rev_table(changeset: RevChangeset, conn: &SqliteConnection) -> Result<(), FlowyError> {
let filter = dsl::rev_table
.filter(dsl::rev_id.eq(changeset.rev_id.as_ref()))
.filter(dsl::doc_id.eq(changeset.doc_id));
@ -46,7 +46,7 @@ impl RevTableSql {
user_id: &str,
doc_id: &str,
conn: &SqliteConnection,
) -> Result<Vec<RevisionRecord>, DocError> {
) -> Result<Vec<RevisionRecord>, FlowyError> {
let filter = dsl::rev_table
.filter(dsl::doc_id.eq(doc_id))
.order(dsl::rev_id.asc())
@ -64,7 +64,7 @@ impl RevTableSql {
doc_id: &str,
revision_id: &i64,
conn: &SqliteConnection,
) -> Result<Option<RevisionRecord>, DocError> {
) -> Result<Option<RevisionRecord>, FlowyError> {
let filter = dsl::rev_table
.filter(dsl::doc_id.eq(doc_id))
.filter(dsl::rev_id.eq(revision_id));
@ -82,7 +82,7 @@ impl RevTableSql {
doc_id: &str,
range: RevisionRange,
conn: &SqliteConnection,
) -> Result<Vec<RevisionRecord>, DocError> {
) -> Result<Vec<RevisionRecord>, FlowyError> {
let rev_tables = dsl::rev_table
.filter(dsl::rev_id.ge(range.start))
.filter(dsl::rev_id.le(range.end))
@ -98,7 +98,7 @@ impl RevTableSql {
}
#[allow(dead_code)]
pub(crate) fn delete_rev_table(doc_id_s: &str, rev_id_s: i64, conn: &SqliteConnection) -> Result<(), DocError> {
pub(crate) fn delete_rev_table(doc_id_s: &str, rev_id_s: i64, conn: &SqliteConnection) -> Result<(), FlowyError> {
let filter = dsl::rev_table
.filter(dsl::rev_id.eq(rev_id_s))
.filter(dsl::doc_id.eq(doc_id_s));

View File

@ -7,7 +7,23 @@ edition = "2018"
[dependencies]
flowy-derive = { path = "../../../shared-lib/flowy-derive" }
derive_more = {version = "0.99", features = ["display"]}
error-code = { path = "../../../shared-lib/error-code" }
lib-dispatch = { path = "../lib-dispatch" }
protobuf = {version = "2.20.0"}
bytes = "1.0"
bytes = "1.0"
flowy-collaboration = { path = "../../../shared-lib/flowy-collaboration", optional = true}
lib-ot = { path = "../../../shared-lib/lib-ot", optional = true}
serde_json = {version = "1.0", optional = true}
backend-service = { path = "../../../shared-lib/backend-service", optional = true}
flowy-database = { path = "../flowy-database", optional = true}
lib-sqlite = { path = "../../../shared-lib/lib-sqlite", optional = true}
r2d2 = { version = "0.8", optional = true}
[features]
collaboration = ["flowy-collaboration"]
ot = ["lib-ot"]
serde = ["serde_json"]
backend = ["backend-service"]
db = ["flowy-database", "lib-sqlite", "r2d2"]

View File

@ -1,13 +1,10 @@
use crate::protobuf::ErrorCode as ProtoBufErrorCode;
use bytes::Bytes;
use derive_more::Display;
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
use error_code::ErrorCode;
use flowy_derive::ProtoBuf;
use lib_dispatch::prelude::{EventResponse, ResponseBuilder};
use protobuf::ProtobufEnum;
use std::{
convert::{TryFrom, TryInto},
fmt::Debug,
};
use std::{convert::TryInto, fmt, fmt::Debug};
pub type FlowyResult<T> = std::result::Result<T, FlowyError>;
#[derive(Debug, Default, Clone, ProtoBuf)]
pub struct FlowyError {
@ -18,7 +15,7 @@ pub struct FlowyError {
pub msg: String,
}
macro_rules! static_any_error {
macro_rules! static_flowy_error {
($name:ident, $code:expr) => {
#[allow(non_snake_case, missing_docs)]
pub fn $name() -> FlowyError { $code.into() }
@ -37,7 +34,34 @@ impl FlowyError {
self
}
static_any_error!(internal, ErrorCode::Internal);
static_flowy_error!(internal, ErrorCode::Internal);
static_flowy_error!(record_not_found, ErrorCode::RecordNotFound);
static_flowy_error!(workspace_name, ErrorCode::WorkspaceNameInvalid);
static_flowy_error!(workspace_id, ErrorCode::WorkspaceIdInvalid);
static_flowy_error!(color_style, ErrorCode::AppColorStyleInvalid);
static_flowy_error!(workspace_desc, ErrorCode::WorkspaceDescTooLong);
static_flowy_error!(app_name, ErrorCode::AppNameInvalid);
static_flowy_error!(invalid_app_id, ErrorCode::AppIdInvalid);
static_flowy_error!(view_name, ErrorCode::ViewNameInvalid);
static_flowy_error!(view_thumbnail, ErrorCode::ViewThumbnailInvalid);
static_flowy_error!(invalid_view_id, ErrorCode::ViewIdInvalid);
static_flowy_error!(view_desc, ErrorCode::ViewDescTooLong);
static_flowy_error!(view_data, ErrorCode::ViewDataInvalid);
static_flowy_error!(unauthorized, ErrorCode::UserUnauthorized);
static_flowy_error!(connection, ErrorCode::ConnectError);
static_flowy_error!(email_empty, ErrorCode::EmailIsEmpty);
static_flowy_error!(email_format, ErrorCode::EmailFormatInvalid);
static_flowy_error!(email_exist, ErrorCode::EmailAlreadyExists);
static_flowy_error!(password_empty, ErrorCode::PasswordIsEmpty);
static_flowy_error!(passworkd_too_long, ErrorCode::PasswordTooLong);
static_flowy_error!(password_forbid_char, ErrorCode::PasswordContainsForbidCharacters);
static_flowy_error!(password_format, ErrorCode::PasswordFormatInvalid);
static_flowy_error!(password_not_match, ErrorCode::PasswordNotMatch);
static_flowy_error!(name_too_long, ErrorCode::UserNameTooLong);
static_flowy_error!(name_forbid_char, ErrorCode::UserNameContainForbiddenCharacters);
static_flowy_error!(name_empty, ErrorCode::UserNameIsEmpty);
static_flowy_error!(user_id, ErrorCode::UserIdInvalid);
static_flowy_error!(user_not_exist, ErrorCode::UserNotExist);
}
impl std::convert::From<ErrorCode> for FlowyError {
@ -49,26 +73,6 @@ impl std::convert::From<ErrorCode> for FlowyError {
}
}
#[derive(Debug, Clone, ProtoBuf_Enum, Display, PartialEq, Eq)]
pub enum ErrorCode {
#[display(fmt = "Internal error")]
Internal = 0,
}
impl ErrorCode {
pub fn value(&self) -> i32 {
let code: ProtoBufErrorCode = self.clone().try_into().unwrap();
code.value()
}
pub fn from_i32(value: i32) -> Self {
match ProtoBufErrorCode::from_i32(value) {
None => ErrorCode::Internal,
Some(code) => ErrorCode::try_from(&code).unwrap(),
}
}
}
pub fn internal_error<T>(e: T) -> FlowyError
where
T: std::fmt::Debug,
@ -76,9 +80,21 @@ where
FlowyError::internal().context(e)
}
impl fmt::Display for FlowyError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}: {}", &self.code, &self.msg) }
}
impl lib_dispatch::Error for FlowyError {
fn as_response(&self) -> EventResponse {
let bytes: Bytes = self.clone().try_into().unwrap();
ResponseBuilder::Err().data(bytes).build()
}
}
impl std::convert::From<std::io::Error> for FlowyError {
fn from(error: std::io::Error) -> Self { FlowyError::internal().context(error) }
}
impl std::convert::From<protobuf::ProtobufError> for FlowyError {
fn from(e: protobuf::ProtobufError) -> Self { FlowyError::internal().context(e) }
}

View File

@ -0,0 +1,22 @@
use crate::FlowyError;
use backend_service::errors::{ErrorCode as ServerErrorCode, ServerError};
use error_code::ErrorCode;
impl std::convert::From<ServerError> for FlowyError {
fn from(error: ServerError) -> Self {
let code = server_error_to_flowy_error(error.code);
FlowyError::new(code, &error.msg)
}
}
fn server_error_to_flowy_error(code: ServerErrorCode) -> ErrorCode {
match code {
ServerErrorCode::UserUnauthorized => ErrorCode::UserUnauthorized,
ServerErrorCode::PasswordNotMatch => ErrorCode::PasswordNotMatch,
ServerErrorCode::RecordNotFound => ErrorCode::RecordNotFound,
ServerErrorCode::ConnectRefused | ServerErrorCode::ConnectTimeout | ServerErrorCode::ConnectClose => {
ErrorCode::ConnectError
},
_ => ErrorCode::Internal,
}
}

View File

@ -0,0 +1,5 @@
use crate::FlowyError;
impl std::convert::From<flowy_collaboration::errors::CollaborateError> for FlowyError {
fn from(error: flowy_collaboration::errors::CollaborateError) -> Self { FlowyError::internal().context(error) }
}

View File

@ -0,0 +1,15 @@
use crate::FlowyError;
impl std::convert::From<flowy_database::Error> for FlowyError {
fn from(error: flowy_database::Error) -> Self { FlowyError::internal().context(error) }
}
impl std::convert::From<::r2d2::Error> for FlowyError {
fn from(error: r2d2::Error) -> Self { FlowyError::internal().context(error) }
}
// use diesel::result::{Error, DatabaseErrorKind};
// use lib_sqlite::ErrorKind;
impl std::convert::From<lib_sqlite::Error> for FlowyError {
fn from(error: lib_sqlite::Error) -> Self { FlowyError::internal().context(error) }
}

View File

@ -0,0 +1,27 @@
#[cfg(feature = "collaboration")]
mod collaborate;
#[cfg(feature = "collaboration")]
pub use collaborate::*;
//
#[cfg(feature = "ot")]
mod ot;
#[cfg(feature = "ot")]
pub use ot::*;
//
#[cfg(feature = "serde")]
mod serde;
#[cfg(feature = "serde")]
pub use serde::*;
//
#[cfg(feature = "backend")]
mod backend;
#[cfg(feature = "backend")]
pub use backend::*;
#[cfg(feature = "db")]
mod database;
#[cfg(feature = "db")]
pub use database::*;

View File

@ -0,0 +1,5 @@
use crate::FlowyError;
impl std::convert::From<lib_ot::errors::OTError> for FlowyError {
fn from(error: lib_ot::errors::OTError) -> Self { FlowyError::internal().context(error) }
}

View File

@ -0,0 +1,5 @@
use crate::FlowyError;
impl std::convert::From<serde_json::Error> for FlowyError {
fn from(error: serde_json::Error) -> Self { FlowyError::internal().context(error) }
}

View File

@ -1,4 +1,6 @@
mod errors;
mod ext;
pub mod protobuf;
pub use error_code::ErrorCode;
pub use errors::*;

View File

@ -217,67 +217,17 @@ impl ::protobuf::reflect::ProtobufValue for FlowyError {
}
}
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
pub enum ErrorCode {
Internal = 0,
}
impl ::protobuf::ProtobufEnum for ErrorCode {
fn value(&self) -> i32 {
*self as i32
}
fn from_i32(value: i32) -> ::std::option::Option<ErrorCode> {
match value {
0 => ::std::option::Option::Some(ErrorCode::Internal),
_ => ::std::option::Option::None
}
}
fn values() -> &'static [Self] {
static values: &'static [ErrorCode] = &[
ErrorCode::Internal,
];
values
}
fn enum_descriptor_static() -> &'static ::protobuf::reflect::EnumDescriptor {
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::EnumDescriptor> = ::protobuf::rt::LazyV2::INIT;
descriptor.get(|| {
::protobuf::reflect::EnumDescriptor::new_pb_name::<ErrorCode>("ErrorCode", file_descriptor_proto())
})
}
}
impl ::std::marker::Copy for ErrorCode {
}
impl ::std::default::Default for ErrorCode {
fn default() -> Self {
ErrorCode::Internal
}
}
impl ::protobuf::reflect::ProtobufValue for ErrorCode {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self))
}
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x0cerrors.proto\"2\n\nFlowyError\x12\x12\n\x04code\x18\x01\x20\x01(\
\x05R\x04code\x12\x10\n\x03msg\x18\x02\x20\x01(\tR\x03msg*\x19\n\tErrorC\
ode\x12\x0c\n\x08Internal\x10\0J\xd9\x01\n\x06\x12\x04\0\0\x08\x01\n\x08\
\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x05\x01\n\n\n\
\x03\x04\0\x01\x12\x03\x02\x08\x12\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\
\x04\x13\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\x04\t\n\x0c\n\x05\x04\0\
\x02\0\x01\x12\x03\x03\n\x0e\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x11\
\x12\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x04\x04\x13\n\x0c\n\x05\x04\0\x02\
\x01\x05\x12\x03\x04\x04\n\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\x0b\
\x0e\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x04\x11\x12\n\n\n\x02\x05\0\
\x12\x04\x06\0\x08\x01\n\n\n\x03\x05\0\x01\x12\x03\x06\x05\x0e\n\x0b\n\
\x04\x05\0\x02\0\x12\x03\x07\x04\x11\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\
\x07\x04\x0c\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x07\x0f\x10b\x06proto3\
\x05R\x04code\x12\x10\n\x03msg\x18\x02\x20\x01(\tR\x03msgJ\x98\x01\n\x06\
\x12\x04\0\0\x05\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\
\x04\x02\0\x05\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x12\n\x0b\n\x04\
\x04\0\x02\0\x12\x03\x03\x04\x13\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\
\x04\t\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\n\x0e\n\x0c\n\x05\x04\0\
\x02\0\x03\x12\x03\x03\x11\x12\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x04\x04\
\x13\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\x04\n\n\x0c\n\x05\x04\0\
\x02\x01\x01\x12\x03\x04\x0b\x0e\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\
\x04\x11\x12b\x06proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

View File

@ -4,6 +4,3 @@ message FlowyError {
int32 code = 1;
string msg = 2;
}
enum ErrorCode {
Internal = 0;
}

View File

@ -1,5 +1,5 @@
use crate::{entities::NetworkState, services::ws::WsManager};
use bytes::Bytes;
use flowy_error::FlowyError;
use lib_dispatch::prelude::{Data, Unit};
use std::sync::Arc;

View File

@ -5,6 +5,6 @@ use std::sync::Arc;
pub fn create(ws_manager: Arc<WsManager>) -> Module {
Module::new()
.name("Flowy-Network")
.data(ws_manager.clone())
.data(ws_manager)
.event(NetworkEvent::UpdateNetworkType, update_network_ty)
}

View File

@ -2,15 +2,12 @@ use bytes::Bytes;
use flowy_collaboration::entities::ws::WsDocumentData;
use flowy_database::ConnectionPool;
use flowy_document::{
errors::{internal_error, DocError},
errors::{internal_error, FlowyError},
module::DocumentUser,
services::ws::{DocumentWebSocket, WsDocumentManager, WsStateReceiver},
};
use flowy_net::services::ws::WsManager;
use flowy_user::{
errors::{ErrorCode, UserError},
services::user::UserSession,
};
use flowy_user::services::user::UserSession;
use lib_ws::{WsMessage, WsMessageHandler, WsModule};
use std::{convert::TryInto, path::Path, sync::Arc};
@ -20,16 +17,14 @@ impl DocumentDepsResolver {
ws_manager: Arc<WsManager>,
user_session: Arc<UserSession>,
) -> (Arc<dyn DocumentUser>, Arc<WsDocumentManager>) {
let user = Arc::new(DocumentUserImpl {
user: user_session.clone(),
});
let user = Arc::new(DocumentUserImpl { user: user_session });
let sender = Arc::new(WsSenderImpl {
ws_manager: ws_manager.clone(),
});
let ws_doc = Arc::new(WsDocumentManager::new(sender));
let ws_handler = Arc::new(DocumentWsMessageReceiver { inner: ws_doc.clone() });
ws_manager.add_handler(ws_handler);
ws_manager.add_handler(ws_handler).unwrap();
(user, ws_doc)
}
}
@ -40,16 +35,12 @@ struct DocumentUserImpl {
impl DocumentUserImpl {}
fn map_user_error(error: UserError) -> DocError {
match ErrorCode::from_i32(error.code) {
ErrorCode::InternalError => DocError::internal().context(error.msg),
_ => DocError::internal().context(error),
}
}
impl DocumentUser for DocumentUserImpl {
fn user_dir(&self) -> Result<String, DocError> {
let dir = self.user.user_dir().map_err(|e| DocError::unauthorized().context(e))?;
fn user_dir(&self) -> Result<String, FlowyError> {
let dir = self
.user
.user_dir()
.map_err(|e| FlowyError::unauthorized().context(e))?;
let doc_dir = format!("{}/doc", dir);
if !Path::new(&doc_dir).exists() {
@ -58,11 +49,11 @@ impl DocumentUser for DocumentUserImpl {
Ok(doc_dir)
}
fn user_id(&self) -> Result<String, DocError> { self.user.user_id().map_err(map_user_error) }
fn user_id(&self) -> Result<String, FlowyError> { self.user.user_id() }
fn token(&self) -> Result<String, DocError> { self.user.token().map_err(map_user_error) }
fn token(&self) -> Result<String, FlowyError> { self.user.token() }
fn db_pool(&self) -> Result<Arc<ConnectionPool>, DocError> { self.user.db_pool().map_err(map_user_error) }
fn db_pool(&self) -> Result<Arc<ConnectionPool>, FlowyError> { self.user.db_pool() }
}
struct WsSenderImpl {
@ -70,7 +61,7 @@ struct WsSenderImpl {
}
impl DocumentWebSocket for WsSenderImpl {
fn send(&self, data: WsDocumentData) -> Result<(), DocError> {
fn send(&self, data: WsDocumentData) -> Result<(), FlowyError> {
let bytes: Bytes = data.try_into().unwrap();
let msg = WsMessage {
module: WsModule::Doc,

View File

@ -1,5 +1,5 @@
use flowy_core::{
errors::WorkspaceError,
errors::FlowyError,
module::{WorkspaceDatabase, WorkspaceUser},
};
use flowy_database::ConnectionPool;
@ -29,23 +29,21 @@ impl WorkspaceDepsResolver {
}
impl WorkspaceDatabase for Resolver {
fn db_pool(&self) -> Result<Arc<ConnectionPool>, WorkspaceError> {
fn db_pool(&self) -> Result<Arc<ConnectionPool>, FlowyError> {
self.user_session
.db_pool()
.map_err(|e| WorkspaceError::internal().context(e))
.map_err(|e| FlowyError::internal().context(e))
}
}
impl WorkspaceUser for Resolver {
fn user_id(&self) -> Result<String, WorkspaceError> {
fn user_id(&self) -> Result<String, FlowyError> {
self.user_session
.user_id()
.map_err(|e| WorkspaceError::internal().context(e))
.map_err(|e| FlowyError::internal().context(e))
}
fn token(&self) -> Result<String, WorkspaceError> {
self.user_session
.token()
.map_err(|e| WorkspaceError::internal().context(e))
fn token(&self) -> Result<String, FlowyError> {
self.user_session.token().map_err(|e| FlowyError::internal().context(e))
}
}

View File

@ -3,7 +3,7 @@ mod deps_resolve;
pub mod module;
use crate::deps_resolve::{DocumentDepsResolver, WorkspaceDepsResolver};
use backend_service::configuration::ClientServerConfiguration;
use flowy_core::{errors::WorkspaceError, module::init_core, prelude::CoreContext};
use flowy_core::{errors::FlowyError, module::init_core, prelude::CoreContext};
use flowy_document::module::FlowyDocument;
use flowy_net::{entities::NetworkType, services::ws::WsManager};
use flowy_user::{
@ -130,7 +130,7 @@ async fn _listen_user_status(
match status {
UserStatus::Login { token } => {
let _ = core.user_did_sign_in(&token).await?;
let _ = ws_manager.start(token).await.unwrap();
let _ = ws_manager.start(token).await?;
},
UserStatus::Logout { .. } => {
core.user_did_logout().await;
@ -143,7 +143,7 @@ async fn _listen_user_status(
let _ = ret.send(());
},
}
Ok::<(), WorkspaceError>(())
Ok::<(), FlowyError>(())
};
match result().await {

View File

@ -1,7 +1,5 @@
use crate::deps_resolve::DocumentDepsResolver;
use backend_service::configuration::ClientServerConfiguration;
use flowy_core::prelude::CoreContext;
use flowy_document::module::FlowyDocument;
use flowy_net::services::ws::WsManager;
use flowy_user::services::user::UserSession;
use lib_dispatch::prelude::Module;

View File

@ -1,28 +1,22 @@
use flowy_user::entities::UserProfile;
use lib_dispatch::prelude::{EventDispatcher, EventResponse, FromBytes, ModuleRequest, StatusCode, ToBytes};
use crate::FlowySDKTest;
use flowy_user::{entities::UserProfile, errors::FlowyError};
use lib_dispatch::prelude::{EventDispatcher, EventResponse, FromBytes, ModuleRequest, StatusCode, ToBytes, *};
use std::{
convert::TryFrom,
fmt::{Debug, Display},
hash::Hash,
marker::PhantomData,
sync::Arc,
};
use crate::FlowySDKTest;
use flowy_core::errors::WorkspaceError;
use flowy_user::errors::UserError;
use lib_dispatch::prelude::*;
use std::{convert::TryFrom, marker::PhantomData, sync::Arc};
pub type CoreModuleEventBuilder = EventBuilder<WorkspaceError>;
pub type CoreModuleEventBuilder = EventBuilder<FlowyError>;
impl CoreModuleEventBuilder {
pub fn new(sdk: FlowySDKTest) -> Self { EventBuilder::test(TestContext::new(sdk)) }
}
pub type UserModuleEventBuilder = EventBuilder<UserError>;
impl UserModuleEventBuilder {
pub fn new(sdk: FlowySDKTest) -> Self { EventBuilder::test(TestContext::new(sdk)) }
pub fn user_profile(&self) -> &Option<UserProfile> { &self.user_profile }
}
pub type UserModuleEventBuilder = CoreModuleEventBuilder;
#[derive(Clone)]
pub struct EventBuilder<E> {
context: TestContext,

View File

@ -13,7 +13,7 @@ use flowy_core::{
};
use flowy_user::{
entities::{SignInRequest, SignUpRequest, UserProfile},
errors::UserError,
errors::FlowyError,
event::UserEvent::{InitUser, SignIn, SignOut, SignUp},
};
use lib_dispatch::prelude::{EventDispatcher, ModuleRequest, ToBytes};
@ -316,7 +316,7 @@ pub fn sign_up(dispatch: Arc<EventDispatcher>) -> SignUpContext {
let request = ModuleRequest::new(SignUp).payload(payload);
let user_profile = EventDispatcher::sync_send(dispatch, request)
.parse::<UserProfile, UserError>()
.parse::<UserProfile, FlowyError>()
.unwrap()
.unwrap();
@ -336,7 +336,7 @@ pub async fn async_sign_up(dispatch: Arc<EventDispatcher>) -> SignUpContext {
let request = ModuleRequest::new(SignUp).payload(payload);
let user_profile = EventDispatcher::async_send(dispatch.clone(), request)
.await
.parse::<UserProfile, UserError>()
.parse::<UserProfile, FlowyError>()
.unwrap()
.unwrap();
@ -361,7 +361,7 @@ fn sign_in(dispatch: Arc<EventDispatcher>) -> UserProfile {
let request = ModuleRequest::new(SignIn).payload(payload);
EventDispatcher::sync_send(dispatch, request)
.parse::<UserProfile, UserError>()
.parse::<UserProfile, FlowyError>()
.unwrap()
.unwrap()
}

View File

@ -19,6 +19,7 @@ flowy-database = { path = "../flowy-database" }
flowy-net = { path = "../flowy-net" }
dart-notify = { path = "../dart-notify" }
lib-dispatch = { path = "../lib-dispatch" }
flowy-error = { path = "../flowy-error", features = ["db", "backend"] }
tracing = { version = "0.1", features = ["log"] }

View File

@ -1,117 +0,0 @@
use bytes::Bytes;
use flowy_derive::ProtoBuf;
pub use flowy_user_infra::errors::ErrorCode;
use lib_dispatch::prelude::{EventResponse, ResponseBuilder};
use std::{convert::TryInto, fmt, fmt::Debug};
#[derive(Debug, Default, Clone, ProtoBuf)]
pub struct UserError {
#[pb(index = 1)]
pub code: i32,
#[pb(index = 2)]
pub msg: String,
}
impl std::fmt::Display for UserError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}: {}", &self.code, &self.msg) }
}
macro_rules! static_user_error {
($name:ident, $code:expr) => {
#[allow(non_snake_case, missing_docs)]
pub fn $name() -> UserError { $code.into() }
};
}
impl UserError {
pub(crate) fn new(code: ErrorCode, msg: &str) -> Self {
Self {
code: code.value(),
msg: msg.to_owned(),
}
}
pub fn context<T: Debug>(mut self, error: T) -> Self {
self.msg = format!("{:?}", error);
self
}
static_user_error!(email_empty, ErrorCode::EmailIsEmpty);
static_user_error!(email_format, ErrorCode::EmailFormatInvalid);
static_user_error!(email_exist, ErrorCode::EmailAlreadyExists);
static_user_error!(password_empty, ErrorCode::PasswordIsEmpty);
static_user_error!(passworkd_too_long, ErrorCode::PasswordTooLong);
static_user_error!(password_forbid_char, ErrorCode::PasswordContainsForbidCharacters);
static_user_error!(password_format, ErrorCode::PasswordFormatInvalid);
static_user_error!(password_not_match, ErrorCode::PasswordNotMatch);
static_user_error!(name_too_long, ErrorCode::UserNameTooLong);
static_user_error!(name_forbid_char, ErrorCode::UserNameContainForbiddenCharacters);
static_user_error!(name_empty, ErrorCode::UserNameIsEmpty);
static_user_error!(user_id, ErrorCode::UserIdInvalid);
static_user_error!(unauthorized, ErrorCode::UserUnauthorized);
static_user_error!(user_not_exist, ErrorCode::UserNotExist);
static_user_error!(internal, ErrorCode::InternalError);
}
impl std::convert::From<ErrorCode> for UserError {
fn from(code: ErrorCode) -> Self {
UserError {
code: code.value(),
msg: format!("{}", code),
}
}
}
impl std::convert::From<flowy_database::Error> for UserError {
fn from(error: flowy_database::Error) -> Self {
match error {
flowy_database::Error::NotFound => UserError::user_not_exist().context(error),
_ => UserError::internal().context(error),
}
}
}
impl std::convert::From<::r2d2::Error> for UserError {
fn from(error: r2d2::Error) -> Self { UserError::internal().context(error) }
}
// use diesel::result::{Error, DatabaseErrorKind};
// use lib_sqlite::ErrorKind;
impl std::convert::From<lib_sqlite::Error> for UserError {
fn from(error: lib_sqlite::Error) -> Self { UserError::internal().context(error) }
}
impl std::convert::From<backend_service::errors::ServerError> for UserError {
fn from(error: backend_service::errors::ServerError) -> Self {
let (code, msg) = server_error_to_user_error(error);
UserError::new(code, &msg)
}
}
use backend_service::errors::ErrorCode as ServerErrorCode;
fn server_error_to_user_error(error: backend_service::errors::ServerError) -> (ErrorCode, String) {
let code = match error.code {
ServerErrorCode::UserUnauthorized => ErrorCode::UserUnauthorized,
ServerErrorCode::PasswordNotMatch => ErrorCode::PasswordNotMatch,
ServerErrorCode::RecordNotFound => ErrorCode::UserNotExist,
ServerErrorCode::ConnectRefused | ServerErrorCode::ConnectTimeout | ServerErrorCode::ConnectClose => {
ErrorCode::ServerError
},
_ => ErrorCode::InternalError,
};
if code != ErrorCode::InternalError {
let msg = format!("{}", &code);
(code, msg)
} else {
(code, error.msg)
}
}
impl lib_dispatch::Error for UserError {
fn as_response(&self) -> EventResponse {
let bytes: Bytes = self.clone().try_into().unwrap();
ResponseBuilder::Err().data(bytes).build()
}
}

View File

@ -2,7 +2,7 @@ use flowy_derive::{Flowy_Event, ProtoBuf_Enum};
use strum_macros::Display;
#[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)]
#[event_err = "UserError"]
#[event_err = "FlowyError"]
pub enum UserEvent {
#[event()]
InitUser = 0,

View File

@ -1,10 +1,13 @@
use crate::{entities::*, errors::UserError, services::user::UserSession};
use crate::{entities::*, errors::FlowyError, services::user::UserSession};
use lib_dispatch::prelude::*;
use std::{convert::TryInto, sync::Arc};
// tracing instrument 👉🏻 https://docs.rs/tracing/0.1.26/tracing/attr.instrument.html
#[tracing::instrument(name = "sign_in", skip(data, session), fields(email = %data.email), err)]
pub async fn sign_in(data: Data<SignInRequest>, session: Unit<Arc<UserSession>>) -> DataResult<UserProfile, UserError> {
pub async fn sign_in(
data: Data<SignInRequest>,
session: Unit<Arc<UserSession>>,
) -> DataResult<UserProfile, FlowyError> {
let params: SignInParams = data.into_inner().try_into()?;
let user_profile = session.sign_in(params).await?;
data_result(user_profile)
@ -19,7 +22,10 @@ pub async fn sign_in(data: Data<SignInRequest>, session: Unit<Arc<UserSession>>)
),
err
)]
pub async fn sign_up(data: Data<SignUpRequest>, session: Unit<Arc<UserSession>>) -> DataResult<UserProfile, UserError> {
pub async fn sign_up(
data: Data<SignUpRequest>,
session: Unit<Arc<UserSession>>,
) -> DataResult<UserProfile, FlowyError> {
let params: SignUpParams = data.into_inner().try_into()?;
let user_profile = session.sign_up(params).await?;

View File

@ -1,28 +1,28 @@
use crate::{entities::*, errors::UserError, services::user::UserSession};
use flowy_net::entities::NetworkState;
use crate::{entities::*, errors::FlowyError, services::user::UserSession};
use lib_dispatch::prelude::*;
use std::{convert::TryInto, sync::Arc};
#[tracing::instrument(skip(session))]
pub async fn init_user_handler(session: Unit<Arc<UserSession>>) -> Result<(), UserError> {
pub async fn init_user_handler(session: Unit<Arc<UserSession>>) -> Result<(), FlowyError> {
let _ = session.init_user().await?;
Ok(())
}
#[tracing::instrument(skip(session))]
pub async fn check_user_handler(session: Unit<Arc<UserSession>>) -> DataResult<UserProfile, UserError> {
pub async fn check_user_handler(session: Unit<Arc<UserSession>>) -> DataResult<UserProfile, FlowyError> {
let user_profile = session.check_user().await?;
data_result(user_profile)
}
#[tracing::instrument(skip(session))]
pub async fn get_user_profile_handler(session: Unit<Arc<UserSession>>) -> DataResult<UserProfile, UserError> {
pub async fn get_user_profile_handler(session: Unit<Arc<UserSession>>) -> DataResult<UserProfile, FlowyError> {
let user_profile = session.user_profile().await?;
data_result(user_profile)
}
#[tracing::instrument(name = "sign_out", skip(session))]
pub async fn sign_out(session: Unit<Arc<UserSession>>) -> Result<(), UserError> {
pub async fn sign_out(session: Unit<Arc<UserSession>>) -> Result<(), FlowyError> {
let _ = session.sign_out().await?;
Ok(())
}
@ -31,7 +31,7 @@ pub async fn sign_out(session: Unit<Arc<UserSession>>) -> Result<(), UserError>
pub async fn update_user_handler(
data: Data<UpdateUserRequest>,
session: Unit<Arc<UserSession>>,
) -> Result<(), UserError> {
) -> Result<(), FlowyError> {
let params: UpdateUserParams = data.into_inner().try_into()?;
session.update_user(params).await?;
Ok(())

View File

@ -1,14 +1,11 @@
mod handlers;
mod sql_tables;
pub mod errors;
pub mod entities;
pub mod event;
mod handlers;
pub mod module;
pub mod notify;
pub mod protobuf;
pub mod services;
mod sql_tables;
#[macro_use]
extern crate flowy_database;
@ -16,3 +13,7 @@ extern crate flowy_database;
pub mod prelude {
pub use crate::{entities::*, services::server::*};
}
pub mod errors {
pub use flowy_error::{internal_error, ErrorCode, FlowyError};
}

View File

@ -1,243 +0,0 @@
// This file is generated by rust-protobuf 2.22.1. Do not edit
// @generated
// https://github.com/rust-lang/rust-clippy/issues/702
#![allow(unknown_lints)]
#![allow(clippy::all)]
#![allow(unused_attributes)]
#![cfg_attr(rustfmt, rustfmt::skip)]
#![allow(box_pointers)]
#![allow(dead_code)]
#![allow(missing_docs)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(trivial_casts)]
#![allow(unused_imports)]
#![allow(unused_results)]
//! Generated file from `errors.proto`
/// Generated files are compatible only with the same version
/// of protobuf runtime.
// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_22_1;
#[derive(PartialEq,Clone,Default)]
pub struct UserError {
// message fields
pub code: i32,
pub msg: ::std::string::String,
// special fields
pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize,
}
impl<'a> ::std::default::Default for &'a UserError {
fn default() -> &'a UserError {
<UserError as ::protobuf::Message>::default_instance()
}
}
impl UserError {
pub fn new() -> UserError {
::std::default::Default::default()
}
// int32 code = 1;
pub fn get_code(&self) -> i32 {
self.code
}
pub fn clear_code(&mut self) {
self.code = 0;
}
// Param is passed by value, moved
pub fn set_code(&mut self, v: i32) {
self.code = v;
}
// string msg = 2;
pub fn get_msg(&self) -> &str {
&self.msg
}
pub fn clear_msg(&mut self) {
self.msg.clear();
}
// Param is passed by value, moved
pub fn set_msg(&mut self, v: ::std::string::String) {
self.msg = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_msg(&mut self) -> &mut ::std::string::String {
&mut self.msg
}
// Take field
pub fn take_msg(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.msg, ::std::string::String::new())
}
}
impl ::protobuf::Message for UserError {
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
while !is.eof()? {
let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number {
1 => {
if wire_type != ::protobuf::wire_format::WireTypeVarint {
return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
}
let tmp = is.read_int32()?;
self.code = tmp;
},
2 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.msg)?;
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
if self.code != 0 {
my_size += ::protobuf::rt::value_size(1, self.code, ::protobuf::wire_format::WireTypeVarint);
}
if !self.msg.is_empty() {
my_size += ::protobuf::rt::string_size(2, &self.msg);
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
if self.code != 0 {
os.write_int32(1, self.code)?;
}
if !self.msg.is_empty() {
os.write_string(2, &self.msg)?;
}
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
}
fn get_cached_size(&self) -> u32 {
self.cached_size.get()
}
fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
&self.unknown_fields
}
fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
&mut self.unknown_fields
}
fn as_any(&self) -> &dyn (::std::any::Any) {
self as &dyn (::std::any::Any)
}
fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
self as &mut dyn (::std::any::Any)
}
fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
self
}
fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
Self::descriptor_static()
}
fn new() -> UserError {
UserError::new()
}
fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
descriptor.get(|| {
let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeInt32>(
"code",
|m: &UserError| { &m.code },
|m: &mut UserError| { &mut m.code },
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"msg",
|m: &UserError| { &m.msg },
|m: &mut UserError| { &mut m.msg },
));
::protobuf::reflect::MessageDescriptor::new_pb_name::<UserError>(
"UserError",
fields,
file_descriptor_proto()
)
})
}
fn default_instance() -> &'static UserError {
static instance: ::protobuf::rt::LazyV2<UserError> = ::protobuf::rt::LazyV2::INIT;
instance.get(UserError::new)
}
}
impl ::protobuf::Clear for UserError {
fn clear(&mut self) {
self.code = 0;
self.msg.clear();
self.unknown_fields.clear();
}
}
impl ::std::fmt::Debug for UserError {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for UserError {
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
::protobuf::reflect::ReflectValueRef::Message(self)
}
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x0cerrors.proto\"1\n\tUserError\x12\x12\n\x04code\x18\x01\x20\x01(\
\x05R\x04code\x12\x10\n\x03msg\x18\x02\x20\x01(\tR\x03msgJ\x98\x01\n\x06\
\x12\x04\0\0\x05\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\
\x04\x02\0\x05\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x11\n\x0b\n\x04\
\x04\0\x02\0\x12\x03\x03\x04\x13\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\
\x04\t\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\n\x0e\n\x0c\n\x05\x04\0\
\x02\0\x03\x12\x03\x03\x11\x12\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x04\x04\
\x13\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\x04\n\n\x0c\n\x05\x04\0\
\x02\x01\x01\x12\x03\x04\x0b\x0e\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\
\x04\x11\x12b\x06proto3\
";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap()
}
pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
file_descriptor_proto_lazy.get(|| {
parse_descriptor_proto()
})
}

View File

@ -4,8 +4,5 @@
mod observable;
pub use observable::*;
mod errors;
pub use errors::*;
mod event;
pub use event::*;

View File

@ -1,6 +0,0 @@
syntax = "proto3";
message UserError {
int32 code = 1;
string msg = 2;
}

View File

@ -8,17 +8,17 @@ use std::sync::Arc;
pub(crate) type Server = Arc<dyn UserServerAPI + Send + Sync>;
use crate::{
entities::{SignInParams, SignInResponse, SignUpParams, SignUpResponse, UpdateUserParams, UserProfile},
errors::UserError,
errors::FlowyError,
};
use backend_service::configuration::ClientServerConfiguration;
use lib_infra::future::FutureResult;
pub trait UserServerAPI {
fn sign_up(&self, params: SignUpParams) -> FutureResult<SignUpResponse, UserError>;
fn sign_in(&self, params: SignInParams) -> FutureResult<SignInResponse, UserError>;
fn sign_out(&self, token: &str) -> FutureResult<(), UserError>;
fn update_user(&self, token: &str, params: UpdateUserParams) -> FutureResult<(), UserError>;
fn get_user(&self, token: &str) -> FutureResult<UserProfile, UserError>;
fn sign_up(&self, params: SignUpParams) -> FutureResult<SignUpResponse, FlowyError>;
fn sign_in(&self, params: SignInParams) -> FutureResult<SignInResponse, FlowyError>;
fn sign_out(&self, token: &str) -> FutureResult<(), FlowyError>;
fn update_user(&self, token: &str, params: UpdateUserParams) -> FutureResult<(), FlowyError>;
fn get_user(&self, token: &str) -> FutureResult<UserProfile, FlowyError>;
fn ws_addr(&self) -> String;
}

View File

@ -1,6 +1,6 @@
use crate::{
entities::{SignInParams, SignInResponse, SignUpParams, SignUpResponse, UpdateUserParams, UserProfile},
errors::UserError,
errors::FlowyError,
services::server::UserServerAPI,
};
use backend_service::{configuration::*, user_request::*};
@ -14,7 +14,7 @@ impl UserHttpServer {
}
impl UserServerAPI for UserHttpServer {
fn sign_up(&self, params: SignUpParams) -> FutureResult<SignUpResponse, UserError> {
fn sign_up(&self, params: SignUpParams) -> FutureResult<SignUpResponse, FlowyError> {
let url = self.config.sign_up_url();
FutureResult::new(async move {
let resp = user_sign_up_request(params, &url).await?;
@ -22,7 +22,7 @@ impl UserServerAPI for UserHttpServer {
})
}
fn sign_in(&self, params: SignInParams) -> FutureResult<SignInResponse, UserError> {
fn sign_in(&self, params: SignInParams) -> FutureResult<SignInResponse, FlowyError> {
let url = self.config.sign_in_url();
FutureResult::new(async move {
let resp = user_sign_in_request(params, &url).await?;
@ -30,7 +30,7 @@ impl UserServerAPI for UserHttpServer {
})
}
fn sign_out(&self, token: &str) -> FutureResult<(), UserError> {
fn sign_out(&self, token: &str) -> FutureResult<(), FlowyError> {
let token = token.to_owned();
let url = self.config.sign_out_url();
FutureResult::new(async move {
@ -39,7 +39,7 @@ impl UserServerAPI for UserHttpServer {
})
}
fn update_user(&self, token: &str, params: UpdateUserParams) -> FutureResult<(), UserError> {
fn update_user(&self, token: &str, params: UpdateUserParams) -> FutureResult<(), FlowyError> {
let token = token.to_owned();
let url = self.config.user_profile_url();
FutureResult::new(async move {
@ -48,7 +48,7 @@ impl UserServerAPI for UserHttpServer {
})
}
fn get_user(&self, token: &str) -> FutureResult<UserProfile, UserError> {
fn get_user(&self, token: &str) -> FutureResult<UserProfile, FlowyError> {
let token = token.to_owned();
let url = self.config.user_profile_url();
FutureResult::new(async move {
@ -77,7 +77,7 @@ impl UserServerAPI for UserHttpServer {
// None => {},
// Some(token) => {
// let error =
// UserError::new(ErrorCode::UserUnauthorized, "");
// FlowyError::new(ErrorCode::UserUnauthorized, "");
// dart_notify(token, UserNotification::UserUnauthorized)
// .error(error) .send()
// },

View File

@ -1,6 +1,6 @@
use crate::{
entities::{SignInParams, SignInResponse, SignUpParams, SignUpResponse, UpdateUserParams, UserProfile},
errors::UserError,
errors::FlowyError,
};
use crate::services::server::UserServerAPI;
@ -11,7 +11,7 @@ pub struct UserServerMock {}
impl UserServerMock {}
impl UserServerAPI for UserServerMock {
fn sign_up(&self, params: SignUpParams) -> FutureResult<SignUpResponse, UserError> {
fn sign_up(&self, params: SignUpParams) -> FutureResult<SignUpResponse, FlowyError> {
let uid = uuid();
FutureResult::new(async move {
Ok(SignUpResponse {
@ -23,7 +23,7 @@ impl UserServerAPI for UserServerMock {
})
}
fn sign_in(&self, params: SignInParams) -> FutureResult<SignInResponse, UserError> {
fn sign_in(&self, params: SignInParams) -> FutureResult<SignInResponse, FlowyError> {
let user_id = uuid();
FutureResult::new(async {
Ok(SignInResponse {
@ -35,13 +35,13 @@ impl UserServerAPI for UserServerMock {
})
}
fn sign_out(&self, _token: &str) -> FutureResult<(), UserError> { FutureResult::new(async { Ok(()) }) }
fn sign_out(&self, _token: &str) -> FutureResult<(), FlowyError> { FutureResult::new(async { Ok(()) }) }
fn update_user(&self, _token: &str, _params: UpdateUserParams) -> FutureResult<(), UserError> {
fn update_user(&self, _token: &str, _params: UpdateUserParams) -> FutureResult<(), FlowyError> {
FutureResult::new(async { Ok(()) })
}
fn get_user(&self, _token: &str) -> FutureResult<UserProfile, UserError> {
fn get_user(&self, _token: &str) -> FutureResult<UserProfile, FlowyError> {
FutureResult::new(async { Ok(UserProfile::default()) })
}

View File

@ -1,4 +1,4 @@
use crate::errors::UserError;
use crate::errors::FlowyError;
use flowy_database::{DBConnection, Database};
use lazy_static::lazy_static;
use lib_sqlite::ConnectionPool;
@ -20,20 +20,20 @@ impl UserDB {
}
}
fn open_user_db(&self, user_id: &str) -> Result<(), UserError> {
fn open_user_db(&self, user_id: &str) -> Result<(), FlowyError> {
if user_id.is_empty() {
return Err(UserError::internal().context("user id is empty"));
return Err(FlowyError::internal().context("user id is empty"));
}
tracing::info!("open user db {}", user_id);
let dir = format!("{}/{}", self.db_dir, user_id);
let db = flowy_database::init(&dir).map_err(|e| {
log::error!("init user db failed, {:?}, user_id: {}", e, user_id);
UserError::internal().context(e)
FlowyError::internal().context(e)
})?;
match DB_MAP.try_write_for(Duration::from_millis(300)) {
None => Err(UserError::internal().context("Acquire write lock to save user db failed")),
None => Err(FlowyError::internal().context("Acquire write lock to save user db failed")),
Some(mut write_guard) => {
write_guard.insert(user_id.to_owned(), db);
Ok(())
@ -41,9 +41,9 @@ impl UserDB {
}
}
pub(crate) fn close_user_db(&self, user_id: &str) -> Result<(), UserError> {
pub(crate) fn close_user_db(&self, user_id: &str) -> Result<(), FlowyError> {
match DB_MAP.try_write_for(Duration::from_millis(300)) {
None => Err(UserError::internal().context("Acquire write lock to close user db failed")),
None => Err(FlowyError::internal().context("Acquire write lock to close user db failed")),
Some(mut write_guard) => {
set_user_db_init(false, user_id);
write_guard.remove(user_id);
@ -52,12 +52,12 @@ impl UserDB {
}
}
pub(crate) fn get_connection(&self, user_id: &str) -> Result<DBConnection, UserError> {
pub(crate) fn get_connection(&self, user_id: &str) -> Result<DBConnection, FlowyError> {
let conn = self.get_pool(user_id)?.get()?;
Ok(conn)
}
pub(crate) fn get_pool(&self, user_id: &str) -> Result<Arc<ConnectionPool>, UserError> {
pub(crate) fn get_pool(&self, user_id: &str) -> Result<Arc<ConnectionPool>, FlowyError> {
// Opti: INIT_LOCK try to lock the INIT_RECORD accesses. Because the write guard
// can not nested in the read guard that will cause the deadlock.
match INIT_LOCK.try_lock_for(Duration::from_millis(300)) {
@ -71,9 +71,11 @@ impl UserDB {
}
match DB_MAP.try_read_for(Duration::from_millis(300)) {
None => Err(UserError::internal().context("Acquire read lock to read user db failed")),
None => Err(FlowyError::internal().context("Acquire read lock to read user db failed")),
Some(read_guard) => match read_guard.get(user_id) {
None => Err(UserError::internal().context("Get connection failed. The database is not initialization")),
None => {
Err(FlowyError::internal().context("Get connection failed. The database is not initialization"))
},
Some(database) => Ok(database.get_pool()),
},
}

View File

@ -1,5 +1,5 @@
use crate::entities::{UserProfile, UserStatus};
use flowy_net::entities::NetworkType;
use tokio::sync::{broadcast, mpsc};
pub struct UserNotifier {

View File

@ -2,7 +2,7 @@ use std::sync::Arc;
use parking_lot::RwLock;
use serde::{Deserialize, Serialize};
use tokio::sync::{broadcast, mpsc};
use tokio::sync::mpsc;
use backend_service::configuration::ClientServerConfiguration;
use flowy_database::{
@ -18,7 +18,7 @@ use lib_sqlite::ConnectionPool;
use crate::{
entities::{SignInParams, SignUpParams, UpdateUserParams, UserProfile},
errors::{ErrorCode, UserError},
errors::{ErrorCode, FlowyError},
notify::*,
services::{
server::{construct_user_server, Server},
@ -26,7 +26,6 @@ use crate::{
},
sql_tables::{UserTable, UserTableChangeset},
};
use flowy_net::entities::NetworkState;
pub struct UserSessionConfig {
root_dir: String,
@ -73,7 +72,7 @@ impl UserSession {
}
}
pub fn db_connection(&self) -> Result<DBConnection, UserError> {
pub fn db_connection(&self) -> Result<DBConnection, FlowyError> {
let user_id = self.get_session()?.user_id;
self.database.get_connection(&user_id)
}
@ -84,13 +83,13 @@ impl UserSession {
//
// let pool = self.db_connection_pool()?;
// let conn: PooledConnection<ConnectionManager> = pool.get()?;
pub fn db_pool(&self) -> Result<Arc<ConnectionPool>, UserError> {
pub fn db_pool(&self) -> Result<Arc<ConnectionPool>, FlowyError> {
let user_id = self.get_session()?.user_id;
self.database.get_pool(&user_id)
}
#[tracing::instrument(level = "debug", skip(self))]
pub async fn sign_in(&self, params: SignInParams) -> Result<UserProfile, UserError> {
pub async fn sign_in(&self, params: SignInParams) -> Result<UserProfile, FlowyError> {
if self.is_login(&params.email) {
self.user_profile().await
} else {
@ -105,7 +104,7 @@ impl UserSession {
}
#[tracing::instrument(level = "debug", skip(self))]
pub async fn sign_up(&self, params: SignUpParams) -> Result<UserProfile, UserError> {
pub async fn sign_up(&self, params: SignUpParams) -> Result<UserProfile, FlowyError> {
if self.is_login(&params.email) {
self.user_profile().await
} else {
@ -123,7 +122,7 @@ impl UserSession {
}
#[tracing::instrument(level = "debug", skip(self))]
pub async fn sign_out(&self) -> Result<(), UserError> {
pub async fn sign_out(&self) -> Result<(), FlowyError> {
let session = self.get_session()?;
let _ =
diesel::delete(dsl::user_table.filter(dsl::id.eq(&session.user_id))).execute(&*(self.db_connection()?))?;
@ -136,7 +135,7 @@ impl UserSession {
}
#[tracing::instrument(level = "debug", skip(self))]
pub async fn update_user(&self, params: UpdateUserParams) -> Result<(), UserError> {
pub async fn update_user(&self, params: UpdateUserParams) -> Result<(), FlowyError> {
let session = self.get_session()?;
let changeset = UserTableChangeset::new(params.clone());
diesel_update_table!(user_table, changeset, &*self.db_connection()?);
@ -145,9 +144,9 @@ impl UserSession {
Ok(())
}
pub async fn init_user(&self) -> Result<(), UserError> { Ok(()) }
pub async fn init_user(&self) -> Result<(), FlowyError> { Ok(()) }
pub async fn check_user(&self) -> Result<UserProfile, UserError> {
pub async fn check_user(&self) -> Result<UserProfile, FlowyError> {
let (user_id, token) = self.get_session()?.into_part();
let user = dsl::user_table
@ -158,7 +157,7 @@ impl UserSession {
Ok(user.into())
}
pub async fn user_profile(&self) -> Result<UserProfile, UserError> {
pub async fn user_profile(&self) -> Result<UserProfile, FlowyError> {
let (user_id, token) = self.get_session()?.into_part();
let user = dsl::user_table
.filter(user_table::id.eq(&user_id))
@ -168,20 +167,20 @@ impl UserSession {
Ok(user.into())
}
pub fn user_dir(&self) -> Result<String, UserError> {
pub fn user_dir(&self) -> Result<String, FlowyError> {
let session = self.get_session()?;
Ok(format!("{}/{}", self.config.root_dir, session.user_id))
}
pub fn user_id(&self) -> Result<String, UserError> { Ok(self.get_session()?.user_id) }
pub fn user_id(&self) -> Result<String, FlowyError> { Ok(self.get_session()?.user_id) }
pub fn user_name(&self) -> Result<String, UserError> { Ok(self.get_session()?.name) }
pub fn user_name(&self) -> Result<String, FlowyError> { Ok(self.get_session()?.name) }
pub fn token(&self) -> Result<String, UserError> { Ok(self.get_session()?.token) }
pub fn token(&self) -> Result<String, FlowyError> { Ok(self.get_session()?.token) }
}
impl UserSession {
fn read_user_profile_on_server(&self, token: &str) -> Result<(), UserError> {
fn read_user_profile_on_server(&self, token: &str) -> Result<(), FlowyError> {
let server = self.server.clone();
let token = token.to_owned();
tokio::spawn(async move {
@ -201,7 +200,7 @@ impl UserSession {
Ok(())
}
async fn update_user_on_server(&self, token: &str, params: UpdateUserParams) -> Result<(), UserError> {
async fn update_user_on_server(&self, token: &str, params: UpdateUserParams) -> Result<(), FlowyError> {
let server = self.server.clone();
let token = token.to_owned();
let _ = tokio::spawn(async move {
@ -217,7 +216,7 @@ impl UserSession {
Ok(())
}
async fn sign_out_on_server(&self, token: &str) -> Result<(), UserError> {
async fn sign_out_on_server(&self, token: &str) -> Result<(), FlowyError> {
let server = self.server.clone();
let token = token.to_owned();
let _ = tokio::spawn(async move {
@ -230,7 +229,7 @@ impl UserSession {
Ok(())
}
async fn save_user(&self, user: UserTable) -> Result<UserTable, UserError> {
async fn save_user(&self, user: UserTable) -> Result<UserTable, FlowyError> {
let conn = self.db_connection()?;
let _ = diesel::insert_into(user_table::table)
.values(user.clone())
@ -238,19 +237,17 @@ impl UserSession {
Ok(user)
}
fn set_session(&self, session: Option<Session>) -> Result<(), UserError> {
fn set_session(&self, session: Option<Session>) -> Result<(), FlowyError> {
tracing::debug!("Set user session: {:?}", session);
match &session {
None => {
KV::remove(&self.config.session_cache_key).map_err(|e| UserError::new(ErrorCode::InternalError, &e))?
},
None => KV::remove(&self.config.session_cache_key).map_err(|e| FlowyError::new(ErrorCode::Internal, &e))?,
Some(session) => KV::set_str(&self.config.session_cache_key, session.clone().into()),
}
*self.session.write() = session;
Ok(())
}
fn get_session(&self) -> Result<Session, UserError> {
fn get_session(&self) -> Result<Session, FlowyError> {
let mut session = { (*self.session.read()).clone() };
if session.is_none() {
match KV::get_str(&self.config.session_cache_key) {
@ -263,7 +260,7 @@ impl UserSession {
}
match session {
None => Err(UserError::unauthorized()),
None => Err(FlowyError::unauthorized()),
Some(session) => Ok(session),
}
}
@ -280,7 +277,7 @@ pub async fn update_user(
_server: Server,
pool: Arc<ConnectionPool>,
params: UpdateUserParams,
) -> Result<(), UserError> {
) -> Result<(), FlowyError> {
let changeset = UserTableChangeset::new(params);
let conn = pool.get()?;
diesel_update_table!(user_table, changeset, &*conn);