mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
refactor errors
This commit is contained in:
@ -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" }
|
||||
|
@ -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(())
|
||||
|
@ -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(());
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
@ -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,
|
||||
|
@ -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};
|
||||
}
|
||||
|
@ -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))?;
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
})
|
||||
}
|
@ -4,8 +4,5 @@
|
||||
mod observable;
|
||||
pub use observable::*;
|
||||
|
||||
mod errors;
|
||||
pub use errors::*;
|
||||
|
||||
mod event;
|
||||
pub use event::*;
|
||||
|
@ -1,6 +0,0 @@
|
||||
syntax = "proto3";
|
||||
|
||||
message WorkspaceError {
|
||||
int32 code = 1;
|
||||
string msg = 2;
|
||||
}
|
@ -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(¶ms.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>(())
|
||||
// // }
|
||||
// // });
|
||||
// //
|
||||
|
@ -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(¶ms.app_id).await?;
|
||||
|
@ -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))?;
|
||||
|
@ -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(
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -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(())
|
||||
}
|
||||
|
@ -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(())
|
||||
}
|
||||
|
@ -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(¶ms.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(¶ms.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));
|
||||
|
@ -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(¶ms.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 ¶ms.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)
|
||||
|
@ -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))
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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(())
|
||||
}
|
||||
|
@ -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"}
|
||||
|
@ -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) }
|
||||
}
|
@ -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};
|
||||
}
|
||||
|
@ -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(¶ms.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
|
||||
|
@ -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()
|
||||
})
|
||||
}
|
@ -3,6 +3,3 @@
|
||||
|
||||
mod observable;
|
||||
pub use observable::*;
|
||||
|
||||
mod errors;
|
||||
pub use errors::*;
|
||||
|
@ -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;
|
||||
}
|
@ -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(¶ms.doc_id) {
|
||||
let edit_ctx = self.make_edit_context(¶ms.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 = ¶ms.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")
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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>(())))
|
||||
}
|
||||
}
|
||||
|
@ -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(())
|
||||
})
|
||||
|
@ -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();
|
||||
|
@ -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) => {
|
||||
|
@ -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()
|
||||
|
@ -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(
|
||||
|
@ -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)
|
||||
|
@ -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(()) })
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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"]
|
||||
|
@ -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) }
|
||||
}
|
||||
|
22
frontend/rust-lib/flowy-error/src/ext/backend.rs
Normal file
22
frontend/rust-lib/flowy-error/src/ext/backend.rs
Normal 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,
|
||||
}
|
||||
}
|
5
frontend/rust-lib/flowy-error/src/ext/collaborate.rs
Normal file
5
frontend/rust-lib/flowy-error/src/ext/collaborate.rs
Normal 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) }
|
||||
}
|
15
frontend/rust-lib/flowy-error/src/ext/database.rs
Normal file
15
frontend/rust-lib/flowy-error/src/ext/database.rs
Normal 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) }
|
||||
}
|
27
frontend/rust-lib/flowy-error/src/ext/mod.rs
Normal file
27
frontend/rust-lib/flowy-error/src/ext/mod.rs
Normal 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::*;
|
5
frontend/rust-lib/flowy-error/src/ext/ot.rs
Normal file
5
frontend/rust-lib/flowy-error/src/ext/ot.rs
Normal 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) }
|
||||
}
|
5
frontend/rust-lib/flowy-error/src/ext/serde.rs
Normal file
5
frontend/rust-lib/flowy-error/src/ext/serde.rs
Normal 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) }
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
mod errors;
|
||||
mod ext;
|
||||
pub mod protobuf;
|
||||
|
||||
pub use error_code::ErrorCode;
|
||||
pub use errors::*;
|
||||
|
@ -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;
|
||||
|
@ -4,6 +4,3 @@ message FlowyError {
|
||||
int32 code = 1;
|
||||
string msg = 2;
|
||||
}
|
||||
enum ErrorCode {
|
||||
Internal = 0;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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"] }
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
@ -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,
|
||||
|
@ -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?;
|
||||
|
||||
|
@ -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(())
|
||||
|
@ -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};
|
||||
}
|
||||
|
@ -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()
|
||||
})
|
||||
}
|
@ -4,8 +4,5 @@
|
||||
mod observable;
|
||||
pub use observable::*;
|
||||
|
||||
mod errors;
|
||||
pub use errors::*;
|
||||
|
||||
mod event;
|
||||
pub use event::*;
|
||||
|
@ -1,6 +0,0 @@
|
||||
syntax = "proto3";
|
||||
|
||||
message UserError {
|
||||
int32 code = 1;
|
||||
string msg = 2;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
// },
|
||||
|
@ -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()) })
|
||||
}
|
||||
|
||||
|
@ -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()),
|
||||
},
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::entities::{UserProfile, UserStatus};
|
||||
use flowy_net::entities::NetworkType;
|
||||
|
||||
use tokio::sync::{broadcast, mpsc};
|
||||
|
||||
pub struct UserNotifier {
|
||||
|
@ -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(¶ms.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(¶ms.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);
|
||||
|
Reference in New Issue
Block a user