From cea83238ebed8742efc1d56b5ab8d7ffc8469e0b Mon Sep 17 00:00:00 2001 From: appflowy Date: Fri, 10 Dec 2021 11:20:21 +0800 Subject: [PATCH 01/39] update ignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index a6c235ffa0..199285461d 100644 --- a/.gitignore +++ b/.gitignore @@ -13,5 +13,5 @@ Cargo.lock **/target/ **/*.db .idea/ -/flowy-test/ +**/flowy-test/** .ruby-version From 29c14949cb9ad22d3dd34b60c9eb767d63c1958c Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 6 Dec 2021 14:41:09 +0800 Subject: [PATCH 02/39] reanme flowy-workspace to flowy-core --- backend/Cargo.lock | 78 ++++---- .../user/presentation/skip_log_in_screen.dart | 2 +- .../workspace/application/app/app_bloc.dart | 2 +- .../workspace/application/doc/doc_bloc.dart | 2 +- .../workspace/application/doc/share_bloc.dart | 2 +- .../workspace/application/menu/menu_bloc.dart | 2 +- .../application/menu/menu_user_bloc.dart | 2 +- .../application/trash/trash_bloc.dart | 2 +- .../workspace/application/view/view_bloc.dart | 2 +- .../application/workspace/welcome_bloc.dart | 2 +- .../app_flowy/lib/workspace/domain/i_app.dart | 2 +- .../app_flowy/lib/workspace/domain/i_doc.dart | 2 +- .../lib/workspace/domain/i_share.dart | 2 +- .../lib/workspace/domain/i_trash.dart | 2 +- .../lib/workspace/domain/i_user.dart | 2 +- .../lib/workspace/domain/i_view.dart | 2 +- .../lib/workspace/domain/i_workspace.dart | 2 +- .../workspace/infrastructure/i_app_impl.dart | 2 +- .../workspace/infrastructure/i_doc_impl.dart | 2 +- .../infrastructure/i_share_impl.dart | 2 +- .../infrastructure/i_trash_impl.dart | 2 +- .../workspace/infrastructure/i_user_impl.dart | 6 +- .../workspace/infrastructure/i_view_impl.dart | 2 +- .../infrastructure/i_workspace_impl.dart | 2 +- .../infrastructure/repos/app_repo.dart | 6 +- .../infrastructure/repos/doc_repo.dart | 2 +- .../infrastructure/repos/helper.dart | 6 +- .../infrastructure/repos/share_repo.dart | 2 +- .../infrastructure/repos/trash_repo.dart | 6 +- .../infrastructure/repos/user_repo.dart | 2 +- .../infrastructure/repos/view_repo.dart | 6 +- .../infrastructure/repos/workspace_repo.dart | 6 +- .../stack_page/doc/doc_stack_page.dart | 2 +- .../flowy_sdk/lib/dispatch/dispatch.dart | 6 +- .../errors.pb.dart | 0 .../errors.pbenum.dart | 0 .../errors.pbjson.dart | 0 .../errors.pbserver.dart | 0 .../event.pb.dart | 0 .../event.pbenum.dart | 0 .../event.pbjson.dart | 0 .../event.pbserver.dart | 0 .../observable.pb.dart | 0 .../observable.pbenum.dart | 0 .../observable.pbjson.dart | 0 .../observable.pbserver.dart | 0 .../protobuf.dart | 0 .../protobuf/flowy-dart-notify/protobuf.dart | 2 - .../flowy-dart-notify/subject.pb.dart | 140 --------------- .../flowy-dart-notify/subject.pbenum.dart | 7 - .../flowy-dart-notify/subject.pbjson.dart | 28 --- .../flowy-dart-notify/subject.pbserver.dart | 9 - .../lib/protobuf/flowy-infra/kv.pb.dart | 167 ------------------ .../lib/protobuf/flowy-infra/kv.pbenum.dart | 7 - .../lib/protobuf/flowy-infra/kv.pbjson.dart | 30 ---- .../lib/protobuf/flowy-infra/kv.pbserver.dart | 9 - .../lib/protobuf/flowy-infra/protobuf.dart | 2 - .../lib/protobuf/flowy-ws/errors.pb.dart | 76 -------- .../lib/protobuf/flowy-ws/errors.pbenum.dart | 28 --- .../lib/protobuf/flowy-ws/errors.pbjson.dart | 33 ---- .../protobuf/flowy-ws/errors.pbserver.dart | 9 - .../lib/protobuf/flowy-ws/msg.pb.dart | 76 -------- .../lib/protobuf/flowy-ws/msg.pbenum.dart | 24 --- .../lib/protobuf/flowy-ws/msg.pbjson.dart | 31 ---- .../lib/protobuf/flowy-ws/msg.pbserver.dart | 9 - .../lib/protobuf/flowy-ws/protobuf.dart | 3 - .../packages/flowy_sdk/lib/rust_stream.dart | 2 +- frontend/rust-lib/Cargo.toml | 2 +- .../Cargo.toml | 2 +- .../Flowy.toml | 0 .../src/errors.rs | 0 .../src/event.rs | 0 .../src/handlers/app_handler.rs | 0 .../src/handlers/mod.rs | 0 .../src/handlers/trash_handler.rs | 0 .../src/handlers/view_handler.rs | 0 .../src/handlers/workspace_handler.rs | 0 .../src/lib.rs | 0 .../src/macros.rs | 0 .../src/module.rs | 0 .../src/notify/mod.rs | 0 .../src/notify/observable.rs | 0 .../src/protobuf/mod.rs | 0 .../src/protobuf/model/errors.rs | 0 .../src/protobuf/model/event.rs | 0 .../src/protobuf/model/mod.rs | 0 .../src/protobuf/model/observable.rs | 0 .../src/protobuf/proto/errors.proto | 0 .../src/protobuf/proto/event.proto | 0 .../src/protobuf/proto/observable.proto | 0 .../src/services/app_controller.rs | 0 .../src/services/database.rs | 0 .../src/services/mod.rs | 0 .../src/services/server/mod.rs | 0 .../src/services/server/server_api.rs | 0 .../src/services/server/server_api_mock.rs | 0 .../src/services/trash_can.rs | 0 .../src/services/view_controller.rs | 0 .../src/services/workspace_controller.rs | 0 .../src/sql_tables/app/app_sql.rs | 0 .../src/sql_tables/app/app_table.rs | 0 .../src/sql_tables/app/mod.rs | 0 .../src/sql_tables/mod.rs | 0 .../src/sql_tables/trash/mod.rs | 0 .../src/sql_tables/trash/trash_sql.rs | 0 .../src/sql_tables/trash/trash_table.rs | 0 .../src/sql_tables/view/mod.rs | 0 .../src/sql_tables/view/view_sql.rs | 0 .../src/sql_tables/view/view_table.rs | 0 .../src/sql_tables/workspace/mod.rs | 0 .../src/sql_tables/workspace/workspace_sql.rs | 0 .../sql_tables/workspace/workspace_table.rs | 0 .../src/util.rs | 0 .../tests/workspace/app_test.rs | 4 +- .../tests/workspace/main.rs | 0 .../tests/workspace/view_test.rs | 4 +- .../tests/workspace/workspace_test.rs | 4 +- frontend/rust-lib/flowy-sdk/Cargo.toml | 4 +- .../src/deps_resolve/workspace_deps.rs | 6 +- frontend/rust-lib/flowy-sdk/src/lib.rs | 4 +- frontend/rust-lib/flowy-sdk/src/module.rs | 4 +- frontend/rust-lib/flowy-test/Cargo.toml | 2 +- frontend/rust-lib/flowy-test/src/builder.rs | 2 +- frontend/rust-lib/flowy-test/src/helper.rs | 10 +- frontend/rust-lib/flowy-test/src/workspace.rs | 4 +- frontend/scripts/makefile/tests.toml | 2 +- 126 files changed, 114 insertions(+), 804 deletions(-) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace => flowy-core}/errors.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace => flowy-core}/errors.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace => flowy-core}/errors.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace => flowy-core}/errors.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace => flowy-core}/event.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace => flowy-core}/event.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace => flowy-core}/event.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace => flowy-core}/event.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace => flowy-core}/observable.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace => flowy-core}/observable.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace => flowy-core}/observable.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace => flowy-core}/observable.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace => flowy-core}/protobuf.dart (100%) delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-dart-notify/protobuf.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-dart-notify/subject.pb.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-dart-notify/subject.pbenum.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-dart-notify/subject.pbjson.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-dart-notify/subject.pbserver.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-infra/kv.pb.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-infra/kv.pbenum.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-infra/kv.pbjson.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-infra/kv.pbserver.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-infra/protobuf.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/errors.pb.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/errors.pbenum.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/errors.pbjson.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/errors.pbserver.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/msg.pb.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/msg.pbenum.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/msg.pbjson.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/msg.pbserver.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/protobuf.dart rename frontend/rust-lib/{flowy-workspace => flowy-core}/Cargo.toml (98%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/Flowy.toml (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/errors.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/event.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/handlers/app_handler.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/handlers/mod.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/handlers/trash_handler.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/handlers/view_handler.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/handlers/workspace_handler.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/lib.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/macros.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/module.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/notify/mod.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/notify/observable.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/protobuf/mod.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/protobuf/model/errors.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/protobuf/model/event.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/protobuf/model/mod.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/protobuf/model/observable.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/protobuf/proto/errors.proto (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/protobuf/proto/event.proto (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/protobuf/proto/observable.proto (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/services/app_controller.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/services/database.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/services/mod.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/services/server/mod.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/services/server/server_api.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/services/server/server_api_mock.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/services/trash_can.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/services/view_controller.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/services/workspace_controller.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/sql_tables/app/app_sql.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/sql_tables/app/app_table.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/sql_tables/app/mod.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/sql_tables/mod.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/sql_tables/trash/mod.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/sql_tables/trash/trash_sql.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/sql_tables/trash/trash_table.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/sql_tables/view/mod.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/sql_tables/view/view_sql.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/sql_tables/view/view_table.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/sql_tables/workspace/mod.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/sql_tables/workspace/workspace_sql.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/sql_tables/workspace/workspace_table.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/src/util.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/tests/workspace/app_test.rs (98%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/tests/workspace/main.rs (100%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/tests/workspace/view_test.rs (98%) rename frontend/rust-lib/{flowy-workspace => flowy-core}/tests/workspace/workspace_test.rs (99%) diff --git a/backend/Cargo.lock b/backend/Cargo.lock index bceb695223..7efe8c9b83 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -1195,6 +1195,43 @@ dependencies = [ "syn", ] +[[package]] +name = "flowy-core" +version = "0.1.0" +dependencies = [ + "backend-service", + "bincode", + "bytes", + "chrono", + "crossbeam", + "crossbeam-utils", + "dart-notify", + "derive_more", + "diesel", + "diesel_derives", + "flowy-database", + "flowy-derive", + "flowy-document", + "flowy-document-infra", + "flowy-workspace-infra", + "futures", + "futures-core", + "lazy_static", + "lib-dispatch", + "lib-infra", + "lib-ot", + "lib-sqlite", + "log", + "parking_lot", + "pin-project 1.0.8", + "protobuf", + "serde", + "strum", + "strum_macros", + "tokio", + "tracing", +] + [[package]] name = "flowy-database" version = "0.1.0" @@ -1280,11 +1317,11 @@ dependencies = [ "backend-service", "bytes", "color-eyre", + "flowy-core", "flowy-database", "flowy-document", "flowy-document-infra", "flowy-user", - "flowy-workspace", "futures-core", "lib-dispatch", "lib-infra", @@ -1304,11 +1341,11 @@ dependencies = [ "bincode", "bytes", "claim", + "flowy-core", "flowy-document", "flowy-document-infra", "flowy-sdk", "flowy-user", - "flowy-workspace", "futures-util", "lib-dispatch", "lib-infra", @@ -1369,43 +1406,6 @@ dependencies = [ "validator", ] -[[package]] -name = "flowy-workspace" -version = "0.1.0" -dependencies = [ - "backend-service", - "bincode", - "bytes", - "chrono", - "crossbeam", - "crossbeam-utils", - "dart-notify", - "derive_more", - "diesel", - "diesel_derives", - "flowy-database", - "flowy-derive", - "flowy-document", - "flowy-document-infra", - "flowy-workspace-infra", - "futures", - "futures-core", - "lazy_static", - "lib-dispatch", - "lib-infra", - "lib-ot", - "lib-sqlite", - "log", - "parking_lot", - "pin-project 1.0.8", - "protobuf", - "serde", - "strum", - "strum_macros", - "tokio", - "tracing", -] - [[package]] name = "flowy-workspace-infra" version = "0.1.0" diff --git a/frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart b/frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart index 2cd490baf9..972ee09285 100644 --- a/frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart +++ b/frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart @@ -10,7 +10,7 @@ import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart b/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart index 67b26580dc..c2af8cf871 100644 --- a/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart @@ -2,7 +2,7 @@ import 'package:app_flowy/workspace/domain/i_app.dart'; import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:dartz/dartz.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/doc/doc_bloc.dart b/frontend/app_flowy/lib/workspace/application/doc/doc_bloc.dart index e90749dd8c..67c7023c8a 100644 --- a/frontend/app_flowy/lib/workspace/application/doc/doc_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/doc/doc_bloc.dart @@ -4,7 +4,7 @@ import 'package:app_flowy/workspace/domain/i_trash.dart'; import 'package:app_flowy/workspace/domain/i_view.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/trash_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:flutter_quill/flutter_quill.dart'; import 'package:flowy_log/flowy_log.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/doc/share_bloc.dart b/frontend/app_flowy/lib/workspace/application/doc/share_bloc.dart index f81495a15a..bfb98d2528 100644 --- a/frontend/app_flowy/lib/workspace/application/doc/share_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/doc/share_bloc.dart @@ -2,7 +2,7 @@ import 'package:app_flowy/workspace/domain/i_share.dart'; import 'package:app_flowy/workspace/infrastructure/markdown/delta_markdown.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/export.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:dartz/dartz.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart b/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart index b6dac402f9..f78eef6e73 100644 --- a/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart @@ -5,7 +5,7 @@ import 'package:app_flowy/workspace/presentation/stack_page/blank/blank_page.dar import 'package:dartz/dartz.dart'; import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:flutter/material.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart b/frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart index 56635c0c89..bff016f9f9 100644 --- a/frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart @@ -2,7 +2,7 @@ import 'package:app_flowy/workspace/domain/i_user.dart'; import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:dartz/dartz.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/trash/trash_bloc.dart b/frontend/app_flowy/lib/workspace/application/trash/trash_bloc.dart index 2505128dd5..2d885d8ff9 100644 --- a/frontend/app_flowy/lib/workspace/application/trash/trash_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/trash/trash_bloc.dart @@ -2,7 +2,7 @@ import 'package:app_flowy/workspace/domain/i_trash.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/trash_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; part 'trash_bloc.freezed.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/view/view_bloc.dart b/frontend/app_flowy/lib/workspace/application/view/view_bloc.dart index ffd1a02466..59c00e44f3 100644 --- a/frontend/app_flowy/lib/workspace/application/view/view_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/view/view_bloc.dart @@ -1,6 +1,6 @@ import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:app_flowy/workspace/domain/i_view.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/workspace/welcome_bloc.dart b/frontend/app_flowy/lib/workspace/application/workspace/welcome_bloc.dart index b53c797744..faba9f421e 100644 --- a/frontend/app_flowy/lib/workspace/application/workspace/welcome_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/workspace/welcome_bloc.dart @@ -2,7 +2,7 @@ import 'package:app_flowy/workspace/domain/i_user.dart'; import 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart'; import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:dartz/dartz.dart'; diff --git a/frontend/app_flowy/lib/workspace/domain/i_app.dart b/frontend/app_flowy/lib/workspace/domain/i_app.dart index 42f14b9166..240ec54c55 100644 --- a/frontend/app_flowy/lib/workspace/domain/i_app.dart +++ b/frontend/app_flowy/lib/workspace/domain/i_app.dart @@ -2,7 +2,7 @@ import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart'; import 'package:dartz/dartz.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; typedef AppUpdatedCallback = void Function(App app); typedef AppViewsChangeCallback = void Function(Either, WorkspaceError> viewsOrFailed); diff --git a/frontend/app_flowy/lib/workspace/domain/i_doc.dart b/frontend/app_flowy/lib/workspace/domain/i_doc.dart index 7956e8fb2b..9092302b70 100644 --- a/frontend/app_flowy/lib/workspace/domain/i_doc.dart +++ b/frontend/app_flowy/lib/workspace/domain/i_doc.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/protobuf/flowy-document-infra/doc.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; abstract class IDoc { Future> readDoc(); diff --git a/frontend/app_flowy/lib/workspace/domain/i_share.dart b/frontend/app_flowy/lib/workspace/domain/i_share.dart index 8fa89111ce..8bf29ce153 100644 --- a/frontend/app_flowy/lib/workspace/domain/i_share.dart +++ b/frontend/app_flowy/lib/workspace/domain/i_share.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; abstract class IShare { Future> exportText(String docId); diff --git a/frontend/app_flowy/lib/workspace/domain/i_trash.dart b/frontend/app_flowy/lib/workspace/domain/i_trash.dart index da0777fde9..57de56e1c0 100644 --- a/frontend/app_flowy/lib/workspace/domain/i_trash.dart +++ b/frontend/app_flowy/lib/workspace/domain/i_trash.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/trash_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; abstract class ITrash { Future, WorkspaceError>> readTrash(); diff --git a/frontend/app_flowy/lib/workspace/domain/i_user.dart b/frontend/app_flowy/lib/workspace/domain/i_user.dart index bedb89c61e..95bc9398b0 100644 --- a/frontend/app_flowy/lib/workspace/domain/i_user.dart +++ b/frontend/app_flowy/lib/workspace/domain/i_user.dart @@ -3,7 +3,7 @@ import 'package:flowy_infra/notifier.dart'; import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; export 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart'; export 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile; diff --git a/frontend/app_flowy/lib/workspace/domain/i_view.dart b/frontend/app_flowy/lib/workspace/domain/i_view.dart index b65bb6ef05..bdddbfcad3 100644 --- a/frontend/app_flowy/lib/workspace/domain/i_view.dart +++ b/frontend/app_flowy/lib/workspace/domain/i_view.dart @@ -1,7 +1,7 @@ import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_infra/notifier.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; typedef ViewUpdatedCallback = void Function(Either); diff --git a/frontend/app_flowy/lib/workspace/domain/i_workspace.dart b/frontend/app_flowy/lib/workspace/domain/i_workspace.dart index 39c8c84924..9837689233 100644 --- a/frontend/app_flowy/lib/workspace/domain/i_workspace.dart +++ b/frontend/app_flowy/lib/workspace/domain/i_workspace.dart @@ -1,6 +1,6 @@ import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart'; import 'package:dartz/dartz.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; typedef WorkspaceAppsChangedCallback = void Function(Either, WorkspaceError> appsOrFail); diff --git a/frontend/app_flowy/lib/workspace/infrastructure/i_app_impl.dart b/frontend/app_flowy/lib/workspace/infrastructure/i_app_impl.dart index 5b6d4768a9..2eb71235b7 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/i_app_impl.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/i_app_impl.dart @@ -2,7 +2,7 @@ import 'package:app_flowy/workspace/infrastructure/repos/app_repo.dart'; import 'package:dartz/dartz.dart'; import 'package:app_flowy/workspace/domain/i_app.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; export 'package:app_flowy/workspace/domain/i_app.dart'; class IAppImpl extends IApp { diff --git a/frontend/app_flowy/lib/workspace/infrastructure/i_doc_impl.dart b/frontend/app_flowy/lib/workspace/infrastructure/i_doc_impl.dart index a290c96b56..141e4c45b4 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/i_doc_impl.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/i_doc_impl.dart @@ -5,7 +5,7 @@ import 'package:dartz/dartz.dart'; import 'package:app_flowy/workspace/domain/i_doc.dart'; import 'package:app_flowy/workspace/infrastructure/repos/doc_repo.dart'; import 'package:flowy_sdk/protobuf/flowy-document-infra/doc.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; class IDocImpl extends IDoc { DocRepository repo; diff --git a/frontend/app_flowy/lib/workspace/infrastructure/i_share_impl.dart b/frontend/app_flowy/lib/workspace/infrastructure/i_share_impl.dart index 05ef1f5c2c..e57df7f516 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/i_share_impl.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/i_share_impl.dart @@ -1,6 +1,6 @@ import 'package:app_flowy/workspace/domain/i_share.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:dartz/dartz.dart'; import 'repos/share_repo.dart'; diff --git a/frontend/app_flowy/lib/workspace/infrastructure/i_trash_impl.dart b/frontend/app_flowy/lib/workspace/infrastructure/i_trash_impl.dart index fb6bae0b9d..fa73c11704 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/i_trash_impl.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/i_trash_impl.dart @@ -2,7 +2,7 @@ import 'package:app_flowy/workspace/domain/i_trash.dart'; import 'package:app_flowy/workspace/infrastructure/repos/trash_repo.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/trash_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; class ITrashImpl implements ITrash { TrashRepo repo; diff --git a/frontend/app_flowy/lib/workspace/infrastructure/i_user_impl.dart b/frontend/app_flowy/lib/workspace/infrastructure/i_user_impl.dart index a65726784a..d1e5ec7f42 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/i_user_impl.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/i_user_impl.dart @@ -5,13 +5,13 @@ import 'package:dartz/dartz.dart'; import 'package:app_flowy/workspace/domain/i_user.dart'; import 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart'; import 'package:flowy_infra/notifier.dart'; -import 'package:flowy_sdk/protobuf/flowy-dart-notify/protobuf.dart'; +import 'package:flowy_sdk/protobuf/dart-notify/protobuf.dart'; import 'package:flowy_sdk/protobuf/flowy-user-infra/errors.pb.dart'; // import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart' as user_error; import 'package:flowy_sdk/protobuf/flowy-user/observable.pb.dart' as user; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/observable.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/observable.pb.dart'; export 'package:app_flowy/workspace/domain/i_user.dart'; export 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart'; import 'package:flowy_sdk/rust_stream.dart'; diff --git a/frontend/app_flowy/lib/workspace/infrastructure/i_view_impl.dart b/frontend/app_flowy/lib/workspace/infrastructure/i_view_impl.dart index 64ccd3b32a..c737076b4e 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/i_view_impl.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/i_view_impl.dart @@ -3,7 +3,7 @@ import 'package:app_flowy/workspace/infrastructure/repos/view_repo.dart'; import 'package:flowy_infra/notifier.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; class IViewImpl extends IView { ViewRepository repo; diff --git a/frontend/app_flowy/lib/workspace/infrastructure/i_workspace_impl.dart b/frontend/app_flowy/lib/workspace/infrastructure/i_workspace_impl.dart index b528b977b4..1d1826b600 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/i_workspace_impl.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/i_workspace_impl.dart @@ -2,7 +2,7 @@ import 'package:app_flowy/workspace/domain/i_workspace.dart'; import 'package:app_flowy/workspace/infrastructure/repos/workspace_repo.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; export 'package:app_flowy/workspace/domain/i_workspace.dart'; diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/app_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/app_repo.dart index 27096b49a7..d915ed4487 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/app_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/app_repo.dart @@ -4,14 +4,14 @@ import 'package:app_flowy/workspace/domain/i_app.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; -import 'package:flowy_sdk/protobuf/flowy-dart-notify/subject.pb.dart'; +import 'package:flowy_sdk/protobuf/dart-notify/subject.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_query.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_update.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pbenum.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/observable.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/observable.pb.dart'; import 'package:flowy_sdk/rust_stream.dart'; import 'helper.dart'; diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/doc_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/doc_repo.dart index 3b0b14a675..b56afffd9f 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/doc_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/doc_repo.dart @@ -2,7 +2,7 @@ import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-document-infra/doc.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_query.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; class DocRepository { final String docId; diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/helper.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/helper.dart index a3ad4fee07..2110e6f725 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/helper.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/helper.dart @@ -1,9 +1,9 @@ import 'dart:typed_data'; -import 'package:flowy_sdk/protobuf/flowy-dart-notify/protobuf.dart'; +import 'package:flowy_sdk/protobuf/dart-notify/protobuf.dart'; import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart'; import 'package:dartz/dartz.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/observable.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/observable.pb.dart'; typedef UserNotificationCallback = void Function(UserNotification, Either); diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/share_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/share_repo.dart index de9482859f..52c72912f3 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/share_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/share_repo.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; class ShareRepo { Future> export(String docId, ExportType type) { diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/trash_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/trash_repo.dart index 5ff35117e1..67123d9264 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/trash_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/trash_repo.dart @@ -4,10 +4,10 @@ import 'package:app_flowy/workspace/domain/i_trash.dart'; import 'package:app_flowy/workspace/infrastructure/repos/helper.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; -import 'package:flowy_sdk/protobuf/flowy-dart-notify/subject.pb.dart'; +import 'package:flowy_sdk/protobuf/dart-notify/subject.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/trash_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/observable.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/observable.pb.dart'; import 'package:flowy_sdk/rust_stream.dart'; class TrashRepo { diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/user_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/user_repo.dart index 19c3308d59..fd613f2f6e 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/user_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/user_repo.dart @@ -6,7 +6,7 @@ import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProf import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_query.pb.dart'; import 'package:app_flowy/workspace/domain/i_user.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; class UserRepo { final UserProfile user; diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/view_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/view_repo.dart index a3a809ef7b..7fd2735abe 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/view_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/view_repo.dart @@ -2,12 +2,12 @@ import 'dart:async'; import 'dart:typed_data'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; -import 'package:flowy_sdk/protobuf/flowy-dart-notify/subject.pb.dart'; +import 'package:flowy_sdk/protobuf/dart-notify/subject.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_query.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_update.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/observable.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/observable.pb.dart'; import 'package:flowy_sdk/rust_stream.dart'; import 'package:app_flowy/workspace/domain/i_view.dart'; diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/workspace_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/workspace_repo.dart index 59f0e5b482..e7faf31091 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/workspace_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/workspace_repo.dart @@ -5,13 +5,13 @@ import 'package:dartz/dartz.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; -import 'package:flowy_sdk/protobuf/flowy-dart-notify/subject.pb.dart'; +import 'package:flowy_sdk/protobuf/dart-notify/subject.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_query.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/observable.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/observable.pb.dart'; import 'package:flowy_sdk/rust_stream.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart index 024b02d8e1..d1b7f7ca8d 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart @@ -14,7 +14,7 @@ import 'package:flowy_infra_ui/widget/rounded_button.dart'; import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/export.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:flutter/material.dart'; import 'package:dartz/dartz.dart' as dartz; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart index 58b7b88e28..0672da7200 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart @@ -4,8 +4,8 @@ import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_sdk/protobuf/dart-ffi/ffi_response.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user/event.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/event.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core/event.pb.dart'; import 'package:flowy_sdk/protobuf/lib-infra/network_state.pb.dart'; import 'package:isolates/isolates.dart'; import 'package:isolates/ports.dart'; @@ -21,7 +21,7 @@ import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart'; import 'package:flowy_sdk/protobuf/flowy-document-infra/protobuf.dart'; // ignore: unused_import -import 'package:flowy_sdk/protobuf/flowy-infra/protobuf.dart'; +import 'package:flowy_sdk/protobuf/lib-infra/protobuf.dart'; import 'package:protobuf/protobuf.dart'; import 'dart:convert' show utf8; import 'error.dart'; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/errors.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/errors.pb.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/errors.pb.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/errors.pb.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/errors.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/errors.pbenum.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/errors.pbenum.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/errors.pbenum.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/errors.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/errors.pbjson.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/errors.pbjson.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/errors.pbjson.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/errors.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/errors.pbserver.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/errors.pbserver.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/errors.pbserver.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/event.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/event.pb.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/event.pb.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/event.pb.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/event.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/event.pbenum.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/event.pbenum.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/event.pbenum.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/event.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/event.pbjson.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/event.pbjson.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/event.pbjson.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/event.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/event.pbserver.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/event.pbserver.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/event.pbserver.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/observable.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/observable.pb.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/observable.pb.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/observable.pb.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/observable.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/observable.pbenum.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/observable.pbenum.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/observable.pbenum.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/observable.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/observable.pbjson.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/observable.pbjson.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/observable.pbjson.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/observable.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/observable.pbserver.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/observable.pbserver.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/observable.pbserver.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/protobuf.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/protobuf.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/protobuf.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/protobuf.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-dart-notify/protobuf.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-dart-notify/protobuf.dart deleted file mode 100644 index 6f21b675f3..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-dart-notify/protobuf.dart +++ /dev/null @@ -1,2 +0,0 @@ -// Auto-generated, do not edit -export './subject.pb.dart'; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-dart-notify/subject.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-dart-notify/subject.pb.dart deleted file mode 100644 index 828600c49e..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-dart-notify/subject.pb.dart +++ /dev/null @@ -1,140 +0,0 @@ -/// -// Generated code. Do not modify. -// source: subject.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields - -import 'dart:core' as $core; - -import 'package:protobuf/protobuf.dart' as $pb; - -enum SubscribeObject_OneOfPayload { - payload, - notSet -} - -enum SubscribeObject_OneOfError { - error, - notSet -} - -class SubscribeObject extends $pb.GeneratedMessage { - static const $core.Map<$core.int, SubscribeObject_OneOfPayload> _SubscribeObject_OneOfPayloadByTag = { - 4 : SubscribeObject_OneOfPayload.payload, - 0 : SubscribeObject_OneOfPayload.notSet - }; - static const $core.Map<$core.int, SubscribeObject_OneOfError> _SubscribeObject_OneOfErrorByTag = { - 5 : SubscribeObject_OneOfError.error, - 0 : SubscribeObject_OneOfError.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'SubscribeObject', createEmptyInstance: create) - ..oo(0, [4]) - ..oo(1, [5]) - ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'source') - ..a<$core.int>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'ty', $pb.PbFieldType.O3) - ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id') - ..a<$core.List<$core.int>>(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'payload', $pb.PbFieldType.OY) - ..a<$core.List<$core.int>>(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'error', $pb.PbFieldType.OY) - ..hasRequiredFields = false - ; - - SubscribeObject._() : super(); - factory SubscribeObject({ - $core.String? source, - $core.int? ty, - $core.String? id, - $core.List<$core.int>? payload, - $core.List<$core.int>? error, - }) { - final _result = create(); - if (source != null) { - _result.source = source; - } - if (ty != null) { - _result.ty = ty; - } - if (id != null) { - _result.id = id; - } - if (payload != null) { - _result.payload = payload; - } - if (error != null) { - _result.error = error; - } - return _result; - } - factory SubscribeObject.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory SubscribeObject.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' - 'Will be removed in next major version') - SubscribeObject clone() => SubscribeObject()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - SubscribeObject copyWith(void Function(SubscribeObject) updates) => super.copyWith((message) => updates(message as SubscribeObject)) as SubscribeObject; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static SubscribeObject create() => SubscribeObject._(); - SubscribeObject createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static SubscribeObject getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static SubscribeObject? _defaultInstance; - - SubscribeObject_OneOfPayload whichOneOfPayload() => _SubscribeObject_OneOfPayloadByTag[$_whichOneof(0)]!; - void clearOneOfPayload() => clearField($_whichOneof(0)); - - SubscribeObject_OneOfError whichOneOfError() => _SubscribeObject_OneOfErrorByTag[$_whichOneof(1)]!; - void clearOneOfError() => clearField($_whichOneof(1)); - - @$pb.TagNumber(1) - $core.String get source => $_getSZ(0); - @$pb.TagNumber(1) - set source($core.String v) { $_setString(0, v); } - @$pb.TagNumber(1) - $core.bool hasSource() => $_has(0); - @$pb.TagNumber(1) - void clearSource() => clearField(1); - - @$pb.TagNumber(2) - $core.int get ty => $_getIZ(1); - @$pb.TagNumber(2) - set ty($core.int v) { $_setSignedInt32(1, v); } - @$pb.TagNumber(2) - $core.bool hasTy() => $_has(1); - @$pb.TagNumber(2) - void clearTy() => clearField(2); - - @$pb.TagNumber(3) - $core.String get id => $_getSZ(2); - @$pb.TagNumber(3) - set id($core.String v) { $_setString(2, v); } - @$pb.TagNumber(3) - $core.bool hasId() => $_has(2); - @$pb.TagNumber(3) - void clearId() => clearField(3); - - @$pb.TagNumber(4) - $core.List<$core.int> get payload => $_getN(3); - @$pb.TagNumber(4) - set payload($core.List<$core.int> v) { $_setBytes(3, v); } - @$pb.TagNumber(4) - $core.bool hasPayload() => $_has(3); - @$pb.TagNumber(4) - void clearPayload() => clearField(4); - - @$pb.TagNumber(5) - $core.List<$core.int> get error => $_getN(4); - @$pb.TagNumber(5) - set error($core.List<$core.int> v) { $_setBytes(4, v); } - @$pb.TagNumber(5) - $core.bool hasError() => $_has(4); - @$pb.TagNumber(5) - void clearError() => clearField(5); -} - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-dart-notify/subject.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-dart-notify/subject.pbenum.dart deleted file mode 100644 index 7ae7ff12c2..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-dart-notify/subject.pbenum.dart +++ /dev/null @@ -1,7 +0,0 @@ -/// -// Generated code. Do not modify. -// source: subject.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-dart-notify/subject.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-dart-notify/subject.pbjson.dart deleted file mode 100644 index 8d8b238ba4..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-dart-notify/subject.pbjson.dart +++ /dev/null @@ -1,28 +0,0 @@ -/// -// Generated code. Do not modify. -// source: subject.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package - -import 'dart:core' as $core; -import 'dart:convert' as $convert; -import 'dart:typed_data' as $typed_data; -@$core.Deprecated('Use subscribeObjectDescriptor instead') -const SubscribeObject$json = const { - '1': 'SubscribeObject', - '2': const [ - const {'1': 'source', '3': 1, '4': 1, '5': 9, '10': 'source'}, - const {'1': 'ty', '3': 2, '4': 1, '5': 5, '10': 'ty'}, - const {'1': 'id', '3': 3, '4': 1, '5': 9, '10': 'id'}, - const {'1': 'payload', '3': 4, '4': 1, '5': 12, '9': 0, '10': 'payload'}, - const {'1': 'error', '3': 5, '4': 1, '5': 12, '9': 1, '10': 'error'}, - ], - '8': const [ - const {'1': 'one_of_payload'}, - const {'1': 'one_of_error'}, - ], -}; - -/// Descriptor for `SubscribeObject`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List subscribeObjectDescriptor = $convert.base64Decode('Cg9TdWJzY3JpYmVPYmplY3QSFgoGc291cmNlGAEgASgJUgZzb3VyY2USDgoCdHkYAiABKAVSAnR5Eg4KAmlkGAMgASgJUgJpZBIaCgdwYXlsb2FkGAQgASgMSABSB3BheWxvYWQSFgoFZXJyb3IYBSABKAxIAVIFZXJyb3JCEAoOb25lX29mX3BheWxvYWRCDgoMb25lX29mX2Vycm9y'); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-dart-notify/subject.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-dart-notify/subject.pbserver.dart deleted file mode 100644 index 1e092ab75a..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-dart-notify/subject.pbserver.dart +++ /dev/null @@ -1,9 +0,0 @@ -/// -// Generated code. Do not modify. -// source: subject.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package - -export 'subject.pb.dart'; - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-infra/kv.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-infra/kv.pb.dart deleted file mode 100644 index 971c06cd0a..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-infra/kv.pb.dart +++ /dev/null @@ -1,167 +0,0 @@ -/// -// Generated code. Do not modify. -// source: kv.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields - -import 'dart:core' as $core; - -import 'package:fixnum/fixnum.dart' as $fixnum; -import 'package:protobuf/protobuf.dart' as $pb; - -enum KeyValue_OneOfStrValue { - strValue, - notSet -} - -enum KeyValue_OneOfIntValue { - intValue, - notSet -} - -enum KeyValue_OneOfFloatValue { - floatValue, - notSet -} - -enum KeyValue_OneOfBoolValue { - boolValue, - notSet -} - -class KeyValue extends $pb.GeneratedMessage { - static const $core.Map<$core.int, KeyValue_OneOfStrValue> _KeyValue_OneOfStrValueByTag = { - 2 : KeyValue_OneOfStrValue.strValue, - 0 : KeyValue_OneOfStrValue.notSet - }; - static const $core.Map<$core.int, KeyValue_OneOfIntValue> _KeyValue_OneOfIntValueByTag = { - 3 : KeyValue_OneOfIntValue.intValue, - 0 : KeyValue_OneOfIntValue.notSet - }; - static const $core.Map<$core.int, KeyValue_OneOfFloatValue> _KeyValue_OneOfFloatValueByTag = { - 4 : KeyValue_OneOfFloatValue.floatValue, - 0 : KeyValue_OneOfFloatValue.notSet - }; - static const $core.Map<$core.int, KeyValue_OneOfBoolValue> _KeyValue_OneOfBoolValueByTag = { - 5 : KeyValue_OneOfBoolValue.boolValue, - 0 : KeyValue_OneOfBoolValue.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'KeyValue', createEmptyInstance: create) - ..oo(0, [2]) - ..oo(1, [3]) - ..oo(2, [4]) - ..oo(3, [5]) - ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'key') - ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'strValue') - ..aInt64(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'intValue') - ..a<$core.double>(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'floatValue', $pb.PbFieldType.OD) - ..aOB(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'boolValue') - ..hasRequiredFields = false - ; - - KeyValue._() : super(); - factory KeyValue({ - $core.String? key, - $core.String? strValue, - $fixnum.Int64? intValue, - $core.double? floatValue, - $core.bool? boolValue, - }) { - final _result = create(); - if (key != null) { - _result.key = key; - } - if (strValue != null) { - _result.strValue = strValue; - } - if (intValue != null) { - _result.intValue = intValue; - } - if (floatValue != null) { - _result.floatValue = floatValue; - } - if (boolValue != null) { - _result.boolValue = boolValue; - } - return _result; - } - factory KeyValue.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory KeyValue.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' - 'Will be removed in next major version') - KeyValue clone() => KeyValue()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - KeyValue copyWith(void Function(KeyValue) updates) => super.copyWith((message) => updates(message as KeyValue)) as KeyValue; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static KeyValue create() => KeyValue._(); - KeyValue createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static KeyValue getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static KeyValue? _defaultInstance; - - KeyValue_OneOfStrValue whichOneOfStrValue() => _KeyValue_OneOfStrValueByTag[$_whichOneof(0)]!; - void clearOneOfStrValue() => clearField($_whichOneof(0)); - - KeyValue_OneOfIntValue whichOneOfIntValue() => _KeyValue_OneOfIntValueByTag[$_whichOneof(1)]!; - void clearOneOfIntValue() => clearField($_whichOneof(1)); - - KeyValue_OneOfFloatValue whichOneOfFloatValue() => _KeyValue_OneOfFloatValueByTag[$_whichOneof(2)]!; - void clearOneOfFloatValue() => clearField($_whichOneof(2)); - - KeyValue_OneOfBoolValue whichOneOfBoolValue() => _KeyValue_OneOfBoolValueByTag[$_whichOneof(3)]!; - void clearOneOfBoolValue() => clearField($_whichOneof(3)); - - @$pb.TagNumber(1) - $core.String get key => $_getSZ(0); - @$pb.TagNumber(1) - set key($core.String v) { $_setString(0, v); } - @$pb.TagNumber(1) - $core.bool hasKey() => $_has(0); - @$pb.TagNumber(1) - void clearKey() => clearField(1); - - @$pb.TagNumber(2) - $core.String get strValue => $_getSZ(1); - @$pb.TagNumber(2) - set strValue($core.String v) { $_setString(1, v); } - @$pb.TagNumber(2) - $core.bool hasStrValue() => $_has(1); - @$pb.TagNumber(2) - void clearStrValue() => clearField(2); - - @$pb.TagNumber(3) - $fixnum.Int64 get intValue => $_getI64(2); - @$pb.TagNumber(3) - set intValue($fixnum.Int64 v) { $_setInt64(2, v); } - @$pb.TagNumber(3) - $core.bool hasIntValue() => $_has(2); - @$pb.TagNumber(3) - void clearIntValue() => clearField(3); - - @$pb.TagNumber(4) - $core.double get floatValue => $_getN(3); - @$pb.TagNumber(4) - set floatValue($core.double v) { $_setDouble(3, v); } - @$pb.TagNumber(4) - $core.bool hasFloatValue() => $_has(3); - @$pb.TagNumber(4) - void clearFloatValue() => clearField(4); - - @$pb.TagNumber(5) - $core.bool get boolValue => $_getBF(4); - @$pb.TagNumber(5) - set boolValue($core.bool v) { $_setBool(4, v); } - @$pb.TagNumber(5) - $core.bool hasBoolValue() => $_has(4); - @$pb.TagNumber(5) - void clearBoolValue() => clearField(5); -} - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-infra/kv.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-infra/kv.pbenum.dart deleted file mode 100644 index 79c2244e07..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-infra/kv.pbenum.dart +++ /dev/null @@ -1,7 +0,0 @@ -/// -// Generated code. Do not modify. -// source: kv.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-infra/kv.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-infra/kv.pbjson.dart deleted file mode 100644 index 45152125bb..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-infra/kv.pbjson.dart +++ /dev/null @@ -1,30 +0,0 @@ -/// -// Generated code. Do not modify. -// source: kv.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package - -import 'dart:core' as $core; -import 'dart:convert' as $convert; -import 'dart:typed_data' as $typed_data; -@$core.Deprecated('Use keyValueDescriptor instead') -const KeyValue$json = const { - '1': 'KeyValue', - '2': const [ - const {'1': 'key', '3': 1, '4': 1, '5': 9, '10': 'key'}, - const {'1': 'str_value', '3': 2, '4': 1, '5': 9, '9': 0, '10': 'strValue'}, - const {'1': 'int_value', '3': 3, '4': 1, '5': 3, '9': 1, '10': 'intValue'}, - const {'1': 'float_value', '3': 4, '4': 1, '5': 1, '9': 2, '10': 'floatValue'}, - const {'1': 'bool_value', '3': 5, '4': 1, '5': 8, '9': 3, '10': 'boolValue'}, - ], - '8': const [ - const {'1': 'one_of_str_value'}, - const {'1': 'one_of_int_value'}, - const {'1': 'one_of_float_value'}, - const {'1': 'one_of_bool_value'}, - ], -}; - -/// Descriptor for `KeyValue`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List keyValueDescriptor = $convert.base64Decode('CghLZXlWYWx1ZRIQCgNrZXkYASABKAlSA2tleRIdCglzdHJfdmFsdWUYAiABKAlIAFIIc3RyVmFsdWUSHQoJaW50X3ZhbHVlGAMgASgDSAFSCGludFZhbHVlEiEKC2Zsb2F0X3ZhbHVlGAQgASgBSAJSCmZsb2F0VmFsdWUSHwoKYm9vbF92YWx1ZRgFIAEoCEgDUglib29sVmFsdWVCEgoQb25lX29mX3N0cl92YWx1ZUISChBvbmVfb2ZfaW50X3ZhbHVlQhQKEm9uZV9vZl9mbG9hdF92YWx1ZUITChFvbmVfb2ZfYm9vbF92YWx1ZQ=='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-infra/kv.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-infra/kv.pbserver.dart deleted file mode 100644 index 0daeedf5a6..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-infra/kv.pbserver.dart +++ /dev/null @@ -1,9 +0,0 @@ -/// -// Generated code. Do not modify. -// source: kv.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package - -export 'kv.pb.dart'; - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-infra/protobuf.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-infra/protobuf.dart deleted file mode 100644 index ccc75e7e37..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-infra/protobuf.dart +++ /dev/null @@ -1,2 +0,0 @@ -// Auto-generated, do not edit -export './kv.pb.dart'; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/errors.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/errors.pb.dart deleted file mode 100644 index 63c73c28f3..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/errors.pb.dart +++ /dev/null @@ -1,76 +0,0 @@ -/// -// Generated code. Do not modify. -// source: errors.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields - -import 'dart:core' as $core; - -import 'package:protobuf/protobuf.dart' as $pb; - -import 'errors.pbenum.dart'; - -export 'errors.pbenum.dart'; - -class WsError extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'WsError', createEmptyInstance: create) - ..e(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'code', $pb.PbFieldType.OE, defaultOrMaker: ErrorCode.InternalError, valueOf: ErrorCode.valueOf, enumValues: ErrorCode.values) - ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'msg') - ..hasRequiredFields = false - ; - - WsError._() : super(); - factory WsError({ - ErrorCode? code, - $core.String? msg, - }) { - final _result = create(); - if (code != null) { - _result.code = code; - } - if (msg != null) { - _result.msg = msg; - } - return _result; - } - factory WsError.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory WsError.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' - 'Will be removed in next major version') - WsError clone() => WsError()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - WsError copyWith(void Function(WsError) updates) => super.copyWith((message) => updates(message as WsError)) as WsError; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static WsError create() => WsError._(); - WsError createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static WsError getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static WsError? _defaultInstance; - - @$pb.TagNumber(1) - ErrorCode get code => $_getN(0); - @$pb.TagNumber(1) - set code(ErrorCode v) { setField(1, v); } - @$pb.TagNumber(1) - $core.bool hasCode() => $_has(0); - @$pb.TagNumber(1) - void clearCode() => clearField(1); - - @$pb.TagNumber(2) - $core.String get msg => $_getSZ(1); - @$pb.TagNumber(2) - set msg($core.String v) { $_setString(1, v); } - @$pb.TagNumber(2) - $core.bool hasMsg() => $_has(1); - @$pb.TagNumber(2) - void clearMsg() => clearField(2); -} - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/errors.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/errors.pbenum.dart deleted file mode 100644 index 215409e69c..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/errors.pbenum.dart +++ /dev/null @@ -1,28 +0,0 @@ -/// -// Generated code. Do not modify. -// source: errors.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields - -// ignore_for_file: UNDEFINED_SHOWN_NAME -import 'dart:core' as $core; -import 'package:protobuf/protobuf.dart' as $pb; - -class ErrorCode extends $pb.ProtobufEnum { - static const ErrorCode InternalError = ErrorCode._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'InternalError'); - static const ErrorCode UnsupportedMessage = ErrorCode._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UnsupportedMessage'); - static const ErrorCode Unauthorized = ErrorCode._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Unauthorized'); - - static const $core.List values = [ - InternalError, - UnsupportedMessage, - Unauthorized, - ]; - - static final $core.Map<$core.int, ErrorCode> _byValue = $pb.ProtobufEnum.initByValue(values); - static ErrorCode? valueOf($core.int value) => _byValue[value]; - - const ErrorCode._($core.int v, $core.String n) : super(v, n); -} - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/errors.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/errors.pbjson.dart deleted file mode 100644 index c1039debcf..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/errors.pbjson.dart +++ /dev/null @@ -1,33 +0,0 @@ -/// -// Generated code. Do not modify. -// source: errors.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package - -import 'dart:core' as $core; -import 'dart:convert' as $convert; -import 'dart:typed_data' as $typed_data; -@$core.Deprecated('Use errorCodeDescriptor instead') -const ErrorCode$json = const { - '1': 'ErrorCode', - '2': const [ - const {'1': 'InternalError', '2': 0}, - const {'1': 'UnsupportedMessage', '2': 1}, - const {'1': 'Unauthorized', '2': 2}, - ], -}; - -/// Descriptor for `ErrorCode`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSEQoNSW50ZXJuYWxFcnJvchAAEhYKElVuc3VwcG9ydGVkTWVzc2FnZRABEhAKDFVuYXV0aG9yaXplZBAC'); -@$core.Deprecated('Use wsErrorDescriptor instead') -const WsError$json = const { - '1': 'WsError', - '2': const [ - const {'1': 'code', '3': 1, '4': 1, '5': 14, '6': '.ErrorCode', '10': 'code'}, - const {'1': 'msg', '3': 2, '4': 1, '5': 9, '10': 'msg'}, - ], -}; - -/// Descriptor for `WsError`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List wsErrorDescriptor = $convert.base64Decode('CgdXc0Vycm9yEh4KBGNvZGUYASABKA4yCi5FcnJvckNvZGVSBGNvZGUSEAoDbXNnGAIgASgJUgNtc2c='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/errors.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/errors.pbserver.dart deleted file mode 100644 index 18b02b9216..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/errors.pbserver.dart +++ /dev/null @@ -1,9 +0,0 @@ -/// -// Generated code. Do not modify. -// source: errors.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package - -export 'errors.pb.dart'; - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/msg.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/msg.pb.dart deleted file mode 100644 index 0c07e01026..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/msg.pb.dart +++ /dev/null @@ -1,76 +0,0 @@ -/// -// Generated code. Do not modify. -// source: msg.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields - -import 'dart:core' as $core; - -import 'package:protobuf/protobuf.dart' as $pb; - -import 'msg.pbenum.dart'; - -export 'msg.pbenum.dart'; - -class WsMessage extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'WsMessage', createEmptyInstance: create) - ..e(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'module', $pb.PbFieldType.OE, defaultOrMaker: WsModule.Doc, valueOf: WsModule.valueOf, enumValues: WsModule.values) - ..a<$core.List<$core.int>>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data', $pb.PbFieldType.OY) - ..hasRequiredFields = false - ; - - WsMessage._() : super(); - factory WsMessage({ - WsModule? module, - $core.List<$core.int>? data, - }) { - final _result = create(); - if (module != null) { - _result.module = module; - } - if (data != null) { - _result.data = data; - } - return _result; - } - factory WsMessage.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory WsMessage.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' - 'Will be removed in next major version') - WsMessage clone() => WsMessage()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - WsMessage copyWith(void Function(WsMessage) updates) => super.copyWith((message) => updates(message as WsMessage)) as WsMessage; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static WsMessage create() => WsMessage._(); - WsMessage createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static WsMessage getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static WsMessage? _defaultInstance; - - @$pb.TagNumber(1) - WsModule get module => $_getN(0); - @$pb.TagNumber(1) - set module(WsModule v) { setField(1, v); } - @$pb.TagNumber(1) - $core.bool hasModule() => $_has(0); - @$pb.TagNumber(1) - void clearModule() => clearField(1); - - @$pb.TagNumber(2) - $core.List<$core.int> get data => $_getN(1); - @$pb.TagNumber(2) - set data($core.List<$core.int> v) { $_setBytes(1, v); } - @$pb.TagNumber(2) - $core.bool hasData() => $_has(1); - @$pb.TagNumber(2) - void clearData() => clearField(2); -} - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/msg.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/msg.pbenum.dart deleted file mode 100644 index dddbfe6eaa..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/msg.pbenum.dart +++ /dev/null @@ -1,24 +0,0 @@ -/// -// Generated code. Do not modify. -// source: msg.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields - -// ignore_for_file: UNDEFINED_SHOWN_NAME -import 'dart:core' as $core; -import 'package:protobuf/protobuf.dart' as $pb; - -class WsModule extends $pb.ProtobufEnum { - static const WsModule Doc = WsModule._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Doc'); - - static const $core.List values = [ - Doc, - ]; - - static final $core.Map<$core.int, WsModule> _byValue = $pb.ProtobufEnum.initByValue(values); - static WsModule? valueOf($core.int value) => _byValue[value]; - - const WsModule._($core.int v, $core.String n) : super(v, n); -} - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/msg.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/msg.pbjson.dart deleted file mode 100644 index 13899cc203..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/msg.pbjson.dart +++ /dev/null @@ -1,31 +0,0 @@ -/// -// Generated code. Do not modify. -// source: msg.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package - -import 'dart:core' as $core; -import 'dart:convert' as $convert; -import 'dart:typed_data' as $typed_data; -@$core.Deprecated('Use wsModuleDescriptor instead') -const WsModule$json = const { - '1': 'WsModule', - '2': const [ - const {'1': 'Doc', '2': 0}, - ], -}; - -/// Descriptor for `WsModule`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List wsModuleDescriptor = $convert.base64Decode('CghXc01vZHVsZRIHCgNEb2MQAA=='); -@$core.Deprecated('Use wsMessageDescriptor instead') -const WsMessage$json = const { - '1': 'WsMessage', - '2': const [ - const {'1': 'module', '3': 1, '4': 1, '5': 14, '6': '.WsModule', '10': 'module'}, - const {'1': 'data', '3': 2, '4': 1, '5': 12, '10': 'data'}, - ], -}; - -/// Descriptor for `WsMessage`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List wsMessageDescriptor = $convert.base64Decode('CglXc01lc3NhZ2USIQoGbW9kdWxlGAEgASgOMgkuV3NNb2R1bGVSBm1vZHVsZRISCgRkYXRhGAIgASgMUgRkYXRh'); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/msg.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/msg.pbserver.dart deleted file mode 100644 index e6a7eccb26..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/msg.pbserver.dart +++ /dev/null @@ -1,9 +0,0 @@ -/// -// Generated code. Do not modify. -// source: msg.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package - -export 'msg.pb.dart'; - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/protobuf.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/protobuf.dart deleted file mode 100644 index 3d5e1cc240..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-ws/protobuf.dart +++ /dev/null @@ -1,3 +0,0 @@ -// Auto-generated, do not edit -export './errors.pb.dart'; -export './msg.pb.dart'; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/rust_stream.dart b/frontend/app_flowy/packages/flowy_sdk/lib/rust_stream.dart index b301841601..633ebfe3b8 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/rust_stream.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/rust_stream.dart @@ -3,7 +3,7 @@ import 'dart:async'; import 'dart:typed_data'; import 'dart:ffi'; import 'package:flowy_log/flowy_log.dart'; -import 'protobuf/flowy-dart-notify/subject.pb.dart'; +import 'protobuf/dart-notify/subject.pb.dart'; typedef ObserverCallback = void Function(SubscribeObject observable); diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index ca4bf6d4bc..592c6e1d6c 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -8,7 +8,7 @@ members = [ "flowy-user", "flowy-test", "flowy-database", - "flowy-workspace", + "flowy-core", "dart-notify", "flowy-document", ] diff --git a/frontend/rust-lib/flowy-workspace/Cargo.toml b/frontend/rust-lib/flowy-core/Cargo.toml similarity index 98% rename from frontend/rust-lib/flowy-workspace/Cargo.toml rename to frontend/rust-lib/flowy-core/Cargo.toml index d4702c08ff..2df640a9e3 100644 --- a/frontend/rust-lib/flowy-workspace/Cargo.toml +++ b/frontend/rust-lib/flowy-core/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "flowy-workspace" +name = "flowy-core" version = "0.1.0" edition = "2018" diff --git a/frontend/rust-lib/flowy-workspace/Flowy.toml b/frontend/rust-lib/flowy-core/Flowy.toml similarity index 100% rename from frontend/rust-lib/flowy-workspace/Flowy.toml rename to frontend/rust-lib/flowy-core/Flowy.toml diff --git a/frontend/rust-lib/flowy-workspace/src/errors.rs b/frontend/rust-lib/flowy-core/src/errors.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/errors.rs rename to frontend/rust-lib/flowy-core/src/errors.rs diff --git a/frontend/rust-lib/flowy-workspace/src/event.rs b/frontend/rust-lib/flowy-core/src/event.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/event.rs rename to frontend/rust-lib/flowy-core/src/event.rs diff --git a/frontend/rust-lib/flowy-workspace/src/handlers/app_handler.rs b/frontend/rust-lib/flowy-core/src/handlers/app_handler.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/handlers/app_handler.rs rename to frontend/rust-lib/flowy-core/src/handlers/app_handler.rs diff --git a/frontend/rust-lib/flowy-workspace/src/handlers/mod.rs b/frontend/rust-lib/flowy-core/src/handlers/mod.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/handlers/mod.rs rename to frontend/rust-lib/flowy-core/src/handlers/mod.rs diff --git a/frontend/rust-lib/flowy-workspace/src/handlers/trash_handler.rs b/frontend/rust-lib/flowy-core/src/handlers/trash_handler.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/handlers/trash_handler.rs rename to frontend/rust-lib/flowy-core/src/handlers/trash_handler.rs diff --git a/frontend/rust-lib/flowy-workspace/src/handlers/view_handler.rs b/frontend/rust-lib/flowy-core/src/handlers/view_handler.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/handlers/view_handler.rs rename to frontend/rust-lib/flowy-core/src/handlers/view_handler.rs diff --git a/frontend/rust-lib/flowy-workspace/src/handlers/workspace_handler.rs b/frontend/rust-lib/flowy-core/src/handlers/workspace_handler.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/handlers/workspace_handler.rs rename to frontend/rust-lib/flowy-core/src/handlers/workspace_handler.rs diff --git a/frontend/rust-lib/flowy-workspace/src/lib.rs b/frontend/rust-lib/flowy-core/src/lib.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/lib.rs rename to frontend/rust-lib/flowy-core/src/lib.rs diff --git a/frontend/rust-lib/flowy-workspace/src/macros.rs b/frontend/rust-lib/flowy-core/src/macros.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/macros.rs rename to frontend/rust-lib/flowy-core/src/macros.rs diff --git a/frontend/rust-lib/flowy-workspace/src/module.rs b/frontend/rust-lib/flowy-core/src/module.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/module.rs rename to frontend/rust-lib/flowy-core/src/module.rs diff --git a/frontend/rust-lib/flowy-workspace/src/notify/mod.rs b/frontend/rust-lib/flowy-core/src/notify/mod.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/notify/mod.rs rename to frontend/rust-lib/flowy-core/src/notify/mod.rs diff --git a/frontend/rust-lib/flowy-workspace/src/notify/observable.rs b/frontend/rust-lib/flowy-core/src/notify/observable.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/notify/observable.rs rename to frontend/rust-lib/flowy-core/src/notify/observable.rs diff --git a/frontend/rust-lib/flowy-workspace/src/protobuf/mod.rs b/frontend/rust-lib/flowy-core/src/protobuf/mod.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/protobuf/mod.rs rename to frontend/rust-lib/flowy-core/src/protobuf/mod.rs diff --git a/frontend/rust-lib/flowy-workspace/src/protobuf/model/errors.rs b/frontend/rust-lib/flowy-core/src/protobuf/model/errors.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/protobuf/model/errors.rs rename to frontend/rust-lib/flowy-core/src/protobuf/model/errors.rs diff --git a/frontend/rust-lib/flowy-workspace/src/protobuf/model/event.rs b/frontend/rust-lib/flowy-core/src/protobuf/model/event.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/protobuf/model/event.rs rename to frontend/rust-lib/flowy-core/src/protobuf/model/event.rs diff --git a/frontend/rust-lib/flowy-workspace/src/protobuf/model/mod.rs b/frontend/rust-lib/flowy-core/src/protobuf/model/mod.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/protobuf/model/mod.rs rename to frontend/rust-lib/flowy-core/src/protobuf/model/mod.rs diff --git a/frontend/rust-lib/flowy-workspace/src/protobuf/model/observable.rs b/frontend/rust-lib/flowy-core/src/protobuf/model/observable.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/protobuf/model/observable.rs rename to frontend/rust-lib/flowy-core/src/protobuf/model/observable.rs diff --git a/frontend/rust-lib/flowy-workspace/src/protobuf/proto/errors.proto b/frontend/rust-lib/flowy-core/src/protobuf/proto/errors.proto similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/protobuf/proto/errors.proto rename to frontend/rust-lib/flowy-core/src/protobuf/proto/errors.proto diff --git a/frontend/rust-lib/flowy-workspace/src/protobuf/proto/event.proto b/frontend/rust-lib/flowy-core/src/protobuf/proto/event.proto similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/protobuf/proto/event.proto rename to frontend/rust-lib/flowy-core/src/protobuf/proto/event.proto diff --git a/frontend/rust-lib/flowy-workspace/src/protobuf/proto/observable.proto b/frontend/rust-lib/flowy-core/src/protobuf/proto/observable.proto similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/protobuf/proto/observable.proto rename to frontend/rust-lib/flowy-core/src/protobuf/proto/observable.proto diff --git a/frontend/rust-lib/flowy-workspace/src/services/app_controller.rs b/frontend/rust-lib/flowy-core/src/services/app_controller.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/services/app_controller.rs rename to frontend/rust-lib/flowy-core/src/services/app_controller.rs diff --git a/frontend/rust-lib/flowy-workspace/src/services/database.rs b/frontend/rust-lib/flowy-core/src/services/database.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/services/database.rs rename to frontend/rust-lib/flowy-core/src/services/database.rs diff --git a/frontend/rust-lib/flowy-workspace/src/services/mod.rs b/frontend/rust-lib/flowy-core/src/services/mod.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/services/mod.rs rename to frontend/rust-lib/flowy-core/src/services/mod.rs diff --git a/frontend/rust-lib/flowy-workspace/src/services/server/mod.rs b/frontend/rust-lib/flowy-core/src/services/server/mod.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/services/server/mod.rs rename to frontend/rust-lib/flowy-core/src/services/server/mod.rs diff --git a/frontend/rust-lib/flowy-workspace/src/services/server/server_api.rs b/frontend/rust-lib/flowy-core/src/services/server/server_api.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/services/server/server_api.rs rename to frontend/rust-lib/flowy-core/src/services/server/server_api.rs diff --git a/frontend/rust-lib/flowy-workspace/src/services/server/server_api_mock.rs b/frontend/rust-lib/flowy-core/src/services/server/server_api_mock.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/services/server/server_api_mock.rs rename to frontend/rust-lib/flowy-core/src/services/server/server_api_mock.rs diff --git a/frontend/rust-lib/flowy-workspace/src/services/trash_can.rs b/frontend/rust-lib/flowy-core/src/services/trash_can.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/services/trash_can.rs rename to frontend/rust-lib/flowy-core/src/services/trash_can.rs diff --git a/frontend/rust-lib/flowy-workspace/src/services/view_controller.rs b/frontend/rust-lib/flowy-core/src/services/view_controller.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/services/view_controller.rs rename to frontend/rust-lib/flowy-core/src/services/view_controller.rs diff --git a/frontend/rust-lib/flowy-workspace/src/services/workspace_controller.rs b/frontend/rust-lib/flowy-core/src/services/workspace_controller.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/services/workspace_controller.rs rename to frontend/rust-lib/flowy-core/src/services/workspace_controller.rs diff --git a/frontend/rust-lib/flowy-workspace/src/sql_tables/app/app_sql.rs b/frontend/rust-lib/flowy-core/src/sql_tables/app/app_sql.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/sql_tables/app/app_sql.rs rename to frontend/rust-lib/flowy-core/src/sql_tables/app/app_sql.rs diff --git a/frontend/rust-lib/flowy-workspace/src/sql_tables/app/app_table.rs b/frontend/rust-lib/flowy-core/src/sql_tables/app/app_table.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/sql_tables/app/app_table.rs rename to frontend/rust-lib/flowy-core/src/sql_tables/app/app_table.rs diff --git a/frontend/rust-lib/flowy-workspace/src/sql_tables/app/mod.rs b/frontend/rust-lib/flowy-core/src/sql_tables/app/mod.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/sql_tables/app/mod.rs rename to frontend/rust-lib/flowy-core/src/sql_tables/app/mod.rs diff --git a/frontend/rust-lib/flowy-workspace/src/sql_tables/mod.rs b/frontend/rust-lib/flowy-core/src/sql_tables/mod.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/sql_tables/mod.rs rename to frontend/rust-lib/flowy-core/src/sql_tables/mod.rs diff --git a/frontend/rust-lib/flowy-workspace/src/sql_tables/trash/mod.rs b/frontend/rust-lib/flowy-core/src/sql_tables/trash/mod.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/sql_tables/trash/mod.rs rename to frontend/rust-lib/flowy-core/src/sql_tables/trash/mod.rs diff --git a/frontend/rust-lib/flowy-workspace/src/sql_tables/trash/trash_sql.rs b/frontend/rust-lib/flowy-core/src/sql_tables/trash/trash_sql.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/sql_tables/trash/trash_sql.rs rename to frontend/rust-lib/flowy-core/src/sql_tables/trash/trash_sql.rs diff --git a/frontend/rust-lib/flowy-workspace/src/sql_tables/trash/trash_table.rs b/frontend/rust-lib/flowy-core/src/sql_tables/trash/trash_table.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/sql_tables/trash/trash_table.rs rename to frontend/rust-lib/flowy-core/src/sql_tables/trash/trash_table.rs diff --git a/frontend/rust-lib/flowy-workspace/src/sql_tables/view/mod.rs b/frontend/rust-lib/flowy-core/src/sql_tables/view/mod.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/sql_tables/view/mod.rs rename to frontend/rust-lib/flowy-core/src/sql_tables/view/mod.rs diff --git a/frontend/rust-lib/flowy-workspace/src/sql_tables/view/view_sql.rs b/frontend/rust-lib/flowy-core/src/sql_tables/view/view_sql.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/sql_tables/view/view_sql.rs rename to frontend/rust-lib/flowy-core/src/sql_tables/view/view_sql.rs diff --git a/frontend/rust-lib/flowy-workspace/src/sql_tables/view/view_table.rs b/frontend/rust-lib/flowy-core/src/sql_tables/view/view_table.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/sql_tables/view/view_table.rs rename to frontend/rust-lib/flowy-core/src/sql_tables/view/view_table.rs diff --git a/frontend/rust-lib/flowy-workspace/src/sql_tables/workspace/mod.rs b/frontend/rust-lib/flowy-core/src/sql_tables/workspace/mod.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/sql_tables/workspace/mod.rs rename to frontend/rust-lib/flowy-core/src/sql_tables/workspace/mod.rs diff --git a/frontend/rust-lib/flowy-workspace/src/sql_tables/workspace/workspace_sql.rs b/frontend/rust-lib/flowy-core/src/sql_tables/workspace/workspace_sql.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/sql_tables/workspace/workspace_sql.rs rename to frontend/rust-lib/flowy-core/src/sql_tables/workspace/workspace_sql.rs diff --git a/frontend/rust-lib/flowy-workspace/src/sql_tables/workspace/workspace_table.rs b/frontend/rust-lib/flowy-core/src/sql_tables/workspace/workspace_table.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/sql_tables/workspace/workspace_table.rs rename to frontend/rust-lib/flowy-core/src/sql_tables/workspace/workspace_table.rs diff --git a/frontend/rust-lib/flowy-workspace/src/util.rs b/frontend/rust-lib/flowy-core/src/util.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/src/util.rs rename to frontend/rust-lib/flowy-core/src/util.rs diff --git a/frontend/rust-lib/flowy-workspace/tests/workspace/app_test.rs b/frontend/rust-lib/flowy-core/tests/workspace/app_test.rs similarity index 98% rename from frontend/rust-lib/flowy-workspace/tests/workspace/app_test.rs rename to frontend/rust-lib/flowy-core/tests/workspace/app_test.rs index cfa4b82088..74521bd0d3 100644 --- a/frontend/rust-lib/flowy-workspace/tests/workspace/app_test.rs +++ b/frontend/rust-lib/flowy-core/tests/workspace/app_test.rs @@ -1,9 +1,9 @@ -use flowy_test::workspace::*; -use flowy_workspace::entities::{ +use flowy_core::entities::{ app::QueryAppRequest, trash::{TrashIdentifier, TrashType}, view::*, }; +use flowy_test::workspace::*; #[tokio::test] #[should_panic] diff --git a/frontend/rust-lib/flowy-workspace/tests/workspace/main.rs b/frontend/rust-lib/flowy-core/tests/workspace/main.rs similarity index 100% rename from frontend/rust-lib/flowy-workspace/tests/workspace/main.rs rename to frontend/rust-lib/flowy-core/tests/workspace/main.rs diff --git a/frontend/rust-lib/flowy-workspace/tests/workspace/view_test.rs b/frontend/rust-lib/flowy-core/tests/workspace/view_test.rs similarity index 98% rename from frontend/rust-lib/flowy-workspace/tests/workspace/view_test.rs rename to frontend/rust-lib/flowy-core/tests/workspace/view_test.rs index 51fa02b2e9..220d0aeb70 100644 --- a/frontend/rust-lib/flowy-workspace/tests/workspace/view_test.rs +++ b/frontend/rust-lib/flowy-core/tests/workspace/view_test.rs @@ -1,9 +1,9 @@ -use flowy_test::{workspace::*, FlowyTest}; -use flowy_workspace::entities::{ +use flowy_core::entities::{ app::QueryAppRequest, trash::{TrashIdentifier, TrashType}, view::*, }; +use flowy_test::{workspace::*, FlowyTest}; #[tokio::test] #[should_panic] diff --git a/frontend/rust-lib/flowy-workspace/tests/workspace/workspace_test.rs b/frontend/rust-lib/flowy-core/tests/workspace/workspace_test.rs similarity index 99% rename from frontend/rust-lib/flowy-workspace/tests/workspace/workspace_test.rs rename to frontend/rust-lib/flowy-core/tests/workspace/workspace_test.rs index 44e13f6664..62f8bbdfa5 100644 --- a/frontend/rust-lib/flowy-workspace/tests/workspace/workspace_test.rs +++ b/frontend/rust-lib/flowy-core/tests/workspace/workspace_test.rs @@ -1,9 +1,9 @@ -use flowy_test::{builder::*, workspace::*, FlowyTest}; -use flowy_workspace::{ +use flowy_core::{ entities::workspace::{CreateWorkspaceRequest, QueryWorkspaceRequest}, event::WorkspaceEvent::*, prelude::*, }; +use flowy_test::{builder::*, workspace::*, FlowyTest}; #[tokio::test] async fn workspace_read_all() { diff --git a/frontend/rust-lib/flowy-sdk/Cargo.toml b/frontend/rust-lib/flowy-sdk/Cargo.toml index a3067469de..057e4a7825 100644 --- a/frontend/rust-lib/flowy-sdk/Cargo.toml +++ b/frontend/rust-lib/flowy-sdk/Cargo.toml @@ -9,7 +9,7 @@ edition = "2018" lib-dispatch = { path = "../lib-dispatch" } lib-log = { path = "../lib-log" } flowy-user = { path = "../flowy-user" } -flowy-workspace = { path = "../flowy-workspace", default-features = false } +flowy-core = { path = "../flowy-core", default-features = false } flowy-database = { path = "../flowy-database" } flowy-document = { path = "../flowy-document" } lib-infra = { path = "../lib-infra" } @@ -36,5 +36,5 @@ tokio = { version = "1", features = ["full"]} futures-util = "0.3.15" [features] -http_server = ["flowy-user/http_server", "flowy-workspace/http_server", "flowy-document/http_server"] +http_server = ["flowy-user/http_server", "flowy-core/http_server", "flowy-document/http_server"] use_bunyan = ["lib-log/use_bunyan"] \ No newline at end of file diff --git a/frontend/rust-lib/flowy-sdk/src/deps_resolve/workspace_deps.rs b/frontend/rust-lib/flowy-sdk/src/deps_resolve/workspace_deps.rs index c1c9d33e72..e89ad9138a 100644 --- a/frontend/rust-lib/flowy-sdk/src/deps_resolve/workspace_deps.rs +++ b/frontend/rust-lib/flowy-sdk/src/deps_resolve/workspace_deps.rs @@ -1,9 +1,9 @@ -use flowy_database::ConnectionPool; -use flowy_user::services::user::UserSession; -use flowy_workspace::{ +use flowy_core::{ errors::WorkspaceError, module::{WorkspaceDatabase, WorkspaceUser}, }; +use flowy_database::ConnectionPool; +use flowy_user::services::user::UserSession; use std::sync::Arc; pub struct WorkspaceDepsResolver { diff --git a/frontend/rust-lib/flowy-sdk/src/lib.rs b/frontend/rust-lib/flowy-sdk/src/lib.rs index 0f9d93f668..fc8aa73fca 100644 --- a/frontend/rust-lib/flowy-sdk/src/lib.rs +++ b/frontend/rust-lib/flowy-sdk/src/lib.rs @@ -3,12 +3,12 @@ mod deps_resolve; pub mod module; use crate::deps_resolve::WorkspaceDepsResolver; use backend_service::configuration::ClientServerConfiguration; +use flowy_core::{errors::WorkspaceError, prelude::WorkspaceController}; use flowy_document::module::FlowyDocument; use flowy_user::{ prelude::UserStatus, services::user::{UserSession, UserSessionConfig}, }; -use flowy_workspace::{errors::WorkspaceError, prelude::WorkspaceController}; use lib_dispatch::prelude::*; use lib_infra::entities::network_state::NetworkType; use module::mk_modules; @@ -177,5 +177,5 @@ fn mk_workspace_controller( ) -> Arc { let workspace_deps = WorkspaceDepsResolver::new(user_session); let (user, database) = workspace_deps.split_into(); - flowy_workspace::module::init_workspace_controller(user, database, flowy_document, server_config) + flowy_core::module::init_workspace_controller(user, database, flowy_document, server_config) } diff --git a/frontend/rust-lib/flowy-sdk/src/module.rs b/frontend/rust-lib/flowy-sdk/src/module.rs index 214d4e6279..61caf42922 100644 --- a/frontend/rust-lib/flowy-sdk/src/module.rs +++ b/frontend/rust-lib/flowy-sdk/src/module.rs @@ -1,8 +1,8 @@ use crate::deps_resolve::DocumentDepsResolver; use backend_service::configuration::ClientServerConfiguration; +use flowy_core::prelude::WorkspaceController; use flowy_document::module::FlowyDocument; use flowy_user::services::user::UserSession; -use flowy_workspace::prelude::WorkspaceController; use lib_dispatch::prelude::Module; use std::sync::Arc; @@ -15,7 +15,7 @@ pub fn mk_modules(workspace_controller: Arc, user_session: fn mk_user_module(user_session: Arc) -> Module { flowy_user::module::create(user_session) } fn mk_workspace_module(workspace_controller: Arc) -> Module { - flowy_workspace::module::create(workspace_controller) + flowy_core::module::create(workspace_controller) } pub fn mk_document_module( diff --git a/frontend/rust-lib/flowy-test/Cargo.toml b/frontend/rust-lib/flowy-test/Cargo.toml index 6c3bafa854..f94de9e574 100644 --- a/frontend/rust-lib/flowy-test/Cargo.toml +++ b/frontend/rust-lib/flowy-test/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" [dependencies] flowy-sdk = { path = "../flowy-sdk"} flowy-user = { path = "../flowy-user"} -flowy-workspace = { path = "../flowy-workspace", default-features = false} +flowy-core = { path = "../flowy-core", default-features = false} flowy-document = { path = "../flowy-document"} lib-dispatch = { path = "../lib-dispatch" } lib-infra = { path = "../lib-infra" } diff --git a/frontend/rust-lib/flowy-test/src/builder.rs b/frontend/rust-lib/flowy-test/src/builder.rs index d48a450dc7..5e23f331a4 100644 --- a/frontend/rust-lib/flowy-test/src/builder.rs +++ b/frontend/rust-lib/flowy-test/src/builder.rs @@ -8,9 +8,9 @@ use std::{ use crate::FlowyTestSDK; use lib_dispatch::prelude::*; +use flowy_core::errors::WorkspaceError; use flowy_sdk::*; use flowy_user::errors::UserError; -use flowy_workspace::errors::WorkspaceError; use std::{convert::TryFrom, marker::PhantomData, sync::Arc}; pub type FlowyWorkspaceTest = Builder; diff --git a/frontend/rust-lib/flowy-test/src/helper.rs b/frontend/rust-lib/flowy-test/src/helper.rs index e0e0e88df6..aa84fd583c 100644 --- a/frontend/rust-lib/flowy-test/src/helper.rs +++ b/frontend/rust-lib/flowy-test/src/helper.rs @@ -2,16 +2,16 @@ use bytes::Bytes; use lib_dispatch::prelude::{EventDispatcher, ModuleRequest, ToBytes}; use lib_infra::{kv::KV, uuid}; +use flowy_core::{ + entities::workspace::{CreateWorkspaceRequest, QueryWorkspaceRequest, Workspace}, + errors::WorkspaceError, + event::WorkspaceEvent::{CreateWorkspace, OpenWorkspace}, +}; use flowy_user::{ entities::{SignInRequest, SignUpRequest, UserProfile}, errors::UserError, event::UserEvent::{SignIn, SignOut, SignUp}, }; -use flowy_workspace::{ - entities::workspace::{CreateWorkspaceRequest, QueryWorkspaceRequest, Workspace}, - errors::WorkspaceError, - event::WorkspaceEvent::{CreateWorkspace, OpenWorkspace}, -}; use std::{fs, path::PathBuf, sync::Arc}; pub fn root_dir() -> String { diff --git a/frontend/rust-lib/flowy-test/src/workspace.rs b/frontend/rust-lib/flowy-test/src/workspace.rs index 6d6000c9f4..d2c2f77b48 100644 --- a/frontend/rust-lib/flowy-test/src/workspace.rs +++ b/frontend/rust-lib/flowy-test/src/workspace.rs @@ -1,6 +1,5 @@ use crate::prelude::*; -use flowy_document_infra::entities::doc::Doc; -use flowy_workspace::{ +use flowy_core::{ entities::{ app::*, trash::{RepeatedTrash, TrashIdentifier}, @@ -10,6 +9,7 @@ use flowy_workspace::{ errors::ErrorCode, event::WorkspaceEvent::*, }; +use flowy_document_infra::entities::doc::Doc; pub struct WorkspaceTest { pub sdk: FlowyTestSDK, diff --git a/frontend/scripts/makefile/tests.toml b/frontend/scripts/makefile/tests.toml index bf177ce5f8..90720d438a 100644 --- a/frontend/scripts/makefile/tests.toml +++ b/frontend/scripts/makefile/tests.toml @@ -13,7 +13,7 @@ cargo test dependencies = ["rm_cache"] script = """ cd rust-lib -cargo test --features "flowy-workspace/http_server","flowy-user/http_server" +cargo test --features "flowy-core/http_server","flowy-user/http_server" """ From 6298a0d96d7b6233fdfeaeaf12d793836f96553f Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 6 Dec 2021 15:49:21 +0800 Subject: [PATCH 03/39] add core --- backend/tests/util/helper.rs | 2 +- .../flowy-core/src/core/flowy_core.rs | 134 ++++++++++++++++++ frontend/rust-lib/flowy-core/src/core/mod.rs | 4 + frontend/rust-lib/flowy-core/src/core/task.rs | 69 +++++++++ .../rust-lib/flowy-core/src/handlers/mod.rs | 9 -- frontend/rust-lib/flowy-core/src/lib.rs | 5 +- frontend/rust-lib/flowy-core/src/module.rs | 63 +++++--- .../{app_controller.rs => app/controller.rs} | 31 ++-- .../app/event_handler.rs} | 4 +- .../flowy-core/src/services/app/mod.rs | 3 + .../app/app_table.rs => services/app/sql.rs} | 85 +++++++++-- .../flowy-core/src/services/database.rs | 1 - .../rust-lib/flowy-core/src/services/mod.rs | 17 ++- .../{trash_can.rs => trash/controller.rs} | 20 ++- .../trash/event_handler.rs} | 14 +- .../flowy-core/src/services/trash/mod.rs | 3 + .../trash_table.rs => services/trash/sql.rs} | 53 ++++++- .../controller.rs} | 22 ++- .../view/event_handler.rs} | 4 +- .../flowy-core/src/services/view/mod.rs | 3 + .../view_table.rs => services/view/sql.rs} | 109 +++++++++++++- .../controller.rs} | 129 +++-------------- .../workspace/event_handler.rs} | 0 .../flowy-core/src/services/workspace/mod.rs | 3 + .../workspace/sql.rs} | 80 ++++++++++- .../flowy-core/src/sql_tables/app/app_sql.rs | 76 ---------- .../flowy-core/src/sql_tables/app/mod.rs | 5 - .../rust-lib/flowy-core/src/sql_tables/mod.rs | 4 - .../flowy-core/src/sql_tables/trash/mod.rs | 5 - .../src/sql_tables/trash/trash_sql.rs | 53 ------- .../flowy-core/src/sql_tables/view/mod.rs | 5 - .../src/sql_tables/view/view_sql.rs | 104 -------------- .../src/sql_tables/workspace/mod.rs | 5 - .../sql_tables/workspace/workspace_table.rs | 71 ---------- frontend/rust-lib/flowy-sdk/src/lib.rs | 48 +++---- frontend/rust-lib/flowy-sdk/src/module.rs | 11 +- 36 files changed, 676 insertions(+), 578 deletions(-) create mode 100644 frontend/rust-lib/flowy-core/src/core/flowy_core.rs create mode 100644 frontend/rust-lib/flowy-core/src/core/mod.rs create mode 100644 frontend/rust-lib/flowy-core/src/core/task.rs delete mode 100644 frontend/rust-lib/flowy-core/src/handlers/mod.rs rename frontend/rust-lib/flowy-core/src/services/{app_controller.rs => app/controller.rs} (95%) rename frontend/rust-lib/flowy-core/src/{handlers/app_handler.rs => services/app/event_handler.rs} (94%) create mode 100644 frontend/rust-lib/flowy-core/src/services/app/mod.rs rename frontend/rust-lib/flowy-core/src/{sql_tables/app/app_table.rs => services/app/sql.rs} (58%) delete mode 100644 frontend/rust-lib/flowy-core/src/services/database.rs rename frontend/rust-lib/flowy-core/src/services/{trash_can.rs => trash/controller.rs} (98%) rename frontend/rust-lib/flowy-core/src/{handlers/trash_handler.rs => services/trash/event_handler.rs} (77%) create mode 100644 frontend/rust-lib/flowy-core/src/services/trash/mod.rs rename frontend/rust-lib/flowy-core/src/{sql_tables/trash/trash_table.rs => services/trash/sql.rs} (58%) rename frontend/rust-lib/flowy-core/src/services/{view_controller.rs => view/controller.rs} (97%) rename frontend/rust-lib/flowy-core/src/{handlers/view_handler.rs => services/view/event_handler.rs} (97%) create mode 100644 frontend/rust-lib/flowy-core/src/services/view/mod.rs rename frontend/rust-lib/flowy-core/src/{sql_tables/view/view_table.rs => services/view/sql.rs} (51%) rename frontend/rust-lib/flowy-core/src/services/{workspace_controller.rs => workspace/controller.rs} (76%) rename frontend/rust-lib/flowy-core/src/{handlers/workspace_handler.rs => services/workspace/event_handler.rs} (100%) create mode 100644 frontend/rust-lib/flowy-core/src/services/workspace/mod.rs rename frontend/rust-lib/flowy-core/src/{sql_tables/workspace/workspace_sql.rs => services/workspace/sql.rs} (50%) delete mode 100644 frontend/rust-lib/flowy-core/src/sql_tables/app/app_sql.rs delete mode 100644 frontend/rust-lib/flowy-core/src/sql_tables/app/mod.rs delete mode 100644 frontend/rust-lib/flowy-core/src/sql_tables/mod.rs delete mode 100644 frontend/rust-lib/flowy-core/src/sql_tables/trash/mod.rs delete mode 100644 frontend/rust-lib/flowy-core/src/sql_tables/trash/trash_sql.rs delete mode 100644 frontend/rust-lib/flowy-core/src/sql_tables/view/mod.rs delete mode 100644 frontend/rust-lib/flowy-core/src/sql_tables/view/view_sql.rs delete mode 100644 frontend/rust-lib/flowy-core/src/sql_tables/workspace/mod.rs delete mode 100644 frontend/rust-lib/flowy-core/src/sql_tables/workspace/workspace_table.rs diff --git a/backend/tests/util/helper.rs b/backend/tests/util/helper.rs index 1b463faa93..93d7d6eb5c 100644 --- a/backend/tests/util/helper.rs +++ b/backend/tests/util/helper.rs @@ -188,7 +188,7 @@ impl std::convert::From for TestUserServer { pg_pool: server.pg_pool, user_token: None, user_id: None, - client_server_config: server.client_server_config.clone(), + client_server_config: server.client_server_config, } } } diff --git a/frontend/rust-lib/flowy-core/src/core/flowy_core.rs b/frontend/rust-lib/flowy-core/src/core/flowy_core.rs new file mode 100644 index 0000000000..03d1f7354f --- /dev/null +++ b/frontend/rust-lib/flowy-core/src/core/flowy_core.rs @@ -0,0 +1,134 @@ +use crate::{ + entities::workspace::RepeatedWorkspace, + errors::{WorkspaceError, WorkspaceResult}, + module::WorkspaceUser, + notify::{send_dart_notification, WorkspaceNotification}, + services::{server::Server, AppController, TrashController, ViewController, WorkspaceController}, +}; +use chrono::Utc; +use flowy_document_infra::{entities::doc::DocDelta, user_default::initial_read_me}; +use flowy_workspace_infra::user_default; +use lazy_static::lazy_static; +use lib_infra::entities::network_state::NetworkType; +use parking_lot::RwLock; +use std::{collections::HashMap, sync::Arc}; + +lazy_static! { + static ref INIT_WORKSPACE: RwLock> = RwLock::new(HashMap::new()); +} + +pub struct FlowyCore { + pub user: Arc, + server: Server, + pub workspace_controller: Arc, + pub(crate) app_controller: Arc, + pub(crate) view_controller: Arc, + pub(crate) trash_controller: Arc, +} + +impl FlowyCore { + pub(crate) fn new( + user: Arc, + server: Server, + workspace_controller: Arc, + app_controller: Arc, + view_controller: Arc, + trash_controller: Arc, + ) -> Self { + if let Ok(token) = user.token() { + INIT_WORKSPACE.write().insert(token, false); + } + + Self { + user, + server, + workspace_controller, + app_controller, + view_controller, + trash_controller, + } + } + + async fn init(&self, token: &str) -> Result<(), WorkspaceError> { + if let Some(is_init) = INIT_WORKSPACE.read().get(token) { + if *is_init { + return Ok(()); + } + } + log::debug!("Start initializing flowy core"); + INIT_WORKSPACE.write().insert(token.to_owned(), true); + let _ = self.server.init(); + let _ = self.workspace_controller.init()?; + let _ = self.app_controller.init()?; + let _ = self.view_controller.init()?; + let _ = self.trash_controller.init()?; + log::debug!("Finish initializing core"); + + Ok(()) + } + + pub fn network_state_changed(&self, new_type: NetworkType) { + match new_type { + NetworkType::UnknownNetworkType => {}, + NetworkType::Wifi => {}, + NetworkType::Cell => {}, + NetworkType::Ethernet => {}, + } + } + + pub async fn user_did_sign_in(&self, token: &str) -> WorkspaceResult<()> { + // TODO: (nathan) do something here + + log::debug!("workspace initialize after sign in"); + let _ = self.init(token).await?; + Ok(()) + } + + pub async fn user_did_logout(&self) { + // TODO: (nathan) do something here + } + + pub async fn user_session_expired(&self) { + // TODO: (nathan) do something here + } + + pub async fn user_did_sign_up(&self, _token: &str) -> WorkspaceResult<()> { + log::debug!("Create user default workspace"); + let time = Utc::now(); + let mut workspace = user_default::create_default_workspace(time); + let apps = workspace.take_apps().into_inner(); + let cloned_workspace = workspace.clone(); + + let _ = self.workspace_controller.create_workspace(workspace).await?; + for mut app in apps { + let views = app.take_belongings().into_inner(); + let _ = self.app_controller.create_app(app).await?; + for (index, view) in views.into_iter().enumerate() { + if index == 0 { + let delta = initial_read_me(); + let doc_delta = DocDelta { + doc_id: view.id.clone(), + data: delta.to_json(), + }; + let _ = self.view_controller.apply_doc_delta(doc_delta).await?; + + self.view_controller.set_latest_view(&view); + } + let _ = self.view_controller.create_view(view).await?; + } + } + + let token = self.user.token()?; + let repeated_workspace = RepeatedWorkspace { + items: vec![cloned_workspace], + }; + + send_dart_notification(&token, WorkspaceNotification::UserCreateWorkspace) + .payload(repeated_workspace) + .send(); + + log::debug!("workspace initialize after sign up"); + let _ = self.init(&token).await?; + Ok(()) + } +} diff --git a/frontend/rust-lib/flowy-core/src/core/mod.rs b/frontend/rust-lib/flowy-core/src/core/mod.rs new file mode 100644 index 0000000000..a21ead744c --- /dev/null +++ b/frontend/rust-lib/flowy-core/src/core/mod.rs @@ -0,0 +1,4 @@ +mod flowy_core; +mod task; + +pub use flowy_core::*; diff --git a/frontend/rust-lib/flowy-core/src/core/task.rs b/frontend/rust-lib/flowy-core/src/core/task.rs new file mode 100644 index 0000000000..01054ee350 --- /dev/null +++ b/frontend/rust-lib/flowy-core/src/core/task.rs @@ -0,0 +1,69 @@ +use crate::{errors::WorkspaceError, services::WorkspaceController}; +use flowy_workspace_infra::entities::workspace::{QueryWorkspaceRequest, RepeatedWorkspace, WorkspaceIdentifier}; +use lib_dispatch::prelude::{data_result, Data, DataResult, Unit}; +use std::{convert::TryInto, sync::Arc}; + +#[tracing::instrument(skip(data, controller), err)] +pub(crate) async fn read_workspaces_handler( + data: Data, + controller: Unit>, +) -> DataResult { + let params: WorkspaceIdentifier = data.into_inner().try_into()?; + let user_id = controller.user.user_id()?; + let workspaces = controller.read_local_workspaces( + params.workspace_id.clone(), + &user_id, + &*controller.database.db_connection()?, + )?; + let _ = controller.read_workspaces_on_server(user_id, params); + + data_result(workspaces) +} + +// #[tracing::instrument(level = "debug", skip(self), err)] +// fn read_workspaces_on_server(&self, user_id: String, params: +// WorkspaceIdentifier) -> Result<(), WorkspaceError> { let (token, server) +// = self.token_with_server()?; let workspace_sql = +// self.workspace_sql.clone(); let app_ctrl = self.app_controller.clone(); +// let view_ctrl = self.view_controller.clone(); +// let conn = self.database.db_connection()?; +// tokio::spawn(async move { +// // Opti: handle the error and retry? +// let workspaces = server.read_workspace(&token, params).await?; +// let _ = (&*conn).immediate_transaction::<_, WorkspaceError, _>(|| { +// tracing::debug!("Save {} workspace", workspaces.len()); +// for workspace in &workspaces.items { +// let m_workspace = workspace.clone(); +// let apps = m_workspace.apps.clone().into_inner(); +// let workspace_table = WorkspaceTable::new(m_workspace, +// &user_id); +// +// let _ = workspace_sql.create_workspace(workspace_table, +// &*conn)?; tracing::debug!("Save {} apps", apps.len()); +// for app in apps { +// let views = app.belongings.clone().into_inner(); +// match app_ctrl.save_app(app, &*conn) { +// Ok(_) => {}, +// Err(e) => log::error!("create app failed: {:?}", e), +// } +// +// tracing::debug!("Save {} views", views.len()); +// for view in views { +// match view_ctrl.save_view(view, &*conn) { +// Ok(_) => {}, +// Err(e) => log::error!("create view failed: {:?}", +// e), } +// } +// } +// } +// Ok(()) +// })?; +// +// send_dart_notification(&token, +// WorkspaceNotification::WorkspaceListUpdated) .payload(workspaces) +// .send(); +// Result::<(), WorkspaceError>::Ok(()) +// }); +// +// Ok(()) +// } diff --git a/frontend/rust-lib/flowy-core/src/handlers/mod.rs b/frontend/rust-lib/flowy-core/src/handlers/mod.rs deleted file mode 100644 index cd1e525370..0000000000 --- a/frontend/rust-lib/flowy-core/src/handlers/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -mod app_handler; -mod trash_handler; -mod view_handler; -mod workspace_handler; - -pub(crate) use app_handler::*; -pub(crate) use trash_handler::*; -pub(crate) use view_handler::*; -pub(crate) use workspace_handler::*; diff --git a/frontend/rust-lib/flowy-core/src/lib.rs b/frontend/rust-lib/flowy-core/src/lib.rs index e3441b8d9c..f3d3d51b8c 100644 --- a/frontend/rust-lib/flowy-core/src/lib.rs +++ b/frontend/rust-lib/flowy-core/src/lib.rs @@ -10,15 +10,14 @@ mod macros; #[macro_use] extern crate flowy_database; +pub mod core; pub mod errors; -pub mod handlers; mod notify; pub mod protobuf; -mod sql_tables; mod util; pub mod prelude { pub use flowy_workspace_infra::entities::{app::*, trash::*, view::*, workspace::*}; - pub use crate::{errors::*, module::*, services::*}; + pub use crate::{core::*, errors::*, module::*}; } diff --git a/frontend/rust-lib/flowy-core/src/module.rs b/frontend/rust-lib/flowy-core/src/module.rs index 00f5672481..d404d31a25 100644 --- a/frontend/rust-lib/flowy-core/src/module.rs +++ b/frontend/rust-lib/flowy-core/src/module.rs @@ -1,15 +1,27 @@ -use crate::{ - errors::WorkspaceError, - event::WorkspaceEvent, - handlers::*, - services::{server::construct_workspace_server, AppController, TrashCan, ViewController, WorkspaceController}, -}; +use std::sync::Arc; + use backend_service::configuration::ClientServerConfiguration; use flowy_database::DBConnection; use flowy_document::module::FlowyDocument; use lib_dispatch::prelude::*; use lib_sqlite::ConnectionPool; -use std::sync::Arc; + +use crate::{ + core::FlowyCore, + errors::WorkspaceError, + event::WorkspaceEvent, + services::{ + app::event_handler::*, + server::construct_workspace_server, + trash::event_handler::*, + view::event_handler::*, + workspace::event_handler::*, + AppController, + TrashController, + ViewController, + WorkspaceController, + }, +}; pub trait WorkspaceDeps: WorkspaceUser + WorkspaceDatabase {} @@ -28,48 +40,57 @@ pub trait WorkspaceDatabase: Send + Sync { } } -pub fn init_workspace_controller( +pub fn init_core( user: Arc, database: Arc, flowy_document: Arc, server_config: &ClientServerConfiguration, -) -> Arc { +) -> Arc { let server = construct_workspace_server(server_config); - let trash_can = Arc::new(TrashCan::new(database.clone(), server.clone(), user.clone())); + let trash_controller = Arc::new(TrashController::new(database.clone(), server.clone(), user.clone())); let view_controller = Arc::new(ViewController::new( user.clone(), database.clone(), server.clone(), - trash_can.clone(), + trash_controller.clone(), flowy_document, )); let app_controller = Arc::new(AppController::new( user.clone(), database.clone(), - trash_can.clone(), + trash_controller.clone(), server.clone(), )); - Arc::new(WorkspaceController::new( + let workspace_controller = Arc::new(WorkspaceController::new( + user.clone(), + database.clone(), + app_controller.clone(), + view_controller.clone(), + trash_controller.clone(), + server.clone(), + )); + + Arc::new(FlowyCore::new( user, - database, + server, + workspace_controller, app_controller, view_controller, - trash_can, - server, + trash_controller, )) } -pub fn create(workspace: Arc) -> Module { +pub fn create(core: Arc) -> Module { let mut module = Module::new() .name("Flowy-Workspace") - .data(workspace.clone()) - .data(workspace.app_controller.clone()) - .data(workspace.view_controller.clone()) - .data(workspace.trash_can.clone()); + .data(core.workspace_controller.clone()) + .data(core.app_controller.clone()) + .data(core.view_controller.clone()) + .data(core.trash_controller.clone()); module = module .event(WorkspaceEvent::CreateWorkspace, create_workspace_handler) diff --git a/frontend/rust-lib/flowy-core/src/services/app_controller.rs b/frontend/rust-lib/flowy-core/src/services/app/controller.rs similarity index 95% rename from frontend/rust-lib/flowy-core/src/services/app_controller.rs rename to frontend/rust-lib/flowy-core/src/services/app/controller.rs index 3845cd8640..107b87a54c 100644 --- a/frontend/rust-lib/flowy-core/src/services/app_controller.rs +++ b/frontend/rust-lib/flowy-core/src/services/app/controller.rs @@ -1,9 +1,3 @@ -use std::{collections::HashSet, sync::Arc}; - -use futures::{FutureExt, StreamExt}; - -use flowy_database::SqliteConnection; - use crate::{ entities::{ app::{App, CreateAppParams, *}, @@ -12,14 +6,21 @@ use crate::{ errors::*, module::{WorkspaceDatabase, WorkspaceUser}, notify::*, - services::{server::Server, TrashCan, TrashEvent}, - sql_tables::app::{AppTable, AppTableChangeset, AppTableSql}, + services::{ + app::sql::{AppTable, AppTableChangeset, AppTableSql}, + server::Server, + TrashController, + TrashEvent, + }, }; +use flowy_database::SqliteConnection; +use futures::{FutureExt, StreamExt}; +use std::{collections::HashSet, sync::Arc}; pub(crate) struct AppController { user: Arc, database: Arc, - trash_can: Arc, + trash_can: Arc, server: Server, } @@ -27,7 +28,7 @@ impl AppController { pub(crate) fn new( user: Arc, database: Arc, - trash_can: Arc, + trash_can: Arc, server: Server, ) -> Self { Self { @@ -185,7 +186,7 @@ impl AppController { } #[tracing::instrument(level = "trace", skip(database, trash_can))] -async fn handle_trash_event(database: Arc, trash_can: Arc, event: TrashEvent) { +async fn handle_trash_event(database: Arc, trash_can: Arc, event: TrashEvent) { let db_result = database.db_connection(); match event { TrashEvent::NewTrash(identifiers, ret) | TrashEvent::Putback(identifiers, ret) => { @@ -226,7 +227,11 @@ async fn handle_trash_event(database: Arc, trash_can: Arc } #[tracing::instrument(skip(workspace_id, trash_can, conn), err)] -fn notify_apps_changed(workspace_id: &str, trash_can: Arc, conn: &SqliteConnection) -> WorkspaceResult<()> { +fn notify_apps_changed( + workspace_id: &str, + trash_can: Arc, + conn: &SqliteConnection, +) -> WorkspaceResult<()> { let repeated_app = read_local_workspace_apps(workspace_id, trash_can, conn)?; send_dart_notification(workspace_id, WorkspaceNotification::WorkspaceAppsChanged) .payload(repeated_app) @@ -236,7 +241,7 @@ fn notify_apps_changed(workspace_id: &str, trash_can: Arc, conn: &Sqli pub fn read_local_workspace_apps( workspace_id: &str, - trash_can: Arc, + trash_can: Arc, conn: &SqliteConnection, ) -> Result { let mut app_tables = AppTableSql::read_workspace_apps(workspace_id, false, conn)?; diff --git a/frontend/rust-lib/flowy-core/src/handlers/app_handler.rs b/frontend/rust-lib/flowy-core/src/services/app/event_handler.rs similarity index 94% rename from frontend/rust-lib/flowy-core/src/handlers/app_handler.rs rename to frontend/rust-lib/flowy-core/src/services/app/event_handler.rs index 38799288db..011af97ade 100644 --- a/frontend/rust-lib/flowy-core/src/handlers/app_handler.rs +++ b/frontend/rust-lib/flowy-core/src/services/app/event_handler.rs @@ -12,7 +12,7 @@ use crate::{ trash::Trash, }, errors::WorkspaceError, - services::{AppController, TrashCan, ViewController}, + services::{AppController, TrashController, ViewController}, }; use lib_dispatch::prelude::{data_result, Data, DataResult, Unit}; use std::{convert::TryInto, sync::Arc}; @@ -30,7 +30,7 @@ pub(crate) async fn create_app_handler( pub(crate) async fn delete_app_handler( data: Data, controller: Unit>, - trash_can: Unit>, + trash_can: Unit>, ) -> Result<(), WorkspaceError> { let params: AppIdentifier = data.into_inner().try_into()?; let trash = controller diff --git a/frontend/rust-lib/flowy-core/src/services/app/mod.rs b/frontend/rust-lib/flowy-core/src/services/app/mod.rs new file mode 100644 index 0000000000..8bf3cc04ff --- /dev/null +++ b/frontend/rust-lib/flowy-core/src/services/app/mod.rs @@ -0,0 +1,3 @@ +pub mod controller; +pub mod event_handler; +pub(crate) mod sql; diff --git a/frontend/rust-lib/flowy-core/src/sql_tables/app/app_table.rs b/frontend/rust-lib/flowy-core/src/services/app/sql.rs similarity index 58% rename from frontend/rust-lib/flowy-core/src/sql_tables/app/app_table.rs rename to frontend/rust-lib/flowy-core/src/services/app/sql.rs index a236d82d32..12b08d55e9 100644 --- a/frontend/rust-lib/flowy-core/src/sql_tables/app/app_table.rs +++ b/frontend/rust-lib/flowy-core/src/services/app/sql.rs @@ -1,18 +1,87 @@ -use std::convert::TryInto; - -use diesel::sql_types::Binary; -use serde::{Deserialize, Serialize, __private::TryFrom}; - -use flowy_database::schema::app_table; - use crate::{ entities::{ app::{App, ColorStyle, UpdateAppParams}, trash::{Trash, TrashType}, view::RepeatedView, }, - sql_tables::workspace::WorkspaceTable, + services::workspace::sql::WorkspaceTable, }; +use diesel::sql_types::Binary; +use flowy_database::{ + prelude::*, + schema::{app_table, app_table::dsl}, + SqliteConnection, +}; +use serde::{Deserialize, Serialize, __private::TryFrom}; +use std::convert::TryInto; + +use crate::errors::WorkspaceError; + +pub struct AppTableSql {} + +impl AppTableSql { + pub(crate) fn create_app(app_table: AppTable, conn: &SqliteConnection) -> Result<(), WorkspaceError> { + match diesel_record_count!(app_table, &app_table.id, conn) { + 0 => diesel_insert_table!(app_table, &app_table, conn), + _ => { + let changeset = AppTableChangeset::from_table(app_table); + diesel_update_table!(app_table, changeset, conn) + }, + } + Ok(()) + } + + pub(crate) fn update_app(changeset: AppTableChangeset, conn: &SqliteConnection) -> Result<(), WorkspaceError> { + diesel_update_table!(app_table, changeset, conn); + Ok(()) + } + + pub(crate) fn read_app(app_id: &str, conn: &SqliteConnection) -> Result { + let filter = dsl::app_table.filter(app_table::id.eq(app_id)).into_boxed(); + let app_table = filter.first::(conn)?; + Ok(app_table) + } + + pub(crate) fn read_workspace_apps( + workspace_id: &str, + is_trash: bool, + conn: &SqliteConnection, + ) -> Result, WorkspaceError> { + let app_table = dsl::app_table + .filter(app_table::workspace_id.eq(workspace_id)) + .filter(app_table::is_trash.eq(is_trash)) + .order(app_table::create_time.asc()) + .load::(conn)?; + + Ok(app_table) + } + + pub(crate) fn delete_app(app_id: &str, conn: &SqliteConnection) -> Result { + let app_table = dsl::app_table + .filter(app_table::id.eq(app_id)) + .first::(conn)?; + diesel_delete_table!(app_table, app_id, conn); + Ok(app_table) + } + + // pub(crate) fn read_views_belong_to_app( + // &self, + // app_id: &str, + // ) -> Result, WorkspaceError> { + // let conn = self.database.db_connection()?; + // + // let views = conn.immediate_transaction::<_, WorkspaceError, _>(|| { + // let app_table: AppTable = dsl::app_table + // .filter(app_table::id.eq(app_id)) + // .first::(&*(conn))?; + // let views = + // ViewTable::belonging_to(&app_table).load::(&*conn)?; + // Ok(views) + // })?; + // + // Ok(views) + // } +} #[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable, Associations)] #[belongs_to(WorkspaceTable, foreign_key = "workspace_id")] diff --git a/frontend/rust-lib/flowy-core/src/services/database.rs b/frontend/rust-lib/flowy-core/src/services/database.rs deleted file mode 100644 index 8b13789179..0000000000 --- a/frontend/rust-lib/flowy-core/src/services/database.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/frontend/rust-lib/flowy-core/src/services/mod.rs b/frontend/rust-lib/flowy-core/src/services/mod.rs index 5678526952..5ce07dd23b 100644 --- a/frontend/rust-lib/flowy-core/src/services/mod.rs +++ b/frontend/rust-lib/flowy-core/src/services/mod.rs @@ -1,11 +1,10 @@ -pub(crate) use app_controller::*; -pub(crate) use trash_can::*; -pub(crate) use view_controller::*; -pub use workspace_controller::*; +pub(crate) use app::controller::*; +pub(crate) use trash::controller::*; +pub(crate) use view::controller::*; +pub(crate) use workspace::controller::*; -mod app_controller; -mod database; +pub(crate) mod app; pub(crate) mod server; -mod trash_can; -mod view_controller; -mod workspace_controller; +pub(crate) mod trash; +pub(crate) mod view; +pub(crate) mod workspace; diff --git a/frontend/rust-lib/flowy-core/src/services/trash_can.rs b/frontend/rust-lib/flowy-core/src/services/trash/controller.rs similarity index 98% rename from frontend/rust-lib/flowy-core/src/services/trash_can.rs rename to frontend/rust-lib/flowy-core/src/services/trash/controller.rs index 716966a0d9..670111860b 100644 --- a/frontend/rust-lib/flowy-core/src/services/trash_can.rs +++ b/frontend/rust-lib/flowy-core/src/services/trash/controller.rs @@ -1,27 +1,23 @@ -use std::{fmt::Formatter, sync::Arc}; - -use crossbeam_utils::thread; -use tokio::sync::{broadcast, mpsc}; - -use flowy_database::SqliteConnection; - use crate::{ entities::trash::{RepeatedTrash, Trash, TrashIdentifier, TrashIdentifiers, TrashType}, errors::{WorkspaceError, WorkspaceResult}, module::{WorkspaceDatabase, WorkspaceUser}, notify::{send_anonymous_dart_notification, WorkspaceNotification}, - services::server::Server, - sql_tables::trash::TrashTableSql, + services::{server::Server, trash::sql::TrashTableSql}, }; +use crossbeam_utils::thread; +use flowy_database::SqliteConnection; +use std::{fmt::Formatter, sync::Arc}; +use tokio::sync::{broadcast, mpsc}; -pub struct TrashCan { +pub struct TrashController { pub database: Arc, notify: broadcast::Sender, server: Server, user: Arc, } -impl TrashCan { +impl TrashController { pub fn new(database: Arc, server: Server, user: Arc) -> Self { let (tx, _) = broadcast::channel(10); @@ -196,7 +192,7 @@ impl TrashCan { } } -impl TrashCan { +impl TrashController { #[tracing::instrument(level = "debug", skip(self, trash), err)] fn create_trash_on_server>(&self, trash: T) -> WorkspaceResult<()> { let token = self.user.token()?; diff --git a/frontend/rust-lib/flowy-core/src/handlers/trash_handler.rs b/frontend/rust-lib/flowy-core/src/services/trash/event_handler.rs similarity index 77% rename from frontend/rust-lib/flowy-core/src/handlers/trash_handler.rs rename to frontend/rust-lib/flowy-core/src/services/trash/event_handler.rs index dff81964e8..3b72f630c0 100644 --- a/frontend/rust-lib/flowy-core/src/handlers/trash_handler.rs +++ b/frontend/rust-lib/flowy-core/src/services/trash/event_handler.rs @@ -1,13 +1,15 @@ use crate::{ entities::trash::{RepeatedTrash, TrashIdentifier, TrashIdentifiers}, errors::WorkspaceError, - services::TrashCan, + services::TrashController, }; use lib_dispatch::prelude::{data_result, Data, DataResult, Unit}; use std::sync::Arc; #[tracing::instrument(skip(controller), err)] -pub(crate) async fn read_trash_handler(controller: Unit>) -> DataResult { +pub(crate) async fn read_trash_handler( + controller: Unit>, +) -> DataResult { let conn = controller.database.db_connection()?; let repeated_trash = controller.read_trash(&conn)?; data_result(repeated_trash) @@ -16,7 +18,7 @@ pub(crate) async fn read_trash_handler(controller: Unit>) -> DataR #[tracing::instrument(skip(identifier, controller), err)] pub(crate) async fn putback_trash_handler( identifier: Data, - controller: Unit>, + controller: Unit>, ) -> Result<(), WorkspaceError> { let _ = controller.putback(&identifier.id).await?; Ok(()) @@ -25,20 +27,20 @@ pub(crate) async fn putback_trash_handler( #[tracing::instrument(skip(identifiers, controller), err)] pub(crate) async fn delete_trash_handler( identifiers: Data, - controller: Unit>, + controller: Unit>, ) -> Result<(), WorkspaceError> { let _ = controller.delete(identifiers.into_inner()).await?; Ok(()) } #[tracing::instrument(skip(controller), err)] -pub(crate) async fn restore_all_handler(controller: Unit>) -> Result<(), WorkspaceError> { +pub(crate) async fn restore_all_handler(controller: Unit>) -> Result<(), WorkspaceError> { let _ = controller.restore_all().await?; Ok(()) } #[tracing::instrument(skip(controller), err)] -pub(crate) async fn delete_all_handler(controller: Unit>) -> Result<(), WorkspaceError> { +pub(crate) async fn delete_all_handler(controller: Unit>) -> Result<(), WorkspaceError> { let _ = controller.delete_all().await?; Ok(()) } diff --git a/frontend/rust-lib/flowy-core/src/services/trash/mod.rs b/frontend/rust-lib/flowy-core/src/services/trash/mod.rs new file mode 100644 index 0000000000..c08fd82307 --- /dev/null +++ b/frontend/rust-lib/flowy-core/src/services/trash/mod.rs @@ -0,0 +1,3 @@ +pub mod controller; +pub mod event_handler; +mod sql; diff --git a/frontend/rust-lib/flowy-core/src/sql_tables/trash/trash_table.rs b/frontend/rust-lib/flowy-core/src/services/trash/sql.rs similarity index 58% rename from frontend/rust-lib/flowy-core/src/sql_tables/trash/trash_table.rs rename to frontend/rust-lib/flowy-core/src/services/trash/sql.rs index b07fc53088..b65b448a96 100644 --- a/frontend/rust-lib/flowy-core/src/sql_tables/trash/trash_table.rs +++ b/frontend/rust-lib/flowy-core/src/services/trash/sql.rs @@ -1,6 +1,55 @@ -use crate::entities::trash::{Trash, TrashType}; +use crate::{ + entities::trash::{RepeatedTrash, Trash, TrashType}, + errors::WorkspaceError, +}; use diesel::sql_types::Integer; -use flowy_database::schema::trash_table; +use flowy_database::{ + prelude::*, + schema::{trash_table, trash_table::dsl}, + SqliteConnection, +}; + +pub struct TrashTableSql {} + +impl TrashTableSql { + pub(crate) fn create_trash(repeated_trash: Vec, conn: &SqliteConnection) -> Result<(), WorkspaceError> { + for trash in repeated_trash { + let trash_table: TrashTable = trash.into(); + match diesel_record_count!(trash_table, &trash_table.id, conn) { + 0 => diesel_insert_table!(trash_table, &trash_table, conn), + _ => { + let changeset = TrashTableChangeset::from(trash_table); + diesel_update_table!(trash_table, changeset, conn) + }, + } + } + + Ok(()) + } + + pub(crate) fn read_all(conn: &SqliteConnection) -> Result { + let trash_tables = dsl::trash_table.load::(conn)?; + let items = trash_tables.into_iter().map(|t| t.into()).collect::>(); + Ok(RepeatedTrash { items }) + } + + pub(crate) fn delete_all(conn: &SqliteConnection) -> Result<(), WorkspaceError> { + let _ = diesel::delete(dsl::trash_table).execute(conn)?; + Ok(()) + } + + pub(crate) fn read(trash_id: &str, conn: &SqliteConnection) -> Result { + let trash_table = dsl::trash_table + .filter(trash_table::id.eq(trash_id)) + .first::(conn)?; + Ok(trash_table) + } + + pub(crate) fn delete_trash(trash_id: &str, conn: &SqliteConnection) -> Result<(), WorkspaceError> { + diesel_delete_table!(trash_table, trash_id, conn); + Ok(()) + } +} #[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable, Associations)] #[table_name = "trash_table"] diff --git a/frontend/rust-lib/flowy-core/src/services/view_controller.rs b/frontend/rust-lib/flowy-core/src/services/view/controller.rs similarity index 97% rename from frontend/rust-lib/flowy-core/src/services/view_controller.rs rename to frontend/rust-lib/flowy-core/src/services/view/controller.rs index d460afe03d..2e98984dd8 100644 --- a/frontend/rust-lib/flowy-core/src/services/view_controller.rs +++ b/frontend/rust-lib/flowy-core/src/services/view/controller.rs @@ -11,8 +11,12 @@ use crate::{ errors::{internal_error, WorkspaceError, WorkspaceResult}, module::{WorkspaceDatabase, WorkspaceUser}, notify::{send_dart_notification, WorkspaceNotification}, - services::{server::Server, TrashCan, TrashEvent}, - sql_tables::view::{ViewTable, ViewTableChangeset, ViewTableSql}, + services::{ + server::Server, + view::sql::{ViewTable, ViewTableChangeset, ViewTableSql}, + TrashController, + TrashEvent, + }, }; use flowy_document::module::FlowyDocument; use flowy_workspace_infra::entities::share::{ExportData, ExportParams}; @@ -24,7 +28,7 @@ pub(crate) struct ViewController { user: Arc, server: Server, database: Arc, - trash_can: Arc, + trash_can: Arc, document: Arc, } @@ -33,7 +37,7 @@ impl ViewController { user: Arc, database: Arc, server: Server, - trash_can: Arc, + trash_can: Arc, document: Arc, ) -> Self { Self { @@ -296,7 +300,7 @@ impl ViewController { async fn handle_trash_event( database: Arc, document: Arc, - trash_can: Arc, + trash_can: Arc, event: TrashEvent, ) { let db_result = database.db_connection(); @@ -372,7 +376,11 @@ fn notify_dart(view_table: ViewTable, notification: WorkspaceNotification) { } #[tracing::instrument(skip(belong_to_id, trash_can, conn), fields(view_count), err)] -fn notify_views_changed(belong_to_id: &str, trash_can: Arc, conn: &SqliteConnection) -> WorkspaceResult<()> { +fn notify_views_changed( + belong_to_id: &str, + trash_can: Arc, + conn: &SqliteConnection, +) -> WorkspaceResult<()> { 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) @@ -383,7 +391,7 @@ fn notify_views_changed(belong_to_id: &str, trash_can: Arc, conn: &Sql fn read_local_belonging_view( belong_to_id: &str, - trash_can: Arc, + trash_can: Arc, conn: &SqliteConnection, ) -> WorkspaceResult { let mut view_tables = ViewTableSql::read_views(belong_to_id, conn)?; diff --git a/frontend/rust-lib/flowy-core/src/handlers/view_handler.rs b/frontend/rust-lib/flowy-core/src/services/view/event_handler.rs similarity index 97% rename from frontend/rust-lib/flowy-core/src/handlers/view_handler.rs rename to frontend/rust-lib/flowy-core/src/services/view/event_handler.rs index 5212d7cb2a..7a1e11e5aa 100644 --- a/frontend/rust-lib/flowy-core/src/handlers/view_handler.rs +++ b/frontend/rust-lib/flowy-core/src/services/view/event_handler.rs @@ -13,7 +13,7 @@ use crate::{ }, }, errors::WorkspaceError, - services::{TrashCan, ViewController}, + services::{TrashController, ViewController}, }; use flowy_document_infra::entities::doc::DocDelta; use flowy_workspace_infra::entities::share::{ExportData, ExportParams, ExportRequest}; @@ -63,7 +63,7 @@ pub(crate) async fn apply_doc_delta_handler( pub(crate) async fn delete_view_handler( data: Data, controller: Unit>, - trash_can: Unit>, + trash_can: Unit>, ) -> Result<(), WorkspaceError> { let params: ViewIdentifiers = data.into_inner().try_into()?; for view_id in ¶ms.view_ids { diff --git a/frontend/rust-lib/flowy-core/src/services/view/mod.rs b/frontend/rust-lib/flowy-core/src/services/view/mod.rs new file mode 100644 index 0000000000..c08fd82307 --- /dev/null +++ b/frontend/rust-lib/flowy-core/src/services/view/mod.rs @@ -0,0 +1,3 @@ +pub mod controller; +pub mod event_handler; +mod sql; diff --git a/frontend/rust-lib/flowy-core/src/sql_tables/view/view_table.rs b/frontend/rust-lib/flowy-core/src/services/view/sql.rs similarity index 51% rename from frontend/rust-lib/flowy-core/src/sql_tables/view/view_table.rs rename to frontend/rust-lib/flowy-core/src/services/view/sql.rs index 54f9f49c44..fedd6310bb 100644 --- a/frontend/rust-lib/flowy-core/src/sql_tables/view/view_table.rs +++ b/frontend/rust-lib/flowy-core/src/services/view/sql.rs @@ -1,15 +1,112 @@ -use diesel::sql_types::Integer; - -use flowy_database::schema::view_table; -use lib_infra::timestamp; - use crate::{ entities::{ trash::{Trash, TrashType}, view::{RepeatedView, UpdateViewParams, View, ViewType}, }, - sql_tables::app::AppTable, + errors::WorkspaceError, + services::app::sql::AppTable, }; +use diesel::sql_types::Integer; +use flowy_database::{ + prelude::*, + schema::{view_table, view_table::dsl}, + SqliteConnection, +}; +use lib_infra::timestamp; + +pub struct ViewTableSql {} + +impl ViewTableSql { + pub(crate) fn create_view(view_table: ViewTable, conn: &SqliteConnection) -> Result<(), WorkspaceError> { + match diesel_record_count!(view_table, &view_table.id, conn) { + 0 => diesel_insert_table!(view_table, &view_table, conn), + _ => { + let changeset = ViewTableChangeset::from_table(view_table); + diesel_update_table!(view_table, changeset, conn) + }, + } + Ok(()) + } + + pub(crate) fn read_view(view_id: &str, conn: &SqliteConnection) -> Result { + // 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(); + // if let Some(is_trash) = is_trash { + // filter = filter.filter(view_table::is_trash.eq(is_trash)); + // } + // let repeated_view = filter.first::(conn)?; + let view_table = dsl::view_table + .filter(view_table::id.eq(view_id)) + .first::(conn)?; + + Ok(view_table) + } + + // belong_to_id will be the app_id or view_id. + pub(crate) fn read_views(belong_to_id: &str, conn: &SqliteConnection) -> Result, WorkspaceError> { + let view_tables = dsl::view_table + .filter(view_table::belong_to_id.eq(belong_to_id)) + .order(view_table::create_time.asc()) + .into_boxed() + .load::(conn)?; + + Ok(view_tables) + } + + pub(crate) fn update_view(changeset: ViewTableChangeset, conn: &SqliteConnection) -> Result<(), WorkspaceError> { + diesel_update_table!(view_table, changeset, conn); + Ok(()) + } + + pub(crate) fn delete_view(view_id: &str, conn: &SqliteConnection) -> Result<(), WorkspaceError> { + diesel_delete_table!(view_table, view_id, conn); + Ok(()) + } +} + +// pub(crate) fn read_views( +// belong_to_id: &str, +// is_trash: Option, +// conn: &SqliteConnection, +// ) -> Result { +// 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)) +// .select(( +// view_table::id, +// view_table::belong_to_id, +// view_table::name, +// view_table::desc, +// view_table::modified_time, +// view_table::create_time, +// view_table::thumbnail, +// view_table::view_type, +// view_table::version, +// )) +// .load(conn)? +// .into_iter() +// .map( +// |(id, belong_to_id, name, desc, create_time, modified_time, +// thumbnail, view_type, version)| { ViewTable { +// id, +// belong_to_id, +// name, +// desc, +// modified_time, +// create_time, +// thumbnail, +// view_type, +// version, +// is_trash: false, +// } +// .into() +// }, +// ) +// .collect::>(); +// +// Ok(RepeatedView { items: views }) +// } #[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable, Associations)] #[belongs_to(AppTable, foreign_key = "belong_to_id")] diff --git a/frontend/rust-lib/flowy-core/src/services/workspace_controller.rs b/frontend/rust-lib/flowy-core/src/services/workspace/controller.rs similarity index 76% rename from frontend/rust-lib/flowy-core/src/services/workspace_controller.rs rename to frontend/rust-lib/flowy-core/src/services/workspace/controller.rs index bbace11f5b..ec42ddfadd 100644 --- a/frontend/rust-lib/flowy-core/src/services/workspace_controller.rs +++ b/frontend/rust-lib/flowy-core/src/services/workspace/controller.rs @@ -2,24 +2,19 @@ use crate::{ errors::*, module::{WorkspaceDatabase, WorkspaceUser}, notify::*, - services::{read_local_workspace_apps, server::Server, AppController, TrashCan, ViewController}, - sql_tables::workspace::{WorkspaceTable, WorkspaceTableChangeset, WorkspaceTableSql}, + services::{ + read_local_workspace_apps, + server::Server, + workspace::sql::{WorkspaceTable, WorkspaceTableChangeset, WorkspaceTableSql}, + AppController, + TrashController, + ViewController, + }, }; -use chrono::Utc; use flowy_database::SqliteConnection; -use flowy_document_infra::{entities::doc::DocDelta, user_default::initial_read_me}; -use flowy_workspace_infra::{ - entities::{app::RepeatedApp, view::View, workspace::*}, - user_default, -}; -use lazy_static::lazy_static; -use lib_infra::{entities::network_state::NetworkType, kv::KV}; -use parking_lot::RwLock; -use std::{collections::HashMap, sync::Arc}; - -lazy_static! { - static ref INIT_WORKSPACE: RwLock> = RwLock::new(HashMap::new()); -} +use flowy_workspace_infra::entities::{app::RepeatedApp, view::View, workspace::*}; +use lib_infra::kv::KV; +use std::sync::Arc; pub struct WorkspaceController { pub user: Arc, @@ -27,7 +22,7 @@ pub struct WorkspaceController { pub(crate) view_controller: Arc, pub(crate) database: Arc, pub(crate) app_controller: Arc, - pub(crate) trash_can: Arc, + pub(crate) trash_controller: Arc, server: Server, } @@ -37,13 +32,9 @@ impl WorkspaceController { database: Arc, app_controller: Arc, view_controller: Arc, - trash_can: Arc, + trash_can: Arc, server: Server, ) -> Self { - if let Ok(token) = user.token() { - INIT_WORKSPACE.write().insert(token, false); - } - let workspace_sql = Arc::new(WorkspaceTableSql {}); Self { user, @@ -51,92 +42,12 @@ impl WorkspaceController { view_controller, database, app_controller, - trash_can, + trash_controller: trash_can, server, } } - async fn init(&self, token: &str) -> Result<(), WorkspaceError> { - log::debug!("Start initializing workspace"); - if let Some(is_init) = INIT_WORKSPACE.read().get(token) { - if *is_init { - return Ok(()); - } - } - log::debug!("Finish initializing workspace"); - INIT_WORKSPACE.write().insert(token.to_owned(), true); - let _ = self.server.init(); - let _ = self.trash_can.init()?; - let _ = self.view_controller.init()?; - let _ = self.app_controller.init()?; - - Ok(()) - } - - pub fn network_state_changed(&self, new_type: NetworkType) { - match new_type { - NetworkType::UnknownNetworkType => {}, - NetworkType::Wifi => {}, - NetworkType::Cell => {}, - NetworkType::Ethernet => {}, - } - } - - pub async fn user_did_sign_in(&self, token: &str) -> WorkspaceResult<()> { - // TODO: (nathan) do something here - - log::debug!("workspace initialize after sign in"); - let _ = self.init(token).await?; - Ok(()) - } - - pub async fn user_did_logout(&self) { - // TODO: (nathan) do something here - } - - pub async fn user_session_expired(&self) { - // TODO: (nathan) do something here - } - - pub async fn user_did_sign_up(&self, _token: &str) -> WorkspaceResult<()> { - log::debug!("Create user default workspace"); - let time = Utc::now(); - let mut workspace = user_default::create_default_workspace(time); - let apps = workspace.take_apps().into_inner(); - let cloned_workspace = workspace.clone(); - - let _ = self.create_workspace(workspace).await?; - for mut app in apps { - let views = app.take_belongings().into_inner(); - let _ = self.app_controller.create_app(app).await?; - for (index, view) in views.into_iter().enumerate() { - if index == 0 { - let delta = initial_read_me(); - let doc_delta = DocDelta { - doc_id: view.id.clone(), - data: delta.to_json(), - }; - let _ = self.view_controller.apply_doc_delta(doc_delta).await?; - - self.view_controller.set_latest_view(&view); - } - let _ = self.view_controller.create_view(view).await?; - } - } - - let token = self.user.token()?; - let repeated_workspace = RepeatedWorkspace { - items: vec![cloned_workspace], - }; - - send_dart_notification(&token, WorkspaceNotification::UserCreateWorkspace) - .payload(repeated_workspace) - .send(); - - log::debug!("workspace initialize after sign up"); - let _ = self.init(&token).await?; - Ok(()) - } + pub(crate) fn init(&self) -> Result<(), WorkspaceError> { Ok(()) } pub(crate) async fn create_workspace_from_params( &self, @@ -263,7 +174,7 @@ impl WorkspaceController { } #[tracing::instrument(level = "debug", skip(self, conn), err)] - fn read_local_workspaces( + pub(crate) fn read_local_workspaces( &self, workspace_id: Option, user_id: &str, @@ -301,7 +212,7 @@ impl WorkspaceController { #[tracing::instrument(level = "debug", skip(self, conn), err)] fn read_local_apps(&self, workspace_id: &str, conn: &SqliteConnection) -> Result { - let repeated_app = read_local_workspace_apps(workspace_id, self.trash_can.clone(), conn)?; + let repeated_app = read_local_workspace_apps(workspace_id, self.trash_controller.clone(), conn)?; Ok(repeated_app) } } @@ -354,7 +265,11 @@ impl WorkspaceController { } #[tracing::instrument(level = "debug", skip(self), err)] - fn read_workspaces_on_server(&self, user_id: String, params: WorkspaceIdentifier) -> Result<(), WorkspaceError> { + pub(crate) fn read_workspaces_on_server( + &self, + user_id: String, + params: WorkspaceIdentifier, + ) -> Result<(), WorkspaceError> { let (token, server) = self.token_with_server()?; let workspace_sql = self.workspace_sql.clone(); let app_ctrl = self.app_controller.clone(); diff --git a/frontend/rust-lib/flowy-core/src/handlers/workspace_handler.rs b/frontend/rust-lib/flowy-core/src/services/workspace/event_handler.rs similarity index 100% rename from frontend/rust-lib/flowy-core/src/handlers/workspace_handler.rs rename to frontend/rust-lib/flowy-core/src/services/workspace/event_handler.rs diff --git a/frontend/rust-lib/flowy-core/src/services/workspace/mod.rs b/frontend/rust-lib/flowy-core/src/services/workspace/mod.rs new file mode 100644 index 0000000000..8bf3cc04ff --- /dev/null +++ b/frontend/rust-lib/flowy-core/src/services/workspace/mod.rs @@ -0,0 +1,3 @@ +pub mod controller; +pub mod event_handler; +pub(crate) mod sql; diff --git a/frontend/rust-lib/flowy-core/src/sql_tables/workspace/workspace_sql.rs b/frontend/rust-lib/flowy-core/src/services/workspace/sql.rs similarity index 50% rename from frontend/rust-lib/flowy-core/src/sql_tables/workspace/workspace_sql.rs rename to frontend/rust-lib/flowy-core/src/services/workspace/sql.rs index c6956b05d4..27fd14a7ab 100644 --- a/frontend/rust-lib/flowy-core/src/sql_tables/workspace/workspace_sql.rs +++ b/frontend/rust-lib/flowy-core/src/services/workspace/sql.rs @@ -1,15 +1,15 @@ +use crate::{ + entities::{ + app::RepeatedApp, + workspace::{UpdateWorkspaceParams, Workspace}, + }, + errors::WorkspaceError, +}; use diesel::SqliteConnection; - use flowy_database::{ prelude::*, schema::{workspace_table, workspace_table::dsl}, }; - -use crate::{ - errors::WorkspaceError, - sql_tables::workspace::{WorkspaceTable, WorkspaceTableChangeset}, -}; - pub(crate) struct WorkspaceTableSql {} impl WorkspaceTableSql { @@ -64,3 +64,69 @@ impl WorkspaceTableSql { Ok(()) } } + +#[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable)] +#[table_name = "workspace_table"] +pub struct WorkspaceTable { + pub id: String, + pub name: String, + pub desc: String, + pub modified_time: i64, + pub create_time: i64, + pub user_id: String, + pub version: i64, +} + +impl WorkspaceTable { + #[allow(dead_code)] + pub fn new(workspace: Workspace, user_id: &str) -> Self { + WorkspaceTable { + id: workspace.id, + name: workspace.name, + desc: workspace.desc, + modified_time: workspace.modified_time, + create_time: workspace.create_time, + user_id: user_id.to_owned(), + version: 0, + } + } +} + +impl std::convert::From for Workspace { + fn from(table: WorkspaceTable) -> Self { + Workspace { + id: table.id, + name: table.name, + desc: table.desc, + apps: RepeatedApp::default(), + modified_time: table.modified_time, + create_time: table.create_time, + } + } +} + +#[derive(AsChangeset, Identifiable, Clone, Default, Debug)] +#[table_name = "workspace_table"] +pub struct WorkspaceTableChangeset { + pub id: String, + pub name: Option, + pub desc: Option, +} + +impl WorkspaceTableChangeset { + pub fn new(params: UpdateWorkspaceParams) -> Self { + WorkspaceTableChangeset { + id: params.id, + name: params.name, + desc: params.desc, + } + } + + pub(crate) fn from_table(table: WorkspaceTable) -> Self { + WorkspaceTableChangeset { + id: table.id, + name: Some(table.name), + desc: Some(table.desc), + } + } +} diff --git a/frontend/rust-lib/flowy-core/src/sql_tables/app/app_sql.rs b/frontend/rust-lib/flowy-core/src/sql_tables/app/app_sql.rs deleted file mode 100644 index 8ce92f0662..0000000000 --- a/frontend/rust-lib/flowy-core/src/sql_tables/app/app_sql.rs +++ /dev/null @@ -1,76 +0,0 @@ -use flowy_database::{ - prelude::*, - schema::{app_table, app_table::dsl}, - SqliteConnection, -}; - -use crate::{ - errors::WorkspaceError, - sql_tables::app::{AppTable, AppTableChangeset}, -}; - -pub struct AppTableSql {} - -impl AppTableSql { - pub(crate) fn create_app(app_table: AppTable, conn: &SqliteConnection) -> Result<(), WorkspaceError> { - match diesel_record_count!(app_table, &app_table.id, conn) { - 0 => diesel_insert_table!(app_table, &app_table, conn), - _ => { - let changeset = AppTableChangeset::from_table(app_table); - diesel_update_table!(app_table, changeset, conn) - }, - } - Ok(()) - } - - pub(crate) fn update_app(changeset: AppTableChangeset, conn: &SqliteConnection) -> Result<(), WorkspaceError> { - diesel_update_table!(app_table, changeset, conn); - Ok(()) - } - - pub(crate) fn read_app(app_id: &str, conn: &SqliteConnection) -> Result { - let filter = dsl::app_table.filter(app_table::id.eq(app_id)).into_boxed(); - let app_table = filter.first::(conn)?; - Ok(app_table) - } - - pub(crate) fn read_workspace_apps( - workspace_id: &str, - is_trash: bool, - conn: &SqliteConnection, - ) -> Result, WorkspaceError> { - let app_table = dsl::app_table - .filter(app_table::workspace_id.eq(workspace_id)) - .filter(app_table::is_trash.eq(is_trash)) - .order(app_table::create_time.asc()) - .load::(conn)?; - - Ok(app_table) - } - - pub(crate) fn delete_app(app_id: &str, conn: &SqliteConnection) -> Result { - let app_table = dsl::app_table - .filter(app_table::id.eq(app_id)) - .first::(conn)?; - diesel_delete_table!(app_table, app_id, conn); - Ok(app_table) - } - - // pub(crate) fn read_views_belong_to_app( - // &self, - // app_id: &str, - // ) -> Result, WorkspaceError> { - // let conn = self.database.db_connection()?; - // - // let views = conn.immediate_transaction::<_, WorkspaceError, _>(|| { - // let app_table: AppTable = dsl::app_table - // .filter(app_table::id.eq(app_id)) - // .first::(&*(conn))?; - // let views = - // ViewTable::belonging_to(&app_table).load::(&*conn)?; - // Ok(views) - // })?; - // - // Ok(views) - // } -} diff --git a/frontend/rust-lib/flowy-core/src/sql_tables/app/mod.rs b/frontend/rust-lib/flowy-core/src/sql_tables/app/mod.rs deleted file mode 100644 index 4e2792e3d1..0000000000 --- a/frontend/rust-lib/flowy-core/src/sql_tables/app/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod app_sql; -mod app_table; - -pub(crate) use app_sql::*; -pub(crate) use app_table::*; diff --git a/frontend/rust-lib/flowy-core/src/sql_tables/mod.rs b/frontend/rust-lib/flowy-core/src/sql_tables/mod.rs deleted file mode 100644 index 3ee0f4b591..0000000000 --- a/frontend/rust-lib/flowy-core/src/sql_tables/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod app; -pub mod trash; -pub mod view; -pub mod workspace; diff --git a/frontend/rust-lib/flowy-core/src/sql_tables/trash/mod.rs b/frontend/rust-lib/flowy-core/src/sql_tables/trash/mod.rs deleted file mode 100644 index c8af3d5dc0..0000000000 --- a/frontend/rust-lib/flowy-core/src/sql_tables/trash/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod trash_sql; -mod trash_table; - -pub(crate) use trash_sql::*; -pub(crate) use trash_table::*; diff --git a/frontend/rust-lib/flowy-core/src/sql_tables/trash/trash_sql.rs b/frontend/rust-lib/flowy-core/src/sql_tables/trash/trash_sql.rs deleted file mode 100644 index 2b489e7be7..0000000000 --- a/frontend/rust-lib/flowy-core/src/sql_tables/trash/trash_sql.rs +++ /dev/null @@ -1,53 +0,0 @@ -use flowy_database::{ - prelude::*, - schema::{trash_table, trash_table::dsl}, - SqliteConnection, -}; - -use crate::{ - entities::trash::{RepeatedTrash, Trash}, - errors::WorkspaceError, - sql_tables::trash::{TrashTable, TrashTableChangeset}, -}; - -pub struct TrashTableSql {} - -impl TrashTableSql { - pub(crate) fn create_trash(repeated_trash: Vec, conn: &SqliteConnection) -> Result<(), WorkspaceError> { - for trash in repeated_trash { - let trash_table: TrashTable = trash.into(); - match diesel_record_count!(trash_table, &trash_table.id, conn) { - 0 => diesel_insert_table!(trash_table, &trash_table, conn), - _ => { - let changeset = TrashTableChangeset::from(trash_table); - diesel_update_table!(trash_table, changeset, conn) - }, - } - } - - Ok(()) - } - - pub(crate) fn read_all(conn: &SqliteConnection) -> Result { - let trash_tables = dsl::trash_table.load::(conn)?; - let items = trash_tables.into_iter().map(|t| t.into()).collect::>(); - Ok(RepeatedTrash { items }) - } - - pub(crate) fn delete_all(conn: &SqliteConnection) -> Result<(), WorkspaceError> { - let _ = diesel::delete(dsl::trash_table).execute(conn)?; - Ok(()) - } - - pub(crate) fn read(trash_id: &str, conn: &SqliteConnection) -> Result { - let trash_table = dsl::trash_table - .filter(trash_table::id.eq(trash_id)) - .first::(conn)?; - Ok(trash_table) - } - - pub(crate) fn delete_trash(trash_id: &str, conn: &SqliteConnection) -> Result<(), WorkspaceError> { - diesel_delete_table!(trash_table, trash_id, conn); - Ok(()) - } -} diff --git a/frontend/rust-lib/flowy-core/src/sql_tables/view/mod.rs b/frontend/rust-lib/flowy-core/src/sql_tables/view/mod.rs deleted file mode 100644 index b2730abed2..0000000000 --- a/frontend/rust-lib/flowy-core/src/sql_tables/view/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod view_sql; -mod view_table; - -pub use view_sql::*; -pub use view_table::*; diff --git a/frontend/rust-lib/flowy-core/src/sql_tables/view/view_sql.rs b/frontend/rust-lib/flowy-core/src/sql_tables/view/view_sql.rs deleted file mode 100644 index c9ef903111..0000000000 --- a/frontend/rust-lib/flowy-core/src/sql_tables/view/view_sql.rs +++ /dev/null @@ -1,104 +0,0 @@ -use flowy_database::{ - prelude::*, - schema::{view_table, view_table::dsl}, - SqliteConnection, -}; - -use crate::{ - errors::WorkspaceError, - sql_tables::view::{ViewTable, ViewTableChangeset}, -}; - -pub struct ViewTableSql {} - -impl ViewTableSql { - pub(crate) fn create_view(view_table: ViewTable, conn: &SqliteConnection) -> Result<(), WorkspaceError> { - match diesel_record_count!(view_table, &view_table.id, conn) { - 0 => diesel_insert_table!(view_table, &view_table, conn), - _ => { - let changeset = ViewTableChangeset::from_table(view_table); - diesel_update_table!(view_table, changeset, conn) - }, - } - Ok(()) - } - - pub(crate) fn read_view(view_id: &str, conn: &SqliteConnection) -> Result { - // 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(); - // if let Some(is_trash) = is_trash { - // filter = filter.filter(view_table::is_trash.eq(is_trash)); - // } - // let repeated_view = filter.first::(conn)?; - let view_table = dsl::view_table - .filter(view_table::id.eq(view_id)) - .first::(conn)?; - - Ok(view_table) - } - - // belong_to_id will be the app_id or view_id. - pub(crate) fn read_views(belong_to_id: &str, conn: &SqliteConnection) -> Result, WorkspaceError> { - let view_tables = dsl::view_table - .filter(view_table::belong_to_id.eq(belong_to_id)) - .order(view_table::create_time.asc()) - .into_boxed() - .load::(conn)?; - - Ok(view_tables) - } - - pub(crate) fn update_view(changeset: ViewTableChangeset, conn: &SqliteConnection) -> Result<(), WorkspaceError> { - diesel_update_table!(view_table, changeset, conn); - Ok(()) - } - - pub(crate) fn delete_view(view_id: &str, conn: &SqliteConnection) -> Result<(), WorkspaceError> { - diesel_delete_table!(view_table, view_id, conn); - Ok(()) - } -} - -// pub(crate) fn read_views( -// belong_to_id: &str, -// is_trash: Option, -// conn: &SqliteConnection, -// ) -> Result { -// 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)) -// .select(( -// view_table::id, -// view_table::belong_to_id, -// view_table::name, -// view_table::desc, -// view_table::modified_time, -// view_table::create_time, -// view_table::thumbnail, -// view_table::view_type, -// view_table::version, -// )) -// .load(conn)? -// .into_iter() -// .map( -// |(id, belong_to_id, name, desc, create_time, modified_time, -// thumbnail, view_type, version)| { ViewTable { -// id, -// belong_to_id, -// name, -// desc, -// modified_time, -// create_time, -// thumbnail, -// view_type, -// version, -// is_trash: false, -// } -// .into() -// }, -// ) -// .collect::>(); -// -// Ok(RepeatedView { items: views }) -// } diff --git a/frontend/rust-lib/flowy-core/src/sql_tables/workspace/mod.rs b/frontend/rust-lib/flowy-core/src/sql_tables/workspace/mod.rs deleted file mode 100644 index e9461c942f..0000000000 --- a/frontend/rust-lib/flowy-core/src/sql_tables/workspace/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod workspace_sql; -mod workspace_table; - -pub(crate) use workspace_sql::*; -pub(crate) use workspace_table::*; diff --git a/frontend/rust-lib/flowy-core/src/sql_tables/workspace/workspace_table.rs b/frontend/rust-lib/flowy-core/src/sql_tables/workspace/workspace_table.rs deleted file mode 100644 index 02816ada2b..0000000000 --- a/frontend/rust-lib/flowy-core/src/sql_tables/workspace/workspace_table.rs +++ /dev/null @@ -1,71 +0,0 @@ -use crate::entities::{ - app::RepeatedApp, - workspace::{UpdateWorkspaceParams, Workspace}, -}; -use flowy_database::schema::workspace_table; - -#[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable)] -#[table_name = "workspace_table"] -pub struct WorkspaceTable { - pub id: String, - pub name: String, - pub desc: String, - pub modified_time: i64, - pub create_time: i64, - pub user_id: String, - pub version: i64, -} - -impl WorkspaceTable { - #[allow(dead_code)] - pub fn new(workspace: Workspace, user_id: &str) -> Self { - WorkspaceTable { - id: workspace.id, - name: workspace.name, - desc: workspace.desc, - modified_time: workspace.modified_time, - create_time: workspace.create_time, - user_id: user_id.to_owned(), - version: 0, - } - } -} - -impl std::convert::From for Workspace { - fn from(table: WorkspaceTable) -> Self { - Workspace { - id: table.id, - name: table.name, - desc: table.desc, - apps: RepeatedApp::default(), - modified_time: table.modified_time, - create_time: table.create_time, - } - } -} - -#[derive(AsChangeset, Identifiable, Clone, Default, Debug)] -#[table_name = "workspace_table"] -pub struct WorkspaceTableChangeset { - pub id: String, - pub name: Option, - pub desc: Option, -} - -impl WorkspaceTableChangeset { - pub fn new(params: UpdateWorkspaceParams) -> Self { - WorkspaceTableChangeset { - id: params.id, - name: params.name, - desc: params.desc, - } - } - - pub(crate) fn from_table(table: WorkspaceTable) -> Self { - WorkspaceTableChangeset { - id: table.id, - name: Some(table.name), - desc: Some(table.desc), - } - } -} diff --git a/frontend/rust-lib/flowy-sdk/src/lib.rs b/frontend/rust-lib/flowy-sdk/src/lib.rs index fc8aa73fca..2eaa4782f3 100644 --- a/frontend/rust-lib/flowy-sdk/src/lib.rs +++ b/frontend/rust-lib/flowy-sdk/src/lib.rs @@ -3,7 +3,7 @@ mod deps_resolve; pub mod module; use crate::deps_resolve::WorkspaceDepsResolver; use backend_service::configuration::ClientServerConfiguration; -use flowy_core::{errors::WorkspaceError, prelude::WorkspaceController}; +use flowy_core::{errors::WorkspaceError, module::init_core, prelude::FlowyCore}; use flowy_document::module::FlowyDocument; use flowy_user::{ prelude::UserStatus, @@ -66,7 +66,7 @@ pub struct FlowySDK { config: FlowySDKConfig, pub user_session: Arc, pub flowy_document: Arc, - pub workspace_ctrl: Arc, + pub core: Arc, pub dispatcher: Arc, } @@ -81,17 +81,17 @@ impl FlowySDK { let user_config = UserSessionConfig::new(&config.root, &config.server_config, &session_cache_key); let user_session = Arc::new(UserSession::new(user_config)); let flowy_document = mk_document_module(user_session.clone(), &config.server_config); - let workspace_ctrl = - mk_workspace_controller(user_session.clone(), flowy_document.clone(), &config.server_config); - let modules = mk_modules(workspace_ctrl.clone(), user_session.clone()); + let core = mk_core(user_session.clone(), flowy_document.clone(), &config.server_config); + + let modules = mk_modules(core.clone(), user_session.clone()); let dispatcher = Arc::new(EventDispatcher::construct(|| modules)); - _init(&dispatcher, user_session.clone(), workspace_ctrl.clone()); + _init(&dispatcher, user_session.clone(), core.clone()); Self { config, user_session, flowy_document, - workspace_ctrl, + core, dispatcher, } } @@ -99,38 +99,35 @@ impl FlowySDK { pub fn dispatcher(&self) -> Arc { self.dispatcher.clone() } } -fn _init(dispatch: &EventDispatcher, user_session: Arc, workspace_controller: Arc) { +fn _init(dispatch: &EventDispatcher, user_session: Arc, core: Arc) { let user_status_subscribe = user_session.notifier.user_status_subscribe(); let network_status_subscribe = user_session.notifier.network_type_subscribe(); - let cloned_workspace_controller = workspace_controller.clone(); + let cloned_core = core.clone(); dispatch.spawn(async move { user_session.init(); - _listen_user_status(user_status_subscribe, workspace_controller.clone()).await; + _listen_user_status(user_status_subscribe, core.clone()).await; }); dispatch.spawn(async move { - _listen_network_status(network_status_subscribe, cloned_workspace_controller).await; + _listen_network_status(network_status_subscribe, cloned_core).await; }); } -async fn _listen_user_status( - mut subscribe: broadcast::Receiver, - workspace_controller: Arc, -) { +async fn _listen_user_status(mut subscribe: broadcast::Receiver, core: Arc) { while let Ok(status) = subscribe.recv().await { let result = || async { match status { UserStatus::Login { token } => { - let _ = workspace_controller.user_did_sign_in(&token).await?; + let _ = core.user_did_sign_in(&token).await?; }, UserStatus::Logout { .. } => { - workspace_controller.user_did_logout().await; + core.user_did_logout().await; }, UserStatus::Expired { .. } => { - workspace_controller.user_session_expired().await; + core.user_session_expired().await; }, UserStatus::SignUp { profile, ret } => { - let _ = workspace_controller.user_did_sign_up(&profile.token).await?; + let _ = core.user_did_sign_up(&profile.token).await?; let _ = ret.send(()); }, } @@ -144,12 +141,9 @@ async fn _listen_user_status( } } -async fn _listen_network_status( - mut subscribe: broadcast::Receiver, - workspace_controller: Arc, -) { +async fn _listen_network_status(mut subscribe: broadcast::Receiver, core: Arc) { while let Ok(new_type) = subscribe.recv().await { - workspace_controller.network_state_changed(new_type); + core.network_state_changed(new_type); } } @@ -170,12 +164,12 @@ fn init_log(config: &FlowySDKConfig) { } } -fn mk_workspace_controller( +fn mk_core( user_session: Arc, flowy_document: Arc, server_config: &ClientServerConfiguration, -) -> Arc { +) -> Arc { let workspace_deps = WorkspaceDepsResolver::new(user_session); let (user, database) = workspace_deps.split_into(); - flowy_core::module::init_workspace_controller(user, database, flowy_document, server_config) + init_core(user, database, flowy_document, server_config) } diff --git a/frontend/rust-lib/flowy-sdk/src/module.rs b/frontend/rust-lib/flowy-sdk/src/module.rs index 61caf42922..ac410b91cf 100644 --- a/frontend/rust-lib/flowy-sdk/src/module.rs +++ b/frontend/rust-lib/flowy-sdk/src/module.rs @@ -1,22 +1,19 @@ use crate::deps_resolve::DocumentDepsResolver; use backend_service::configuration::ClientServerConfiguration; -use flowy_core::prelude::WorkspaceController; +use flowy_core::prelude::FlowyCore; use flowy_document::module::FlowyDocument; use flowy_user::services::user::UserSession; use lib_dispatch::prelude::Module; use std::sync::Arc; -pub fn mk_modules(workspace_controller: Arc, user_session: Arc) -> Vec { +pub fn mk_modules(core: Arc, user_session: Arc) -> Vec { let user_module = mk_user_module(user_session); - let workspace_module = mk_workspace_module(workspace_controller); + let workspace_module = mk_core_module(core); vec![user_module, workspace_module] } fn mk_user_module(user_session: Arc) -> Module { flowy_user::module::create(user_session) } - -fn mk_workspace_module(workspace_controller: Arc) -> Module { - flowy_core::module::create(workspace_controller) -} +fn mk_core_module(core: Arc) -> Module { flowy_core::module::create(core) } pub fn mk_document_module( user_session: Arc, From 8457682092fbc27a072ae11f7502f11d721d4287 Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 6 Dec 2021 21:47:21 +0800 Subject: [PATCH 04/39] refactor backend dir hierarchi --- backend/src/application.rs | 15 +-- backend/src/context.rs | 6 +- backend/src/entities/token.rs | 2 +- backend/src/lib.rs | 3 +- backend/src/middleware/auth_middleware.rs | 2 +- backend/src/{service => services}/app/app.rs | 4 +- backend/src/{service => services}/app/mod.rs | 0 .../src/{service => services}/app/router.rs | 2 +- .../{service => services}/app/sql_builder.rs | 0 backend/src/{service => services}/doc/crud.rs | 0 .../doc/edit/edit_actor.rs | 6 +- .../{service => services}/doc/edit/editor.rs | 10 +- .../src/{service => services}/doc/edit/mod.rs | 0 .../src/{service => services}/doc/manager.rs | 6 +- backend/src/{service => services}/doc/mod.rs | 0 .../src/{service => services}/doc/router.rs | 2 +- .../src/{service => services}/doc/ws_actor.rs | 10 +- .../{service/log/mod.rs => services/log.rs} | 0 backend/src/{service => services}/mod.rs | 1 - .../src/{service => services}/trash/mod.rs | 0 .../src/{service => services}/trash/router.rs | 2 +- .../src/{service => services}/trash/trash.rs | 2 +- .../src/{service => services}/user/auth.rs | 5 +- .../{service => services}/user/logged_user.rs | 0 backend/src/{service => services}/user/mod.rs | 0 .../src/{service => services}/user/router.rs | 2 +- .../user/user_default.rs | 5 +- .../src/{service => services}/user/utils.rs | 0 backend/src/{service => services}/util.rs | 0 backend/src/{service => services}/view/mod.rs | 0 .../src/{service => services}/view/router.rs | 2 +- .../{service => services}/view/sql_builder.rs | 0 .../src/{service => services}/view/view.rs | 2 +- .../{service => services}/workspace/mod.rs | 0 .../{service => services}/workspace/router.rs | 2 +- .../workspace/sql_builder.rs | 0 .../workspace/workspace.rs | 2 +- .../{service/ws => web_socket}/biz_handler.rs | 3 +- .../ws => web_socket}/entities/connect.rs | 2 +- .../ws => web_socket}/entities/message.rs | 0 .../ws => web_socket}/entities/mod.rs | 0 backend/src/{service/ws => web_socket}/mod.rs | 0 .../src/{service/ws => web_socket}/router.rs | 6 +- .../{service/ws => web_socket}/ws_client.rs | 14 +-- .../{service/ws => web_socket}/ws_server.rs | 2 +- .../src/core/aggregate_tasks/mod.rs | 3 + .../core/aggregate_tasks/workspace_task.rs | 60 +++++++++ .../core/{flowy_core.rs => core_context.rs} | 49 ++++---- .../flowy-core/src/core/event_handler.rs | 56 +++++++++ frontend/rust-lib/flowy-core/src/core/mod.rs | 7 +- frontend/rust-lib/flowy-core/src/core/task.rs | 69 ----------- frontend/rust-lib/flowy-core/src/module.rs | 14 +-- .../flowy-core/src/services/app/controller.rs | 4 +- .../flowy-core/src/services/server/mod.rs | 2 +- .../src/services/server/server_api.rs | 8 +- .../src/services/workspace/controller.rs | 115 ++---------------- .../src/services/workspace/event_handler.rs | 18 --- .../flowy-core/src/services/workspace/sql.rs | 10 +- frontend/rust-lib/flowy-sdk/src/lib.rs | 12 +- frontend/rust-lib/flowy-sdk/src/module.rs | 6 +- .../flowy-user/src/services/server/mod.rs | 2 +- .../src/services/server/server_api.rs | 6 +- 62 files changed, 247 insertions(+), 314 deletions(-) rename backend/src/{service => services}/app/app.rs (96%) rename backend/src/{service => services}/app/mod.rs (100%) rename backend/src/{service => services}/app/router.rs (99%) rename backend/src/{service => services}/app/sql_builder.rs (100%) rename backend/src/{service => services}/doc/crud.rs (100%) rename backend/src/{service => services}/doc/edit/edit_actor.rs (97%) rename backend/src/{service => services}/doc/edit/editor.rs (98%) rename backend/src/{service => services}/doc/edit/mod.rs (100%) rename backend/src/{service => services}/doc/manager.rs (97%) rename backend/src/{service => services}/doc/mod.rs (100%) rename backend/src/{service => services}/doc/router.rs (98%) rename backend/src/{service => services}/doc/ws_actor.rs (95%) rename backend/src/{service/log/mod.rs => services/log.rs} (100%) rename backend/src/{service => services}/mod.rs (91%) rename backend/src/{service => services}/trash/mod.rs (100%) rename backend/src/{service => services}/trash/router.rs (99%) rename backend/src/{service => services}/trash/trash.rs (99%) rename backend/src/{service => services}/user/auth.rs (97%) rename backend/src/{service => services}/user/logged_user.rs (100%) rename backend/src/{service => services}/user/mod.rs (100%) rename backend/src/{service => services}/user/router.rs (99%) rename backend/src/{service => services}/user/user_default.rs (93%) rename backend/src/{service => services}/user/utils.rs (100%) rename backend/src/{service => services}/util.rs (100%) rename backend/src/{service => services}/view/mod.rs (100%) rename backend/src/{service => services}/view/router.rs (99%) rename backend/src/{service => services}/view/sql_builder.rs (100%) rename backend/src/{service => services}/view/view.rs (99%) rename backend/src/{service => services}/workspace/mod.rs (100%) rename backend/src/{service => services}/workspace/router.rs (99%) rename backend/src/{service => services}/workspace/sql_builder.rs (100%) rename backend/src/{service => services}/workspace/workspace.rs (98%) rename backend/src/{service/ws => web_socket}/biz_handler.rs (94%) rename backend/src/{service/ws => web_socket}/entities/connect.rs (96%) rename backend/src/{service/ws => web_socket}/entities/message.rs (100%) rename backend/src/{service/ws => web_socket}/entities/mod.rs (100%) rename backend/src/{service/ws => web_socket}/mod.rs (100%) rename backend/src/{service/ws => web_socket}/router.rs (91%) rename backend/src/{service/ws => web_socket}/ws_client.rs (95%) rename backend/src/{service/ws => web_socket}/ws_server.rs (98%) create mode 100644 frontend/rust-lib/flowy-core/src/core/aggregate_tasks/mod.rs create mode 100644 frontend/rust-lib/flowy-core/src/core/aggregate_tasks/workspace_task.rs rename frontend/rust-lib/flowy-core/src/core/{flowy_core.rs => core_context.rs} (94%) create mode 100644 frontend/rust-lib/flowy-core/src/core/event_handler.rs delete mode 100644 frontend/rust-lib/flowy-core/src/core/task.rs diff --git a/backend/src/application.rs b/backend/src/application.rs index 53cbedf468..f05b44767d 100644 --- a/backend/src/application.rs +++ b/backend/src/application.rs @@ -1,9 +1,8 @@ -use std::{net::TcpListener, time::Duration}; - use actix::Actor; use actix_identity::{CookieIdentityPolicy, IdentityService}; use actix_web::{dev::Server, middleware, web, web::Data, App, HttpServer, Scope}; use sqlx::{postgres::PgPoolOptions, PgPool}; +use std::{net::TcpListener, time::Duration}; use tokio::time::interval; use crate::{ @@ -13,16 +12,15 @@ use crate::{ Settings, }, context::AppContext, - service::{ + services::{ app::router as app, doc::router as doc, trash::router as trash, user::router as user, view::router as view, workspace::router as workspace, - ws, - ws::WsServer, }, + web_socket::WsServer, }; pub struct Application { @@ -75,7 +73,7 @@ async fn period_check(_pool: Data) { } } -fn ws_scope() -> Scope { web::scope("/ws").service(ws::router::establish_ws_connection) } +fn ws_scope() -> Scope { web::scope("/ws").service(crate::web_socket::router::establish_ws_connection) } fn user_scope() -> Scope { // https://developer.mozilla.org/en-US/docs/Web/HTTP @@ -124,6 +122,9 @@ fn user_scope() -> Scope { .route(web::delete().to(trash::delete_handler)) .route(web::get().to(trash::read_handler)) ) + .service(web::resource("/sync") + .route(web::post().to(trash::create_handler)) + ) // password .service(web::resource("/password_change") .route(web::post().to(user::change_password)) @@ -131,7 +132,7 @@ fn user_scope() -> Scope { } pub async fn init_app_context(configuration: &Settings) -> AppContext { - let _ = crate::service::log::Builder::new("flowy-server") + let _ = crate::services::log::Builder::new("flowy-server") .env_filter("Trace") .build(); let pg_pool = get_connection_pool(&configuration.database) diff --git a/backend/src/context.rs b/backend/src/context.rs index 7b01cc556b..7f424e59c4 100644 --- a/backend/src/context.rs +++ b/backend/src/context.rs @@ -1,6 +1,6 @@ -use crate::service::{ - doc::manager::DocBiz, - ws::{WsBizHandlers, WsServer}, +use crate::{ + services::doc::manager::DocBiz, + web_socket::{WsBizHandlers, WsServer}, }; use actix::Addr; use actix_web::web::Data; diff --git a/backend/src/entities/token.rs b/backend/src/entities/token.rs index 3327c672ef..ce8a657c50 100644 --- a/backend/src/entities/token.rs +++ b/backend/src/entities/token.rs @@ -74,7 +74,7 @@ impl Token { } } -use crate::service::user::EXPIRED_DURATION_DAYS; +use crate::services::user::EXPIRED_DURATION_DAYS; use actix_web::{dev::Payload, FromRequest, HttpRequest}; use backend_service::configuration::HEADER_TOKEN; use futures::future::{ready, Ready}; diff --git a/backend/src/lib.rs b/backend/src/lib.rs index f49c851ce3..a76cf88986 100644 --- a/backend/src/lib.rs +++ b/backend/src/lib.rs @@ -3,5 +3,6 @@ pub mod config; pub mod context; mod entities; mod middleware; -pub mod service; +pub mod services; mod sqlx_ext; +pub mod web_socket; diff --git a/backend/src/middleware/auth_middleware.rs b/backend/src/middleware/auth_middleware.rs index 1b7a136a25..d0972a0c95 100644 --- a/backend/src/middleware/auth_middleware.rs +++ b/backend/src/middleware/auth_middleware.rs @@ -1,4 +1,4 @@ -use crate::service::user::{LoggedUser, AUTHORIZED_USERS}; +use crate::services::user::{LoggedUser, AUTHORIZED_USERS}; use actix_service::{Service, Transform}; use actix_web::{ dev::{ServiceRequest, ServiceResponse}, diff --git a/backend/src/service/app/app.rs b/backend/src/services/app/app.rs similarity index 96% rename from backend/src/service/app/app.rs rename to backend/src/services/app/app.rs index acc2355e95..39ed88de09 100644 --- a/backend/src/service/app/app.rs +++ b/backend/src/services/app/app.rs @@ -1,10 +1,10 @@ use crate::{ entities::workspace::{AppTable, APP_TABLE}, - service::{app::sql_builder::*, user::LoggedUser, view::read_view_belong_to_id}, + services::{app::sql_builder::*, user::LoggedUser, view::read_view_belong_to_id}, sqlx_ext::{map_sqlx_error, DBTransaction, SqlBuilder}, }; -use crate::service::trash::read_trash_ids; +use crate::services::trash::read_trash_ids; use backend_service::errors::{invalid_params, ServerError}; use chrono::Utc; use flowy_workspace_infra::{ diff --git a/backend/src/service/app/mod.rs b/backend/src/services/app/mod.rs similarity index 100% rename from backend/src/service/app/mod.rs rename to backend/src/services/app/mod.rs diff --git a/backend/src/service/app/router.rs b/backend/src/services/app/router.rs similarity index 99% rename from backend/src/service/app/router.rs rename to backend/src/services/app/router.rs index f95539a5d9..7dd3fa8233 100644 --- a/backend/src/service/app/router.rs +++ b/backend/src/services/app/router.rs @@ -7,7 +7,7 @@ use flowy_workspace_infra::protobuf::{AppIdentifier, CreateAppParams, UpdateAppP use protobuf::Message; use sqlx::PgPool; -use crate::service::{ +use crate::services::{ app::{ app::{create_app, delete_app, read_app, update_app}, sql_builder::check_app_id, diff --git a/backend/src/service/app/sql_builder.rs b/backend/src/services/app/sql_builder.rs similarity index 100% rename from backend/src/service/app/sql_builder.rs rename to backend/src/services/app/sql_builder.rs diff --git a/backend/src/service/doc/crud.rs b/backend/src/services/doc/crud.rs similarity index 100% rename from backend/src/service/doc/crud.rs rename to backend/src/services/doc/crud.rs diff --git a/backend/src/service/doc/edit/edit_actor.rs b/backend/src/services/doc/edit/edit_actor.rs similarity index 97% rename from backend/src/service/doc/edit/edit_actor.rs rename to backend/src/services/doc/edit/edit_actor.rs index c883c0ab70..985bf49d00 100644 --- a/backend/src/service/doc/edit/edit_actor.rs +++ b/backend/src/services/doc/edit/edit_actor.rs @@ -1,6 +1,6 @@ -use crate::service::{ - doc::edit::ServerDocEditor, - ws::{entities::Socket, WsUser}, +use crate::{ + services::doc::edit::ServerDocEditor, + web_socket::{entities::Socket, WsUser}, }; use actix_web::web::Data; use async_stream::stream; diff --git a/backend/src/service/doc/edit/editor.rs b/backend/src/services/doc/edit/editor.rs similarity index 98% rename from backend/src/service/doc/edit/editor.rs rename to backend/src/services/doc/edit/editor.rs index a10c0e87e4..f148a9d692 100644 --- a/backend/src/service/doc/edit/editor.rs +++ b/backend/src/services/doc/edit/editor.rs @@ -1,7 +1,9 @@ -use crate::service::{ - doc::{edit::edit_actor::EditUser, update_doc}, - util::md5, - ws::{entities::Socket, WsMessageAdaptor}, +use crate::{ + services::{ + doc::{edit::edit_actor::EditUser, update_doc}, + util::md5, + }, + web_socket::{entities::Socket, WsMessageAdaptor}, }; use actix_web::web::Data; use backend_service::errors::{internal_error, ServerError}; diff --git a/backend/src/service/doc/edit/mod.rs b/backend/src/services/doc/edit/mod.rs similarity index 100% rename from backend/src/service/doc/edit/mod.rs rename to backend/src/services/doc/edit/mod.rs diff --git a/backend/src/service/doc/manager.rs b/backend/src/services/doc/manager.rs similarity index 97% rename from backend/src/service/doc/manager.rs rename to backend/src/services/doc/manager.rs index 3d66848f01..960edd5e8e 100644 --- a/backend/src/service/doc/manager.rs +++ b/backend/src/services/doc/manager.rs @@ -1,10 +1,10 @@ -use crate::service::{ - doc::{ +use crate::{ + services::doc::{ edit::edit_actor::{EditDocActor, EditMsg}, read_doc, ws_actor::{DocWsActor, DocWsMsg}, }, - ws::{entities::Socket, WsBizHandler, WsClientData, WsUser}, + web_socket::{entities::Socket, WsBizHandler, WsClientData, WsUser}, }; use actix_web::web::Data; use backend_service::errors::{internal_error, Result as DocResult, ServerError}; diff --git a/backend/src/service/doc/mod.rs b/backend/src/services/doc/mod.rs similarity index 100% rename from backend/src/service/doc/mod.rs rename to backend/src/services/doc/mod.rs diff --git a/backend/src/service/doc/router.rs b/backend/src/services/doc/router.rs similarity index 98% rename from backend/src/service/doc/router.rs rename to backend/src/services/doc/router.rs index 1bad2b3d7f..8446c4336b 100644 --- a/backend/src/service/doc/router.rs +++ b/backend/src/services/doc/router.rs @@ -1,4 +1,4 @@ -use crate::service::{ +use crate::services::{ doc::{create_doc, read_doc, update_doc}, util::parse_from_payload, }; diff --git a/backend/src/service/doc/ws_actor.rs b/backend/src/services/doc/ws_actor.rs similarity index 95% rename from backend/src/service/doc/ws_actor.rs rename to backend/src/services/doc/ws_actor.rs index 7f08651550..0ba431fff6 100644 --- a/backend/src/service/doc/ws_actor.rs +++ b/backend/src/services/doc/ws_actor.rs @@ -1,7 +1,9 @@ -use crate::service::{ - doc::manager::{DocManager, DocOpenHandle}, - util::{md5, parse_from_bytes}, - ws::{entities::Socket, WsClientData, WsUser}, +use crate::{ + services::{ + doc::manager::{DocManager, DocOpenHandle}, + util::{md5, parse_from_bytes}, + }, + web_socket::{entities::Socket, WsClientData, WsUser}, }; use actix_rt::task::spawn_blocking; use actix_web::web::Data; diff --git a/backend/src/service/log/mod.rs b/backend/src/services/log.rs similarity index 100% rename from backend/src/service/log/mod.rs rename to backend/src/services/log.rs diff --git a/backend/src/service/mod.rs b/backend/src/services/mod.rs similarity index 91% rename from backend/src/service/mod.rs rename to backend/src/services/mod.rs index 89e640c441..5e53a5a81e 100644 --- a/backend/src/service/mod.rs +++ b/backend/src/services/mod.rs @@ -6,4 +6,3 @@ pub mod user; pub(crate) mod util; pub mod view; pub mod workspace; -pub mod ws; diff --git a/backend/src/service/trash/mod.rs b/backend/src/services/trash/mod.rs similarity index 100% rename from backend/src/service/trash/mod.rs rename to backend/src/services/trash/mod.rs diff --git a/backend/src/service/trash/router.rs b/backend/src/services/trash/router.rs similarity index 99% rename from backend/src/service/trash/router.rs rename to backend/src/services/trash/router.rs index cc267117a0..3ff7298136 100644 --- a/backend/src/service/trash/router.rs +++ b/backend/src/services/trash/router.rs @@ -1,4 +1,4 @@ -use crate::service::{ +use crate::services::{ trash::{create_trash, delete_all_trash, delete_trash, read_trash}, user::LoggedUser, util::parse_from_payload, diff --git a/backend/src/service/trash/trash.rs b/backend/src/services/trash/trash.rs similarity index 99% rename from backend/src/service/trash/trash.rs rename to backend/src/services/trash/trash.rs index 200a776feb..6ce9892ee2 100644 --- a/backend/src/service/trash/trash.rs +++ b/backend/src/services/trash/trash.rs @@ -1,6 +1,6 @@ use crate::{ entities::workspace::{TrashTable, TRASH_TABLE}, - service::{ + services::{ app::app::{delete_app, read_app_table}, user::LoggedUser, view::{delete_view, read_view_table}, diff --git a/backend/src/service/user/auth.rs b/backend/src/services/user/auth.rs similarity index 97% rename from backend/src/service/user/auth.rs rename to backend/src/services/user/auth.rs index b2b9437ac6..19d0759969 100644 --- a/backend/src/service/user/auth.rs +++ b/backend/src/services/user/auth.rs @@ -1,6 +1,6 @@ use crate::{ entities::{token::Token, user::UserTable}, - service::user::{hash_password, verify_password, LoggedUser}, + services::user::{hash_password, verify_password, LoggedUser}, sqlx_ext::{map_sqlx_error, DBTransaction, SqlBuilder}, }; use anyhow::Context; @@ -16,7 +16,7 @@ use flowy_user_infra::{ use sqlx::{PgPool, Postgres}; use super::AUTHORIZED_USERS; -use crate::service::user::user_default::create_default_workspace; +use crate::services::user::user_default::create_default_workspace; pub async fn sign_in(pool: &PgPool, params: SignInParams) -> Result { let email = UserEmail::parse(params.email).map_err(|e| ServerError::params_invalid().context(e))?; @@ -68,7 +68,6 @@ pub async fn register_user(pool: &PgPool, params: SignUpParams) -> Result, user_id: &str, diff --git a/backend/src/service/user/utils.rs b/backend/src/services/user/utils.rs similarity index 100% rename from backend/src/service/user/utils.rs rename to backend/src/services/user/utils.rs diff --git a/backend/src/service/util.rs b/backend/src/services/util.rs similarity index 100% rename from backend/src/service/util.rs rename to backend/src/services/util.rs diff --git a/backend/src/service/view/mod.rs b/backend/src/services/view/mod.rs similarity index 100% rename from backend/src/service/view/mod.rs rename to backend/src/services/view/mod.rs diff --git a/backend/src/service/view/router.rs b/backend/src/services/view/router.rs similarity index 99% rename from backend/src/service/view/router.rs rename to backend/src/services/view/router.rs index 30f3066f92..ee67637973 100644 --- a/backend/src/service/view/router.rs +++ b/backend/src/services/view/router.rs @@ -1,4 +1,4 @@ -use crate::service::{ +use crate::services::{ doc::manager::DocBiz, user::LoggedUser, util::parse_from_payload, diff --git a/backend/src/service/view/sql_builder.rs b/backend/src/services/view/sql_builder.rs similarity index 100% rename from backend/src/service/view/sql_builder.rs rename to backend/src/services/view/sql_builder.rs diff --git a/backend/src/service/view/view.rs b/backend/src/services/view/view.rs similarity index 99% rename from backend/src/service/view/view.rs rename to backend/src/services/view/view.rs index 0769a16f13..543f51964f 100644 --- a/backend/src/service/view/view.rs +++ b/backend/src/services/view/view.rs @@ -1,6 +1,6 @@ use crate::{ entities::workspace::{ViewTable, VIEW_TABLE}, - service::{ + services::{ doc::{create_doc, delete_doc}, trash::read_trash_ids, user::LoggedUser, diff --git a/backend/src/service/workspace/mod.rs b/backend/src/services/workspace/mod.rs similarity index 100% rename from backend/src/service/workspace/mod.rs rename to backend/src/services/workspace/mod.rs diff --git a/backend/src/service/workspace/router.rs b/backend/src/services/workspace/router.rs similarity index 99% rename from backend/src/service/workspace/router.rs rename to backend/src/services/workspace/router.rs index 47313059aa..b760c2912c 100644 --- a/backend/src/service/workspace/router.rs +++ b/backend/src/services/workspace/router.rs @@ -1,4 +1,4 @@ -use crate::service::{ +use crate::services::{ user::LoggedUser, util::parse_from_payload, workspace::{ diff --git a/backend/src/service/workspace/sql_builder.rs b/backend/src/services/workspace/sql_builder.rs similarity index 100% rename from backend/src/service/workspace/sql_builder.rs rename to backend/src/services/workspace/sql_builder.rs diff --git a/backend/src/service/workspace/workspace.rs b/backend/src/services/workspace/workspace.rs similarity index 98% rename from backend/src/service/workspace/workspace.rs rename to backend/src/services/workspace/workspace.rs index 7e1f73414e..fc7800a9ef 100644 --- a/backend/src/service/workspace/workspace.rs +++ b/backend/src/services/workspace/workspace.rs @@ -1,7 +1,7 @@ use super::sql_builder::NewWorkspaceBuilder; use crate::{ entities::workspace::{AppTable, WorkspaceTable, WORKSPACE_TABLE}, - service::{app::app::read_app, user::LoggedUser, workspace::sql_builder::*}, + services::{app::app::read_app, user::LoggedUser, workspace::sql_builder::*}, sqlx_ext::*, }; use anyhow::Context; diff --git a/backend/src/service/ws/biz_handler.rs b/backend/src/web_socket/biz_handler.rs similarity index 94% rename from backend/src/service/ws/biz_handler.rs rename to backend/src/web_socket/biz_handler.rs index efb86a8df1..2b98b60db3 100644 --- a/backend/src/service/ws/biz_handler.rs +++ b/backend/src/web_socket/biz_handler.rs @@ -1,5 +1,4 @@ -use crate::service::ws::WsClientData; - +use crate::web_socket::WsClientData; use lib_ws::WsModule; use std::{collections::HashMap, sync::Arc}; diff --git a/backend/src/service/ws/entities/connect.rs b/backend/src/web_socket/entities/connect.rs similarity index 96% rename from backend/src/service/ws/entities/connect.rs rename to backend/src/web_socket/entities/connect.rs index 45e0584b2a..c44ddc7898 100644 --- a/backend/src/service/ws/entities/connect.rs +++ b/backend/src/web_socket/entities/connect.rs @@ -1,4 +1,4 @@ -use crate::service::ws::WsMessageAdaptor; +use crate::web_socket::WsMessageAdaptor; use actix::{Message, Recipient}; use backend_service::errors::ServerError; use serde::{Deserialize, Serialize}; diff --git a/backend/src/service/ws/entities/message.rs b/backend/src/web_socket/entities/message.rs similarity index 100% rename from backend/src/service/ws/entities/message.rs rename to backend/src/web_socket/entities/message.rs diff --git a/backend/src/service/ws/entities/mod.rs b/backend/src/web_socket/entities/mod.rs similarity index 100% rename from backend/src/service/ws/entities/mod.rs rename to backend/src/web_socket/entities/mod.rs diff --git a/backend/src/service/ws/mod.rs b/backend/src/web_socket/mod.rs similarity index 100% rename from backend/src/service/ws/mod.rs rename to backend/src/web_socket/mod.rs diff --git a/backend/src/service/ws/router.rs b/backend/src/web_socket/router.rs similarity index 91% rename from backend/src/service/ws/router.rs rename to backend/src/web_socket/router.rs index faf68e3323..d6c5c2c53b 100644 --- a/backend/src/service/ws/router.rs +++ b/backend/src/web_socket/router.rs @@ -1,6 +1,6 @@ -use crate::service::{ - user::LoggedUser, - ws::{WsBizHandlers, WsClient, WsServer, WsUser}, +use crate::{ + services::user::LoggedUser, + web_socket::{WsBizHandlers, WsClient, WsServer, WsUser}, }; use actix::Addr; use actix_web::{ diff --git a/backend/src/service/ws/ws_client.rs b/backend/src/web_socket/ws_client.rs similarity index 95% rename from backend/src/service/ws/ws_client.rs rename to backend/src/web_socket/ws_client.rs index d793a7bfd5..d356f1c405 100644 --- a/backend/src/service/ws/ws_client.rs +++ b/backend/src/web_socket/ws_client.rs @@ -1,13 +1,11 @@ use crate::{ config::{HEARTBEAT_INTERVAL, PING_TIMEOUT}, - service::{ - user::LoggedUser, - ws::{ - entities::{Connect, Disconnect, Socket}, - WsBizHandlers, - WsMessageAdaptor, - WsServer, - }, + services::user::LoggedUser, + web_socket::{ + entities::{Connect, Disconnect, Socket}, + WsBizHandlers, + WsMessageAdaptor, + WsServer, }, }; use actix::*; diff --git a/backend/src/service/ws/ws_server.rs b/backend/src/web_socket/ws_server.rs similarity index 98% rename from backend/src/service/ws/ws_server.rs rename to backend/src/web_socket/ws_server.rs index 3e6e622ec3..8525d486e3 100644 --- a/backend/src/service/ws/ws_server.rs +++ b/backend/src/web_socket/ws_server.rs @@ -1,4 +1,4 @@ -use crate::service::ws::{ +use crate::web_socket::{ entities::{Connect, Disconnect, Session, SessionId}, WsMessageAdaptor, }; diff --git a/frontend/rust-lib/flowy-core/src/core/aggregate_tasks/mod.rs b/frontend/rust-lib/flowy-core/src/core/aggregate_tasks/mod.rs new file mode 100644 index 0000000000..e14803561f --- /dev/null +++ b/frontend/rust-lib/flowy-core/src/core/aggregate_tasks/mod.rs @@ -0,0 +1,3 @@ +mod workspace_task; + +pub use workspace_task::*; diff --git a/frontend/rust-lib/flowy-core/src/core/aggregate_tasks/workspace_task.rs b/frontend/rust-lib/flowy-core/src/core/aggregate_tasks/workspace_task.rs new file mode 100644 index 0000000000..07f24c1a88 --- /dev/null +++ b/frontend/rust-lib/flowy-core/src/core/aggregate_tasks/workspace_task.rs @@ -0,0 +1,60 @@ +use crate::{ + core::CoreContext, + errors::WorkspaceError, + notify::{send_dart_notification, WorkspaceNotification}, + services::workspace::sql::{WorkspaceTable, WorkspaceTableSql}, +}; +use flowy_workspace_infra::entities::workspace::WorkspaceIdentifier; +use lib_dispatch::prelude::Unit; +use std::sync::Arc; + +#[tracing::instrument(level = "debug", skip(core), err)] +pub fn read_workspaces_on_server( + core: Unit>, + user_id: String, + params: WorkspaceIdentifier, +) -> Result<(), WorkspaceError> { + let (token, server) = (core.user.token()?, core.server.clone()); + let app_ctrl = core.app_controller.clone(); + let view_ctrl = core.view_controller.clone(); + let conn = core.database.db_connection()?; + + tokio::spawn(async move { + // Opti: handle the error and retry? + let workspaces = server.read_workspace(&token, params).await?; + let _ = (&*conn).immediate_transaction::<_, WorkspaceError, _>(|| { + tracing::debug!("Save {} workspace", workspaces.len()); + for workspace in &workspaces.items { + let m_workspace = workspace.clone(); + let apps = m_workspace.apps.clone().into_inner(); + let workspace_table = WorkspaceTable::new(m_workspace, &user_id); + + let _ = WorkspaceTableSql::create_workspace(workspace_table, &*conn)?; + tracing::debug!("Save {} apps", apps.len()); + for app in apps { + let views = app.belongings.clone().into_inner(); + match app_ctrl.save_app(app, &*conn) { + Ok(_) => {}, + Err(e) => log::error!("create app failed: {:?}", e), + } + + tracing::debug!("Save {} views", views.len()); + for view in views { + match view_ctrl.save_view(view, &*conn) { + Ok(_) => {}, + Err(e) => log::error!("create view failed: {:?}", e), + } + } + } + } + Ok(()) + })?; + + send_dart_notification(&token, WorkspaceNotification::WorkspaceListUpdated) + .payload(workspaces) + .send(); + Result::<(), WorkspaceError>::Ok(()) + }); + + Ok(()) +} diff --git a/frontend/rust-lib/flowy-core/src/core/flowy_core.rs b/frontend/rust-lib/flowy-core/src/core/core_context.rs similarity index 94% rename from frontend/rust-lib/flowy-core/src/core/flowy_core.rs rename to frontend/rust-lib/flowy-core/src/core/core_context.rs index 03d1f7354f..c00dbd19f1 100644 --- a/frontend/rust-lib/flowy-core/src/core/flowy_core.rs +++ b/frontend/rust-lib/flowy-core/src/core/core_context.rs @@ -1,7 +1,7 @@ use crate::{ entities::workspace::RepeatedWorkspace, errors::{WorkspaceError, WorkspaceResult}, - module::WorkspaceUser, + module::{WorkspaceDatabase, WorkspaceUser}, notify::{send_dart_notification, WorkspaceNotification}, services::{server::Server, AppController, TrashController, ViewController, WorkspaceController}, }; @@ -12,24 +12,25 @@ use lazy_static::lazy_static; use lib_infra::entities::network_state::NetworkType; use parking_lot::RwLock; use std::{collections::HashMap, sync::Arc}; - lazy_static! { static ref INIT_WORKSPACE: RwLock> = RwLock::new(HashMap::new()); } -pub struct FlowyCore { +pub struct CoreContext { pub user: Arc, - server: Server, + pub(crate) server: Server, + pub(crate) database: Arc, pub workspace_controller: Arc, pub(crate) app_controller: Arc, pub(crate) view_controller: Arc, pub(crate) trash_controller: Arc, } -impl FlowyCore { +impl CoreContext { pub(crate) fn new( user: Arc, server: Server, + database: Arc, workspace_controller: Arc, app_controller: Arc, view_controller: Arc, @@ -42,6 +43,7 @@ impl FlowyCore { Self { user, server, + database, workspace_controller, app_controller, view_controller, @@ -49,24 +51,6 @@ impl FlowyCore { } } - async fn init(&self, token: &str) -> Result<(), WorkspaceError> { - if let Some(is_init) = INIT_WORKSPACE.read().get(token) { - if *is_init { - return Ok(()); - } - } - log::debug!("Start initializing flowy core"); - INIT_WORKSPACE.write().insert(token.to_owned(), true); - let _ = self.server.init(); - let _ = self.workspace_controller.init()?; - let _ = self.app_controller.init()?; - let _ = self.view_controller.init()?; - let _ = self.trash_controller.init()?; - log::debug!("Finish initializing core"); - - Ok(()) - } - pub fn network_state_changed(&self, new_type: NetworkType) { match new_type { NetworkType::UnknownNetworkType => {}, @@ -77,8 +61,6 @@ impl FlowyCore { } pub async fn user_did_sign_in(&self, token: &str) -> WorkspaceResult<()> { - // TODO: (nathan) do something here - log::debug!("workspace initialize after sign in"); let _ = self.init(token).await?; Ok(()) @@ -131,4 +113,21 @@ impl FlowyCore { let _ = self.init(&token).await?; Ok(()) } + + async fn init(&self, token: &str) -> Result<(), WorkspaceError> { + if let Some(is_init) = INIT_WORKSPACE.read().get(token) { + if *is_init { + return Ok(()); + } + } + log::debug!("Start initializing flowy core"); + INIT_WORKSPACE.write().insert(token.to_owned(), true); + let _ = self.workspace_controller.init()?; + let _ = self.app_controller.init()?; + let _ = self.view_controller.init()?; + let _ = self.trash_controller.init()?; + log::debug!("Finish initializing core"); + + Ok(()) + } } diff --git a/frontend/rust-lib/flowy-core/src/core/event_handler.rs b/frontend/rust-lib/flowy-core/src/core/event_handler.rs new file mode 100644 index 0000000000..e451ec35f3 --- /dev/null +++ b/frontend/rust-lib/flowy-core/src/core/event_handler.rs @@ -0,0 +1,56 @@ +use crate::{ + core::{aggregate_tasks::read_workspaces_on_server, CoreContext}, + errors::WorkspaceError, + services::{get_current_workspace, read_local_workspace_apps}, +}; +use flowy_workspace_infra::entities::{ + view::View, + workspace::{CurrentWorkspaceSetting, QueryWorkspaceRequest, RepeatedWorkspace, WorkspaceIdentifier}, +}; +use lib_dispatch::prelude::{data_result, Data, DataResult, Unit}; +use std::{convert::TryInto, sync::Arc}; + +#[tracing::instrument(skip(data, core), err)] +pub(crate) async fn read_workspaces_handler( + data: Data, + core: Unit>, +) -> DataResult { + 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 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(); + workspace.apps.items = apps; + } + Ok(workspaces) + })?; + + let _ = read_workspaces_on_server(core, user_id, params); + + data_result(workspaces) +} + +#[tracing::instrument(skip(core), err)] +pub async fn read_cur_workspace_handler( + core: Unit>, +) -> DataResult { + let workspace_id = get_current_workspace()?; + let user_id = core.user.user_id()?; + let params = WorkspaceIdentifier { + workspace_id: Some(workspace_id.clone()), + }; + let conn = &*core.database.db_connection()?; + let workspace = core + .workspace_controller + .read_local_workspace(workspace_id, &user_id, conn)?; + + let latest_view: Option = core.view_controller.latest_visit_view().unwrap_or(None); + let setting = CurrentWorkspaceSetting { workspace, latest_view }; + let _ = read_workspaces_on_server(core, user_id, params); + data_result(setting) +} diff --git a/frontend/rust-lib/flowy-core/src/core/mod.rs b/frontend/rust-lib/flowy-core/src/core/mod.rs index a21ead744c..626ce77015 100644 --- a/frontend/rust-lib/flowy-core/src/core/mod.rs +++ b/frontend/rust-lib/flowy-core/src/core/mod.rs @@ -1,4 +1,5 @@ -mod flowy_core; -mod task; +mod aggregate_tasks; +mod core_context; -pub use flowy_core::*; +pub mod event_handler; +pub use core_context::*; diff --git a/frontend/rust-lib/flowy-core/src/core/task.rs b/frontend/rust-lib/flowy-core/src/core/task.rs deleted file mode 100644 index 01054ee350..0000000000 --- a/frontend/rust-lib/flowy-core/src/core/task.rs +++ /dev/null @@ -1,69 +0,0 @@ -use crate::{errors::WorkspaceError, services::WorkspaceController}; -use flowy_workspace_infra::entities::workspace::{QueryWorkspaceRequest, RepeatedWorkspace, WorkspaceIdentifier}; -use lib_dispatch::prelude::{data_result, Data, DataResult, Unit}; -use std::{convert::TryInto, sync::Arc}; - -#[tracing::instrument(skip(data, controller), err)] -pub(crate) async fn read_workspaces_handler( - data: Data, - controller: Unit>, -) -> DataResult { - let params: WorkspaceIdentifier = data.into_inner().try_into()?; - let user_id = controller.user.user_id()?; - let workspaces = controller.read_local_workspaces( - params.workspace_id.clone(), - &user_id, - &*controller.database.db_connection()?, - )?; - let _ = controller.read_workspaces_on_server(user_id, params); - - data_result(workspaces) -} - -// #[tracing::instrument(level = "debug", skip(self), err)] -// fn read_workspaces_on_server(&self, user_id: String, params: -// WorkspaceIdentifier) -> Result<(), WorkspaceError> { let (token, server) -// = self.token_with_server()?; let workspace_sql = -// self.workspace_sql.clone(); let app_ctrl = self.app_controller.clone(); -// let view_ctrl = self.view_controller.clone(); -// let conn = self.database.db_connection()?; -// tokio::spawn(async move { -// // Opti: handle the error and retry? -// let workspaces = server.read_workspace(&token, params).await?; -// let _ = (&*conn).immediate_transaction::<_, WorkspaceError, _>(|| { -// tracing::debug!("Save {} workspace", workspaces.len()); -// for workspace in &workspaces.items { -// let m_workspace = workspace.clone(); -// let apps = m_workspace.apps.clone().into_inner(); -// let workspace_table = WorkspaceTable::new(m_workspace, -// &user_id); -// -// let _ = workspace_sql.create_workspace(workspace_table, -// &*conn)?; tracing::debug!("Save {} apps", apps.len()); -// for app in apps { -// let views = app.belongings.clone().into_inner(); -// match app_ctrl.save_app(app, &*conn) { -// Ok(_) => {}, -// Err(e) => log::error!("create app failed: {:?}", e), -// } -// -// tracing::debug!("Save {} views", views.len()); -// for view in views { -// match view_ctrl.save_view(view, &*conn) { -// Ok(_) => {}, -// Err(e) => log::error!("create view failed: {:?}", -// e), } -// } -// } -// } -// Ok(()) -// })?; -// -// send_dart_notification(&token, -// WorkspaceNotification::WorkspaceListUpdated) .payload(workspaces) -// .send(); -// Result::<(), WorkspaceError>::Ok(()) -// }); -// -// Ok(()) -// } diff --git a/frontend/rust-lib/flowy-core/src/module.rs b/frontend/rust-lib/flowy-core/src/module.rs index d404d31a25..6ea6b64f8d 100644 --- a/frontend/rust-lib/flowy-core/src/module.rs +++ b/frontend/rust-lib/flowy-core/src/module.rs @@ -7,7 +7,7 @@ use lib_dispatch::prelude::*; use lib_sqlite::ConnectionPool; use crate::{ - core::FlowyCore, + core::{event_handler::*, CoreContext}, errors::WorkspaceError, event::WorkspaceEvent, services::{ @@ -45,7 +45,7 @@ pub fn init_core( database: Arc, flowy_document: Arc, server_config: &ClientServerConfiguration, -) -> Arc { +) -> Arc { let server = construct_workspace_server(server_config); let trash_controller = Arc::new(TrashController::new(database.clone(), server.clone(), user.clone())); @@ -68,15 +68,14 @@ pub fn init_core( let workspace_controller = Arc::new(WorkspaceController::new( user.clone(), database.clone(), - app_controller.clone(), - view_controller.clone(), trash_controller.clone(), server.clone(), )); - Arc::new(FlowyCore::new( + Arc::new(CoreContext::new( user, server, + database, workspace_controller, app_controller, view_controller, @@ -84,13 +83,14 @@ pub fn init_core( )) } -pub fn create(core: Arc) -> Module { +pub fn create(core: Arc) -> Module { let mut module = Module::new() .name("Flowy-Workspace") .data(core.workspace_controller.clone()) .data(core.app_controller.clone()) .data(core.view_controller.clone()) - .data(core.trash_controller.clone()); + .data(core.trash_controller.clone()) + .data(core.clone()); module = module .event(WorkspaceEvent::CreateWorkspace, create_workspace_handler) diff --git a/frontend/rust-lib/flowy-core/src/services/app/controller.rs b/frontend/rust-lib/flowy-core/src/services/app/controller.rs index 107b87a54c..e35b2f9f7b 100644 --- a/frontend/rust-lib/flowy-core/src/services/app/controller.rs +++ b/frontend/rust-lib/flowy-core/src/services/app/controller.rs @@ -241,11 +241,11 @@ fn notify_apps_changed( pub fn read_local_workspace_apps( workspace_id: &str, - trash_can: Arc, + trash_controller: Arc, conn: &SqliteConnection, ) -> Result { let mut app_tables = AppTableSql::read_workspace_apps(workspace_id, false, conn)?; - let trash_ids = trash_can.trash_ids(conn)?; + let trash_ids = trash_controller.trash_ids(conn)?; app_tables.retain(|app_table| !trash_ids.contains(&app_table.id)); let apps = app_tables.into_iter().map(|table| table.into()).collect::>(); diff --git a/frontend/rust-lib/flowy-core/src/services/server/mod.rs b/frontend/rust-lib/flowy-core/src/services/server/mod.rs index 408ed260ea..08e231b80d 100644 --- a/frontend/rust-lib/flowy-core/src/services/server/mod.rs +++ b/frontend/rust-lib/flowy-core/src/services/server/mod.rs @@ -66,7 +66,7 @@ pub(crate) fn construct_workspace_server( config: &ClientServerConfiguration, ) -> Arc { if cfg!(feature = "http_server") { - Arc::new(WorkspaceServer::new(config.clone())) + Arc::new(WorkspaceHttpServer::new(config.clone())) } else { Arc::new(WorkspaceServerMock {}) } diff --git a/frontend/rust-lib/flowy-core/src/services/server/server_api.rs b/frontend/rust-lib/flowy-core/src/services/server/server_api.rs index 4386d64f90..eab8668db6 100644 --- a/frontend/rust-lib/flowy-core/src/services/server/server_api.rs +++ b/frontend/rust-lib/flowy-core/src/services/server/server_api.rs @@ -13,15 +13,15 @@ use backend_service::{configuration::ClientServerConfiguration, middleware::*, w use flowy_workspace_infra::errors::ErrorCode; use lib_infra::future::ResultFuture; -pub struct WorkspaceServer { +pub struct WorkspaceHttpServer { config: ClientServerConfiguration, } -impl WorkspaceServer { - pub fn new(config: ClientServerConfiguration) -> WorkspaceServer { Self { config } } +impl WorkspaceHttpServer { + pub fn new(config: ClientServerConfiguration) -> WorkspaceHttpServer { Self { config } } } -impl WorkspaceServerAPI for WorkspaceServer { +impl WorkspaceServerAPI for WorkspaceHttpServer { fn init(&self) { let mut rx = BACKEND_API_MIDDLEWARE.invalid_token_subscribe(); tokio::spawn(async move { diff --git a/frontend/rust-lib/flowy-core/src/services/workspace/controller.rs b/frontend/rust-lib/flowy-core/src/services/workspace/controller.rs index ec42ddfadd..789fb6a0a0 100644 --- a/frontend/rust-lib/flowy-core/src/services/workspace/controller.rs +++ b/frontend/rust-lib/flowy-core/src/services/workspace/controller.rs @@ -6,22 +6,17 @@ use crate::{ read_local_workspace_apps, server::Server, workspace::sql::{WorkspaceTable, WorkspaceTableChangeset, WorkspaceTableSql}, - AppController, TrashController, - ViewController, }, }; use flowy_database::SqliteConnection; -use flowy_workspace_infra::entities::{app::RepeatedApp, view::View, workspace::*}; +use flowy_workspace_infra::entities::{app::RepeatedApp, workspace::*}; use lib_infra::kv::KV; use std::sync::Arc; pub struct WorkspaceController { pub user: Arc, - pub(crate) workspace_sql: Arc, - pub(crate) view_controller: Arc, pub(crate) database: Arc, - pub(crate) app_controller: Arc, pub(crate) trash_controller: Arc, server: Server, } @@ -30,18 +25,12 @@ impl WorkspaceController { pub(crate) fn new( user: Arc, database: Arc, - app_controller: Arc, - view_controller: Arc, trash_can: Arc, server: Server, ) -> Self { - let workspace_sql = Arc::new(WorkspaceTableSql {}); Self { user, - workspace_sql, - view_controller, database, - app_controller, trash_controller: trash_can, server, } @@ -74,7 +63,7 @@ impl WorkspaceController { // other journaling modes, EXCLUSIVE prevents other database connections from // reading the database while the transaction is underway. conn.immediate_transaction::<_, WorkspaceError, _>(|| { - self.workspace_sql.create_workspace(workspace_table, conn)?; + WorkspaceTableSql::create_workspace(workspace_table, conn)?; let repeated_workspace = self.read_local_workspaces(None, &user_id, conn)?; send_dart_notification(&token, WorkspaceNotification::UserCreateWorkspace) .payload(repeated_workspace) @@ -94,7 +83,7 @@ impl WorkspaceController { let workspace_id = changeset.id.clone(); let conn = &*self.database.db_connection()?; conn.immediate_transaction::<_, WorkspaceError, _>(|| { - let _ = self.workspace_sql.update_workspace(changeset, conn)?; + 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)?; send_dart_notification(&workspace_id, WorkspaceNotification::WorkspaceUpdated) @@ -115,7 +104,7 @@ impl WorkspaceController { let token = self.user.token()?; let conn = &*self.database.db_connection()?; conn.immediate_transaction::<_, WorkspaceError, _>(|| { - let _ = self.workspace_sql.delete_workspace(workspace_id, conn)?; + let _ = WorkspaceTableSql::delete_workspace(workspace_id, conn)?; let repeated_workspace = self.read_local_workspaces(None, &user_id, conn)?; send_dart_notification(&token, WorkspaceNotification::UserDeleteWorkspace) .payload(repeated_workspace) @@ -140,31 +129,6 @@ impl WorkspaceController { } } - pub(crate) async fn read_workspaces( - &self, - params: WorkspaceIdentifier, - ) -> Result { - let user_id = self.user.user_id()?; - let workspaces = - self.read_local_workspaces(params.workspace_id.clone(), &user_id, &*self.database.db_connection()?)?; - let _ = self.read_workspaces_on_server(user_id, params); - Ok(workspaces) - } - - pub(crate) async fn read_current_workspace(&self) -> Result { - let workspace_id = get_current_workspace()?; - let user_id = self.user.user_id()?; - let params = WorkspaceIdentifier { - workspace_id: Some(workspace_id.clone()), - }; - let workspace = self.read_local_workspace(workspace_id, &user_id, &*self.database.db_connection()?)?; - - let latest_view: Option = self.view_controller.latest_visit_view().unwrap_or(None); - let setting = CurrentWorkspaceSetting { workspace, latest_view }; - let _ = self.read_workspaces_on_server(user_id, params)?; - Ok(setting) - } - pub(crate) async fn read_current_workspace_apps(&self) -> Result { let workspace_id = get_current_workspace()?; let conn = self.database.db_connection()?; @@ -181,19 +145,17 @@ impl WorkspaceController { conn: &SqliteConnection, ) -> Result { let workspace_id = workspace_id.to_owned(); - let workspace_tables = self.workspace_sql.read_workspaces(workspace_id, user_id, conn)?; + let workspace_tables = WorkspaceTableSql::read_workspaces(workspace_id, user_id, conn)?; let mut workspaces = vec![]; for table in workspace_tables { - let apps = self.read_local_apps(&table.id, conn)?.into_inner(); - let mut workspace: Workspace = table.into(); - workspace.apps.items = apps; + let workspace: Workspace = table.into(); workspaces.push(workspace); } Ok(RepeatedWorkspace { items: workspaces }) } - fn read_local_workspace( + pub(crate) fn read_local_workspace( &self, workspace_id: String, user_id: &str, @@ -218,12 +180,6 @@ impl WorkspaceController { } impl WorkspaceController { - fn token_with_server(&self) -> Result<(String, Server), WorkspaceError> { - let token = self.user.token()?; - let server = self.server.clone(); - Ok((token, server)) - } - #[tracing::instrument(level = "debug", skip(self), err)] async fn create_workspace_on_server(&self, params: CreateWorkspaceParams) -> Result { let token = self.user.token()?; @@ -233,7 +189,7 @@ impl WorkspaceController { #[tracing::instrument(level = "debug", skip(self), err)] fn update_workspace_on_server(&self, params: UpdateWorkspaceParams) -> Result<(), WorkspaceError> { - let (token, server) = self.token_with_server()?; + let (token, server) = (self.user.token()?, self.server.clone()); tokio::spawn(async move { match server.update_workspace(&token, params).await { Ok(_) => {}, @@ -251,7 +207,7 @@ impl WorkspaceController { let params = WorkspaceIdentifier { workspace_id: Some(workspace_id.to_string()), }; - let (token, server) = self.token_with_server()?; + let (token, server) = (self.user.token()?, self.server.clone()); tokio::spawn(async move { match server.delete_workspace(&token, params).await { Ok(_) => {}, @@ -263,64 +219,13 @@ impl WorkspaceController { }); Ok(()) } - - #[tracing::instrument(level = "debug", skip(self), err)] - pub(crate) fn read_workspaces_on_server( - &self, - user_id: String, - params: WorkspaceIdentifier, - ) -> Result<(), WorkspaceError> { - let (token, server) = self.token_with_server()?; - let workspace_sql = self.workspace_sql.clone(); - let app_ctrl = self.app_controller.clone(); - let view_ctrl = self.view_controller.clone(); - let conn = self.database.db_connection()?; - tokio::spawn(async move { - // Opti: handle the error and retry? - let workspaces = server.read_workspace(&token, params).await?; - let _ = (&*conn).immediate_transaction::<_, WorkspaceError, _>(|| { - tracing::debug!("Save {} workspace", workspaces.len()); - for workspace in &workspaces.items { - let m_workspace = workspace.clone(); - let apps = m_workspace.apps.clone().into_inner(); - let workspace_table = WorkspaceTable::new(m_workspace, &user_id); - - let _ = workspace_sql.create_workspace(workspace_table, &*conn)?; - tracing::debug!("Save {} apps", apps.len()); - for app in apps { - let views = app.belongings.clone().into_inner(); - match app_ctrl.save_app(app, &*conn) { - Ok(_) => {}, - Err(e) => log::error!("create app failed: {:?}", e), - } - - tracing::debug!("Save {} views", views.len()); - for view in views { - match view_ctrl.save_view(view, &*conn) { - Ok(_) => {}, - Err(e) => log::error!("create view failed: {:?}", e), - } - } - } - } - Ok(()) - })?; - - send_dart_notification(&token, WorkspaceNotification::WorkspaceListUpdated) - .payload(workspaces) - .send(); - Result::<(), WorkspaceError>::Ok(()) - }); - - Ok(()) - } } 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()); } -fn get_current_workspace() -> Result { +pub fn get_current_workspace() -> Result { match KV::get_str(CURRENT_WORKSPACE_ID) { None => Err(WorkspaceError::record_not_found() .context("Current workspace not found or should call open workspace first")), diff --git a/frontend/rust-lib/flowy-core/src/services/workspace/event_handler.rs b/frontend/rust-lib/flowy-core/src/services/workspace/event_handler.rs index 4060a2ec16..e52ed5772c 100644 --- a/frontend/rust-lib/flowy-core/src/services/workspace/event_handler.rs +++ b/frontend/rust-lib/flowy-core/src/services/workspace/event_handler.rs @@ -15,14 +15,6 @@ pub(crate) async fn create_workspace_handler( data_result(detail) } -#[tracing::instrument(skip(controller), err)] -pub(crate) async fn read_cur_workspace_handler( - controller: Unit>, -) -> DataResult { - let workspace = controller.read_current_workspace().await?; - data_result(workspace) -} - #[tracing::instrument(skip(controller), err)] pub(crate) async fn read_workspace_apps_handler( controller: Unit>, @@ -31,16 +23,6 @@ pub(crate) async fn read_workspace_apps_handler( data_result(repeated_app) } -#[tracing::instrument(skip(data, controller), err)] -pub(crate) async fn read_workspaces_handler( - data: Data, - controller: Unit>, -) -> DataResult { - let params: WorkspaceIdentifier = data.into_inner().try_into()?; - let workspaces = controller.read_workspaces(params).await?; - data_result(workspaces) -} - #[tracing::instrument(skip(data, controller), err)] pub(crate) async fn open_workspace_handler( data: Data, diff --git a/frontend/rust-lib/flowy-core/src/services/workspace/sql.rs b/frontend/rust-lib/flowy-core/src/services/workspace/sql.rs index 27fd14a7ab..bda1a8def9 100644 --- a/frontend/rust-lib/flowy-core/src/services/workspace/sql.rs +++ b/frontend/rust-lib/flowy-core/src/services/workspace/sql.rs @@ -13,11 +13,7 @@ use flowy_database::{ pub(crate) struct WorkspaceTableSql {} impl WorkspaceTableSql { - pub(crate) fn create_workspace( - &self, - table: WorkspaceTable, - conn: &SqliteConnection, - ) -> Result<(), WorkspaceError> { + pub(crate) fn create_workspace(table: WorkspaceTable, conn: &SqliteConnection) -> Result<(), WorkspaceError> { match diesel_record_count!(workspace_table, &table.id, conn) { 0 => diesel_insert_table!(workspace_table, &table, conn), _ => { @@ -29,7 +25,6 @@ impl WorkspaceTableSql { } pub(crate) fn read_workspaces( - &self, workspace_id: Option, user_id: &str, conn: &SqliteConnection, @@ -50,7 +45,6 @@ impl WorkspaceTableSql { #[allow(dead_code)] pub(crate) fn update_workspace( - &self, changeset: WorkspaceTableChangeset, conn: &SqliteConnection, ) -> Result<(), WorkspaceError> { @@ -59,7 +53,7 @@ impl WorkspaceTableSql { } #[allow(dead_code)] - pub(crate) fn delete_workspace(&self, workspace_id: &str, conn: &SqliteConnection) -> Result<(), WorkspaceError> { + pub(crate) fn delete_workspace(workspace_id: &str, conn: &SqliteConnection) -> Result<(), WorkspaceError> { diesel_delete_table!(workspace_table, workspace_id, conn); Ok(()) } diff --git a/frontend/rust-lib/flowy-sdk/src/lib.rs b/frontend/rust-lib/flowy-sdk/src/lib.rs index 2eaa4782f3..2f2322d478 100644 --- a/frontend/rust-lib/flowy-sdk/src/lib.rs +++ b/frontend/rust-lib/flowy-sdk/src/lib.rs @@ -3,7 +3,7 @@ mod deps_resolve; pub mod module; use crate::deps_resolve::WorkspaceDepsResolver; use backend_service::configuration::ClientServerConfiguration; -use flowy_core::{errors::WorkspaceError, module::init_core, prelude::FlowyCore}; +use flowy_core::{errors::WorkspaceError, module::init_core, prelude::CoreContext}; use flowy_document::module::FlowyDocument; use flowy_user::{ prelude::UserStatus, @@ -66,7 +66,7 @@ pub struct FlowySDK { config: FlowySDKConfig, pub user_session: Arc, pub flowy_document: Arc, - pub core: Arc, + pub core: Arc, pub dispatcher: Arc, } @@ -99,7 +99,7 @@ impl FlowySDK { pub fn dispatcher(&self) -> Arc { self.dispatcher.clone() } } -fn _init(dispatch: &EventDispatcher, user_session: Arc, core: Arc) { +fn _init(dispatch: &EventDispatcher, user_session: Arc, core: Arc) { let user_status_subscribe = user_session.notifier.user_status_subscribe(); let network_status_subscribe = user_session.notifier.network_type_subscribe(); let cloned_core = core.clone(); @@ -113,7 +113,7 @@ fn _init(dispatch: &EventDispatcher, user_session: Arc, core: Arc, core: Arc) { +async fn _listen_user_status(mut subscribe: broadcast::Receiver, core: Arc) { while let Ok(status) = subscribe.recv().await { let result = || async { match status { @@ -141,7 +141,7 @@ async fn _listen_user_status(mut subscribe: broadcast::Receiver, cor } } -async fn _listen_network_status(mut subscribe: broadcast::Receiver, core: Arc) { +async fn _listen_network_status(mut subscribe: broadcast::Receiver, core: Arc) { while let Ok(new_type) = subscribe.recv().await { core.network_state_changed(new_type); } @@ -168,7 +168,7 @@ fn mk_core( user_session: Arc, flowy_document: Arc, server_config: &ClientServerConfiguration, -) -> Arc { +) -> Arc { let workspace_deps = WorkspaceDepsResolver::new(user_session); let (user, database) = workspace_deps.split_into(); init_core(user, database, flowy_document, server_config) diff --git a/frontend/rust-lib/flowy-sdk/src/module.rs b/frontend/rust-lib/flowy-sdk/src/module.rs index ac410b91cf..155a5e02ce 100644 --- a/frontend/rust-lib/flowy-sdk/src/module.rs +++ b/frontend/rust-lib/flowy-sdk/src/module.rs @@ -1,19 +1,19 @@ use crate::deps_resolve::DocumentDepsResolver; use backend_service::configuration::ClientServerConfiguration; -use flowy_core::prelude::FlowyCore; +use flowy_core::prelude::CoreContext; use flowy_document::module::FlowyDocument; use flowy_user::services::user::UserSession; use lib_dispatch::prelude::Module; use std::sync::Arc; -pub fn mk_modules(core: Arc, user_session: Arc) -> Vec { +pub fn mk_modules(core: Arc, user_session: Arc) -> Vec { let user_module = mk_user_module(user_session); let workspace_module = mk_core_module(core); vec![user_module, workspace_module] } fn mk_user_module(user_session: Arc) -> Module { flowy_user::module::create(user_session) } -fn mk_core_module(core: Arc) -> Module { flowy_core::module::create(core) } +fn mk_core_module(core: Arc) -> Module { flowy_core::module::create(core) } pub fn mk_document_module( user_session: Arc, diff --git a/frontend/rust-lib/flowy-user/src/services/server/mod.rs b/frontend/rust-lib/flowy-user/src/services/server/mod.rs index a0696d21f1..81d61938af 100644 --- a/frontend/rust-lib/flowy-user/src/services/server/mod.rs +++ b/frontend/rust-lib/flowy-user/src/services/server/mod.rs @@ -23,7 +23,7 @@ pub trait UserServerAPI { pub(crate) fn construct_user_server(config: &ClientServerConfiguration) -> Arc { if cfg!(feature = "http_server") { - Arc::new(UserServer::new(config.clone())) + Arc::new(UserHttpServer::new(config.clone())) } else { Arc::new(UserServerMock {}) } diff --git a/frontend/rust-lib/flowy-user/src/services/server/server_api.rs b/frontend/rust-lib/flowy-user/src/services/server/server_api.rs index 9e7bc5a7aa..096836a509 100644 --- a/frontend/rust-lib/flowy-user/src/services/server/server_api.rs +++ b/frontend/rust-lib/flowy-user/src/services/server/server_api.rs @@ -6,14 +6,14 @@ use crate::{ use backend_service::{configuration::*, user_request::*}; use lib_infra::future::ResultFuture; -pub struct UserServer { +pub struct UserHttpServer { config: ClientServerConfiguration, } -impl UserServer { +impl UserHttpServer { pub fn new(config: ClientServerConfiguration) -> Self { Self { config } } } -impl UserServerAPI for UserServer { +impl UserServerAPI for UserHttpServer { fn sign_up(&self, params: SignUpParams) -> ResultFuture { let url = self.config.sign_up_url(); ResultFuture::new(async move { From 2f413a8e670556571d1604ec2463a8d85b5b636b Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 7 Dec 2021 10:39:01 +0800 Subject: [PATCH 05/39] generic lib-ot --- backend/src/services/doc/edit/editor.rs | 12 +- backend/src/services/user/auth.rs | 1 - backend/tests/document/edit.rs | 6 +- backend/tests/document/helper.rs | 10 +- .../src/services/doc/edit/editor.rs | 18 +- .../src/services/doc/edit/queue.rs | 24 +- .../src/services/doc/revision/manager.rs | 8 +- .../src/services/doc/revision/persistence.rs | 10 +- .../tests/editor/attribute_test.rs | 12 +- .../flowy-document/tests/editor/mod.rs | 36 +-- .../flowy-document/tests/editor/op_test.rs | 131 +++++----- .../flowy-document/tests/editor/serde_test.rs | 32 +-- .../flowy-document-infra/src/core/document.rs | 34 +-- .../core/extensions/delete/default_delete.rs | 4 +- .../delete/preserve_line_format_merge.rs | 15 +- .../src/core/extensions/format/helper.rs | 10 +- .../extensions/format/resolve_block_format.rs | 12 +- .../format/resolve_inline_format.rs | 4 +- .../core/extensions/insert/auto_exit_block.rs | 13 +- .../src/core/extensions/insert/auto_format.rs | 16 +- .../core/extensions/insert/default_insert.rs | 18 +- .../src/core/extensions/insert/mod.rs | 10 +- .../insert/preserve_block_format.rs | 16 +- .../insert/preserve_inline_format.rs | 18 +- .../insert/reset_format_on_new_line.rs | 18 +- .../src/core/extensions/mod.rs | 8 +- .../flowy-document-infra/src/core/history.rs | 16 +- .../flowy-document-infra/src/core/view.rs | 18 +- .../src/entities/doc/doc.rs | 8 +- .../src/entities/doc/revision.rs | 4 +- .../flowy-document-infra/src/user_default.rs | 8 +- .../lib-ot/src/core/attributes/attribute.rs | 92 +++---- .../lib-ot/src/core/attributes/attributes.rs | 98 ++++--- .../src/core/attributes/attributes_serde.rs | 92 +++---- .../lib-ot/src/core/attributes/builder.rs | 10 +- .../lib-ot/src/core/attributes/macros.rs | 8 +- shared-lib/lib-ot/src/core/delta/builder.rs | 28 +- shared-lib/lib-ot/src/core/delta/cursor.rs | 38 +-- shared-lib/lib-ot/src/core/delta/delta.rs | 163 +++++++----- .../lib-ot/src/core/delta/delta_serde.rs | 28 +- shared-lib/lib-ot/src/core/delta/iterator.rs | 84 +++--- .../lib-ot/src/core/operation/builder.rs | 29 ++- .../lib-ot/src/core/operation/operation.rs | 149 +++++++---- .../src/core/operation/operation_serde.rs | 240 +++++++++++++++++- 44 files changed, 1023 insertions(+), 586 deletions(-) diff --git a/backend/src/services/doc/edit/editor.rs b/backend/src/services/doc/edit/editor.rs index f148a9d692..e685af5a96 100644 --- a/backend/src/services/doc/edit/editor.rs +++ b/backend/src/services/doc/edit/editor.rs @@ -13,7 +13,7 @@ use flowy_document_infra::{ entities::ws::{WsDataType, WsDocumentData}, protobuf::{Doc, RevId, RevType, Revision, RevisionRange, UpdateDocParams}, }; -use lib_ot::core::{Delta, OperationTransformable}; +use lib_ot::core::{OperationTransformable, RichTextDelta}; use parking_lot::RwLock; use protobuf::Message; use sqlx::PgPool; @@ -35,7 +35,7 @@ pub struct ServerDocEditor { impl ServerDocEditor { pub fn new(doc: Doc) -> Result { - let delta = Delta::from_bytes(&doc.data).map_err(internal_error)?; + let delta = RichTextDelta::from_bytes(&doc.data).map_err(internal_error)?; let document = Arc::new(RwLock::new(Document::from_delta(delta))); let users = DashMap::new(); Ok(Self { @@ -123,7 +123,7 @@ impl ServerDocEditor { pub fn document_json(&self) -> String { self.document.read().to_json() } async fn compose_revision(&self, revision: &Revision, pg_pool: Data) -> Result<(), ServerError> { - let delta = Delta::from_bytes(&revision.delta_data).map_err(internal_error)?; + let delta = RichTextDelta::from_bytes(&revision.delta_data).map_err(internal_error)?; let _ = self.compose_delta(delta)?; let _ = self.rev_id.fetch_update(SeqCst, SeqCst, |_e| Some(revision.rev_id)); let _ = self.save_revision(&revision, pg_pool).await?; @@ -132,7 +132,7 @@ impl ServerDocEditor { #[tracing::instrument(level = "debug", skip(self, revision))] fn transform_revision(&self, revision: &Revision) -> Result { - let cli_delta = Delta::from_bytes(&revision.delta_data).map_err(internal_error)?; + let cli_delta = RichTextDelta::from_bytes(&revision.delta_data).map_err(internal_error)?; let (cli_prime, server_prime) = self .document .read() @@ -145,7 +145,7 @@ impl ServerDocEditor { Ok(cli_revision) } - fn mk_revision(&self, base_rev_id: i64, delta: Delta) -> Revision { + fn mk_revision(&self, base_rev_id: i64, delta: RichTextDelta) -> Revision { let delta_data = delta.to_bytes().to_vec(); let md5 = md5(&delta_data); Revision { @@ -167,7 +167,7 @@ impl ServerDocEditor { result, ) )] - fn compose_delta(&self, delta: Delta) -> Result<(), ServerError> { + fn compose_delta(&self, delta: RichTextDelta) -> Result<(), ServerError> { if delta.is_empty() { log::warn!("Composed delta is empty"); } diff --git a/backend/src/services/user/auth.rs b/backend/src/services/user/auth.rs index 19d0759969..16e8367940 100644 --- a/backend/src/services/user/auth.rs +++ b/backend/src/services/user/auth.rs @@ -16,7 +16,6 @@ use flowy_user_infra::{ use sqlx::{PgPool, Postgres}; use super::AUTHORIZED_USERS; -use crate::services::user::user_default::create_default_workspace; pub async fn sign_in(pool: &PgPool, params: SignInParams) -> Result { let email = UserEmail::parse(params.email).map_err(|e| ServerError::params_invalid().context(e))?; diff --git a/backend/tests/document/edit.rs b/backend/tests/document/edit.rs index b883c1759e..d821b0d9e6 100644 --- a/backend/tests/document/edit.rs +++ b/backend/tests/document/edit.rs @@ -1,6 +1,6 @@ use crate::document::helper::{DocScript, DocumentTest}; use flowy_document_infra::core::{Document, FlowyDoc}; -use lib_ot::core::{Attribute, Interval}; +use lib_ot::core::{Interval, RichTextAttribute}; #[rustfmt::skip] // ┌─────────┐ ┌─────────┐ @@ -51,11 +51,11 @@ async fn delta_sync_while_editing_with_attribute() { DocScript::ClientConnectWs, DocScript::ClientOpenDoc, DocScript::ClientInsertText(0, "abc"), - DocScript::ClientFormatText(Interval::new(0, 3), Attribute::Bold(true)), + DocScript::ClientFormatText(Interval::new(0, 3), RichTextAttribute::Bold(true)), DocScript::AssertClient(r#"[{"insert":"abc","attributes":{"bold":true}},{"insert":"\n"}]"#), DocScript::AssertServer(r#"[{"insert":"abc","attributes":{"bold":true}},{"insert":"\n"}]"#, 2), DocScript::ClientInsertText(3, "efg"), - DocScript::ClientFormatText(Interval::new(3, 5), Attribute::Italic(true)), + DocScript::ClientFormatText(Interval::new(3, 5), RichTextAttribute::Italic(true)), DocScript::AssertClient(r#"[{"insert":"abc","attributes":{"bold":true}},{"insert":"ef","attributes":{"bold":true,"italic":true}},{"insert":"g","attributes":{"bold":true}},{"insert":"\n"}]"#), DocScript::AssertServer(r#"[{"insert":"abc","attributes":{"bold":true}},{"insert":"ef","attributes":{"bold":true,"italic":true}},{"insert":"g","attributes":{"bold":true}},{"insert":"\n"}]"#, 4), ]) diff --git a/backend/tests/document/helper.rs b/backend/tests/document/helper.rs index 494617ef8d..1e93834b9b 100644 --- a/backend/tests/document/helper.rs +++ b/backend/tests/document/helper.rs @@ -1,7 +1,7 @@ #![allow(clippy::all)] #![cfg_attr(rustfmt, rustfmt::skip)] use actix_web::web::Data; -use backend::service::doc::{crud::update_doc, manager::DocManager}; +use backend::services::doc::{crud::update_doc, manager::DocManager}; use flowy_document::services::doc::ClientDocEditor as ClientEditDocContext; use flowy_test::{workspace::ViewTest, FlowyTest}; use flowy_user::services::user::UserSession; @@ -12,7 +12,7 @@ use tokio::time::{sleep, Duration}; // use crate::helper::*; use crate::util::helper::{spawn_server, TestServer}; use flowy_document_infra::{entities::doc::DocIdentifier, protobuf::UpdateDocParams}; -use lib_ot::core::{Attribute, Delta, Interval}; +use lib_ot::core::{RichTextAttribute, RichTextDelta, Interval}; use parking_lot::RwLock; pub struct DocumentTest { @@ -23,7 +23,7 @@ pub struct DocumentTest { pub enum DocScript { ClientConnectWs, ClientInsertText(usize, &'static str), - ClientFormatText(Interval, Attribute), + ClientFormatText(Interval, RichTextAttribute), ClientOpenDoc, AssertClient(&'static str), AssertServer(&'static str, i64), @@ -150,8 +150,8 @@ async fn run_scripts(context: Arc>, scripts: Vec(&self, index: usize, data: T) -> Result<(), DocError> { - let (ret, rx) = oneshot::channel::>(); + let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::Insert { index, data: data.to_string(), @@ -73,7 +73,7 @@ impl ClientDocEditor { } pub async fn delete(&self, interval: Interval) -> Result<(), DocError> { - let (ret, rx) = oneshot::channel::>(); + let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::Delete { interval, ret }; let _ = self.edit_tx.send(msg); let delta = rx.await.map_err(internal_error)??; @@ -81,8 +81,8 @@ impl ClientDocEditor { Ok(()) } - pub async fn format(&self, interval: Interval, attribute: Attribute) -> Result<(), DocError> { - let (ret, rx) = oneshot::channel::>(); + pub async fn format(&self, interval: Interval, attribute: RichTextAttribute) -> Result<(), DocError> { + let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::Format { interval, attribute, @@ -95,7 +95,7 @@ impl ClientDocEditor { } pub async fn replace(&mut self, interval: Interval, data: T) -> Result<(), DocError> { - let (ret, rx) = oneshot::channel::>(); + let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::Replace { interval, data: data.to_string(), @@ -149,7 +149,7 @@ impl ClientDocEditor { }) } - async fn save_local_delta(&self, delta: Delta) -> Result { + async fn save_local_delta(&self, delta: RichTextDelta) -> Result { 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(); @@ -160,7 +160,7 @@ impl ClientDocEditor { #[tracing::instrument(level = "debug", skip(self, data), err)] pub(crate) async fn composing_local_delta(&self, data: Bytes) -> Result<(), DocError> { - let delta = Delta::from_bytes(&data)?; + let delta = RichTextDelta::from_bytes(&data)?; let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::ComposeDelta { delta: delta.clone(), @@ -314,7 +314,7 @@ fn spawn_rev_receiver(mut receiver: mpsc::UnboundedReceiver, ws: Arc) -> UnboundedSender { +fn spawn_edit_queue(doc_id: &str, delta: RichTextDelta, _pool: Arc) -> UnboundedSender { let (sender, receiver) = mpsc::unbounded_channel::(); let actor = EditCommandQueue::new(doc_id, delta, receiver); tokio::spawn(actor.run()); diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs index 0584dabc1b..caeb062601 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs @@ -6,7 +6,7 @@ use flowy_document_infra::{ errors::DocumentError, }; use futures::stream::StreamExt; -use lib_ot::core::{Attribute, Delta, Interval, OperationTransformable}; +use lib_ot::core::{Interval, OperationTransformable, RichTextAttribute, RichTextDelta}; use std::{convert::TryFrom, sync::Arc}; use tokio::sync::{mpsc, oneshot, RwLock}; @@ -17,7 +17,7 @@ pub(crate) struct EditCommandQueue { } impl EditCommandQueue { - pub(crate) fn new(doc_id: &str, delta: Delta, receiver: mpsc::UnboundedReceiver) -> Self { + pub(crate) fn new(doc_id: &str, delta: RichTextDelta, receiver: mpsc::UnboundedReceiver) -> Self { let document = Arc::new(RwLock::new(Document::from_delta(delta))); Self { doc_id: doc_id.to_owned(), @@ -54,7 +54,7 @@ impl EditCommandQueue { }, EditCommand::RemoteRevision { bytes, ret } => { let revision = Revision::try_from(bytes)?; - let delta = Delta::from_bytes(&revision.delta_data)?; + let delta = RichTextDelta::from_bytes(&revision.delta_data)?; let rev_id: RevId = revision.rev_id.into(); let (server_prime, client_prime) = self.document.read().await.delta().transform(&delta)?; let transform_delta = TransformDeltas { @@ -107,7 +107,7 @@ impl EditCommandQueue { } #[tracing::instrument(level = "debug", skip(self, delta), fields(compose_result), err)] - async fn composed_delta(&self, delta: Delta) -> Result<(), DocumentError> { + async fn composed_delta(&self, delta: RichTextDelta) -> Result<(), DocumentError> { // tracing::debug!("{:?} thread handle_message", thread::current(),); let mut document = self.document.write().await; tracing::Span::current().record( @@ -125,7 +125,7 @@ impl EditCommandQueue { pub(crate) type Ret = oneshot::Sender>; pub(crate) enum EditCommand { ComposeDelta { - delta: Delta, + delta: RichTextDelta, ret: Ret<()>, }, RemoteRevision { @@ -135,22 +135,22 @@ pub(crate) enum EditCommand { Insert { index: usize, data: String, - ret: Ret, + ret: Ret, }, Delete { interval: Interval, - ret: Ret, + ret: Ret, }, Format { interval: Interval, - attribute: Attribute, - ret: Ret, + attribute: RichTextAttribute, + ret: Ret, }, Replace { interval: Interval, data: String, - ret: Ret, + ret: Ret, }, CanUndo { ret: oneshot::Sender, @@ -170,7 +170,7 @@ pub(crate) enum EditCommand { } pub(crate) struct TransformDeltas { - pub client_prime: Delta, - pub server_prime: Delta, + pub client_prime: RichTextDelta, + pub server_prime: RichTextDelta, pub server_rev_id: RevId, } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs index 89d7587fef..063c82d664 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs @@ -8,7 +8,7 @@ use flowy_document_infra::{ util::RevIdCounter, }; use lib_infra::future::ResultFuture; -use lib_ot::core::{Delta, OperationTransformable}; +use lib_ot::core::{OperationTransformable, RichTextDelta}; use std::sync::Arc; use tokio::sync::mpsc; @@ -38,7 +38,7 @@ impl RevisionManager { } } - pub async fn load_document(&mut self) -> DocResult { + pub async fn load_document(&mut self) -> DocResult { let doc = self.rev_store.fetch_document().await?; self.update_rev_id_counter_value(doc.rev_id); Ok(doc.delta()?) @@ -67,9 +67,9 @@ impl RevisionManager { pub async fn mk_revisions(&self, range: RevisionRange) -> Result { debug_assert!(range.doc_id == self.doc_id); let revisions = self.rev_store.revs_in_range(range.clone()).await?; - let mut new_delta = Delta::new(); + let mut new_delta = RichTextDelta::new(); for revision in revisions { - match Delta::from_bytes(revision.delta_data) { + match RichTextDelta::from_bytes(revision.delta_data) { Ok(delta) => { new_delta = new_delta.compose(&delta)?; }, diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/persistence.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/persistence.rs index f425db7ef0..1b63e33e88 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/persistence.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/persistence.rs @@ -9,7 +9,7 @@ use flowy_database::{ConnectionPool, SqliteConnection}; use flowy_document_infra::entities::doc::{revision_from_doc, Doc, RevId, RevType, Revision, RevisionRange}; use futures::stream::StreamExt; use lib_infra::future::ResultFuture; -use lib_ot::core::{Delta, Operation, OperationTransformable}; +use lib_ot::core::{Operation, OperationTransformable, RichTextDelta}; use std::{collections::VecDeque, sync::Arc, time::Duration}; use tokio::{ sync::{broadcast, mpsc, RwLock}, @@ -188,9 +188,9 @@ async fn fetch_from_local(doc_id: &str, persistence: Arc) -> DocRes let base_rev_id: RevId = revisions.last().unwrap().base_rev_id.into(); let rev_id: RevId = revisions.last().unwrap().rev_id.into(); - let mut delta = Delta::new(); + let mut delta = RichTextDelta::new(); for (_, revision) in revisions.into_iter().enumerate() { - match Delta::from_bytes(revision.delta_data) { + match RichTextDelta::from_bytes(revision.delta_data) { Ok(local_delta) => { delta = delta.compose(&local_delta)?; }, @@ -225,7 +225,7 @@ async fn fetch_from_local(doc_id: &str, persistence: Arc) -> DocRes } #[cfg(debug_assertions)] -fn validate_delta(doc_id: &str, persistence: Arc, conn: &SqliteConnection, delta: &Delta) { +fn validate_delta(doc_id: &str, persistence: Arc, conn: &SqliteConnection, delta: &RichTextDelta) { if delta.ops.last().is_none() { return; } @@ -236,7 +236,7 @@ fn validate_delta(doc_id: &str, persistence: Arc, conn: &SqliteConn let result = || { let revisions = persistence.rev_sql.read_rev_tables(&doc_id, conn)?; for revision in revisions { - let delta = Delta::from_bytes(revision.delta_data)?; + let delta = RichTextDelta::from_bytes(revision.delta_data)?; log::error!("Invalid revision: {}:{}", revision.rev_id, delta.to_json()); } Ok::<(), DocError>(()) diff --git a/frontend/rust-lib/flowy-document/tests/editor/attribute_test.rs b/frontend/rust-lib/flowy-document/tests/editor/attribute_test.rs index b817e1f646..80b987262f 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/attribute_test.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/attribute_test.rs @@ -1,7 +1,7 @@ #![cfg_attr(rustfmt, rustfmt::skip)] use crate::editor::{TestBuilder, TestOp::*}; use flowy_document_infra::core::{FlowyDoc, PlainDoc}; -use lib_ot::core::{Delta, Interval, OperationTransformable, NEW_LINE, WHITESPACE, FlowyStr}; +use lib_ot::core::{Interval, OperationTransformable, NEW_LINE, WHITESPACE, FlowyStr, RichTextDelta}; use unicode_segmentation::UnicodeSegmentation; #[test] @@ -760,12 +760,12 @@ fn attributes_preserve_list_format_on_merge() { #[test] fn delta_compose() { - let mut delta = Delta::from_json(r#"[{"insert":"\n"}]"#).unwrap(); + let mut delta = RichTextDelta::from_json(r#"[{"insert":"\n"}]"#).unwrap(); let deltas = vec![ - Delta::from_json(r#"[{"retain":1,"attributes":{"list":"unchecked"}}]"#).unwrap(), - Delta::from_json(r#"[{"insert":"a"}]"#).unwrap(), - Delta::from_json(r#"[{"retain":1},{"insert":"\n","attributes":{"list":"unchecked"}}]"#).unwrap(), - Delta::from_json(r#"[{"retain":2},{"retain":1,"attributes":{"list":""}}]"#).unwrap(), + RichTextDelta::from_json(r#"[{"retain":1,"attributes":{"list":"unchecked"}}]"#).unwrap(), + RichTextDelta::from_json(r#"[{"insert":"a"}]"#).unwrap(), + RichTextDelta::from_json(r#"[{"retain":1},{"insert":"\n","attributes":{"list":"unchecked"}}]"#).unwrap(), + RichTextDelta::from_json(r#"[{"retain":2},{"retain":1,"attributes":{"list":""}}]"#).unwrap(), ]; for d in deltas { diff --git a/frontend/rust-lib/flowy-document/tests/editor/mod.rs b/frontend/rust-lib/flowy-document/tests/editor/mod.rs index 99b8c2ef07..1447fda4f3 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/mod.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/mod.rs @@ -80,8 +80,8 @@ pub enum TestOp { pub struct TestBuilder { documents: Vec, - deltas: Vec>, - primes: Vec>, + deltas: Vec>, + primes: Vec>, } impl TestBuilder { @@ -125,11 +125,11 @@ impl TestBuilder { TestOp::InsertBold(delta_i, s, iv) => { let document = &mut self.documents[*delta_i]; document.insert(iv.start, s).unwrap(); - document.format(*iv, Attribute::Bold(true)).unwrap(); + document.format(*iv, RichTextAttribute::Bold(true)).unwrap(); }, TestOp::Bold(delta_i, iv, enable) => { let document = &mut self.documents[*delta_i]; - let attribute = Attribute::Bold(*enable); + let attribute = RichTextAttribute::Bold(*enable); let delta = document.format(*iv, attribute).unwrap(); tracing::trace!("Bold delta: {}", delta.to_json()); self.deltas.insert(*delta_i, Some(delta)); @@ -137,8 +137,8 @@ impl TestBuilder { TestOp::Italic(delta_i, iv, enable) => { let document = &mut self.documents[*delta_i]; let attribute = match *enable { - true => Attribute::Italic(true), - false => Attribute::Italic(false), + true => RichTextAttribute::Italic(true), + false => RichTextAttribute::Italic(false), }; let delta = document.format(*iv, attribute).unwrap(); tracing::trace!("Italic delta: {}", delta.to_json()); @@ -146,21 +146,21 @@ impl TestBuilder { }, TestOp::Header(delta_i, iv, level) => { let document = &mut self.documents[*delta_i]; - let attribute = Attribute::Header(*level); + let attribute = RichTextAttribute::Header(*level); let delta = document.format(*iv, attribute).unwrap(); tracing::trace!("Header delta: {}", delta.to_json()); self.deltas.insert(*delta_i, Some(delta)); }, TestOp::Link(delta_i, iv, link) => { let document = &mut self.documents[*delta_i]; - let attribute = Attribute::Link(link.to_owned()); + let attribute = RichTextAttribute::Link(link.to_owned()); let delta = document.format(*iv, attribute).unwrap(); tracing::trace!("Link delta: {}", delta.to_json()); self.deltas.insert(*delta_i, Some(delta)); }, TestOp::Bullet(delta_i, iv, enable) => { let document = &mut self.documents[*delta_i]; - let attribute = Attribute::Bullet(*enable); + let attribute = RichTextAttribute::Bullet(*enable); let delta = document.format(*iv, attribute).unwrap(); tracing::debug!("Bullet delta: {}", delta.to_json()); @@ -225,8 +225,8 @@ impl TestBuilder { TestOp::AssertDocJson(delta_i, expected) => { let delta_json = self.documents[*delta_i].to_json(); - let expected_delta: Delta = serde_json::from_str(expected).unwrap(); - let target_delta: Delta = serde_json::from_str(&delta_json).unwrap(); + let expected_delta: RichTextDelta = serde_json::from_str(expected).unwrap(); + let target_delta: RichTextDelta = serde_json::from_str(&delta_json).unwrap(); if expected_delta != target_delta { log::error!("✅ expect: {}", expected,); @@ -237,8 +237,8 @@ impl TestBuilder { TestOp::AssertPrimeJson(doc_i, expected) => { let prime_json = self.primes[*doc_i].as_ref().unwrap().to_json(); - let expected_prime: Delta = serde_json::from_str(expected).unwrap(); - let target_prime: Delta = serde_json::from_str(&prime_json).unwrap(); + let expected_prime: RichTextDelta = serde_json::from_str(expected).unwrap(); + let target_prime: RichTextDelta = serde_json::from_str(&prime_json).unwrap(); if expected_prime != target_prime { log::error!("✅ expect prime: {}", expected,); @@ -292,8 +292,8 @@ impl Rng { .collect() } - pub fn gen_delta(&mut self, s: &str) -> Delta { - let mut delta = Delta::default(); + pub fn gen_delta(&mut self, s: &str) -> RichTextDelta { + let mut delta = RichTextDelta::default(); loop { let left = s.chars().count() - delta.base_len; if left == 0 { @@ -306,18 +306,18 @@ impl Rng { }; match self.0.gen_range(0.0, 1.0) { f if f < 0.2 => { - delta.insert(&self.gen_string(i), Attributes::default()); + delta.insert(&self.gen_string(i), RichTextAttributes::default()); }, f if f < 0.4 => { delta.delete(i); }, _ => { - delta.retain(i, Attributes::default()); + delta.retain(i, RichTextAttributes::default()); }, } } if self.0.gen_range(0.0, 1.0) < 0.3 { - delta.insert(&("1".to_owned() + &self.gen_string(10)), Attributes::default()); + delta.insert(&("1".to_owned() + &self.gen_string(10)), RichTextAttributes::default()); } delta } diff --git a/frontend/rust-lib/flowy-document/tests/editor/op_test.rs b/frontend/rust-lib/flowy-document/tests/editor/op_test.rs index f7b69e171e..deff6dbd8d 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/op_test.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/op_test.rs @@ -35,7 +35,7 @@ fn attributes_insert_text_at_middle() { #[test] fn delta_get_ops_in_interval_1() { - let mut delta = Delta::default(); + let mut delta = RichTextDelta::default(); let insert_a = OpBuilder::insert("123").build(); let insert_b = OpBuilder::insert("4").build(); @@ -48,7 +48,7 @@ fn delta_get_ops_in_interval_1() { #[test] fn delta_get_ops_in_interval_2() { - let mut delta = Delta::default(); + let mut delta = RichTextDelta::default(); let insert_a = OpBuilder::insert("123").build(); let insert_b = OpBuilder::insert("4").build(); let insert_c = OpBuilder::insert("5").build(); @@ -92,7 +92,7 @@ fn delta_get_ops_in_interval_2() { #[test] fn delta_get_ops_in_interval_3() { - let mut delta = Delta::default(); + let mut delta = RichTextDelta::default(); let insert_a = OpBuilder::insert("123456").build(); delta.add(insert_a.clone()); assert_eq!( @@ -103,7 +103,7 @@ fn delta_get_ops_in_interval_3() { #[test] fn delta_get_ops_in_interval_4() { - let mut delta = Delta::default(); + let mut delta = RichTextDelta::default(); let insert_a = OpBuilder::insert("12").build(); let insert_b = OpBuilder::insert("34").build(); let insert_c = OpBuilder::insert("56").build(); @@ -133,7 +133,7 @@ fn delta_get_ops_in_interval_4() { #[test] fn delta_get_ops_in_interval_5() { - let mut delta = Delta::default(); + let mut delta = RichTextDelta::default(); let insert_a = OpBuilder::insert("123456").build(); let insert_b = OpBuilder::insert("789").build(); delta.ops.push(insert_a.clone()); @@ -151,7 +151,7 @@ fn delta_get_ops_in_interval_5() { #[test] fn delta_get_ops_in_interval_6() { - let mut delta = Delta::default(); + let mut delta = RichTextDelta::default(); let insert_a = OpBuilder::insert("12345678").build(); delta.add(insert_a.clone()); assert_eq!( @@ -162,7 +162,7 @@ fn delta_get_ops_in_interval_6() { #[test] fn delta_get_ops_in_interval_7() { - let mut delta = Delta::default(); + let mut delta = RichTextDelta::default(); let insert_a = OpBuilder::insert("12345").build(); let retain_a = OpBuilder::retain(3).build(); @@ -182,7 +182,7 @@ fn delta_get_ops_in_interval_7() { #[test] fn delta_seek_1() { - let mut delta = Delta::default(); + let mut delta = RichTextDelta::default(); let insert_a = OpBuilder::insert("12345").build(); let retain_a = OpBuilder::retain(3).build(); delta.add(insert_a.clone()); @@ -194,7 +194,7 @@ fn delta_seek_1() { #[test] fn delta_seek_2() { - let mut delta = Delta::default(); + let mut delta = RichTextDelta::default(); delta.add(OpBuilder::insert("12345").build()); let mut iter = DeltaIter::new(&delta); @@ -203,7 +203,7 @@ fn delta_seek_2() { #[test] fn delta_seek_3() { - let mut delta = Delta::default(); + let mut delta = RichTextDelta::default(); delta.add(OpBuilder::insert("12345").build()); let mut iter = DeltaIter::new(&delta); @@ -218,7 +218,7 @@ fn delta_seek_3() { #[test] fn delta_seek_4() { - let mut delta = Delta::default(); + let mut delta = RichTextDelta::default(); delta.add(OpBuilder::insert("12345").build()); let mut iter = DeltaIter::new(&delta); @@ -228,10 +228,10 @@ fn delta_seek_4() { #[test] fn delta_seek_5() { - let mut delta = Delta::default(); + let mut delta = RichTextDelta::default(); let attributes = AttributeBuilder::new() - .add_attr(Attribute::Bold(true)) - .add_attr(Attribute::Italic(true)) + .add_attr(RichTextAttribute::Bold(true)) + .add_attr(RichTextAttribute::Italic(true)) .build(); delta.add(OpBuilder::insert("1234").attributes(attributes.clone()).build()); @@ -248,7 +248,7 @@ fn delta_seek_5() { #[test] fn delta_next_op_len_test() { - let mut delta = Delta::default(); + let mut delta = RichTextDelta::default(); delta.add(OpBuilder::insert("12345").build()); let mut iter = DeltaIter::new(&delta); @@ -261,7 +261,7 @@ fn delta_next_op_len_test() { #[test] fn delta_next_op_len_test2() { - let mut delta = Delta::default(); + let mut delta = RichTextDelta::default(); delta.add(OpBuilder::insert("12345").build()); let mut iter = DeltaIter::new(&delta); @@ -272,7 +272,7 @@ fn delta_next_op_len_test2() { #[test] fn delta_next_op_with_len_zero() { - let mut delta = Delta::default(); + let mut delta = RichTextDelta::default(); delta.add(OpBuilder::insert("12345").build()); let mut iter = DeltaIter::new(&delta); assert_eq!(iter.next_op_with_len(0), None,); @@ -281,7 +281,7 @@ fn delta_next_op_with_len_zero() { #[test] fn delta_next_op_with_len_cross_op_return_last() { - let mut delta = Delta::default(); + let mut delta = RichTextDelta::default(); delta.add(OpBuilder::insert("12345").build()); delta.add(OpBuilder::retain(1).build()); delta.add(OpBuilder::insert("678").build()); @@ -294,16 +294,16 @@ fn delta_next_op_with_len_cross_op_return_last() { #[test] fn lengths() { - let mut delta = Delta::default(); + let mut delta = RichTextDelta::default(); assert_eq!(delta.base_len, 0); assert_eq!(delta.target_len, 0); - delta.retain(5, Attributes::default()); + delta.retain(5, RichTextAttributes::default()); assert_eq!(delta.base_len, 5); assert_eq!(delta.target_len, 5); - delta.insert("abc", Attributes::default()); + delta.insert("abc", RichTextAttributes::default()); assert_eq!(delta.base_len, 5); assert_eq!(delta.target_len, 8); - delta.retain(2, Attributes::default()); + delta.retain(2, RichTextAttributes::default()); assert_eq!(delta.base_len, 7); assert_eq!(delta.target_len, 10); delta.delete(2); @@ -312,11 +312,11 @@ fn lengths() { } #[test] fn sequence() { - let mut delta = Delta::default(); - delta.retain(5, Attributes::default()); - delta.retain(0, Attributes::default()); - delta.insert("appflowy", Attributes::default()); - delta.insert("", Attributes::default()); + let mut delta = RichTextDelta::default(); + delta.retain(5, RichTextAttributes::default()); + delta.retain(0, RichTextAttributes::default()); + delta.insert("appflowy", RichTextAttributes::default()); + delta.insert("", RichTextAttributes::default()); delta.delete(3); delta.delete(0); assert_eq!(delta.ops.len(), 3); @@ -335,12 +335,12 @@ fn apply_1000() { #[test] fn apply() { let s = "hello world,".to_owned(); - let mut delta_a = Delta::default(); - delta_a.insert(&s, Attributes::default()); + let mut delta_a = RichTextDelta::default(); + delta_a.insert(&s, RichTextAttributes::default()); - let mut delta_b = Delta::default(); - delta_b.retain(s.len(), Attributes::default()); - delta_b.insert("appflowy", Attributes::default()); + let mut delta_b = RichTextDelta::default(); + delta_b.retain(s.len(), RichTextAttributes::default()); + delta_b.insert("appflowy", RichTextAttributes::default()); let after_a = delta_a.apply("").unwrap(); let after_b = delta_b.apply(&after_a).unwrap(); @@ -349,16 +349,16 @@ fn apply() { #[test] fn base_len_test() { - let mut delta_a = Delta::default(); - delta_a.insert("a", Attributes::default()); - delta_a.insert("b", Attributes::default()); - delta_a.insert("c", Attributes::default()); + let mut delta_a = RichTextDelta::default(); + delta_a.insert("a", RichTextAttributes::default()); + delta_a.insert("b", RichTextAttributes::default()); + delta_a.insert("c", RichTextAttributes::default()); let s = "hello world,".to_owned(); delta_a.delete(s.len()); let after_a = delta_a.apply(&s).unwrap(); - delta_a.insert("d", Attributes::default()); + delta_a.insert("d", RichTextAttributes::default()); assert_eq!("abc", &after_a); } @@ -377,43 +377,43 @@ fn invert() { #[test] fn empty_ops() { - let mut delta = Delta::default(); - delta.retain(0, Attributes::default()); - delta.insert("", Attributes::default()); + let mut delta = RichTextDelta::default(); + delta.retain(0, RichTextAttributes::default()); + delta.insert("", RichTextAttributes::default()); delta.delete(0); assert_eq!(delta.ops.len(), 0); } #[test] fn eq() { - let mut delta_a = Delta::default(); + let mut delta_a = RichTextDelta::default(); delta_a.delete(1); - delta_a.insert("lo", Attributes::default()); - delta_a.retain(2, Attributes::default()); - delta_a.retain(3, Attributes::default()); - let mut delta_b = Delta::default(); + delta_a.insert("lo", RichTextAttributes::default()); + delta_a.retain(2, RichTextAttributes::default()); + delta_a.retain(3, RichTextAttributes::default()); + let mut delta_b = RichTextDelta::default(); delta_b.delete(1); - delta_b.insert("l", Attributes::default()); - delta_b.insert("o", Attributes::default()); - delta_b.retain(5, Attributes::default()); + delta_b.insert("l", RichTextAttributes::default()); + delta_b.insert("o", RichTextAttributes::default()); + delta_b.retain(5, RichTextAttributes::default()); assert_eq!(delta_a, delta_b); delta_a.delete(1); - delta_b.retain(1, Attributes::default()); + delta_b.retain(1, RichTextAttributes::default()); assert_ne!(delta_a, delta_b); } #[test] fn ops_merging() { - let mut delta = Delta::default(); + let mut delta = RichTextDelta::default(); assert_eq!(delta.ops.len(), 0); - delta.retain(2, Attributes::default()); + delta.retain(2, RichTextAttributes::default()); assert_eq!(delta.ops.len(), 1); assert_eq!(delta.ops.last(), Some(&OpBuilder::retain(2).build())); - delta.retain(3, Attributes::default()); + delta.retain(3, RichTextAttributes::default()); assert_eq!(delta.ops.len(), 1); assert_eq!(delta.ops.last(), Some(&OpBuilder::retain(5).build())); - delta.insert("abc", Attributes::default()); + delta.insert("abc", RichTextAttributes::default()); assert_eq!(delta.ops.len(), 2); assert_eq!(delta.ops.last(), Some(&OpBuilder::insert("abc").build())); - delta.insert("xyz", Attributes::default()); + delta.insert("xyz", RichTextAttributes::default()); assert_eq!(delta.ops.len(), 2); assert_eq!(delta.ops.last(), Some(&OpBuilder::insert("abcxyz").build())); delta.delete(1); @@ -425,13 +425,13 @@ fn ops_merging() { } #[test] fn is_noop() { - let mut delta = Delta::default(); + let mut delta = RichTextDelta::default(); assert!(delta.is_noop()); - delta.retain(5, Attributes::default()); + delta.retain(5, RichTextAttributes::default()); assert!(delta.is_noop()); - delta.retain(3, Attributes::default()); + delta.retain(3, RichTextAttributes::default()); assert!(delta.is_noop()); - delta.insert("lorem", Attributes::default()); + delta.insert("lorem", RichTextAttributes::default()); assert!(!delta.is_noop()); } #[test] @@ -473,15 +473,18 @@ fn transform_random_delta() { #[test] fn transform_with_two_delta_test() { - let mut a = Delta::default(); + let mut a = RichTextDelta::default(); let mut a_s = String::new(); - a.insert("123", AttributeBuilder::new().add_attr(Attribute::Bold(true)).build()); + a.insert( + "123", + AttributeBuilder::new().add_attr(RichTextAttribute::Bold(true)).build(), + ); a_s = a.apply(&a_s).unwrap(); assert_eq!(&a_s, "123"); - let mut b = Delta::default(); + let mut b = RichTextDelta::default(); let mut b_s = String::new(); - b.insert("456", Attributes::default()); + b.insert("456", RichTextAttributes::default()); b_s = b.apply(&b_s).unwrap(); assert_eq!(&b_s, "456"); @@ -569,10 +572,10 @@ fn transform_two_conflict_non_seq_delta() { #[test] fn delta_invert_no_attribute_delta() { - let mut delta = Delta::default(); + let mut delta = RichTextDelta::default(); delta.add(OpBuilder::insert("123").build()); - let mut change = Delta::default(); + let mut change = RichTextDelta::default(); change.add(OpBuilder::retain(3).build()); change.add(OpBuilder::insert("456").build()); let undo = change.invert(&delta); diff --git a/frontend/rust-lib/flowy-document/tests/editor/serde_test.rs b/frontend/rust-lib/flowy-document/tests/editor/serde_test.rs index 6efa0db6d1..5f634bce5e 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/serde_test.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/serde_test.rs @@ -4,14 +4,14 @@ use lib_ot::core::*; #[test] fn operation_insert_serialize_test() { let attributes = AttributeBuilder::new() - .add_attr(Attribute::Bold(true)) - .add_attr(Attribute::Italic(true)) + .add_attr(RichTextAttribute::Bold(true)) + .add_attr(RichTextAttribute::Italic(true)) .build(); let operation = OpBuilder::insert("123").attributes(attributes).build(); let json = serde_json::to_string(&operation).unwrap(); eprintln!("{}", json); - let insert_op: Operation = serde_json::from_str(&json).unwrap(); + let insert_op: RichTextOperation = serde_json::from_str(&json).unwrap(); assert_eq!(insert_op, operation); } @@ -20,23 +20,23 @@ fn operation_retain_serialize_test() { let operation = Operation::Retain(12.into()); let json = serde_json::to_string(&operation).unwrap(); eprintln!("{}", json); - let insert_op: Operation = serde_json::from_str(&json).unwrap(); + let insert_op: RichTextOperation = serde_json::from_str(&json).unwrap(); assert_eq!(insert_op, operation); } #[test] fn operation_delete_serialize_test() { - let operation = Operation::Delete(2); + let operation = RichTextOperation::Delete(2); let json = serde_json::to_string(&operation).unwrap(); - let insert_op: Operation = serde_json::from_str(&json).unwrap(); + let insert_op: RichTextOperation = serde_json::from_str(&json).unwrap(); assert_eq!(insert_op, operation); } #[test] fn attributes_serialize_test() { let attributes = AttributeBuilder::new() - .add_attr(Attribute::Bold(true)) - .add_attr(Attribute::Italic(true)) + .add_attr(RichTextAttribute::Bold(true)) + .add_attr(RichTextAttribute::Italic(true)) .build(); let retain = OpBuilder::insert("123").attributes(attributes).build(); @@ -49,8 +49,8 @@ fn delta_serialize_multi_attribute_test() { let mut delta = Delta::default(); let attributes = AttributeBuilder::new() - .add_attr(Attribute::Bold(true)) - .add_attr(Attribute::Italic(true)) + .add_attr(RichTextAttribute::Bold(true)) + .add_attr(RichTextAttribute::Italic(true)) .build(); let retain = OpBuilder::insert("123").attributes(attributes).build(); @@ -73,7 +73,7 @@ fn delta_deserialize_test() { {"retain":2,"attributes":{"italic":"true","bold":"true"}}, {"retain":2,"attributes":{"italic":true,"bold":true}} ]"#; - let delta = Delta::from_json(json).unwrap(); + let delta = RichTextDelta::from_json(json).unwrap(); eprintln!("{}", delta); } @@ -82,10 +82,10 @@ fn delta_deserialize_null_test() { let json = r#"[ {"retain":7,"attributes":{"bold":null}} ]"#; - let delta1 = Delta::from_json(json).unwrap(); + let delta1 = RichTextDelta::from_json(json).unwrap(); - let mut attribute = Attribute::Bold(true); - attribute.value = AttributeValue(None); + let mut attribute = RichTextAttribute::Bold(true); + attribute.value = RichTextAttributeValue(None); let delta2 = DeltaBuilder::new().retain_with_attributes(7, attribute.into()).build(); assert_eq!(delta2.to_json(), r#"[{"retain":7,"attributes":{"bold":""}}]"#); @@ -94,8 +94,8 @@ fn delta_deserialize_null_test() { #[test] fn delta_serde_null_test() { - let mut attribute = Attribute::Bold(true); - attribute.value = AttributeValue(None); + let mut attribute = RichTextAttribute::Bold(true); + attribute.value = RichTextAttributeValue(None); assert_eq!(attribute.to_json(), r#"{"bold":""}"#); } diff --git a/shared-lib/flowy-document-infra/src/core/document.rs b/shared-lib/flowy-document-infra/src/core/document.rs index dbd92488e9..31a8f40986 100644 --- a/shared-lib/flowy-document-infra/src/core/document.rs +++ b/shared-lib/flowy-document-infra/src/core/document.rs @@ -10,21 +10,21 @@ use lib_ot::core::*; use tokio::sync::mpsc; pub trait CustomDocument { - fn init_delta() -> Delta; + fn init_delta() -> RichTextDelta; } pub struct PlainDoc(); impl CustomDocument for PlainDoc { - fn init_delta() -> Delta { Delta::new() } + fn init_delta() -> RichTextDelta { RichTextDelta::new() } } pub struct FlowyDoc(); impl CustomDocument for FlowyDoc { - fn init_delta() -> Delta { doc_initial_delta() } + fn init_delta() -> RichTextDelta { doc_initial_delta() } } pub struct Document { - delta: Delta, + delta: RichTextDelta, history: History, view: View, last_edit_time: usize, @@ -34,7 +34,7 @@ pub struct Document { impl Document { pub fn new() -> Self { Self::from_delta(C::init_delta()) } - pub fn from_delta(delta: Delta) -> Self { + pub fn from_delta(delta: RichTextDelta) -> Self { Document { delta, history: History::new(), @@ -45,7 +45,7 @@ impl Document { } pub fn from_json(json: &str) -> Result { - let delta = Delta::from_json(json)?; + let delta = RichTextDelta::from_json(json)?; Ok(Self::from_delta(delta)) } @@ -55,11 +55,11 @@ impl Document { pub fn to_plain_string(&self) -> String { self.delta.apply("").unwrap() } - pub fn delta(&self) -> &Delta { &self.delta } + pub fn delta(&self) -> &RichTextDelta { &self.delta } pub fn set_notify(&mut self, notify: mpsc::UnboundedSender<()>) { self.notify = Some(notify); } - pub fn set_delta(&mut self, data: Delta) { + pub fn set_delta(&mut self, data: RichTextDelta) { self.delta = data; match &self.notify { @@ -70,7 +70,7 @@ impl Document { } } - pub fn compose_delta(&mut self, mut delta: Delta) -> Result<(), DocumentError> { + pub fn compose_delta(&mut self, mut delta: RichTextDelta) -> Result<(), DocumentError> { trim(&mut delta); tracing::trace!("{} compose {}", &self.delta.to_json(), delta.to_json()); let mut composed_delta = self.delta.compose(&delta)?; @@ -100,7 +100,7 @@ impl Document { Ok(()) } - pub fn insert(&mut self, index: usize, data: T) -> Result { + pub fn insert(&mut self, index: usize, data: T) -> Result { let interval = Interval::new(index, index); let _ = validate_interval(&self.delta, &interval)?; @@ -111,7 +111,7 @@ impl Document { Ok(delta) } - pub fn delete(&mut self, interval: Interval) -> Result { + pub fn delete(&mut self, interval: Interval) -> Result { let _ = validate_interval(&self.delta, &interval)?; debug_assert_eq!(interval.is_empty(), false); let delete = self.view.delete(&self.delta, interval)?; @@ -122,7 +122,7 @@ impl Document { Ok(delete) } - pub fn format(&mut self, interval: Interval, attribute: Attribute) -> Result { + pub fn format(&mut self, interval: Interval, attribute: RichTextAttribute) -> Result { let _ = validate_interval(&self.delta, &interval)?; tracing::trace!("format with {} at {}", attribute, interval); let format_delta = self.view.format(&self.delta, attribute, interval).unwrap(); @@ -132,9 +132,9 @@ impl Document { Ok(format_delta) } - pub fn replace(&mut self, interval: Interval, data: T) -> Result { + pub fn replace(&mut self, interval: Interval, data: T) -> Result { let _ = validate_interval(&self.delta, &interval)?; - let mut delta = Delta::default(); + let mut delta = RichTextDelta::default(); let text = data.to_string(); if !text.is_empty() { delta = self.view.insert(&self.delta, &text, interval)?; @@ -184,7 +184,7 @@ impl Document { } impl Document { - fn invert(&self, delta: &Delta) -> Result<(Delta, Delta), DocumentError> { + fn invert(&self, delta: &RichTextDelta) -> Result<(RichTextDelta, RichTextDelta), DocumentError> { // c = a.compose(b) // d = b.invert(a) // a = c.compose(d) @@ -195,7 +195,7 @@ impl Document { } } -fn validate_interval(delta: &Delta, interval: &Interval) -> Result<(), DocumentError> { +fn validate_interval(delta: &RichTextDelta, interval: &Interval) -> Result<(), DocumentError> { if delta.target_len < interval.end { log::error!("{:?} out of bounds. should 0..{}", interval, delta.target_len); return Err(DocumentError::out_of_bound()); @@ -204,7 +204,7 @@ fn validate_interval(delta: &Delta, interval: &Interval) -> Result<(), DocumentE } /// Removes trailing retain operation with empty attributes, if present. -pub fn trim(delta: &mut Delta) { +pub fn trim(delta: &mut RichTextDelta) { if let Some(last) = delta.ops.last() { if last.is_retain() && last.is_plain() { delta.ops.pop(); diff --git a/shared-lib/flowy-document-infra/src/core/extensions/delete/default_delete.rs b/shared-lib/flowy-document-infra/src/core/extensions/delete/default_delete.rs index 47674b906d..a96f8c5a34 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/delete/default_delete.rs +++ b/shared-lib/flowy-document-infra/src/core/extensions/delete/default_delete.rs @@ -1,11 +1,11 @@ use crate::core::extensions::DeleteExt; -use lib_ot::core::{Delta, DeltaBuilder, Interval}; +use lib_ot::core::{DeltaBuilder, Interval, RichTextDelta}; pub struct DefaultDelete {} impl DeleteExt for DefaultDelete { fn ext_name(&self) -> &str { "DefaultDelete" } - fn apply(&self, _delta: &Delta, interval: Interval) -> Option { + fn apply(&self, _delta: &RichTextDelta, interval: Interval) -> Option { Some( DeltaBuilder::new() .retain(interval.start) diff --git a/shared-lib/flowy-document-infra/src/core/extensions/delete/preserve_line_format_merge.rs b/shared-lib/flowy-document-infra/src/core/extensions/delete/preserve_line_format_merge.rs index cfabbd89e7..c49a40dfa5 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/delete/preserve_line_format_merge.rs +++ b/shared-lib/flowy-document-infra/src/core/extensions/delete/preserve_line_format_merge.rs @@ -1,11 +1,20 @@ use crate::{core::extensions::DeleteExt, util::is_newline}; -use lib_ot::core::{plain_attributes, CharMetric, Delta, DeltaBuilder, DeltaIter, Interval, NEW_LINE}; +use lib_ot::core::{ + plain_attributes, + Attributes, + CharMetric, + DeltaBuilder, + DeltaIter, + Interval, + RichTextDelta, + NEW_LINE, +}; pub struct PreserveLineFormatOnMerge {} impl DeleteExt for PreserveLineFormatOnMerge { fn ext_name(&self) -> &str { "PreserveLineFormatOnMerge" } - fn apply(&self, delta: &Delta, interval: Interval) -> Option { + fn apply(&self, delta: &RichTextDelta, interval: Interval) -> Option { if interval.is_empty() { return None; } @@ -40,7 +49,7 @@ impl DeleteExt for PreserveLineFormatOnMerge { attributes.mark_all_as_removed_except(None); if newline_op.has_attribute() { - attributes.extend(newline_op.get_attributes()); + attributes.extend_other(newline_op.get_attributes()); } new_delta.retain(line_break, plain_attributes()); diff --git a/shared-lib/flowy-document-infra/src/core/extensions/format/helper.rs b/shared-lib/flowy-document-infra/src/core/extensions/format/helper.rs index c4cac2efaa..1ecb3b3589 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/format/helper.rs +++ b/shared-lib/flowy-document-infra/src/core/extensions/format/helper.rs @@ -1,8 +1,12 @@ use crate::util::find_newline; -use lib_ot::core::{plain_attributes, Attribute, AttributeScope, Delta, Operation}; +use lib_ot::core::{plain_attributes, AttributeScope, RichTextAttribute, RichTextDelta, RichTextOperation}; -pub(crate) fn line_break(op: &Operation, attribute: &Attribute, scope: AttributeScope) -> Delta { - let mut new_delta = Delta::new(); +pub(crate) fn line_break( + op: &RichTextOperation, + attribute: &RichTextAttribute, + scope: AttributeScope, +) -> RichTextDelta { + let mut new_delta = RichTextDelta::new(); let mut start = 0; let end = op.len(); let mut s = op.get_data(); diff --git a/shared-lib/flowy-document-infra/src/core/extensions/format/resolve_block_format.rs b/shared-lib/flowy-document-infra/src/core/extensions/format/resolve_block_format.rs index 18c353fd77..0af20a1bac 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/format/resolve_block_format.rs +++ b/shared-lib/flowy-document-infra/src/core/extensions/format/resolve_block_format.rs @@ -2,13 +2,21 @@ use crate::{ core::extensions::{format::helper::line_break, FormatExt}, util::find_newline, }; -use lib_ot::core::{plain_attributes, Attribute, AttributeScope, Delta, DeltaBuilder, DeltaIter, Interval}; +use lib_ot::core::{ + plain_attributes, + AttributeScope, + DeltaBuilder, + DeltaIter, + Interval, + RichTextAttribute, + RichTextDelta, +}; pub struct ResolveBlockFormat {} impl FormatExt for ResolveBlockFormat { fn ext_name(&self) -> &str { std::any::type_name::() } - fn apply(&self, delta: &Delta, interval: Interval, attribute: &Attribute) -> Option { + fn apply(&self, delta: &RichTextDelta, interval: Interval, attribute: &RichTextAttribute) -> Option { if attribute.scope != AttributeScope::Block { return None; } diff --git a/shared-lib/flowy-document-infra/src/core/extensions/format/resolve_inline_format.rs b/shared-lib/flowy-document-infra/src/core/extensions/format/resolve_inline_format.rs index 3bb03467cf..e85839104c 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/format/resolve_inline_format.rs +++ b/shared-lib/flowy-document-infra/src/core/extensions/format/resolve_inline_format.rs @@ -2,13 +2,13 @@ use crate::{ core::extensions::{format::helper::line_break, FormatExt}, util::find_newline, }; -use lib_ot::core::{Attribute, AttributeScope, Delta, DeltaBuilder, DeltaIter, Interval}; +use lib_ot::core::{AttributeScope, DeltaBuilder, DeltaIter, Interval, RichTextAttribute, RichTextDelta}; pub struct ResolveInlineFormat {} impl FormatExt for ResolveInlineFormat { fn ext_name(&self) -> &str { std::any::type_name::() } - fn apply(&self, delta: &Delta, interval: Interval, attribute: &Attribute) -> Option { + fn apply(&self, delta: &RichTextDelta, interval: Interval, attribute: &RichTextAttribute) -> Option { if attribute.scope != AttributeScope::Inline { return None; } diff --git a/shared-lib/flowy-document-infra/src/core/extensions/insert/auto_exit_block.rs b/shared-lib/flowy-document-infra/src/core/extensions/insert/auto_exit_block.rs index d2d331635c..d440cd8060 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/insert/auto_exit_block.rs +++ b/shared-lib/flowy-document-infra/src/core/extensions/insert/auto_exit_block.rs @@ -1,12 +1,19 @@ use crate::{core::extensions::InsertExt, util::is_newline}; -use lib_ot::core::{attributes_except_header, is_empty_line_at_index, AttributeKey, Delta, DeltaBuilder, DeltaIter}; +use lib_ot::core::{ + attributes_except_header, + is_empty_line_at_index, + DeltaBuilder, + DeltaIter, + RichTextAttributeKey, + RichTextDelta, +}; pub struct AutoExitBlock {} impl InsertExt for AutoExitBlock { fn ext_name(&self) -> &str { std::any::type_name::() } - fn apply(&self, delta: &Delta, replace_len: usize, text: &str, index: usize) -> Option { + fn apply(&self, delta: &RichTextDelta, replace_len: usize, text: &str, index: usize) -> Option { // Auto exit block will be triggered by enter two new lines if !is_newline(text) { return None; @@ -39,7 +46,7 @@ impl InsertExt for AutoExitBlock { }, } - attributes.mark_all_as_removed_except(Some(AttributeKey::Header)); + attributes.mark_all_as_removed_except(Some(RichTextAttributeKey::Header)); Some( DeltaBuilder::new() diff --git a/shared-lib/flowy-document-infra/src/core/extensions/insert/auto_format.rs b/shared-lib/flowy-document-infra/src/core/extensions/insert/auto_format.rs index fe814f27ee..5f517a43c5 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/insert/auto_format.rs +++ b/shared-lib/flowy-document-infra/src/core/extensions/insert/auto_format.rs @@ -1,5 +1,13 @@ use crate::{core::extensions::InsertExt, util::is_whitespace}; -use lib_ot::core::{count_utf16_code_units, plain_attributes, Attribute, Attributes, Delta, DeltaBuilder, DeltaIter}; +use lib_ot::core::{ + count_utf16_code_units, + plain_attributes, + DeltaBuilder, + DeltaIter, + RichTextAttribute, + RichTextAttributes, + RichTextDelta, +}; use std::cmp::min; use url::Url; @@ -7,7 +15,7 @@ pub struct AutoFormatExt {} impl InsertExt for AutoFormatExt { fn ext_name(&self) -> &str { std::any::type_name::() } - fn apply(&self, delta: &Delta, replace_len: usize, text: &str, index: usize) -> Option { + fn apply(&self, delta: &RichTextDelta, replace_len: usize, text: &str, index: usize) -> Option { // enter whitespace to trigger auto format if !is_whitespace(text) { return None; @@ -55,9 +63,9 @@ pub enum AutoFormatter { } impl AutoFormatter { - pub fn to_attributes(&self) -> Attributes { + pub fn to_attributes(&self) -> RichTextAttributes { match self { - AutoFormatter::Url(url) => Attribute::Link(url.as_str()).into(), + AutoFormatter::Url(url) => RichTextAttribute::Link(url.as_str()).into(), } } diff --git a/shared-lib/flowy-document-infra/src/core/extensions/insert/default_insert.rs b/shared-lib/flowy-document-infra/src/core/extensions/insert/default_insert.rs index 5fd207e383..76f31d84e2 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/insert/default_insert.rs +++ b/shared-lib/flowy-document-infra/src/core/extensions/insert/default_insert.rs @@ -1,13 +1,21 @@ use crate::core::extensions::InsertExt; -use lib_ot::core::{AttributeKey, Attributes, Delta, DeltaBuilder, DeltaIter, NEW_LINE}; +use lib_ot::core::{ + Attributes, + DeltaBuilder, + DeltaIter, + RichTextAttributeKey, + RichTextAttributes, + RichTextDelta, + NEW_LINE, +}; pub struct DefaultInsertAttribute {} impl InsertExt for DefaultInsertAttribute { fn ext_name(&self) -> &str { std::any::type_name::() } - fn apply(&self, delta: &Delta, replace_len: usize, text: &str, index: usize) -> Option { + fn apply(&self, delta: &RichTextDelta, replace_len: usize, text: &str, index: usize) -> Option { let iter = DeltaIter::new(delta); - let mut attributes = Attributes::new(); + let mut attributes = RichTextAttributes::new(); // Enable each line split by "\n" remains the block attributes. for example: // insert "\n" to "123456" at index 3 @@ -18,8 +26,8 @@ impl InsertExt for DefaultInsertAttribute { match iter.last() { None => {}, Some(op) => { - if op.get_attributes().contains_key(&AttributeKey::Header) { - attributes.extend(op.get_attributes()); + if op.get_attributes().contains_key(&RichTextAttributeKey::Header) { + attributes.extend_other(op.get_attributes()); } }, } diff --git a/shared-lib/flowy-document-infra/src/core/extensions/insert/mod.rs b/shared-lib/flowy-document-infra/src/core/extensions/insert/mod.rs index b70105e6bf..fe8e167915 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/insert/mod.rs +++ b/shared-lib/flowy-document-infra/src/core/extensions/insert/mod.rs @@ -2,7 +2,7 @@ use crate::core::extensions::InsertExt; pub use auto_exit_block::*; pub use auto_format::*; pub use default_insert::*; -use lib_ot::core::Delta; +use lib_ot::core::RichTextDelta; pub use preserve_block_format::*; pub use preserve_inline_format::*; pub use reset_format_on_new_line::*; @@ -18,12 +18,16 @@ pub struct InsertEmbedsExt {} impl InsertExt for InsertEmbedsExt { fn ext_name(&self) -> &str { "InsertEmbedsExt" } - fn apply(&self, _delta: &Delta, _replace_len: usize, _text: &str, _index: usize) -> Option { None } + fn apply(&self, _delta: &RichTextDelta, _replace_len: usize, _text: &str, _index: usize) -> Option { + None + } } pub struct ForceNewlineForInsertsAroundEmbedExt {} impl InsertExt for ForceNewlineForInsertsAroundEmbedExt { fn ext_name(&self) -> &str { "ForceNewlineForInsertsAroundEmbedExt" } - fn apply(&self, _delta: &Delta, _replace_len: usize, _text: &str, _index: usize) -> Option { None } + fn apply(&self, _delta: &RichTextDelta, _replace_len: usize, _text: &str, _index: usize) -> Option { + None + } } diff --git a/shared-lib/flowy-document-infra/src/core/extensions/insert/preserve_block_format.rs b/shared-lib/flowy-document-infra/src/core/extensions/insert/preserve_block_format.rs index 0d29210ae0..671b1bbe74 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/insert/preserve_block_format.rs +++ b/shared-lib/flowy-document-infra/src/core/extensions/insert/preserve_block_format.rs @@ -2,12 +2,12 @@ use crate::{core::extensions::InsertExt, util::is_newline}; use lib_ot::core::{ attributes_except_header, plain_attributes, - Attribute, - AttributeKey, - Attributes, - Delta, DeltaBuilder, DeltaIter, + RichTextAttribute, + RichTextAttributeKey, + RichTextAttributes, + RichTextDelta, NEW_LINE, }; @@ -15,7 +15,7 @@ pub struct PreserveBlockFormatOnInsert {} impl InsertExt for PreserveBlockFormatOnInsert { fn ext_name(&self) -> &str { std::any::type_name::() } - fn apply(&self, delta: &Delta, replace_len: usize, text: &str, index: usize) -> Option { + fn apply(&self, delta: &RichTextDelta, replace_len: usize, text: &str, index: usize) -> Option { if !is_newline(text) { return None; } @@ -30,9 +30,9 @@ impl InsertExt for PreserveBlockFormatOnInsert { return None; } - let mut reset_attribute = Attributes::new(); - if newline_attributes.contains_key(&AttributeKey::Header) { - reset_attribute.add(Attribute::Header(1)); + let mut reset_attribute = RichTextAttributes::new(); + if newline_attributes.contains_key(&RichTextAttributeKey::Header) { + reset_attribute.add(RichTextAttribute::Header(1)); } let lines: Vec<_> = text.split(NEW_LINE).collect(); diff --git a/shared-lib/flowy-document-infra/src/core/extensions/insert/preserve_inline_format.rs b/shared-lib/flowy-document-infra/src/core/extensions/insert/preserve_inline_format.rs index aa72fa4302..11b4e188fc 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/insert/preserve_inline_format.rs +++ b/shared-lib/flowy-document-infra/src/core/extensions/insert/preserve_inline_format.rs @@ -2,13 +2,21 @@ use crate::{ core::extensions::InsertExt, util::{contain_newline, is_newline}, }; -use lib_ot::core::{plain_attributes, AttributeKey, Delta, DeltaBuilder, DeltaIter, OpNewline, NEW_LINE}; +use lib_ot::core::{ + plain_attributes, + DeltaBuilder, + DeltaIter, + OpNewline, + RichTextAttributeKey, + RichTextDelta, + NEW_LINE, +}; pub struct PreserveInlineFormat {} impl InsertExt for PreserveInlineFormat { fn ext_name(&self) -> &str { std::any::type_name::() } - fn apply(&self, delta: &Delta, replace_len: usize, text: &str, index: usize) -> Option { + fn apply(&self, delta: &RichTextDelta, replace_len: usize, text: &str, index: usize) -> Option { if contain_newline(text) { return None; } @@ -20,7 +28,7 @@ impl InsertExt for PreserveInlineFormat { } let mut attributes = prev.get_attributes(); - if attributes.is_empty() || !attributes.contains_key(&AttributeKey::Link) { + if attributes.is_empty() || !attributes.contains_key(&RichTextAttributeKey::Link) { return Some( DeltaBuilder::new() .retain(index + replace_len) @@ -52,7 +60,7 @@ pub struct PreserveLineFormatOnSplit {} impl InsertExt for PreserveLineFormatOnSplit { fn ext_name(&self) -> &str { std::any::type_name::() } - fn apply(&self, delta: &Delta, replace_len: usize, text: &str, index: usize) -> Option { + fn apply(&self, delta: &RichTextDelta, replace_len: usize, text: &str, index: usize) -> Option { if !is_newline(text) { return None; } @@ -69,7 +77,7 @@ impl InsertExt for PreserveLineFormatOnSplit { return None; } - let mut new_delta = Delta::new(); + let mut new_delta = RichTextDelta::new(); new_delta.retain(index + replace_len, plain_attributes()); if newline_status.is_contain() { diff --git a/shared-lib/flowy-document-infra/src/core/extensions/insert/reset_format_on_new_line.rs b/shared-lib/flowy-document-infra/src/core/extensions/insert/reset_format_on_new_line.rs index 0e1699a814..d1abaf3179 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/insert/reset_format_on_new_line.rs +++ b/shared-lib/flowy-document-infra/src/core/extensions/insert/reset_format_on_new_line.rs @@ -1,11 +1,19 @@ use crate::{core::extensions::InsertExt, util::is_newline}; -use lib_ot::core::{AttributeKey, Attributes, CharMetric, Delta, DeltaBuilder, DeltaIter, NEW_LINE}; +use lib_ot::core::{ + CharMetric, + DeltaBuilder, + DeltaIter, + RichTextAttributeKey, + RichTextAttributes, + RichTextDelta, + NEW_LINE, +}; pub struct ResetLineFormatOnNewLine {} impl InsertExt for ResetLineFormatOnNewLine { fn ext_name(&self) -> &str { std::any::type_name::() } - fn apply(&self, delta: &Delta, replace_len: usize, text: &str, index: usize) -> Option { + fn apply(&self, delta: &RichTextDelta, replace_len: usize, text: &str, index: usize) -> Option { if !is_newline(text) { return None; } @@ -17,9 +25,9 @@ impl InsertExt for ResetLineFormatOnNewLine { return None; } - let mut reset_attribute = Attributes::new(); - if next_op.get_attributes().contains_key(&AttributeKey::Header) { - reset_attribute.delete(&AttributeKey::Header); + let mut reset_attribute = RichTextAttributes::new(); + if next_op.get_attributes().contains_key(&RichTextAttributeKey::Header) { + reset_attribute.delete(&RichTextAttributeKey::Header); } let len = index + replace_len; diff --git a/shared-lib/flowy-document-infra/src/core/extensions/mod.rs b/shared-lib/flowy-document-infra/src/core/extensions/mod.rs index 584dee2d68..31f8b1189c 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/mod.rs +++ b/shared-lib/flowy-document-infra/src/core/extensions/mod.rs @@ -2,7 +2,7 @@ pub use delete::*; pub use format::*; pub use insert::*; -use lib_ot::core::{Attribute, Delta, Interval}; +use lib_ot::core::{Interval, RichTextAttribute, RichTextDelta}; mod delete; mod format; @@ -14,15 +14,15 @@ pub type DeleteExtension = Box; pub trait InsertExt { fn ext_name(&self) -> &str; - fn apply(&self, delta: &Delta, replace_len: usize, text: &str, index: usize) -> Option; + fn apply(&self, delta: &RichTextDelta, replace_len: usize, text: &str, index: usize) -> Option; } pub trait FormatExt { fn ext_name(&self) -> &str; - fn apply(&self, delta: &Delta, interval: Interval, attribute: &Attribute) -> Option; + fn apply(&self, delta: &RichTextDelta, interval: Interval, attribute: &RichTextAttribute) -> Option; } pub trait DeleteExt { fn ext_name(&self) -> &str; - fn apply(&self, delta: &Delta, interval: Interval) -> Option; + fn apply(&self, delta: &RichTextDelta, interval: Interval) -> Option; } diff --git a/shared-lib/flowy-document-infra/src/core/history.rs b/shared-lib/flowy-document-infra/src/core/history.rs index aa76493c81..82c411b109 100644 --- a/shared-lib/flowy-document-infra/src/core/history.rs +++ b/shared-lib/flowy-document-infra/src/core/history.rs @@ -1,4 +1,4 @@ -use lib_ot::core::Delta; +use lib_ot::core::RichTextDelta; const MAX_UNDOS: usize = 20; @@ -21,8 +21,8 @@ impl UndoResult { pub struct History { #[allow(dead_code)] cur_undo: usize, - undos: Vec, - redoes: Vec, + undos: Vec, + redoes: Vec, capacity: usize, } @@ -44,11 +44,11 @@ impl History { pub fn can_redo(&self) -> bool { !self.redoes.is_empty() } - pub fn add_undo(&mut self, delta: Delta) { self.undos.push(delta); } + pub fn add_undo(&mut self, delta: RichTextDelta) { self.undos.push(delta); } - pub fn add_redo(&mut self, delta: Delta) { self.redoes.push(delta); } + pub fn add_redo(&mut self, delta: RichTextDelta) { self.redoes.push(delta); } - pub fn record(&mut self, delta: Delta) { + pub fn record(&mut self, delta: RichTextDelta) { if delta.ops.is_empty() { return; } @@ -61,7 +61,7 @@ impl History { } } - pub fn undo(&mut self) -> Option { + pub fn undo(&mut self) -> Option { if !self.can_undo() { return None; } @@ -69,7 +69,7 @@ impl History { Some(delta) } - pub fn redo(&mut self) -> Option { + pub fn redo(&mut self) -> Option { if !self.can_redo() { return None; } diff --git a/shared-lib/flowy-document-infra/src/core/view.rs b/shared-lib/flowy-document-infra/src/core/view.rs index 984b461169..cd2d61c73e 100644 --- a/shared-lib/flowy-document-infra/src/core/view.rs +++ b/shared-lib/flowy-document-infra/src/core/view.rs @@ -1,6 +1,6 @@ use crate::core::extensions::*; use lib_ot::{ - core::{trim, Attribute, Delta, Interval}, + core::{trim, Interval, RichTextAttribute, RichTextDelta}, errors::{ErrorBuilder, OTError, OTErrorCode}, }; @@ -21,7 +21,12 @@ impl View { } } - pub(crate) fn insert(&self, delta: &Delta, text: &str, interval: Interval) -> Result { + pub(crate) fn insert( + &self, + delta: &RichTextDelta, + text: &str, + interval: Interval, + ) -> Result { let mut new_delta = None; for ext in &self.insert_exts { if let Some(mut delta) = ext.apply(delta, interval.size(), text, interval.start) { @@ -38,7 +43,7 @@ impl View { } } - pub(crate) fn delete(&self, delta: &Delta, interval: Interval) -> Result { + pub(crate) fn delete(&self, delta: &RichTextDelta, interval: Interval) -> Result { let mut new_delta = None; for ext in &self.delete_exts { if let Some(mut delta) = ext.apply(delta, interval) { @@ -55,7 +60,12 @@ impl View { } } - pub(crate) fn format(&self, delta: &Delta, attribute: Attribute, interval: Interval) -> Result { + pub(crate) fn format( + &self, + delta: &RichTextDelta, + attribute: RichTextAttribute, + interval: Interval, + ) -> Result { let mut new_delta = None; for ext in &self.format_exts { if let Some(mut delta) = ext.apply(delta, interval, &attribute) { diff --git a/shared-lib/flowy-document-infra/src/entities/doc/doc.rs b/shared-lib/flowy-document-infra/src/entities/doc/doc.rs index 3502f81768..90b4c73056 100644 --- a/shared-lib/flowy-document-infra/src/entities/doc/doc.rs +++ b/shared-lib/flowy-document-infra/src/entities/doc/doc.rs @@ -1,5 +1,5 @@ use flowy_derive::ProtoBuf; -use lib_ot::{core::Delta, errors::OTError}; +use lib_ot::{core::RichTextDelta, errors::OTError}; #[derive(ProtoBuf, Default, Debug, Clone)] pub struct CreateDocParams { @@ -35,8 +35,8 @@ pub struct Doc { } impl Doc { - pub fn delta(&self) -> Result { - let delta = Delta::from_bytes(&self.data)?; + pub fn delta(&self) -> Result { + let delta = RichTextDelta::from_bytes(&self.data)?; Ok(delta) } } @@ -59,7 +59,7 @@ pub struct DocDelta { pub doc_id: String, #[pb(index = 2)] - pub data: String, // Delta + pub data: String, // RichTextDelta } #[derive(ProtoBuf, Default, Debug, Clone)] diff --git a/shared-lib/flowy-document-infra/src/entities/doc/revision.rs b/shared-lib/flowy-document-infra/src/entities/doc/revision.rs index 0fdc6b871c..ba4a68d86d 100644 --- a/shared-lib/flowy-document-infra/src/entities/doc/revision.rs +++ b/shared-lib/flowy-document-infra/src/entities/doc/revision.rs @@ -1,6 +1,6 @@ use crate::{entities::doc::Doc, util::md5}; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; -use lib_ot::core::Delta; +use lib_ot::core::RichTextDelta; use std::{fmt::Formatter, ops::RangeInclusive}; #[derive(Debug, ProtoBuf_Enum, Clone, Eq, PartialEq)] @@ -87,7 +87,7 @@ impl std::fmt::Debug for Revision { let _ = f.write_fmt(format_args!("doc_id {}, ", self.doc_id))?; let _ = f.write_fmt(format_args!("base_rev_id {}, ", self.base_rev_id))?; let _ = f.write_fmt(format_args!("rev_id {}, ", self.rev_id))?; - match Delta::from_bytes(&self.delta_data) { + match RichTextDelta::from_bytes(&self.delta_data) { Ok(delta) => { let _ = f.write_fmt(format_args!("delta {:?}", delta.to_json()))?; }, diff --git a/shared-lib/flowy-document-infra/src/user_default.rs b/shared-lib/flowy-document-infra/src/user_default.rs index a40e302ed4..91cf28321d 100644 --- a/shared-lib/flowy-document-infra/src/user_default.rs +++ b/shared-lib/flowy-document-infra/src/user_default.rs @@ -1,15 +1,15 @@ -use lib_ot::core::{Delta, DeltaBuilder}; +use lib_ot::core::{DeltaBuilder, RichTextDelta}; #[inline] -pub fn doc_initial_delta() -> Delta { DeltaBuilder::new().insert("\n").build() } +pub fn doc_initial_delta() -> RichTextDelta { DeltaBuilder::new().insert("\n").build() } #[inline] pub fn doc_initial_string() -> String { doc_initial_delta().to_json() } #[inline] -pub fn initial_read_me() -> Delta { +pub fn initial_read_me() -> RichTextDelta { let json = include_str!("READ_ME.json"); - Delta::from_json(json).unwrap() + RichTextDelta::from_json(json).unwrap() } #[cfg(test)] diff --git a/shared-lib/lib-ot/src/core/attributes/attribute.rs b/shared-lib/lib-ot/src/core/attributes/attribute.rs index 631af478aa..45fe5fbec9 100644 --- a/shared-lib/lib-ot/src/core/attributes/attribute.rs +++ b/shared-lib/lib-ot/src/core/attributes/attribute.rs @@ -1,19 +1,19 @@ #![allow(non_snake_case)] -use crate::{block_attribute, core::Attributes, ignore_attribute, inline_attribute, list_attribute}; +use crate::{block_attribute, core::RichTextAttributes, ignore_attribute, inline_attribute, list_attribute}; use lazy_static::lazy_static; use std::{collections::HashSet, fmt, fmt::Formatter, iter::FromIterator}; use strum_macros::Display; #[derive(Debug, Clone)] -pub struct Attribute { - pub key: AttributeKey, - pub value: AttributeValue, +pub struct RichTextAttribute { + pub key: RichTextAttributeKey, + pub value: RichTextAttributeValue, pub scope: AttributeScope, } -impl Attribute { +impl RichTextAttribute { // inline inline_attribute!(Bold, bool); inline_attribute!(Italic, bool); @@ -55,16 +55,16 @@ impl Attribute { } } -impl fmt::Display for Attribute { +impl fmt::Display for RichTextAttribute { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let s = format!("{:?}:{:?} {:?}", self.key, self.value.0, self.scope); f.write_str(&s) } } -impl std::convert::From for Attributes { - fn from(attr: Attribute) -> Self { - let mut attributes = Attributes::new(); +impl std::convert::From for RichTextAttributes { + fn from(attr: RichTextAttribute) -> Self { + let mut attributes = RichTextAttributes::new(); attributes.add(attr); attributes } @@ -73,7 +73,7 @@ impl std::convert::From for Attributes { #[derive(Clone, Debug, Display, Hash, Eq, PartialEq, serde::Serialize, serde::Deserialize)] // serde.rs/variant-attrs.html // #[serde(rename_all = "snake_case")] -pub enum AttributeKey { +pub enum RichTextAttributeKey { #[serde(rename = "bold")] Bold, #[serde(rename = "italic")] @@ -114,80 +114,80 @@ pub enum AttributeKey { // pub trait AttributeValueData<'a>: Serialize + Deserialize<'a> {} #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct AttributeValue(pub Option); +pub struct RichTextAttributeValue(pub Option); -impl std::convert::From<&usize> for AttributeValue { - fn from(val: &usize) -> Self { AttributeValue::from(*val) } +impl std::convert::From<&usize> for RichTextAttributeValue { + fn from(val: &usize) -> Self { RichTextAttributeValue::from(*val) } } -impl std::convert::From for AttributeValue { +impl std::convert::From for RichTextAttributeValue { fn from(val: usize) -> Self { if val > 0_usize { - AttributeValue(Some(format!("{}", val))) + RichTextAttributeValue(Some(format!("{}", val))) } else { - AttributeValue(None) + RichTextAttributeValue(None) } } } -impl std::convert::From<&str> for AttributeValue { +impl std::convert::From<&str> for RichTextAttributeValue { fn from(val: &str) -> Self { val.to_owned().into() } } -impl std::convert::From for AttributeValue { +impl std::convert::From for RichTextAttributeValue { fn from(val: String) -> Self { if val.is_empty() { - AttributeValue(None) + RichTextAttributeValue(None) } else { - AttributeValue(Some(val)) + RichTextAttributeValue(Some(val)) } } } -impl std::convert::From<&bool> for AttributeValue { - fn from(val: &bool) -> Self { AttributeValue::from(*val) } +impl std::convert::From<&bool> for RichTextAttributeValue { + fn from(val: &bool) -> Self { RichTextAttributeValue::from(*val) } } -impl std::convert::From for AttributeValue { +impl std::convert::From for RichTextAttributeValue { fn from(val: bool) -> Self { let val = match val { true => Some("true".to_owned()), false => None, }; - AttributeValue(val) + RichTextAttributeValue(val) } } -pub fn is_block_except_header(k: &AttributeKey) -> bool { - if k == &AttributeKey::Header { +pub fn is_block_except_header(k: &RichTextAttributeKey) -> bool { + if k == &RichTextAttributeKey::Header { return false; } BLOCK_KEYS.contains(k) } lazy_static! { - static ref BLOCK_KEYS: HashSet = HashSet::from_iter(vec![ - AttributeKey::Header, - AttributeKey::Indent, - AttributeKey::Align, - AttributeKey::CodeBlock, - AttributeKey::List, - AttributeKey::BlockQuote, + static ref BLOCK_KEYS: HashSet = HashSet::from_iter(vec![ + RichTextAttributeKey::Header, + RichTextAttributeKey::Indent, + RichTextAttributeKey::Align, + RichTextAttributeKey::CodeBlock, + RichTextAttributeKey::List, + RichTextAttributeKey::BlockQuote, ]); - static ref INLINE_KEYS: HashSet = HashSet::from_iter(vec![ - AttributeKey::Bold, - AttributeKey::Italic, - AttributeKey::Underline, - AttributeKey::StrikeThrough, - AttributeKey::Link, - AttributeKey::Color, - AttributeKey::Font, - AttributeKey::Size, - AttributeKey::Background, - AttributeKey::InlineCode, + static ref INLINE_KEYS: HashSet = HashSet::from_iter(vec![ + RichTextAttributeKey::Bold, + RichTextAttributeKey::Italic, + RichTextAttributeKey::Underline, + RichTextAttributeKey::StrikeThrough, + RichTextAttributeKey::Link, + RichTextAttributeKey::Color, + RichTextAttributeKey::Font, + RichTextAttributeKey::Size, + RichTextAttributeKey::Background, + RichTextAttributeKey::InlineCode, ]); - static ref INGORE_KEYS: HashSet = - HashSet::from_iter(vec![AttributeKey::Width, AttributeKey::Height,]); + static ref INGORE_KEYS: HashSet = + HashSet::from_iter(vec![RichTextAttributeKey::Width, RichTextAttributeKey::Height,]); } #[derive(Debug, PartialEq, Eq, Clone)] diff --git a/shared-lib/lib-ot/src/core/attributes/attributes.rs b/shared-lib/lib-ot/src/core/attributes/attributes.rs index 2046ed0766..c52c4a7898 100644 --- a/shared-lib/lib-ot/src/core/attributes/attributes.rs +++ b/shared-lib/lib-ot/src/core/attributes/attributes.rs @@ -1,15 +1,22 @@ use crate::{ - core::{Attribute, AttributeKey, AttributeValue, Operation, OperationTransformable}, + core::{ + Attributes, + OperationTransformable, + RichTextAttribute, + RichTextAttributeKey, + RichTextAttributeValue, + RichTextOperation, + }, errors::OTError, }; use std::{collections::HashMap, fmt}; #[derive(Debug, Clone, Eq, PartialEq)] -pub struct Attributes { - pub(crate) inner: HashMap, +pub struct RichTextAttributes { + pub(crate) inner: HashMap, } -impl std::default::Default for Attributes { +impl std::default::Default for RichTextAttributes { fn default() -> Self { Self { inner: HashMap::with_capacity(0), @@ -17,27 +24,31 @@ impl std::default::Default for Attributes { } } -impl fmt::Display for Attributes { +impl fmt::Display for RichTextAttributes { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_fmt(format_args!("{:?}", self.inner)) } } -pub fn plain_attributes() -> Attributes { Attributes::default() } +pub fn plain_attributes() -> RichTextAttributes { RichTextAttributes::default() } -impl Attributes { - pub fn new() -> Self { Attributes { inner: HashMap::new() } } +impl RichTextAttributes { + pub fn new() -> Self { RichTextAttributes { inner: HashMap::new() } } pub fn is_empty(&self) -> bool { self.inner.is_empty() } - pub fn add(&mut self, attribute: Attribute) { - let Attribute { key, value, scope: _ } = attribute; + pub fn add(&mut self, attribute: RichTextAttribute) { + let RichTextAttribute { key, value, scope: _ } = attribute; self.inner.insert(key, value); } - pub fn add_kv(&mut self, key: AttributeKey, value: AttributeValue) { self.inner.insert(key, value); } + pub fn add_kv(&mut self, key: RichTextAttributeKey, value: RichTextAttributeValue) { + self.inner.insert(key, value); + } - pub fn delete(&mut self, key: &AttributeKey) { self.inner.insert(key.clone(), AttributeValue(None)); } + pub fn delete(&mut self, key: &RichTextAttributeKey) { + self.inner.insert(key.clone(), RichTextAttributeValue(None)); + } - pub fn mark_all_as_removed_except(&mut self, attribute: Option) { + pub fn mark_all_as_removed_except(&mut self, attribute: Option) { match attribute { None => { self.inner.iter_mut().for_each(|(_k, v)| v.0 = None); @@ -52,7 +63,7 @@ impl Attributes { } } - pub fn remove(&mut self, key: AttributeKey) { self.inner.retain(|k, _| k != &key); } + pub fn remove(&mut self, key: RichTextAttributeKey) { self.inner.retain(|k, _| k != &key); } // pub fn block_attributes_except_header(attributes: &Attributes) -> Attributes // { let mut new_attributes = Attributes::new(); @@ -65,14 +76,9 @@ impl Attributes { // new_attributes // } - // Remove the empty attribute which value is None. - pub fn remove_empty(&mut self) { self.inner.retain(|_, v| v.0.is_some()); } - - pub fn extend(&mut self, other: Attributes) { self.inner.extend(other.inner); } - // Update inner by constructing new attributes from the other if it's // not None and replace the key/value with self key/value. - pub fn merge(&mut self, other: Option) { + pub fn merge(&mut self, other: Option) { if other.is_none() { return; } @@ -85,13 +91,21 @@ impl Attributes { } } -impl OperationTransformable for Attributes { +impl Attributes for RichTextAttributes { + fn is_empty(&self) -> bool { self.inner.is_empty() } + + fn remove_empty(&mut self) { self.inner.retain(|_, v| v.0.is_some()); } + + fn extend_other(&mut self, other: Self) { self.inner.extend(other.inner); } +} + +impl OperationTransformable for RichTextAttributes { fn compose(&self, other: &Self) -> Result where Self: Sized, { let mut attributes = self.clone(); - attributes.extend(other.clone()); + attributes.extend_other(other.clone()); Ok(attributes) } @@ -99,25 +113,29 @@ impl OperationTransformable for Attributes { where Self: Sized, { - let a = self.iter().fold(Attributes::new(), |mut new_attributes, (k, v)| { - if !other.contains_key(k) { - new_attributes.insert(k.clone(), v.clone()); - } - new_attributes - }); + let a = self + .iter() + .fold(RichTextAttributes::new(), |mut new_attributes, (k, v)| { + if !other.contains_key(k) { + new_attributes.insert(k.clone(), v.clone()); + } + new_attributes + }); - let b = other.iter().fold(Attributes::new(), |mut new_attributes, (k, v)| { - if !self.contains_key(k) { - new_attributes.insert(k.clone(), v.clone()); - } - new_attributes - }); + let b = other + .iter() + .fold(RichTextAttributes::new(), |mut new_attributes, (k, v)| { + if !self.contains_key(k) { + new_attributes.insert(k.clone(), v.clone()); + } + new_attributes + }); Ok((a, b)) } fn invert(&self, other: &Self) -> Self { - let base_inverted = other.iter().fold(Attributes::new(), |mut attributes, (k, v)| { + let base_inverted = other.iter().fold(RichTextAttributes::new(), |mut attributes, (k, v)| { if other.get(k) != self.get(k) && self.contains_key(k) { attributes.insert(k.clone(), v.clone()); } @@ -135,18 +153,18 @@ impl OperationTransformable for Attributes { } } -impl std::ops::Deref for Attributes { - type Target = HashMap; +impl std::ops::Deref for RichTextAttributes { + type Target = HashMap; fn deref(&self) -> &Self::Target { &self.inner } } -impl std::ops::DerefMut for Attributes { +impl std::ops::DerefMut for RichTextAttributes { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner } } -pub fn attributes_except_header(op: &Operation) -> Attributes { +pub fn attributes_except_header(op: &RichTextOperation) -> RichTextAttributes { let mut attributes = op.get_attributes(); - attributes.remove(AttributeKey::Header); + attributes.remove(RichTextAttributeKey::Header); attributes } diff --git a/shared-lib/lib-ot/src/core/attributes/attributes_serde.rs b/shared-lib/lib-ot/src/core/attributes/attributes_serde.rs index c3e911bbc1..5552297b72 100644 --- a/shared-lib/lib-ot/src/core/attributes/attributes_serde.rs +++ b/shared-lib/lib-ot/src/core/attributes/attributes_serde.rs @@ -1,6 +1,6 @@ #[rustfmt::skip] -use crate::core::AttributeValue; -use crate::core::{Attribute, AttributeKey, Attributes}; +use crate::core::RichTextAttributeValue; +use crate::core::{RichTextAttribute, RichTextAttributeKey, RichTextAttributes}; use serde::{ de, de::{MapAccess, Visitor}, @@ -12,7 +12,7 @@ use serde::{ }; use std::fmt; -impl Serialize for Attribute { +impl Serialize for RichTextAttribute { fn serialize(&self, serializer: S) -> Result<::Ok, ::Error> where S: Serializer, @@ -23,7 +23,7 @@ impl Serialize for Attribute { } } -impl Serialize for Attributes { +impl Serialize for RichTextAttributes { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -40,39 +40,43 @@ impl Serialize for Attributes { } } -fn serial_attribute(map_serializer: &mut S, key: &AttributeKey, value: &AttributeValue) -> Result<(), E> +fn serial_attribute( + map_serializer: &mut S, + key: &RichTextAttributeKey, + value: &RichTextAttributeValue, +) -> Result<(), E> where S: SerializeMap, E: From<::Error>, { if let Some(v) = &value.0 { match key { - AttributeKey::Bold - | AttributeKey::Italic - | AttributeKey::Underline - | AttributeKey::StrikeThrough - | AttributeKey::CodeBlock - | AttributeKey::InlineCode - | AttributeKey::BlockQuote => match &v.parse::() { + RichTextAttributeKey::Bold + | RichTextAttributeKey::Italic + | RichTextAttributeKey::Underline + | RichTextAttributeKey::StrikeThrough + | RichTextAttributeKey::CodeBlock + | RichTextAttributeKey::InlineCode + | RichTextAttributeKey::BlockQuote => match &v.parse::() { Ok(value) => map_serializer.serialize_entry(&key, value)?, Err(e) => log::error!("Serial {:?} failed. {:?}", &key, e), }, - AttributeKey::Font - | AttributeKey::Size - | AttributeKey::Header - | AttributeKey::Indent - | AttributeKey::Width - | AttributeKey::Height => match &v.parse::() { + RichTextAttributeKey::Font + | RichTextAttributeKey::Size + | RichTextAttributeKey::Header + | RichTextAttributeKey::Indent + | RichTextAttributeKey::Width + | RichTextAttributeKey::Height => match &v.parse::() { Ok(value) => map_serializer.serialize_entry(&key, value)?, Err(e) => log::error!("Serial {:?} failed. {:?}", &key, e), }, - AttributeKey::Link - | AttributeKey::Color - | AttributeKey::Background - | AttributeKey::Align - | AttributeKey::List => { + RichTextAttributeKey::Link + | RichTextAttributeKey::Color + | RichTextAttributeKey::Background + | RichTextAttributeKey::Align + | RichTextAttributeKey::List => { map_serializer.serialize_entry(&key, v)?; }, } @@ -82,23 +86,23 @@ where Ok(()) } -impl<'de> Deserialize<'de> for Attributes { - fn deserialize(deserializer: D) -> Result +impl<'de> Deserialize<'de> for RichTextAttributes { + fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct AttributesVisitor; impl<'de> Visitor<'de> for AttributesVisitor { - type Value = Attributes; + type Value = RichTextAttributes; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Expect map") } fn visit_map(self, mut map: A) -> Result where A: MapAccess<'de>, { - let mut attributes = Attributes::new(); - while let Some(key) = map.next_key::()? { - let value = map.next_value::()?; + let mut attributes = RichTextAttributes::new(); + while let Some(key) = map.next_key::()? { + let value = map.next_value::()?; attributes.add_kv(key, value); } @@ -109,7 +113,7 @@ impl<'de> Deserialize<'de> for Attributes { } } -impl Serialize for AttributeValue { +impl Serialize for RichTextAttributeValue { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -121,14 +125,14 @@ impl Serialize for AttributeValue { } } -impl<'de> Deserialize<'de> for AttributeValue { - fn deserialize(deserializer: D) -> Result +impl<'de> Deserialize<'de> for RichTextAttributeValue { + fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct AttributeValueVisitor; impl<'de> Visitor<'de> for AttributeValueVisitor { - type Value = AttributeValue; + type Value = RichTextAttributeValue; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("bool, usize or string") } @@ -143,56 +147,56 @@ impl<'de> Deserialize<'de> for AttributeValue { where E: de::Error, { - Ok(AttributeValue(Some(format!("{}", value)))) + Ok(RichTextAttributeValue(Some(format!("{}", value)))) } fn visit_i16(self, value: i16) -> Result where E: de::Error, { - Ok(AttributeValue(Some(format!("{}", value)))) + Ok(RichTextAttributeValue(Some(format!("{}", value)))) } fn visit_i32(self, value: i32) -> Result where E: de::Error, { - Ok(AttributeValue(Some(format!("{}", value)))) + Ok(RichTextAttributeValue(Some(format!("{}", value)))) } fn visit_i64(self, value: i64) -> Result where E: de::Error, { - Ok(AttributeValue(Some(format!("{}", value)))) + Ok(RichTextAttributeValue(Some(format!("{}", value)))) } fn visit_u8(self, value: u8) -> Result where E: de::Error, { - Ok(AttributeValue(Some(format!("{}", value)))) + Ok(RichTextAttributeValue(Some(format!("{}", value)))) } fn visit_u16(self, value: u16) -> Result where E: de::Error, { - Ok(AttributeValue(Some(format!("{}", value)))) + Ok(RichTextAttributeValue(Some(format!("{}", value)))) } fn visit_u32(self, value: u32) -> Result where E: de::Error, { - Ok(AttributeValue(Some(format!("{}", value)))) + Ok(RichTextAttributeValue(Some(format!("{}", value)))) } fn visit_u64(self, value: u64) -> Result where E: de::Error, { - Ok(AttributeValue(Some(format!("{}", value)))) + Ok(RichTextAttributeValue(Some(format!("{}", value)))) } fn visit_str(self, s: &str) -> Result @@ -206,7 +210,7 @@ impl<'de> Deserialize<'de> for AttributeValue { where E: de::Error, { - Ok(AttributeValue(None)) + Ok(RichTextAttributeValue(None)) } fn visit_unit(self) -> Result @@ -214,7 +218,7 @@ impl<'de> Deserialize<'de> for AttributeValue { E: de::Error, { // the value that contains null will be processed here. - Ok(AttributeValue(None)) + Ok(RichTextAttributeValue(None)) } fn visit_map(self, map: A) -> Result @@ -223,7 +227,7 @@ impl<'de> Deserialize<'de> for AttributeValue { { // https://github.com/serde-rs/json/issues/505 let mut map = map; - let value = map.next_value::()?; + let value = map.next_value::()?; Ok(value) } } diff --git a/shared-lib/lib-ot/src/core/attributes/builder.rs b/shared-lib/lib-ot/src/core/attributes/builder.rs index 599149cc8c..98c0721371 100644 --- a/shared-lib/lib-ot/src/core/attributes/builder.rs +++ b/shared-lib/lib-ot/src/core/attributes/builder.rs @@ -1,13 +1,13 @@ #![allow(non_snake_case)] -use crate::core::{Attribute, Attributes}; +use crate::core::{RichTextAttribute, RichTextAttributes}; pub struct AttributeBuilder { - inner: Attributes, + inner: RichTextAttributes, } impl std::default::Default for AttributeBuilder { fn default() -> Self { Self { - inner: Attributes::default(), + inner: RichTextAttributes::default(), } } } @@ -15,10 +15,10 @@ impl std::default::Default for AttributeBuilder { impl AttributeBuilder { pub fn new() -> Self { AttributeBuilder::default() } - pub fn add_attr(mut self, attribute: Attribute) -> Self { + pub fn add_attr(mut self, attribute: RichTextAttribute) -> Self { self.inner.add(attribute); self } - pub fn build(self) -> Attributes { self.inner } + pub fn build(self) -> RichTextAttributes { self.inner } } diff --git a/shared-lib/lib-ot/src/core/attributes/macros.rs b/shared-lib/lib-ot/src/core/attributes/macros.rs index dcdaf50f42..28fe903183 100644 --- a/shared-lib/lib-ot/src/core/attributes/macros.rs +++ b/shared-lib/lib-ot/src/core/attributes/macros.rs @@ -6,7 +6,7 @@ macro_rules! inline_attribute { ) => { pub fn $key(value: $value) -> Self { Self { - key: AttributeKey::$key, + key: RichTextAttributeKey::$key, value: value.into(), scope: AttributeScope::Inline, } @@ -22,7 +22,7 @@ macro_rules! block_attribute { ) => { pub fn $key(value: $value) -> Self { Self { - key: AttributeKey::$key, + key: RichTextAttributeKey::$key, value: value.into(), scope: AttributeScope::Block, } @@ -41,7 +41,7 @@ macro_rules! list_attribute { true => $value, false => "", }; - Attribute::List(value) + RichTextAttribute::List(value) } }; } @@ -54,7 +54,7 @@ macro_rules! ignore_attribute { ) => { pub fn $key(value: $value) -> Self { Self { - key: AttributeKey::$key, + key: RichTextAttributeKey::$key, value: value.into(), scope: AttributeScope::Ignore, } diff --git a/shared-lib/lib-ot/src/core/delta/builder.rs b/shared-lib/lib-ot/src/core/delta/builder.rs index 351872ac10..369aa33366 100644 --- a/shared-lib/lib-ot/src/core/delta/builder.rs +++ b/shared-lib/lib-ot/src/core/delta/builder.rs @@ -1,23 +1,29 @@ -use crate::core::{plain_attributes, Attributes, Delta, Operation}; +use crate::core::{Attributes, Delta, Operation}; -pub struct DeltaBuilder { - delta: Delta, +pub struct DeltaBuilder { + delta: Delta, } -impl std::default::Default for DeltaBuilder { +impl std::default::Default for DeltaBuilder +where + T: Attributes, +{ fn default() -> Self { Self { delta: Delta::new() } } } -impl DeltaBuilder { +impl DeltaBuilder +where + T: Attributes, +{ pub fn new() -> Self { DeltaBuilder::default() } - pub fn retain_with_attributes(mut self, n: usize, attrs: Attributes) -> Self { + pub fn retain_with_attributes(mut self, n: usize, attrs: T) -> Self { self.delta.retain(n, attrs); self } pub fn retain(mut self, n: usize) -> Self { - self.delta.retain(n, plain_attributes()); + self.delta.retain(n, T::default()); self } @@ -26,13 +32,13 @@ impl DeltaBuilder { self } - pub fn insert_with_attributes(mut self, s: &str, attrs: Attributes) -> Self { + pub fn insert_with_attributes(mut self, s: &str, attrs: T) -> Self { self.delta.insert(s, attrs); self } pub fn insert(mut self, s: &str) -> Self { - self.delta.insert(s, plain_attributes()); + self.delta.insert(s, T::default()); self } @@ -41,10 +47,10 @@ impl DeltaBuilder { self } - pub fn build(self) -> Delta { self.delta } + pub fn build(self) -> Delta { self.delta } } -pub fn trim(delta: &mut Delta) { +pub fn trim(delta: &mut Delta) { let remove_last = match delta.ops.last() { None => false, Some(op) => match op { diff --git a/shared-lib/lib-ot/src/core/delta/cursor.rs b/shared-lib/lib-ot/src/core/delta/cursor.rs index 4b9fc77e1b..7524bded43 100644 --- a/shared-lib/lib-ot/src/core/delta/cursor.rs +++ b/shared-lib/lib-ot/src/core/delta/cursor.rs @@ -1,22 +1,25 @@ use crate::{ - core::{Delta, Interval, Operation}, + core::{Attributes, Delta, Interval, Operation}, errors::{ErrorBuilder, OTError, OTErrorCode}, }; use std::{cmp::min, iter::Enumerate, slice::Iter}; #[derive(Debug)] -pub struct OpCursor<'a> { - pub(crate) delta: &'a Delta, +pub struct OpCursor<'a, T: Attributes> { + pub(crate) delta: &'a Delta, pub(crate) origin_iv: Interval, pub(crate) consume_iv: Interval, pub(crate) consume_count: usize, pub(crate) op_index: usize, - iter: Enumerate>, - next_op: Option, + iter: Enumerate>>, + next_op: Option>, } -impl<'a> OpCursor<'a> { - pub fn new(delta: &'a Delta, interval: Interval) -> OpCursor<'a> { +impl<'a, T> OpCursor<'a, T> +where + T: Attributes, +{ + pub fn new(delta: &'a Delta, interval: Interval) -> OpCursor<'a, T> { // debug_assert!(interval.start <= delta.target_len); let mut cursor = Self { delta, @@ -34,11 +37,11 @@ impl<'a> OpCursor<'a> { // get the next operation interval pub fn next_iv(&self) -> Interval { self.next_iv_before(None).unwrap_or_else(|| Interval::new(0, 0)) } - pub fn next_op(&mut self) -> Option { self.next_with_len(None) } + pub fn next_op(&mut self) -> Option> { self.next_with_len(None) } // get the last operation before the end. // checkout the delta_next_op_with_len_cross_op_return_last test for more detail - pub fn next_with_len(&mut self, force_end: Option) -> Option { + pub fn next_with_len(&mut self, force_end: Option) -> Option> { let mut find_op = None; let holder = self.next_op.clone(); let mut next_op = holder.as_ref(); @@ -121,7 +124,7 @@ impl<'a> OpCursor<'a> { Some(interval) } - pub fn next_iter_op(&self) -> Option<&Operation> { + pub fn next_iter_op(&self) -> Option<&Operation> { let mut next_op = self.next_op.as_ref(); if next_op.is_none() { let mut offset = 0; @@ -137,7 +140,10 @@ impl<'a> OpCursor<'a> { } } -fn find_next<'a>(cursor: &mut OpCursor<'a>) -> Option<&'a Operation> { +fn find_next<'a, T>(cursor: &mut OpCursor<'a, T>) -> Option<&'a Operation> +where + T: Attributes, +{ match cursor.iter.next() { None => None, Some((o_index, op)) => { @@ -149,13 +155,13 @@ fn find_next<'a>(cursor: &mut OpCursor<'a>) -> Option<&'a Operation> { type SeekResult = Result<(), OTError>; pub trait Metric { - fn seek(cursor: &mut OpCursor, index: usize) -> SeekResult; + fn seek(cursor: &mut OpCursor, index: usize) -> SeekResult; } -pub struct OpMetric {} +pub struct OpMetric(); impl Metric for OpMetric { - fn seek(cursor: &mut OpCursor, index: usize) -> SeekResult { + fn seek(cursor: &mut OpCursor, index: usize) -> SeekResult { let _ = check_bound(cursor.op_index, index)?; let mut seek_cursor = OpCursor::new(cursor.delta, cursor.origin_iv); let mut offset = 0; @@ -170,10 +176,10 @@ impl Metric for OpMetric { } } -pub struct CharMetric {} +pub struct CharMetric(); impl Metric for CharMetric { - fn seek(cursor: &mut OpCursor, index: usize) -> SeekResult { + fn seek(cursor: &mut OpCursor, index: usize) -> SeekResult { if index > 0 { let _ = check_bound(cursor.consume_count, index)?; let _ = cursor.next_with_len(Some(index)); diff --git a/shared-lib/lib-ot/src/core/delta/delta.rs b/shared-lib/lib-ot/src/core/delta/delta.rs index 17b2a221ed..fc78cd3ae3 100644 --- a/shared-lib/lib-ot/src/core/delta/delta.rs +++ b/shared-lib/lib-ot/src/core/delta/delta.rs @@ -3,6 +3,7 @@ use crate::{ errors::{ErrorBuilder, OTError, OTErrorCode}, }; use bytes::Bytes; +use serde::de::DeserializeOwned; use std::{ cmp::{min, Ordering}, fmt, @@ -13,13 +14,16 @@ use std::{ // Opti: optimize the memory usage with Arc_mut or Cow #[derive(Clone, Debug, PartialEq, Eq)] -pub struct Delta { - pub ops: Vec, +pub struct Delta { + pub ops: Vec>, pub base_len: usize, pub target_len: usize, } -impl Default for Delta { +impl Default for Delta +where + T: Attributes, +{ fn default() -> Self { Self { ops: Vec::new(), @@ -29,28 +33,10 @@ impl Default for Delta { } } -impl FromStr for Delta { - type Err = (); - - fn from_str(s: &str) -> Result { - let mut delta = Delta::with_capacity(1); - delta.add(Operation::Insert(s.into())); - Ok(delta) - } -} - -impl std::convert::TryFrom> for Delta { - type Error = OTError; - fn try_from(bytes: Vec) -> Result { Delta::from_bytes(bytes) } -} - -impl std::convert::TryFrom for Delta { - type Error = OTError; - - fn try_from(bytes: Bytes) -> Result { Delta::from_bytes(&bytes) } -} - -impl fmt::Display for Delta { +impl fmt::Display for Delta +where + T: Attributes, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // f.write_str(&serde_json::to_string(self).unwrap_or("".to_owned()))?; f.write_str("[ ")?; @@ -62,8 +48,11 @@ impl fmt::Display for Delta { } } -impl FromIterator for Delta { - fn from_iter>(ops: T) -> Self { +impl FromIterator> for Delta +where + T: Attributes, +{ + fn from_iter>>(ops: I) -> Self { let mut operations = Delta::default(); for op in ops { operations.add(op); @@ -72,30 +61,12 @@ impl FromIterator for Delta { } } -impl Delta { +impl Delta +where + T: Attributes, +{ pub fn new() -> Self { Self::default() } - pub fn from_json(json: &str) -> Result { - let delta: Delta = serde_json::from_str(json).map_err(|e| { - tracing::trace!("Deserialize failed: {:?}", e); - tracing::trace!("{:?}", json); - e - })?; - Ok(delta) - } - - pub fn to_json(&self) -> String { serde_json::to_string(self).unwrap_or_else(|_| "".to_owned()) } - - pub fn from_bytes>(bytes: T) -> Result { - let json = str::from_utf8(bytes.as_ref())?; - Self::from_json(json) - } - - pub fn to_bytes(&self) -> Bytes { - let json = self.to_json(); - Bytes::from(json.into_bytes()) - } - #[inline] pub fn with_capacity(capacity: usize) -> Self { Self { @@ -105,7 +76,7 @@ impl Delta { } } - pub fn add(&mut self, op: Operation) { + pub fn add(&mut self, op: Operation) { match op { Operation::Delete(i) => self.delete(i), Operation::Insert(i) => self.insert(&i.s, i.attributes), @@ -125,7 +96,7 @@ impl Delta { } } - pub fn insert(&mut self, s: &str, attributes: Attributes) { + pub fn insert(&mut self, s: &str, attributes: T) { let s: FlowyStr = s.into(); if s.is_empty() { return; @@ -133,20 +104,20 @@ impl Delta { self.target_len += s.count_utf16_code_units(); let new_last = match self.ops.as_mut_slice() { - [.., Operation::Insert(insert)] => { + [.., Operation::::Insert(insert)] => { // insert.merge_or_new_op(&s, attributes) }, - [.., Operation::Insert(pre_insert), Operation::Delete(_)] => { + [.., Operation::::Insert(pre_insert), Operation::Delete(_)] => { // pre_insert.merge_or_new_op(&s, attributes) }, - [.., op_last @ Operation::Delete(_)] => { + [.., op_last @ Operation::::Delete(_)] => { let new_last = op_last.clone(); - *op_last = OpBuilder::insert(&s).attributes(attributes).build(); + *op_last = OpBuilder::::insert(&s).attributes(attributes).build(); Some(new_last) }, - _ => Some(OpBuilder::insert(&s).attributes(attributes).build()), + _ => Some(OpBuilder::::insert(&s).attributes(attributes).build()), }; match new_last { @@ -155,19 +126,19 @@ impl Delta { } } - pub fn retain(&mut self, n: usize, attributes: Attributes) { + pub fn retain(&mut self, n: usize, attributes: T) { if n == 0 { return; } self.base_len += n as usize; self.target_len += n as usize; - if let Some(Operation::Retain(retain)) = self.ops.last_mut() { + if let Some(Operation::::Retain(retain)) = self.ops.last_mut() { if let Some(new_op) = retain.merge_or_new(n, attributes) { self.ops.push(new_op); } } else { - self.ops.push(OpBuilder::retain(n).attributes(attributes).build()); + self.ops.push(OpBuilder::::retain(n).attributes(attributes).build()); } } @@ -207,7 +178,7 @@ impl Delta { for op in &self.ops { match &op { Operation::Retain(retain) => { - inverted.retain(retain.n, Attributes::default()); + inverted.retain(retain.n, T::default()); // TODO: use advance_by instead, but it's unstable now // chars.advance_by(retain.num) for _ in 0..retain.n { @@ -234,7 +205,10 @@ impl Delta { pub fn extend(&mut self, other: Self) { other.ops.into_iter().for_each(|op| self.add(op)); } } -impl OperationTransformable for Delta { +impl OperationTransformable for Delta +where + T: Attributes, +{ fn compose(&self, other: &Self) -> Result where Self: Sized, @@ -453,7 +427,13 @@ impl OperationTransformable for Delta { } } -fn invert_from_other(base: &mut Delta, other: &Delta, operation: &Operation, start: usize, end: usize) { +fn invert_from_other( + base: &mut Delta, + other: &Delta, + operation: &Operation, + start: usize, + end: usize, +) { tracing::trace!("invert op: {} [{}:{}]", operation, start, end); let other_ops = DeltaIter::from_interval(other, Interval::new(start, end)).ops(); other_ops.into_iter().for_each(|other_op| match operation { @@ -476,10 +456,10 @@ fn invert_from_other(base: &mut Delta, other: &Delta, operation: &Operation, sta }); } -fn transform_op_attribute(left: &Option, right: &Option) -> Attributes { +fn transform_op_attribute(left: &Option>, right: &Option>) -> T { if left.is_none() { if right.is_none() { - return Attributes::default(); + return T::default(); } return right.as_ref().unwrap().get_attributes(); } @@ -488,3 +468,58 @@ fn transform_op_attribute(left: &Option, right: &Option) - // TODO: It's ok to unwrap? left.transform(&right).unwrap().0 } + +pub type RichTextDelta = Delta; + +impl Delta +where + T: Attributes + DeserializeOwned, +{ + pub fn from_json(json: &str) -> Result { + let delta = serde_json::from_str(json).map_err(|e| { + tracing::trace!("Deserialize failed: {:?}", e); + tracing::trace!("{:?}", json); + e + })?; + Ok(delta) + } + + pub fn from_bytes>(bytes: B) -> Result { + let json = str::from_utf8(bytes.as_ref())?.to_owned(); + let val = Self::from_json(&json)?; + Ok(val) + } +} + +impl Delta +where + T: Attributes + serde::Serialize, +{ + pub fn to_json(&self) -> String { serde_json::to_string(self).unwrap_or_else(|_| "".to_owned()) } + + pub fn to_bytes(&self) -> Bytes { + let json = self.to_json(); + Bytes::from(json.into_bytes()) + } +} + +impl FromStr for RichTextDelta { + type Err = (); + + fn from_str(s: &str) -> Result { + let mut delta = Delta::with_capacity(1); + delta.add(Operation::Insert(s.into())); + Ok(delta) + } +} + +impl std::convert::TryFrom> for RichTextDelta { + type Error = OTError; + fn try_from(bytes: Vec) -> Result { Delta::from_bytes(bytes) } +} + +impl std::convert::TryFrom for RichTextDelta { + type Error = OTError; + + fn try_from(bytes: Bytes) -> Result { Delta::from_bytes(&bytes) } +} diff --git a/shared-lib/lib-ot/src/core/delta/delta_serde.rs b/shared-lib/lib-ot/src/core/delta/delta_serde.rs index b6be5891ab..51045fc764 100644 --- a/shared-lib/lib-ot/src/core/delta/delta_serde.rs +++ b/shared-lib/lib-ot/src/core/delta/delta_serde.rs @@ -1,4 +1,4 @@ -use crate::core::Delta; +use crate::core::{Attributes, Delta}; use serde::{ de::{SeqAccess, Visitor}, ser::SerializeSeq, @@ -7,9 +7,12 @@ use serde::{ Serialize, Serializer, }; -use std::fmt; +use std::{fmt, marker::PhantomData}; -impl Serialize for Delta { +impl Serialize for Delta +where + T: Attributes + Serialize, +{ fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -22,18 +25,25 @@ impl Serialize for Delta { } } -impl<'de> Deserialize<'de> for Delta { - fn deserialize(deserializer: D) -> Result +impl<'de, T> Deserialize<'de> for Delta +where + T: Attributes + Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, { - struct OperationSeqVisitor; + struct OperationSeqVisitor(PhantomData T>); - impl<'de> Visitor<'de> for OperationSeqVisitor { - type Value = Delta; + impl<'de, T> Visitor<'de> for OperationSeqVisitor + where + T: Attributes + Deserialize<'de>, + { + type Value = Delta; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a sequence") } + #[inline] fn visit_seq(self, mut seq: A) -> Result where A: SeqAccess<'de>, @@ -46,6 +56,6 @@ impl<'de> Deserialize<'de> for Delta { } } - deserializer.deserialize_seq(OperationSeqVisitor) + deserializer.deserialize_seq(OperationSeqVisitor(PhantomData)) } } diff --git a/shared-lib/lib-ot/src/core/delta/iterator.rs b/shared-lib/lib-ot/src/core/delta/iterator.rs index 4ecb6087ba..478428877c 100644 --- a/shared-lib/lib-ot/src/core/delta/iterator.rs +++ b/shared-lib/lib-ot/src/core/delta/iterator.rs @@ -1,32 +1,35 @@ use super::cursor::*; -use crate::core::{Attributes, Delta, Interval, Operation, NEW_LINE}; +use crate::core::{Attributes, Delta, Interval, Operation, RichTextAttributes, NEW_LINE}; use std::ops::{Deref, DerefMut}; pub(crate) const MAX_IV_LEN: usize = i32::MAX as usize; -pub struct DeltaIter<'a> { - cursor: OpCursor<'a>, +pub struct DeltaIter<'a, T: Attributes> { + cursor: OpCursor<'a, T>, } -impl<'a> DeltaIter<'a> { - pub fn new(delta: &'a Delta) -> Self { +impl<'a, T> DeltaIter<'a, T> +where + T: Attributes, +{ + pub fn new(delta: &'a Delta) -> Self { let interval = Interval::new(0, MAX_IV_LEN); Self::from_interval(delta, interval) } - pub fn from_offset(delta: &'a Delta, offset: usize) -> Self { + pub fn from_offset(delta: &'a Delta, offset: usize) -> Self { let interval = Interval::new(0, MAX_IV_LEN); let mut iter = Self::from_interval(delta, interval); iter.seek::(offset); iter } - pub fn from_interval(delta: &'a Delta, interval: Interval) -> Self { + pub fn from_interval(delta: &'a Delta, interval: Interval) -> Self { let cursor = OpCursor::new(delta, interval); Self { cursor } } - pub fn ops(&mut self) -> Vec { self.collect::>() } + pub fn ops(&mut self) -> Vec> { self.collect::>() } pub fn next_op_len(&self) -> Option { let interval = self.cursor.next_iv(); @@ -37,12 +40,12 @@ impl<'a> DeltaIter<'a> { } } - pub fn next_op(&mut self) -> Option { self.cursor.next_op() } + pub fn next_op(&mut self) -> Option> { self.cursor.next_op() } - pub fn next_op_with_len(&mut self, len: usize) -> Option { self.cursor.next_with_len(Some(len)) } + pub fn next_op_with_len(&mut self, len: usize) -> Option> { self.cursor.next_with_len(Some(len)) } // find next op contains NEW_LINE - pub fn next_op_with_newline(&mut self) -> Option<(Operation, usize)> { + pub fn next_op_with_newline(&mut self) -> Option<(Operation, usize)> { let mut offset = 0; while self.has_next() { if let Some(op) = self.next_op() { @@ -87,12 +90,15 @@ impl<'a> DeltaIter<'a> { } } -impl<'a> Iterator for DeltaIter<'a> { - type Item = Operation; +impl<'a, T> Iterator for DeltaIter<'a, T> +where + T: Attributes, +{ + type Item = Operation; fn next(&mut self) -> Option { self.next_op() } } -pub fn is_empty_line_at_index(delta: &Delta, index: usize) -> bool { +pub fn is_empty_line_at_index(delta: &Delta, index: usize) -> bool { let mut iter = DeltaIter::new(delta); let (prev, next) = (iter.next_op_with_len(index), iter.next_op()); if prev.is_none() { @@ -108,58 +114,70 @@ pub fn is_empty_line_at_index(delta: &Delta, index: usize) -> bool { OpNewline::parse(&prev).is_end() && OpNewline::parse(&next).is_start() } -pub struct AttributesIter<'a> { - delta_iter: DeltaIter<'a>, +pub struct AttributesIter<'a, T: Attributes> { + delta_iter: DeltaIter<'a, T>, } -impl<'a> AttributesIter<'a> { - pub fn new(delta: &'a Delta) -> Self { +impl<'a, T> AttributesIter<'a, T> +where + T: Attributes, +{ + pub fn new(delta: &'a Delta) -> Self { let interval = Interval::new(0, usize::MAX); Self::from_interval(delta, interval) } - pub fn from_interval(delta: &'a Delta, interval: Interval) -> Self { + pub fn from_interval(delta: &'a Delta, interval: Interval) -> Self { let delta_iter = DeltaIter::from_interval(delta, interval); Self { delta_iter } } - pub fn next_or_empty(&mut self) -> Attributes { + pub fn next_or_empty(&mut self) -> T { match self.next() { - None => Attributes::default(), + None => T::default(), Some((_, attributes)) => attributes, } } } -impl<'a> Deref for AttributesIter<'a> { - type Target = DeltaIter<'a>; +impl<'a, T> Deref for AttributesIter<'a, T> +where + T: Attributes, +{ + type Target = DeltaIter<'a, T>; fn deref(&self) -> &Self::Target { &self.delta_iter } } -impl<'a> DerefMut for AttributesIter<'a> { +impl<'a, T> DerefMut for AttributesIter<'a, T> +where + T: Attributes, +{ fn deref_mut(&mut self) -> &mut Self::Target { &mut self.delta_iter } } -impl<'a> Iterator for AttributesIter<'a> { - type Item = (usize, Attributes); +impl<'a, T> Iterator for AttributesIter<'a, T> +where + T: Attributes, +{ + type Item = (usize, T); fn next(&mut self) -> Option { let next_op = self.delta_iter.next_op(); next_op.as_ref()?; let mut length: usize = 0; - let mut attributes = Attributes::new(); + let mut attributes = T::default(); match next_op.unwrap() { - Operation::Delete(_n) => {}, - Operation::Retain(retain) => { + Operation::::Delete(_n) => {}, + Operation::::Retain(retain) => { tracing::trace!("extend retain attributes with {} ", &retain.attributes); - attributes.extend(retain.attributes.clone()); + attributes.extend_other(retain.attributes.clone()); length = retain.n; }, - Operation::Insert(insert) => { + Operation::::Insert(insert) => { tracing::trace!("extend insert attributes with {} ", &insert.attributes); - attributes.extend(insert.attributes.clone()); + attributes.extend_other(insert.attributes.clone()); length = insert.count_of_code_units(); }, } @@ -178,7 +196,7 @@ pub enum OpNewline { } impl OpNewline { - pub fn parse(op: &Operation) -> OpNewline { + pub fn parse(op: &Operation) -> OpNewline { let s = op.get_data(); if s == NEW_LINE { diff --git a/shared-lib/lib-ot/src/core/operation/builder.rs b/shared-lib/lib-ot/src/core/operation/builder.rs index a640267fdc..d7484a3613 100644 --- a/shared-lib/lib-ot/src/core/operation/builder.rs +++ b/shared-lib/lib-ot/src/core/operation/builder.rs @@ -1,30 +1,35 @@ -use crate::core::{Attributes, Operation}; +use crate::core::{Attributes, Operation, RichTextAttributes}; -pub struct OpBuilder { - ty: Operation, - attrs: Attributes, +pub type RichTextOpBuilder = OpBuilder; + +pub struct OpBuilder { + ty: Operation, + attrs: T, } -impl OpBuilder { - pub fn new(ty: Operation) -> OpBuilder { +impl OpBuilder +where + T: Attributes, +{ + pub fn new(ty: Operation) -> OpBuilder { OpBuilder { ty, - attrs: Attributes::default(), + attrs: T::default(), } } - pub fn retain(n: usize) -> OpBuilder { OpBuilder::new(Operation::Retain(n.into())) } + pub fn retain(n: usize) -> OpBuilder { OpBuilder::new(Operation::Retain(n.into())) } - pub fn delete(n: usize) -> OpBuilder { OpBuilder::new(Operation::Delete(n)) } + pub fn delete(n: usize) -> OpBuilder { OpBuilder::new(Operation::Delete(n)) } - pub fn insert(s: &str) -> OpBuilder { OpBuilder::new(Operation::Insert(s.into())) } + pub fn insert(s: &str) -> OpBuilder { OpBuilder::new(Operation::Insert(s.into())) } - pub fn attributes(mut self, attrs: Attributes) -> OpBuilder { + pub fn attributes(mut self, attrs: T) -> OpBuilder { self.attrs = attrs; self } - pub fn build(self) -> Operation { + pub fn build(self) -> Operation { let mut operation = self.ty; match &mut operation { Operation::Delete(_) => {}, diff --git a/shared-lib/lib-ot/src/core/operation/operation.rs b/shared-lib/lib-ot/src/core/operation/operation.rs index b7378cbc40..c8f74370e2 100644 --- a/shared-lib/lib-ot/src/core/operation/operation.rs +++ b/shared-lib/lib-ot/src/core/operation/operation.rs @@ -1,19 +1,39 @@ -use crate::core::{Attribute, Attributes, FlowyStr, Interval, OpBuilder}; +use crate::core::{FlowyStr, Interval, OpBuilder, OperationTransformable, RichTextAttribute, RichTextAttributes}; use serde::__private::Formatter; use std::{ cmp::min, fmt, + fmt::Debug, ops::{Deref, DerefMut}, }; -#[derive(Debug, Clone, Eq, PartialEq)] -pub enum Operation { - Delete(usize), - Retain(Retain), - Insert(Insert), +pub trait Attributes: fmt::Display + Eq + PartialEq + Default + Clone + Debug + OperationTransformable { + fn is_empty(&self) -> bool; + + // Remove the empty attribute which value is None. + fn remove_empty(&mut self); + + fn extend_other(&mut self, other: Self); } -impl Operation { +pub type RichTextOperation = Operation; +impl RichTextOperation { + pub fn contain_attribute(&self, attribute: &RichTextAttribute) -> bool { + self.get_attributes().contains_key(&attribute.key) + } +} + +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum Operation { + Delete(usize), + Retain(Retain), + Insert(Insert), +} + +impl Operation +where + T: Attributes, +{ pub fn get_data(&self) -> &str { match self { Operation::Delete(_) => "", @@ -22,15 +42,15 @@ impl Operation { } } - pub fn get_attributes(&self) -> Attributes { + pub fn get_attributes(&self) -> T { match self { - Operation::Delete(_) => Attributes::default(), + Operation::Delete(_) => T::default(), Operation::Retain(retain) => retain.attributes.clone(), Operation::Insert(insert) => insert.attributes.clone(), } } - pub fn set_attributes(&mut self, attributes: Attributes) { + pub fn set_attributes(&mut self, attributes: T) { match self { Operation::Delete(_) => log::error!("Delete should not contains attributes"), Operation::Retain(retain) => retain.attributes = attributes, @@ -40,10 +60,6 @@ impl Operation { pub fn has_attribute(&self) -> bool { !self.get_attributes().is_empty() } - pub fn contain_attribute(&self, attribute: &Attribute) -> bool { - self.get_attributes().contains_key(&attribute.key) - } - pub fn len(&self) -> usize { match self { Operation::Delete(n) => *n, @@ -55,28 +71,28 @@ impl Operation { pub fn is_empty(&self) -> bool { self.len() == 0 } #[allow(dead_code)] - pub fn split(&self, index: usize) -> (Option, Option) { + pub fn split(&self, index: usize) -> (Option>, Option>) { debug_assert!(index < self.len()); let left; let right; match self { Operation::Delete(n) => { - left = Some(OpBuilder::delete(index).build()); - right = Some(OpBuilder::delete(*n - index).build()); + left = Some(OpBuilder::::delete(index).build()); + right = Some(OpBuilder::::delete(*n - index).build()); }, Operation::Retain(retain) => { - left = Some(OpBuilder::delete(index).build()); - right = Some(OpBuilder::delete(retain.n - index).build()); + left = Some(OpBuilder::::delete(index).build()); + right = Some(OpBuilder::::delete(retain.n - index).build()); }, Operation::Insert(insert) => { let attributes = self.get_attributes(); left = Some( - OpBuilder::insert(&insert.s[0..index]) + OpBuilder::::insert(&insert.s[0..index]) .attributes(attributes.clone()) .build(), ); right = Some( - OpBuilder::insert(&insert.s[index..insert.count_of_code_units()]) + OpBuilder::::insert(&insert.s[index..insert.count_of_code_units()]) .attributes(attributes) .build(), ); @@ -86,7 +102,7 @@ impl Operation { (left, right) } - pub fn shrink(&self, interval: Interval) -> Option { + pub fn shrink(&self, interval: Interval) -> Option> { let op = match self { Operation::Delete(n) => OpBuilder::delete(min(*n, interval.size())).build(), Operation::Retain(retain) => OpBuilder::retain(min(retain.n, interval.size())) @@ -145,7 +161,10 @@ impl Operation { } } -impl fmt::Display for Operation { +impl fmt::Display for Operation +where + T: Attributes, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("{")?; match self { @@ -164,15 +183,18 @@ impl fmt::Display for Operation { } } -#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)] -pub struct Retain { - #[serde(rename(serialize = "retain", deserialize = "retain"))] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Retain { + // #[serde(rename(serialize = "retain", deserialize = "retain"))] pub n: usize, - #[serde(skip_serializing_if = "is_empty")] - pub attributes: Attributes, + // #[serde(skip_serializing_if = "is_empty")] + pub attributes: T, } -impl fmt::Display for Retain { +impl fmt::Display for Retain +where + T: Attributes, +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { if self.attributes.is_empty() { f.write_fmt(format_args!("retain: {}", self.n)) @@ -182,8 +204,11 @@ impl fmt::Display for Retain { } } -impl Retain { - pub fn merge_or_new(&mut self, n: usize, attributes: Attributes) -> Option { +impl Retain +where + T: Attributes, +{ + pub fn merge_or_new(&mut self, n: usize, attributes: T) -> Option> { tracing::trace!( "merge_retain_or_new_op: len: {:?}, l: {} - r: {}", n, @@ -201,35 +226,47 @@ impl Retain { pub fn is_plain(&self) -> bool { self.attributes.is_empty() } } -impl std::convert::From for Retain { +impl std::convert::From for Retain +where + T: Attributes, +{ fn from(n: usize) -> Self { Retain { n, - attributes: Attributes::default(), + attributes: T::default(), } } } -impl Deref for Retain { +impl Deref for Retain +where + T: Attributes, +{ type Target = usize; fn deref(&self) -> &Self::Target { &self.n } } -impl DerefMut for Retain { +impl DerefMut for Retain +where + T: Attributes, +{ fn deref_mut(&mut self) -> &mut Self::Target { &mut self.n } } -#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)] -pub struct Insert { - #[serde(rename(serialize = "insert", deserialize = "insert"))] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Insert { + // #[serde(rename(serialize = "insert", deserialize = "insert"))] pub s: FlowyStr, - #[serde(skip_serializing_if = "is_empty")] - pub attributes: Attributes, + // #[serde(skip_serializing_if = "is_empty")] + pub attributes: T, } -impl fmt::Display for Insert { +impl fmt::Display for Insert +where + T: Attributes, +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let mut s = self.s.clone(); if s.ends_with('\n') { @@ -247,41 +284,51 @@ impl fmt::Display for Insert { } } -impl Insert { +impl Insert +where + T: Attributes, +{ pub fn count_of_code_units(&self) -> usize { self.s.count_utf16_code_units() } - pub fn merge_or_new_op(&mut self, s: &str, attributes: Attributes) -> Option { + pub fn merge_or_new_op(&mut self, s: &str, attributes: T) -> Option> { if self.attributes == attributes { self.s += s; None } else { - Some(OpBuilder::insert(s).attributes(attributes).build()) + Some(OpBuilder::::insert(s).attributes(attributes).build()) } } pub fn is_plain(&self) -> bool { self.attributes.is_empty() } } -impl std::convert::From for Insert { +impl std::convert::From for Insert +where + T: Attributes, +{ fn from(s: String) -> Self { Insert { s: s.into(), - attributes: Attributes::default(), + attributes: T::default(), } } } -impl std::convert::From<&str> for Insert { +impl std::convert::From<&str> for Insert +where + T: Attributes, +{ fn from(s: &str) -> Self { Insert::from(s.to_owned()) } } -impl std::convert::From for Insert { +impl std::convert::From for Insert +where + T: Attributes, +{ fn from(s: FlowyStr) -> Self { Insert { s, - attributes: Attributes::default(), + attributes: T::default(), } } } - -fn is_empty(attributes: &Attributes) -> bool { attributes.is_empty() } diff --git a/shared-lib/lib-ot/src/core/operation/operation_serde.rs b/shared-lib/lib-ot/src/core/operation/operation_serde.rs index 868eefdb55..7f8391281e 100644 --- a/shared-lib/lib-ot/src/core/operation/operation_serde.rs +++ b/shared-lib/lib-ot/src/core/operation/operation_serde.rs @@ -1,16 +1,19 @@ -use crate::core::{Attributes, Operation}; +use crate::core::{Attributes, FlowyStr, Insert, Operation, Retain}; use serde::{ de, - de::{MapAccess, Visitor}, + de::{MapAccess, SeqAccess, Visitor}, ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer, }; -use std::fmt; +use std::{fmt, marker::PhantomData}; -impl Serialize for Operation { +impl Serialize for Operation +where + T: Attributes + Serialize, +{ fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -27,20 +30,27 @@ impl Serialize for Operation { } } -impl<'de> Deserialize<'de> for Operation { - fn deserialize(deserializer: D) -> Result +impl<'de, T> Deserialize<'de> for Operation +where + T: Attributes + Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, { - struct OperationVisitor; + struct OperationVisitor(PhantomData T>); - impl<'de> Visitor<'de> for OperationVisitor { - type Value = Operation; + impl<'de, T> Visitor<'de> for OperationVisitor + where + T: Attributes + Deserialize<'de>, + { + type Value = Operation; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("an integer between -2^64 and 2^63 or a string") } + #[inline] fn visit_map(self, mut map: V) -> Result where V: MapAccess<'de>, @@ -53,27 +63,27 @@ impl<'de> Deserialize<'de> for Operation { if operation.is_some() { return Err(de::Error::duplicate_field("operation")); } - operation = Some(Operation::Delete(map.next_value()?)); + operation = Some(Operation::::Delete(map.next_value()?)); }, "retain" => { if operation.is_some() { return Err(de::Error::duplicate_field("operation")); } let i: usize = map.next_value()?; - operation = Some(Operation::Retain(i.into())); + operation = Some(Operation::::Retain(i.into())); }, "insert" => { if operation.is_some() { return Err(de::Error::duplicate_field("operation")); } let i: String = map.next_value()?; - operation = Some(Operation::Insert(i.into())); + operation = Some(Operation::::Insert(i.into())); }, "attributes" => { if attributes.is_some() { return Err(de::Error::duplicate_field("attributes")); } - let map: Attributes = map.next_value()?; + let map: T = map.next_value()?; attributes = Some(map); }, _ => panic!(), @@ -91,6 +101,208 @@ impl<'de> Deserialize<'de> for Operation { } } - deserializer.deserialize_any(OperationVisitor) + deserializer.deserialize_any(OperationVisitor(PhantomData)) + } +} + +impl Serialize for Retain +where + T: Attributes + Serialize, +{ + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let len = false as usize + 1 + if self.attributes.is_empty() { 0 } else { 1 }; + let mut serde_state = serializer.serialize_struct("Retain", len)?; + let _ = serde::ser::SerializeStruct::serialize_field(&mut serde_state, "retain", &self.n)?; + if !self.attributes.is_empty() { + let _ = serde::ser::SerializeStruct::serialize_field(&mut serde_state, "attributes", &self.attributes)?; + } + serde::ser::SerializeStruct::end(serde_state) + } +} + +impl<'de, T> Deserialize<'de> for Retain +where + T: Attributes + Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result>::Error> + where + D: Deserializer<'de>, + { + struct RetainVisitor(PhantomData T>); + + impl<'de, T> Visitor<'de> for RetainVisitor + where + T: Attributes + Deserialize<'de>, + { + type Value = Retain; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("struct Retain") } + + #[inline] + fn visit_seq(self, mut seq: A) -> Result + where + A: SeqAccess<'de>, + { + let len = match serde::de::SeqAccess::next_element::(&mut seq)? { + Some(val) => val, + None => { + return Err(de::Error::invalid_length(0, &"struct Retain with 2 elements")); + }, + }; + + let attributes = match serde::de::SeqAccess::next_element::(&mut seq)? { + Some(val) => val, + None => { + return Err(de::Error::invalid_length(1, &"struct Retain with 2 elements")); + }, + }; + + Ok(Retain:: { n: len, attributes }) + } + + #[inline] + fn visit_map(self, mut map: V) -> Result + where + V: MapAccess<'de>, + { + let mut len: Option = None; + let mut attributes: Option = None; + while let Some(key) = map.next_key()? { + match key { + "retain" => { + if len.is_some() { + return Err(de::Error::duplicate_field("retain")); + } + len = Some(map.next_value()?); + }, + "attributes" => { + if attributes.is_some() { + return Err(de::Error::duplicate_field("attributes")); + } + attributes = Some(map.next_value()?); + }, + _ => panic!(), + } + } + + if len.is_none() { + return Err(de::Error::missing_field("len")); + } + + if attributes.is_none() { + return Err(de::Error::missing_field("attributes")); + } + Ok(Retain:: { + n: len.unwrap(), + attributes: attributes.unwrap(), + }) + } + } + const FIELDS: &[&str] = &["retain", "attributes"]; + serde::Deserializer::deserialize_struct(deserializer, "Retain", FIELDS, RetainVisitor(PhantomData)) + } +} + +impl Serialize for Insert +where + T: Attributes + Serialize, +{ + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let len = false as usize + 1 + if self.attributes.is_empty() { 0 } else { 1 }; + let mut serde_state = serializer.serialize_struct("Insert", len)?; + let _ = serde::ser::SerializeStruct::serialize_field(&mut serde_state, "insert", &self.s)?; + if !self.attributes.is_empty() { + let _ = serde::ser::SerializeStruct::serialize_field(&mut serde_state, "attributes", &self.attributes)?; + } + serde::ser::SerializeStruct::end(serde_state) + } +} + +impl<'de, T> Deserialize<'de> for Insert +where + T: Attributes + Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result>::Error> + where + D: Deserializer<'de>, + { + struct InsertVisitor(PhantomData T>); + + impl<'de, T> Visitor<'de> for InsertVisitor + where + T: Attributes + Deserialize<'de>, + { + type Value = Insert; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("struct Insert") } + + #[inline] + fn visit_seq(self, mut seq: A) -> Result + where + A: SeqAccess<'de>, + { + let s = match serde::de::SeqAccess::next_element::(&mut seq)? { + Some(val) => val, + None => { + return Err(de::Error::invalid_length(0, &"struct Insert with 2 elements")); + }, + }; + + let attributes = match serde::de::SeqAccess::next_element::(&mut seq)? { + Some(val) => val, + None => { + return Err(de::Error::invalid_length(1, &"struct Retain with 2 elements")); + }, + }; + + Ok(Insert:: { s, attributes }) + } + + #[inline] + fn visit_map(self, mut map: V) -> Result + where + V: MapAccess<'de>, + { + let mut s: Option = None; + let mut attributes: Option = None; + while let Some(key) = map.next_key()? { + match key { + "insert" => { + if s.is_some() { + return Err(de::Error::duplicate_field("insert")); + } + s = Some(map.next_value()?); + }, + "attributes" => { + if attributes.is_some() { + return Err(de::Error::duplicate_field("attributes")); + } + attributes = Some(map.next_value()?); + }, + _ => panic!(), + } + } + + if s.is_none() { + return Err(de::Error::missing_field("s")); + } + + if attributes.is_none() { + return Err(de::Error::missing_field("attributes")); + } + Ok(Insert:: { + s: s.unwrap(), + attributes: attributes.unwrap(), + }) + } + } + const FIELDS: &[&str] = &["insert", "attributes"]; + serde::Deserializer::deserialize_struct(deserializer, "Insert", FIELDS, InsertVisitor(PhantomData)) } } From 8a9a23ddbee9c21e9fe481a329aba914a1b17a35 Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 7 Dec 2021 19:59:08 +0800 Subject: [PATCH 06/39] add rich_text crate --- backend/src/services/doc/edit/editor.rs | 2 +- backend/tests/document/edit.rs | 2 +- backend/tests/document/helper.rs | 3 +- .../src/services/doc/edit/editor.rs | 5 +- .../src/services/doc/edit/queue.rs | 5 +- .../src/services/doc/revision/manager.rs | 2 +- .../src/services/doc/revision/persistence.rs | 5 +- .../tests/editor/attribute_test.rs | 3 +- .../flowy-document/tests/editor/mod.rs | 5 +- .../flowy-document/tests/editor/op_test.rs | 5 +- .../flowy-document/tests/editor/serde_test.rs | 5 +- .../flowy-document-infra/src/core/document.rs | 5 +- .../core/extensions/delete/default_delete.rs | 5 +- .../delete/preserve_line_format_merge.rs | 12 +- .../src/core/extensions/format/helper.rs | 5 +- .../extensions/format/resolve_block_format.rs | 11 +- .../format/resolve_inline_format.rs | 5 +- .../core/extensions/insert/auto_exit_block.rs | 10 +- .../src/core/extensions/insert/auto_format.rs | 11 +- .../core/extensions/insert/default_insert.rs | 11 +- .../src/core/extensions/insert/mod.rs | 2 +- .../insert/preserve_block_format.rs | 20 +- .../insert/preserve_inline_format.rs | 11 +- .../insert/reset_format_on_new_line.rs | 11 +- .../src/core/extensions/mod.rs | 5 +- .../flowy-document-infra/src/core/history.rs | 2 +- .../flowy-document-infra/src/core/view.rs | 3 +- .../src/entities/doc/doc.rs | 2 +- .../src/entities/doc/revision.rs | 2 +- .../flowy-document-infra/src/user_default.rs | 2 +- .../lib-ot/src/core/attributes/attributes.rs | 170 ----------------- shared-lib/lib-ot/src/core/delta/delta.rs | 21 ++- shared-lib/lib-ot/src/core/delta/iterator.rs | 5 +- shared-lib/lib-ot/src/core/mod.rs | 2 - .../lib-ot/src/core/operation/builder.rs | 5 +- .../lib-ot/src/core/operation/operation.rs | 5 +- shared-lib/lib-ot/src/lib.rs | 1 + .../attribute.rs => rich_text/attributes.rs} | 176 +++++++++++++++++- .../attributes_serde.rs | 3 +- .../{core/attributes => rich_text}/builder.rs | 3 +- shared-lib/lib-ot/src/rich_text/delta.rs | 3 + .../{core/attributes => rich_text}/macros.rs | 0 .../src/{core/attributes => rich_text}/mod.rs | 5 +- shared-lib/lib-ot/tests/main.rs | 0 44 files changed, 296 insertions(+), 280 deletions(-) delete mode 100644 shared-lib/lib-ot/src/core/attributes/attributes.rs rename shared-lib/lib-ot/src/{core/attributes/attribute.rs => rich_text/attributes.rs} (51%) rename shared-lib/lib-ot/src/{core/attributes => rich_text}/attributes_serde.rs (98%) rename shared-lib/lib-ot/src/{core/attributes => rich_text}/builder.rs (89%) create mode 100644 shared-lib/lib-ot/src/rich_text/delta.rs rename shared-lib/lib-ot/src/{core/attributes => rich_text}/macros.rs (100%) rename shared-lib/lib-ot/src/{core/attributes => rich_text}/mod.rs (62%) create mode 100644 shared-lib/lib-ot/tests/main.rs diff --git a/backend/src/services/doc/edit/editor.rs b/backend/src/services/doc/edit/editor.rs index e685af5a96..49b0929769 100644 --- a/backend/src/services/doc/edit/editor.rs +++ b/backend/src/services/doc/edit/editor.rs @@ -13,7 +13,7 @@ use flowy_document_infra::{ entities::ws::{WsDataType, WsDocumentData}, protobuf::{Doc, RevId, RevType, Revision, RevisionRange, UpdateDocParams}, }; -use lib_ot::core::{OperationTransformable, RichTextDelta}; +use lib_ot::{core::OperationTransformable, rich_text::RichTextDelta}; use parking_lot::RwLock; use protobuf::Message; use sqlx::PgPool; diff --git a/backend/tests/document/edit.rs b/backend/tests/document/edit.rs index d821b0d9e6..30d2be0850 100644 --- a/backend/tests/document/edit.rs +++ b/backend/tests/document/edit.rs @@ -1,6 +1,6 @@ use crate::document::helper::{DocScript, DocumentTest}; use flowy_document_infra::core::{Document, FlowyDoc}; -use lib_ot::core::{Interval, RichTextAttribute}; +use lib_ot::{core::Interval, rich_text::RichTextAttribute}; #[rustfmt::skip] // ┌─────────┐ ┌─────────┐ diff --git a/backend/tests/document/helper.rs b/backend/tests/document/helper.rs index 1e93834b9b..3c173b2028 100644 --- a/backend/tests/document/helper.rs +++ b/backend/tests/document/helper.rs @@ -12,8 +12,9 @@ use tokio::time::{sleep, Duration}; // use crate::helper::*; use crate::util::helper::{spawn_server, TestServer}; use flowy_document_infra::{entities::doc::DocIdentifier, protobuf::UpdateDocParams}; -use lib_ot::core::{RichTextAttribute, RichTextDelta, Interval}; +use lib_ot::rich_text::{RichTextAttribute, RichTextDelta}; use parking_lot::RwLock; +use lib_ot::core::Interval; pub struct DocumentTest { server: TestServer, diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs index 1e8300c781..56560b18d8 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs @@ -17,7 +17,10 @@ use flowy_document_infra::{ errors::DocumentResult, }; use lib_infra::retry::{ExponentialBackoff, Retry}; -use lib_ot::core::{Interval, RichTextAttribute, RichTextDelta}; +use lib_ot::{ + core::Interval, + rich_text::{RichTextAttribute, RichTextDelta}, +}; use lib_ws::WsConnectState; use std::{convert::TryFrom, sync::Arc}; use tokio::sync::{mpsc, mpsc::UnboundedSender, oneshot}; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs index caeb062601..d5a2dc10dd 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs @@ -6,7 +6,10 @@ use flowy_document_infra::{ errors::DocumentError, }; use futures::stream::StreamExt; -use lib_ot::core::{Interval, OperationTransformable, RichTextAttribute, RichTextDelta}; +use lib_ot::{ + core::{Interval, OperationTransformable}, + rich_text::{RichTextAttribute, RichTextDelta}, +}; use std::{convert::TryFrom, sync::Arc}; use tokio::sync::{mpsc, oneshot, RwLock}; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs index 063c82d664..c765b4bbfa 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs @@ -8,7 +8,7 @@ use flowy_document_infra::{ util::RevIdCounter, }; use lib_infra::future::ResultFuture; -use lib_ot::core::{OperationTransformable, RichTextDelta}; +use lib_ot::{core::OperationTransformable, rich_text::RichTextDelta}; use std::sync::Arc; use tokio::sync::mpsc; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/persistence.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/persistence.rs index 1b63e33e88..6c0f808726 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/persistence.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/persistence.rs @@ -9,7 +9,10 @@ use flowy_database::{ConnectionPool, SqliteConnection}; use flowy_document_infra::entities::doc::{revision_from_doc, Doc, RevId, RevType, Revision, RevisionRange}; use futures::stream::StreamExt; use lib_infra::future::ResultFuture; -use lib_ot::core::{Operation, OperationTransformable, RichTextDelta}; +use lib_ot::{ + core::{Operation, OperationTransformable}, + rich_text::RichTextDelta, +}; use std::{collections::VecDeque, sync::Arc, time::Duration}; use tokio::{ sync::{broadcast, mpsc, RwLock}, diff --git a/frontend/rust-lib/flowy-document/tests/editor/attribute_test.rs b/frontend/rust-lib/flowy-document/tests/editor/attribute_test.rs index 80b987262f..957d03d2ef 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/attribute_test.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/attribute_test.rs @@ -1,8 +1,9 @@ #![cfg_attr(rustfmt, rustfmt::skip)] use crate::editor::{TestBuilder, TestOp::*}; use flowy_document_infra::core::{FlowyDoc, PlainDoc}; -use lib_ot::core::{Interval, OperationTransformable, NEW_LINE, WHITESPACE, FlowyStr, RichTextDelta}; +use lib_ot::core::{Interval, OperationTransformable, NEW_LINE, WHITESPACE, FlowyStr}; use unicode_segmentation::UnicodeSegmentation; +use lib_ot::rich_text::RichTextDelta; #[test] fn attributes_bold_added() { diff --git a/frontend/rust-lib/flowy-document/tests/editor/mod.rs b/frontend/rust-lib/flowy-document/tests/editor/mod.rs index 1447fda4f3..a6fb4624b5 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/mod.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/mod.rs @@ -6,7 +6,10 @@ mod undo_redo_test; use derive_more::Display; use flowy_document_infra::core::{CustomDocument, Document}; -use lib_ot::core::*; +use lib_ot::{ + core::*, + rich_text::{RichTextAttribute, RichTextAttributes, RichTextDelta}, +}; use rand::{prelude::*, Rng as WrappedRng}; use std::{sync::Once, time::Duration}; diff --git a/frontend/rust-lib/flowy-document/tests/editor/op_test.rs b/frontend/rust-lib/flowy-document/tests/editor/op_test.rs index deff6dbd8d..7968de167b 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/op_test.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/op_test.rs @@ -1,7 +1,10 @@ #![allow(clippy::all)] use crate::editor::{Rng, TestBuilder, TestOp::*}; use flowy_document_infra::core::{FlowyDoc, PlainDoc}; -use lib_ot::core::*; +use lib_ot::{ + core::*, + rich_text::{AttributeBuilder, RichTextAttribute, RichTextAttributes, RichTextDelta}, +}; #[test] fn attributes_insert_text() { diff --git a/frontend/rust-lib/flowy-document/tests/editor/serde_test.rs b/frontend/rust-lib/flowy-document/tests/editor/serde_test.rs index 5f634bce5e..a4a0ff3994 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/serde_test.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/serde_test.rs @@ -1,5 +1,8 @@ use flowy_document_infra::core::{Document, PlainDoc}; -use lib_ot::core::*; +use lib_ot::{ + core::*, + rich_text::{AttributeBuilder, RichTextAttribute, RichTextAttributeValue, RichTextDelta}, +}; #[test] fn operation_insert_serialize_test() { diff --git a/shared-lib/flowy-document-infra/src/core/document.rs b/shared-lib/flowy-document-infra/src/core/document.rs index 31a8f40986..0618f56ee4 100644 --- a/shared-lib/flowy-document-infra/src/core/document.rs +++ b/shared-lib/flowy-document-infra/src/core/document.rs @@ -6,7 +6,10 @@ use crate::{ errors::DocumentError, user_default::doc_initial_delta, }; -use lib_ot::core::*; +use lib_ot::{ + core::*, + rich_text::{RichTextAttribute, RichTextDelta}, +}; use tokio::sync::mpsc; pub trait CustomDocument { diff --git a/shared-lib/flowy-document-infra/src/core/extensions/delete/default_delete.rs b/shared-lib/flowy-document-infra/src/core/extensions/delete/default_delete.rs index a96f8c5a34..32c767cd5d 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/delete/default_delete.rs +++ b/shared-lib/flowy-document-infra/src/core/extensions/delete/default_delete.rs @@ -1,5 +1,8 @@ use crate::core::extensions::DeleteExt; -use lib_ot::core::{DeltaBuilder, Interval, RichTextDelta}; +use lib_ot::{ + core::{DeltaBuilder, Interval}, + rich_text::RichTextDelta, +}; pub struct DefaultDelete {} impl DeleteExt for DefaultDelete { diff --git a/shared-lib/flowy-document-infra/src/core/extensions/delete/preserve_line_format_merge.rs b/shared-lib/flowy-document-infra/src/core/extensions/delete/preserve_line_format_merge.rs index c49a40dfa5..8b8ed215e8 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/delete/preserve_line_format_merge.rs +++ b/shared-lib/flowy-document-infra/src/core/extensions/delete/preserve_line_format_merge.rs @@ -1,13 +1,7 @@ use crate::{core::extensions::DeleteExt, util::is_newline}; -use lib_ot::core::{ - plain_attributes, - Attributes, - CharMetric, - DeltaBuilder, - DeltaIter, - Interval, - RichTextDelta, - NEW_LINE, +use lib_ot::{ + core::{Attributes, CharMetric, DeltaBuilder, DeltaIter, Interval, NEW_LINE}, + rich_text::{plain_attributes, RichTextDelta}, }; pub struct PreserveLineFormatOnMerge {} diff --git a/shared-lib/flowy-document-infra/src/core/extensions/format/helper.rs b/shared-lib/flowy-document-infra/src/core/extensions/format/helper.rs index 1ecb3b3589..d800595ffb 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/format/helper.rs +++ b/shared-lib/flowy-document-infra/src/core/extensions/format/helper.rs @@ -1,5 +1,8 @@ use crate::util::find_newline; -use lib_ot::core::{plain_attributes, AttributeScope, RichTextAttribute, RichTextDelta, RichTextOperation}; +use lib_ot::{ + core::RichTextOperation, + rich_text::{plain_attributes, AttributeScope, RichTextAttribute, RichTextDelta}, +}; pub(crate) fn line_break( op: &RichTextOperation, diff --git a/shared-lib/flowy-document-infra/src/core/extensions/format/resolve_block_format.rs b/shared-lib/flowy-document-infra/src/core/extensions/format/resolve_block_format.rs index 0af20a1bac..7854a6fbc5 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/format/resolve_block_format.rs +++ b/shared-lib/flowy-document-infra/src/core/extensions/format/resolve_block_format.rs @@ -2,14 +2,9 @@ use crate::{ core::extensions::{format::helper::line_break, FormatExt}, util::find_newline, }; -use lib_ot::core::{ - plain_attributes, - AttributeScope, - DeltaBuilder, - DeltaIter, - Interval, - RichTextAttribute, - RichTextDelta, +use lib_ot::{ + core::{DeltaBuilder, DeltaIter, Interval}, + rich_text::{plain_attributes, AttributeScope, RichTextAttribute, RichTextDelta}, }; pub struct ResolveBlockFormat {} diff --git a/shared-lib/flowy-document-infra/src/core/extensions/format/resolve_inline_format.rs b/shared-lib/flowy-document-infra/src/core/extensions/format/resolve_inline_format.rs index e85839104c..82ae255559 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/format/resolve_inline_format.rs +++ b/shared-lib/flowy-document-infra/src/core/extensions/format/resolve_inline_format.rs @@ -2,7 +2,10 @@ use crate::{ core::extensions::{format::helper::line_break, FormatExt}, util::find_newline, }; -use lib_ot::core::{AttributeScope, DeltaBuilder, DeltaIter, Interval, RichTextAttribute, RichTextDelta}; +use lib_ot::{ + core::{DeltaBuilder, DeltaIter, Interval}, + rich_text::{AttributeScope, RichTextAttribute, RichTextDelta}, +}; pub struct ResolveInlineFormat {} impl FormatExt for ResolveInlineFormat { diff --git a/shared-lib/flowy-document-infra/src/core/extensions/insert/auto_exit_block.rs b/shared-lib/flowy-document-infra/src/core/extensions/insert/auto_exit_block.rs index d440cd8060..8b9fa77d2a 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/insert/auto_exit_block.rs +++ b/shared-lib/flowy-document-infra/src/core/extensions/insert/auto_exit_block.rs @@ -1,11 +1,7 @@ use crate::{core::extensions::InsertExt, util::is_newline}; -use lib_ot::core::{ - attributes_except_header, - is_empty_line_at_index, - DeltaBuilder, - DeltaIter, - RichTextAttributeKey, - RichTextDelta, +use lib_ot::{ + core::{is_empty_line_at_index, DeltaBuilder, DeltaIter}, + rich_text::{attributes_except_header, RichTextAttributeKey, RichTextDelta}, }; pub struct AutoExitBlock {} diff --git a/shared-lib/flowy-document-infra/src/core/extensions/insert/auto_format.rs b/shared-lib/flowy-document-infra/src/core/extensions/insert/auto_format.rs index 5f517a43c5..4887f80ba4 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/insert/auto_format.rs +++ b/shared-lib/flowy-document-infra/src/core/extensions/insert/auto_format.rs @@ -1,12 +1,7 @@ use crate::{core::extensions::InsertExt, util::is_whitespace}; -use lib_ot::core::{ - count_utf16_code_units, - plain_attributes, - DeltaBuilder, - DeltaIter, - RichTextAttribute, - RichTextAttributes, - RichTextDelta, +use lib_ot::{ + core::{count_utf16_code_units, DeltaBuilder, DeltaIter}, + rich_text::{plain_attributes, RichTextAttribute, RichTextAttributes, RichTextDelta}, }; use std::cmp::min; use url::Url; diff --git a/shared-lib/flowy-document-infra/src/core/extensions/insert/default_insert.rs b/shared-lib/flowy-document-infra/src/core/extensions/insert/default_insert.rs index 76f31d84e2..1d3e897427 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/insert/default_insert.rs +++ b/shared-lib/flowy-document-infra/src/core/extensions/insert/default_insert.rs @@ -1,12 +1,7 @@ use crate::core::extensions::InsertExt; -use lib_ot::core::{ - Attributes, - DeltaBuilder, - DeltaIter, - RichTextAttributeKey, - RichTextAttributes, - RichTextDelta, - NEW_LINE, +use lib_ot::{ + core::{Attributes, DeltaBuilder, DeltaIter, NEW_LINE}, + rich_text::{RichTextAttributeKey, RichTextAttributes, RichTextDelta}, }; pub struct DefaultInsertAttribute {} diff --git a/shared-lib/flowy-document-infra/src/core/extensions/insert/mod.rs b/shared-lib/flowy-document-infra/src/core/extensions/insert/mod.rs index fe8e167915..8e353018d0 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/insert/mod.rs +++ b/shared-lib/flowy-document-infra/src/core/extensions/insert/mod.rs @@ -2,7 +2,7 @@ use crate::core::extensions::InsertExt; pub use auto_exit_block::*; pub use auto_format::*; pub use default_insert::*; -use lib_ot::core::RichTextDelta; +use lib_ot::rich_text::RichTextDelta; pub use preserve_block_format::*; pub use preserve_inline_format::*; pub use reset_format_on_new_line::*; diff --git a/shared-lib/flowy-document-infra/src/core/extensions/insert/preserve_block_format.rs b/shared-lib/flowy-document-infra/src/core/extensions/insert/preserve_block_format.rs index 671b1bbe74..47301f7090 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/insert/preserve_block_format.rs +++ b/shared-lib/flowy-document-infra/src/core/extensions/insert/preserve_block_format.rs @@ -1,14 +1,14 @@ use crate::{core::extensions::InsertExt, util::is_newline}; -use lib_ot::core::{ - attributes_except_header, - plain_attributes, - DeltaBuilder, - DeltaIter, - RichTextAttribute, - RichTextAttributeKey, - RichTextAttributes, - RichTextDelta, - NEW_LINE, +use lib_ot::{ + core::{DeltaBuilder, DeltaIter, NEW_LINE}, + rich_text::{ + attributes_except_header, + plain_attributes, + RichTextAttribute, + RichTextAttributeKey, + RichTextAttributes, + RichTextDelta, + }, }; pub struct PreserveBlockFormatOnInsert {} diff --git a/shared-lib/flowy-document-infra/src/core/extensions/insert/preserve_inline_format.rs b/shared-lib/flowy-document-infra/src/core/extensions/insert/preserve_inline_format.rs index 11b4e188fc..d97d913c31 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/insert/preserve_inline_format.rs +++ b/shared-lib/flowy-document-infra/src/core/extensions/insert/preserve_inline_format.rs @@ -2,14 +2,9 @@ use crate::{ core::extensions::InsertExt, util::{contain_newline, is_newline}, }; -use lib_ot::core::{ - plain_attributes, - DeltaBuilder, - DeltaIter, - OpNewline, - RichTextAttributeKey, - RichTextDelta, - NEW_LINE, +use lib_ot::{ + core::{DeltaBuilder, DeltaIter, OpNewline, NEW_LINE}, + rich_text::{plain_attributes, RichTextAttributeKey, RichTextDelta}, }; pub struct PreserveInlineFormat {} diff --git a/shared-lib/flowy-document-infra/src/core/extensions/insert/reset_format_on_new_line.rs b/shared-lib/flowy-document-infra/src/core/extensions/insert/reset_format_on_new_line.rs index d1abaf3179..4e22c5767c 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/insert/reset_format_on_new_line.rs +++ b/shared-lib/flowy-document-infra/src/core/extensions/insert/reset_format_on_new_line.rs @@ -1,12 +1,7 @@ use crate::{core::extensions::InsertExt, util::is_newline}; -use lib_ot::core::{ - CharMetric, - DeltaBuilder, - DeltaIter, - RichTextAttributeKey, - RichTextAttributes, - RichTextDelta, - NEW_LINE, +use lib_ot::{ + core::{CharMetric, DeltaBuilder, DeltaIter, NEW_LINE}, + rich_text::{RichTextAttributeKey, RichTextAttributes, RichTextDelta}, }; pub struct ResetLineFormatOnNewLine {} diff --git a/shared-lib/flowy-document-infra/src/core/extensions/mod.rs b/shared-lib/flowy-document-infra/src/core/extensions/mod.rs index 31f8b1189c..4c67f6b888 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/mod.rs +++ b/shared-lib/flowy-document-infra/src/core/extensions/mod.rs @@ -2,7 +2,10 @@ pub use delete::*; pub use format::*; pub use insert::*; -use lib_ot::core::{Interval, RichTextAttribute, RichTextDelta}; +use lib_ot::{ + core::Interval, + rich_text::{RichTextAttribute, RichTextDelta}, +}; mod delete; mod format; diff --git a/shared-lib/flowy-document-infra/src/core/history.rs b/shared-lib/flowy-document-infra/src/core/history.rs index 82c411b109..a233263824 100644 --- a/shared-lib/flowy-document-infra/src/core/history.rs +++ b/shared-lib/flowy-document-infra/src/core/history.rs @@ -1,4 +1,4 @@ -use lib_ot::core::RichTextDelta; +use lib_ot::rich_text::RichTextDelta; const MAX_UNDOS: usize = 20; diff --git a/shared-lib/flowy-document-infra/src/core/view.rs b/shared-lib/flowy-document-infra/src/core/view.rs index cd2d61c73e..9f5335def5 100644 --- a/shared-lib/flowy-document-infra/src/core/view.rs +++ b/shared-lib/flowy-document-infra/src/core/view.rs @@ -1,7 +1,8 @@ use crate::core::extensions::*; use lib_ot::{ - core::{trim, Interval, RichTextAttribute, RichTextDelta}, + core::{trim, Interval}, errors::{ErrorBuilder, OTError, OTErrorCode}, + rich_text::{RichTextAttribute, RichTextDelta}, }; pub const RECORD_THRESHOLD: usize = 400; // in milliseconds diff --git a/shared-lib/flowy-document-infra/src/entities/doc/doc.rs b/shared-lib/flowy-document-infra/src/entities/doc/doc.rs index 90b4c73056..151bef5b57 100644 --- a/shared-lib/flowy-document-infra/src/entities/doc/doc.rs +++ b/shared-lib/flowy-document-infra/src/entities/doc/doc.rs @@ -1,5 +1,5 @@ use flowy_derive::ProtoBuf; -use lib_ot::{core::RichTextDelta, errors::OTError}; +use lib_ot::{errors::OTError, rich_text::RichTextDelta}; #[derive(ProtoBuf, Default, Debug, Clone)] pub struct CreateDocParams { diff --git a/shared-lib/flowy-document-infra/src/entities/doc/revision.rs b/shared-lib/flowy-document-infra/src/entities/doc/revision.rs index ba4a68d86d..cb0ea3ce25 100644 --- a/shared-lib/flowy-document-infra/src/entities/doc/revision.rs +++ b/shared-lib/flowy-document-infra/src/entities/doc/revision.rs @@ -1,6 +1,6 @@ use crate::{entities::doc::Doc, util::md5}; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; -use lib_ot::core::RichTextDelta; +use lib_ot::rich_text::RichTextDelta; use std::{fmt::Formatter, ops::RangeInclusive}; #[derive(Debug, ProtoBuf_Enum, Clone, Eq, PartialEq)] diff --git a/shared-lib/flowy-document-infra/src/user_default.rs b/shared-lib/flowy-document-infra/src/user_default.rs index 91cf28321d..961d3a377a 100644 --- a/shared-lib/flowy-document-infra/src/user_default.rs +++ b/shared-lib/flowy-document-infra/src/user_default.rs @@ -1,4 +1,4 @@ -use lib_ot::core::{DeltaBuilder, RichTextDelta}; +use lib_ot::{core::DeltaBuilder, rich_text::RichTextDelta}; #[inline] pub fn doc_initial_delta() -> RichTextDelta { DeltaBuilder::new().insert("\n").build() } diff --git a/shared-lib/lib-ot/src/core/attributes/attributes.rs b/shared-lib/lib-ot/src/core/attributes/attributes.rs deleted file mode 100644 index c52c4a7898..0000000000 --- a/shared-lib/lib-ot/src/core/attributes/attributes.rs +++ /dev/null @@ -1,170 +0,0 @@ -use crate::{ - core::{ - Attributes, - OperationTransformable, - RichTextAttribute, - RichTextAttributeKey, - RichTextAttributeValue, - RichTextOperation, - }, - errors::OTError, -}; -use std::{collections::HashMap, fmt}; - -#[derive(Debug, Clone, Eq, PartialEq)] -pub struct RichTextAttributes { - pub(crate) inner: HashMap, -} - -impl std::default::Default for RichTextAttributes { - fn default() -> Self { - Self { - inner: HashMap::with_capacity(0), - } - } -} - -impl fmt::Display for RichTextAttributes { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_fmt(format_args!("{:?}", self.inner)) } -} - -pub fn plain_attributes() -> RichTextAttributes { RichTextAttributes::default() } - -impl RichTextAttributes { - pub fn new() -> Self { RichTextAttributes { inner: HashMap::new() } } - - pub fn is_empty(&self) -> bool { self.inner.is_empty() } - - pub fn add(&mut self, attribute: RichTextAttribute) { - let RichTextAttribute { key, value, scope: _ } = attribute; - self.inner.insert(key, value); - } - - pub fn add_kv(&mut self, key: RichTextAttributeKey, value: RichTextAttributeValue) { - self.inner.insert(key, value); - } - - pub fn delete(&mut self, key: &RichTextAttributeKey) { - self.inner.insert(key.clone(), RichTextAttributeValue(None)); - } - - pub fn mark_all_as_removed_except(&mut self, attribute: Option) { - match attribute { - None => { - self.inner.iter_mut().for_each(|(_k, v)| v.0 = None); - }, - Some(attribute) => { - self.inner.iter_mut().for_each(|(k, v)| { - if k != &attribute { - v.0 = None; - } - }); - }, - } - } - - pub fn remove(&mut self, key: RichTextAttributeKey) { self.inner.retain(|k, _| k != &key); } - - // pub fn block_attributes_except_header(attributes: &Attributes) -> Attributes - // { let mut new_attributes = Attributes::new(); - // attributes.iter().for_each(|(k, v)| { - // if k != &AttributeKey::Header { - // new_attributes.insert(k.clone(), v.clone()); - // } - // }); - // - // new_attributes - // } - - // Update inner by constructing new attributes from the other if it's - // not None and replace the key/value with self key/value. - pub fn merge(&mut self, other: Option) { - if other.is_none() { - return; - } - - let mut new_attributes = other.unwrap().inner; - self.inner.iter().for_each(|(k, v)| { - new_attributes.insert(k.clone(), v.clone()); - }); - self.inner = new_attributes; - } -} - -impl Attributes for RichTextAttributes { - fn is_empty(&self) -> bool { self.inner.is_empty() } - - fn remove_empty(&mut self) { self.inner.retain(|_, v| v.0.is_some()); } - - fn extend_other(&mut self, other: Self) { self.inner.extend(other.inner); } -} - -impl OperationTransformable for RichTextAttributes { - fn compose(&self, other: &Self) -> Result - where - Self: Sized, - { - let mut attributes = self.clone(); - attributes.extend_other(other.clone()); - Ok(attributes) - } - - fn transform(&self, other: &Self) -> Result<(Self, Self), OTError> - where - Self: Sized, - { - let a = self - .iter() - .fold(RichTextAttributes::new(), |mut new_attributes, (k, v)| { - if !other.contains_key(k) { - new_attributes.insert(k.clone(), v.clone()); - } - new_attributes - }); - - let b = other - .iter() - .fold(RichTextAttributes::new(), |mut new_attributes, (k, v)| { - if !self.contains_key(k) { - new_attributes.insert(k.clone(), v.clone()); - } - new_attributes - }); - - Ok((a, b)) - } - - fn invert(&self, other: &Self) -> Self { - let base_inverted = other.iter().fold(RichTextAttributes::new(), |mut attributes, (k, v)| { - if other.get(k) != self.get(k) && self.contains_key(k) { - attributes.insert(k.clone(), v.clone()); - } - attributes - }); - - let inverted = self.iter().fold(base_inverted, |mut attributes, (k, _)| { - if other.get(k) != self.get(k) && !other.contains_key(k) { - attributes.delete(k); - } - attributes - }); - - inverted - } -} - -impl std::ops::Deref for RichTextAttributes { - type Target = HashMap; - - fn deref(&self) -> &Self::Target { &self.inner } -} - -impl std::ops::DerefMut for RichTextAttributes { - fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner } -} - -pub fn attributes_except_header(op: &RichTextOperation) -> RichTextAttributes { - let mut attributes = op.get_attributes(); - attributes.remove(RichTextAttributeKey::Header); - attributes -} diff --git a/shared-lib/lib-ot/src/core/delta/delta.rs b/shared-lib/lib-ot/src/core/delta/delta.rs index fc78cd3ae3..d219a14288 100644 --- a/shared-lib/lib-ot/src/core/delta/delta.rs +++ b/shared-lib/lib-ot/src/core/delta/delta.rs @@ -1,5 +1,5 @@ use crate::{ - core::{attributes::*, operation::*, DeltaIter, FlowyStr, Interval, OperationTransformable, MAX_IV_LEN}, + core::{operation::*, DeltaIter, FlowyStr, Interval, OperationTransformable, MAX_IV_LEN}, errors::{ErrorBuilder, OTError, OTErrorCode}, }; use bytes::Bytes; @@ -469,8 +469,6 @@ fn transform_op_attribute(left: &Option>, right: &Op left.transform(&right).unwrap().0 } -pub type RichTextDelta = Delta; - impl Delta where T: Attributes + DeserializeOwned, @@ -503,22 +501,31 @@ where } } -impl FromStr for RichTextDelta { +impl FromStr for Delta +where + T: Attributes, +{ type Err = (); - fn from_str(s: &str) -> Result { + fn from_str(s: &str) -> Result, Self::Err> { let mut delta = Delta::with_capacity(1); delta.add(Operation::Insert(s.into())); Ok(delta) } } -impl std::convert::TryFrom> for RichTextDelta { +impl std::convert::TryFrom> for Delta +where + T: Attributes + DeserializeOwned, +{ type Error = OTError; fn try_from(bytes: Vec) -> Result { Delta::from_bytes(bytes) } } -impl std::convert::TryFrom for RichTextDelta { +impl std::convert::TryFrom for Delta +where + T: Attributes + DeserializeOwned, +{ type Error = OTError; fn try_from(bytes: Bytes) -> Result { Delta::from_bytes(&bytes) } diff --git a/shared-lib/lib-ot/src/core/delta/iterator.rs b/shared-lib/lib-ot/src/core/delta/iterator.rs index 478428877c..5a45e21ca8 100644 --- a/shared-lib/lib-ot/src/core/delta/iterator.rs +++ b/shared-lib/lib-ot/src/core/delta/iterator.rs @@ -1,5 +1,8 @@ use super::cursor::*; -use crate::core::{Attributes, Delta, Interval, Operation, RichTextAttributes, NEW_LINE}; +use crate::{ + core::{Attributes, Delta, Interval, Operation, NEW_LINE}, + rich_text::RichTextAttributes, +}; use std::ops::{Deref, DerefMut}; pub(crate) const MAX_IV_LEN: usize = i32::MAX as usize; diff --git a/shared-lib/lib-ot/src/core/mod.rs b/shared-lib/lib-ot/src/core/mod.rs index 6897ef8c63..b5bc594246 100644 --- a/shared-lib/lib-ot/src/core/mod.rs +++ b/shared-lib/lib-ot/src/core/mod.rs @@ -1,11 +1,9 @@ -mod attributes; mod delta; mod flowy_str; mod interval; mod operation; use crate::errors::OTError; -pub use attributes::*; pub use delta::*; pub use flowy_str::*; pub use interval::*; diff --git a/shared-lib/lib-ot/src/core/operation/builder.rs b/shared-lib/lib-ot/src/core/operation/builder.rs index d7484a3613..efd63c2bff 100644 --- a/shared-lib/lib-ot/src/core/operation/builder.rs +++ b/shared-lib/lib-ot/src/core/operation/builder.rs @@ -1,4 +1,7 @@ -use crate::core::{Attributes, Operation, RichTextAttributes}; +use crate::{ + core::{Attributes, Operation}, + rich_text::RichTextAttributes, +}; pub type RichTextOpBuilder = OpBuilder; diff --git a/shared-lib/lib-ot/src/core/operation/operation.rs b/shared-lib/lib-ot/src/core/operation/operation.rs index c8f74370e2..13a775e356 100644 --- a/shared-lib/lib-ot/src/core/operation/operation.rs +++ b/shared-lib/lib-ot/src/core/operation/operation.rs @@ -1,4 +1,7 @@ -use crate::core::{FlowyStr, Interval, OpBuilder, OperationTransformable, RichTextAttribute, RichTextAttributes}; +use crate::{ + core::{FlowyStr, Interval, OpBuilder, OperationTransformable}, + rich_text::{RichTextAttribute, RichTextAttributes}, +}; use serde::__private::Formatter; use std::{ cmp::min, diff --git a/shared-lib/lib-ot/src/lib.rs b/shared-lib/lib-ot/src/lib.rs index fec82dd9cf..5a3be0ede7 100644 --- a/shared-lib/lib-ot/src/lib.rs +++ b/shared-lib/lib-ot/src/lib.rs @@ -1,2 +1,3 @@ pub mod core; pub mod errors; +pub mod rich_text; diff --git a/shared-lib/lib-ot/src/core/attributes/attribute.rs b/shared-lib/lib-ot/src/rich_text/attributes.rs similarity index 51% rename from shared-lib/lib-ot/src/core/attributes/attribute.rs rename to shared-lib/lib-ot/src/rich_text/attributes.rs index 45fe5fbec9..5af66a817a 100644 --- a/shared-lib/lib-ot/src/core/attributes/attribute.rs +++ b/shared-lib/lib-ot/src/rich_text/attributes.rs @@ -1,11 +1,179 @@ #![allow(non_snake_case)] - -use crate::{block_attribute, core::RichTextAttributes, ignore_attribute, inline_attribute, list_attribute}; +use crate::{ + block_attribute, + core::{Attributes, OperationTransformable, RichTextOperation}, + errors::OTError, + ignore_attribute, + inline_attribute, + list_attribute, +}; use lazy_static::lazy_static; - -use std::{collections::HashSet, fmt, fmt::Formatter, iter::FromIterator}; +use std::{ + collections::{HashMap, HashSet}, + fmt, + fmt::Formatter, + iter::FromIterator, +}; use strum_macros::Display; +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct RichTextAttributes { + pub(crate) inner: HashMap, +} + +impl std::default::Default for RichTextAttributes { + fn default() -> Self { + Self { + inner: HashMap::with_capacity(0), + } + } +} + +impl fmt::Display for RichTextAttributes { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_fmt(format_args!("{:?}", self.inner)) } +} + +pub fn plain_attributes() -> RichTextAttributes { RichTextAttributes::default() } + +impl RichTextAttributes { + pub fn new() -> Self { RichTextAttributes { inner: HashMap::new() } } + + pub fn is_empty(&self) -> bool { self.inner.is_empty() } + + pub fn add(&mut self, attribute: RichTextAttribute) { + let RichTextAttribute { key, value, scope: _ } = attribute; + self.inner.insert(key, value); + } + + pub fn add_kv(&mut self, key: RichTextAttributeKey, value: RichTextAttributeValue) { + self.inner.insert(key, value); + } + + pub fn delete(&mut self, key: &RichTextAttributeKey) { + self.inner.insert(key.clone(), RichTextAttributeValue(None)); + } + + pub fn mark_all_as_removed_except(&mut self, attribute: Option) { + match attribute { + None => { + self.inner.iter_mut().for_each(|(_k, v)| v.0 = None); + }, + Some(attribute) => { + self.inner.iter_mut().for_each(|(k, v)| { + if k != &attribute { + v.0 = None; + } + }); + }, + } + } + + pub fn remove(&mut self, key: RichTextAttributeKey) { self.inner.retain(|k, _| k != &key); } + + // pub fn block_attributes_except_header(attributes: &Attributes) -> Attributes + // { let mut new_attributes = Attributes::new(); + // attributes.iter().for_each(|(k, v)| { + // if k != &AttributeKey::Header { + // new_attributes.insert(k.clone(), v.clone()); + // } + // }); + // + // new_attributes + // } + + // Update inner by constructing new attributes from the other if it's + // not None and replace the key/value with self key/value. + pub fn merge(&mut self, other: Option) { + if other.is_none() { + return; + } + + let mut new_attributes = other.unwrap().inner; + self.inner.iter().for_each(|(k, v)| { + new_attributes.insert(k.clone(), v.clone()); + }); + self.inner = new_attributes; + } +} + +impl Attributes for RichTextAttributes { + fn is_empty(&self) -> bool { self.inner.is_empty() } + + fn remove_empty(&mut self) { self.inner.retain(|_, v| v.0.is_some()); } + + fn extend_other(&mut self, other: Self) { self.inner.extend(other.inner); } +} + +impl OperationTransformable for RichTextAttributes { + fn compose(&self, other: &Self) -> Result + where + Self: Sized, + { + let mut attributes = self.clone(); + attributes.extend_other(other.clone()); + Ok(attributes) + } + + fn transform(&self, other: &Self) -> Result<(Self, Self), OTError> + where + Self: Sized, + { + let a = self + .iter() + .fold(RichTextAttributes::new(), |mut new_attributes, (k, v)| { + if !other.contains_key(k) { + new_attributes.insert(k.clone(), v.clone()); + } + new_attributes + }); + + let b = other + .iter() + .fold(RichTextAttributes::new(), |mut new_attributes, (k, v)| { + if !self.contains_key(k) { + new_attributes.insert(k.clone(), v.clone()); + } + new_attributes + }); + + Ok((a, b)) + } + + fn invert(&self, other: &Self) -> Self { + let base_inverted = other.iter().fold(RichTextAttributes::new(), |mut attributes, (k, v)| { + if other.get(k) != self.get(k) && self.contains_key(k) { + attributes.insert(k.clone(), v.clone()); + } + attributes + }); + + let inverted = self.iter().fold(base_inverted, |mut attributes, (k, _)| { + if other.get(k) != self.get(k) && !other.contains_key(k) { + attributes.delete(k); + } + attributes + }); + + inverted + } +} + +impl std::ops::Deref for RichTextAttributes { + type Target = HashMap; + + fn deref(&self) -> &Self::Target { &self.inner } +} + +impl std::ops::DerefMut for RichTextAttributes { + fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner } +} + +pub fn attributes_except_header(op: &RichTextOperation) -> RichTextAttributes { + let mut attributes = op.get_attributes(); + attributes.remove(RichTextAttributeKey::Header); + attributes +} + #[derive(Debug, Clone)] pub struct RichTextAttribute { pub key: RichTextAttributeKey, diff --git a/shared-lib/lib-ot/src/core/attributes/attributes_serde.rs b/shared-lib/lib-ot/src/rich_text/attributes_serde.rs similarity index 98% rename from shared-lib/lib-ot/src/core/attributes/attributes_serde.rs rename to shared-lib/lib-ot/src/rich_text/attributes_serde.rs index 5552297b72..87506ecd99 100644 --- a/shared-lib/lib-ot/src/core/attributes/attributes_serde.rs +++ b/shared-lib/lib-ot/src/rich_text/attributes_serde.rs @@ -1,6 +1,5 @@ #[rustfmt::skip] -use crate::core::RichTextAttributeValue; -use crate::core::{RichTextAttribute, RichTextAttributeKey, RichTextAttributes}; +use crate::rich_text::{RichTextAttribute, RichTextAttributeKey, RichTextAttributes, RichTextAttributeValue}; use serde::{ de, de::{MapAccess, Visitor}, diff --git a/shared-lib/lib-ot/src/core/attributes/builder.rs b/shared-lib/lib-ot/src/rich_text/builder.rs similarity index 89% rename from shared-lib/lib-ot/src/core/attributes/builder.rs rename to shared-lib/lib-ot/src/rich_text/builder.rs index 98c0721371..40d9666d1d 100644 --- a/shared-lib/lib-ot/src/core/attributes/builder.rs +++ b/shared-lib/lib-ot/src/rich_text/builder.rs @@ -1,5 +1,6 @@ #![allow(non_snake_case)] -use crate::core::{RichTextAttribute, RichTextAttributes}; +use crate::rich_text::{RichTextAttribute, RichTextAttributes}; + pub struct AttributeBuilder { inner: RichTextAttributes, } diff --git a/shared-lib/lib-ot/src/rich_text/delta.rs b/shared-lib/lib-ot/src/rich_text/delta.rs new file mode 100644 index 0000000000..03f3b2479f --- /dev/null +++ b/shared-lib/lib-ot/src/rich_text/delta.rs @@ -0,0 +1,3 @@ +use crate::{core::Delta, rich_text::RichTextAttributes}; + +pub type RichTextDelta = Delta; diff --git a/shared-lib/lib-ot/src/core/attributes/macros.rs b/shared-lib/lib-ot/src/rich_text/macros.rs similarity index 100% rename from shared-lib/lib-ot/src/core/attributes/macros.rs rename to shared-lib/lib-ot/src/rich_text/macros.rs diff --git a/shared-lib/lib-ot/src/core/attributes/mod.rs b/shared-lib/lib-ot/src/rich_text/mod.rs similarity index 62% rename from shared-lib/lib-ot/src/core/attributes/mod.rs rename to shared-lib/lib-ot/src/rich_text/mod.rs index 8df7b064a3..c4f09161ac 100644 --- a/shared-lib/lib-ot/src/core/attributes/mod.rs +++ b/shared-lib/lib-ot/src/rich_text/mod.rs @@ -1,12 +1,11 @@ -#![allow(clippy::module_inception)] -mod attribute; mod attributes; mod attributes_serde; mod builder; #[macro_use] mod macros; +mod delta; -pub use attribute::*; pub use attributes::*; pub use builder::*; +pub use delta::*; diff --git a/shared-lib/lib-ot/tests/main.rs b/shared-lib/lib-ot/tests/main.rs new file mode 100644 index 0000000000..e69de29bb2 From 23f4684d3f361cd8727398b8d8e4acb4cebfeb1a Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 7 Dec 2021 22:32:34 +0800 Subject: [PATCH 07/39] add revision cache layer --- backend/Cargo.lock | 5 + backend/src/services/doc/edit/edit_actor.rs | 3 +- backend/src/services/doc/edit/editor.rs | 8 +- backend/src/services/doc/manager.rs | 3 +- backend/src/services/doc/ws_actor.rs | 3 +- .../flowy-document-infra/protobuf.dart | 1 - .../revision.pb.dart => lib-ot/model.pb.dart} | 100 ++--- .../model.pbenum.dart} | 2 +- .../model.pbjson.dart} | 22 +- .../model.pbserver.dart} | 4 +- .../lib/protobuf/lib-ot/protobuf.dart | 2 + .../src/services/doc/edit/editor.rs | 3 +- .../src/services/doc/edit/model.rs | 3 +- .../src/services/doc/edit/queue.rs | 2 +- .../src/services/doc/revision/manager.rs | 11 +- .../src/services/doc/revision/model.rs | 41 +- .../src/services/doc/revision/persistence.rs | 22 +- .../src/sql_tables/doc/rev_sql.rs | 6 +- .../src/sql_tables/doc/rev_table.rs | 36 +- shared-lib/Cargo.lock | 5 + .../src/derive_cache/derive_cache.rs | 8 +- .../src/entities/doc/mod.rs | 2 - .../src/entities/ws/ws.rs | 6 +- .../src/protobuf/model/mod.rs | 3 - shared-lib/lib-ot/Cargo.toml | 6 + shared-lib/lib-ot/Flowy.toml | 3 + shared-lib/lib-ot/src/errors.rs | 26 +- shared-lib/lib-ot/src/lib.rs | 2 + shared-lib/lib-ot/src/protobuf/mod.rs | 4 + shared-lib/lib-ot/src/protobuf/model/mod.rs | 5 + .../src/protobuf/model/model.rs} | 399 +++++++++--------- .../src/protobuf/proto/model.proto} | 6 +- shared-lib/lib-ot/src/revision/cache.rs | 109 +++++ shared-lib/lib-ot/src/revision/mod.rs | 5 + .../src/revision/model.rs} | 100 ++--- 35 files changed, 549 insertions(+), 417 deletions(-) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-document-infra/revision.pb.dart => lib-ot/model.pb.dart} (99%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-document-infra/revision.pbenum.dart => lib-ot/model.pbenum.dart} (97%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-document-infra/revision.pbjson.dart => lib-ot/model.pbjson.dart} (99%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-document-infra/revision.pbserver.dart => lib-ot/model.pbserver.dart} (85%) create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/protobuf.dart create mode 100644 shared-lib/lib-ot/Flowy.toml create mode 100644 shared-lib/lib-ot/src/protobuf/mod.rs create mode 100644 shared-lib/lib-ot/src/protobuf/model/mod.rs rename shared-lib/{flowy-document-infra/src/protobuf/model/revision.rs => lib-ot/src/protobuf/model/model.rs} (87%) rename shared-lib/{flowy-document-infra/src/protobuf/proto/revision.proto => lib-ot/src/protobuf/proto/model.proto} (100%) create mode 100644 shared-lib/lib-ot/src/revision/cache.rs create mode 100644 shared-lib/lib-ot/src/revision/mod.rs rename shared-lib/{flowy-document-infra/src/entities/doc/revision.rs => lib-ot/src/revision/model.rs} (79%) diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 7efe8c9b83..2b3c3bd2c3 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -1972,13 +1972,18 @@ version = "0.1.0" dependencies = [ "bytecount", "bytes", + "dashmap", "derive_more", + "flowy-derive", "lazy_static", "log", + "md5", + "protobuf", "serde", "serde_json", "strum", "strum_macros", + "tokio", "tracing", ] diff --git a/backend/src/services/doc/edit/edit_actor.rs b/backend/src/services/doc/edit/edit_actor.rs index 985bf49d00..f73dfa0237 100644 --- a/backend/src/services/doc/edit/edit_actor.rs +++ b/backend/src/services/doc/edit/edit_actor.rs @@ -5,8 +5,9 @@ use crate::{ use actix_web::web::Data; use async_stream::stream; use backend_service::errors::{internal_error, Result as DocResult, ServerError}; -use flowy_document_infra::protobuf::{Doc, Revision}; +use flowy_document_infra::protobuf::Doc; use futures::stream::StreamExt; +use lib_ot::protobuf::Revision; use sqlx::PgPool; use std::sync::{atomic::Ordering::SeqCst, Arc}; use tokio::{ diff --git a/backend/src/services/doc/edit/editor.rs b/backend/src/services/doc/edit/editor.rs index 49b0929769..96b10c710d 100644 --- a/backend/src/services/doc/edit/editor.rs +++ b/backend/src/services/doc/edit/editor.rs @@ -11,9 +11,13 @@ use dashmap::DashMap; use flowy_document_infra::{ core::Document, entities::ws::{WsDataType, WsDocumentData}, - protobuf::{Doc, RevId, RevType, Revision, RevisionRange, UpdateDocParams}, + protobuf::{Doc, UpdateDocParams}, +}; +use lib_ot::{ + core::OperationTransformable, + protobuf::{RevId, RevType, Revision, RevisionRange}, + rich_text::RichTextDelta, }; -use lib_ot::{core::OperationTransformable, rich_text::RichTextDelta}; use parking_lot::RwLock; use protobuf::Message; use sqlx::PgPool; diff --git a/backend/src/services/doc/manager.rs b/backend/src/services/doc/manager.rs index 960edd5e8e..f0de848da1 100644 --- a/backend/src/services/doc/manager.rs +++ b/backend/src/services/doc/manager.rs @@ -9,7 +9,8 @@ use crate::{ use actix_web::web::Data; use backend_service::errors::{internal_error, Result as DocResult, ServerError}; use dashmap::DashMap; -use flowy_document_infra::protobuf::{Doc, DocIdentifier, Revision}; +use flowy_document_infra::protobuf::{Doc, DocIdentifier}; +use lib_ot::protobuf::Revision; use sqlx::PgPool; use std::sync::Arc; use tokio::{ diff --git a/backend/src/services/doc/ws_actor.rs b/backend/src/services/doc/ws_actor.rs index 0ba431fff6..1a8fa60de0 100644 --- a/backend/src/services/doc/ws_actor.rs +++ b/backend/src/services/doc/ws_actor.rs @@ -9,8 +9,9 @@ use actix_rt::task::spawn_blocking; use actix_web::web::Data; use async_stream::stream; use backend_service::errors::{internal_error, Result as DocResult, ServerError}; -use flowy_document_infra::protobuf::{NewDocUser, Revision, WsDataType, WsDocumentData}; +use flowy_document_infra::protobuf::{NewDocUser, WsDataType, WsDocumentData}; use futures::stream::StreamExt; +use lib_ot::protobuf::Revision; use sqlx::PgPool; use std::sync::Arc; use tokio::sync::{mpsc, oneshot}; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/protobuf.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/protobuf.dart index 7626c5708b..bba338f3b8 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/protobuf.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/protobuf.dart @@ -1,4 +1,3 @@ // Auto-generated, do not edit export './ws.pb.dart'; -export './revision.pb.dart'; export './doc.pb.dart'; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/revision.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/model.pb.dart similarity index 99% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/revision.pb.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/model.pb.dart index 979820558d..a19ab537be 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/revision.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/model.pb.dart @@ -1,6 +1,6 @@ /// // Generated code. Do not modify. -// source: revision.proto +// source: model.proto // // @dart = 2.12 // ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields @@ -10,56 +10,9 @@ import 'dart:core' as $core; import 'package:fixnum/fixnum.dart' as $fixnum; import 'package:protobuf/protobuf.dart' as $pb; -import 'revision.pbenum.dart'; +import 'model.pbenum.dart'; -export 'revision.pbenum.dart'; - -class RevId extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'RevId', createEmptyInstance: create) - ..aInt64(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'value') - ..hasRequiredFields = false - ; - - RevId._() : super(); - factory RevId({ - $fixnum.Int64? value, - }) { - final _result = create(); - if (value != null) { - _result.value = value; - } - return _result; - } - factory RevId.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory RevId.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' - 'Will be removed in next major version') - RevId clone() => RevId()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - RevId copyWith(void Function(RevId) updates) => super.copyWith((message) => updates(message as RevId)) as RevId; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static RevId create() => RevId._(); - RevId createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static RevId getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static RevId? _defaultInstance; - - @$pb.TagNumber(1) - $fixnum.Int64 get value => $_getI64(0); - @$pb.TagNumber(1) - set value($fixnum.Int64 v) { $_setInt64(0, v); } - @$pb.TagNumber(1) - $core.bool hasValue() => $_has(0); - @$pb.TagNumber(1) - void clearValue() => clearField(1); -} +export 'model.pbenum.dart'; class Revision extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'Revision', createEmptyInstance: create) @@ -178,6 +131,53 @@ class Revision extends $pb.GeneratedMessage { void clearTy() => clearField(6); } +class RevId extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'RevId', createEmptyInstance: create) + ..aInt64(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'value') + ..hasRequiredFields = false + ; + + RevId._() : super(); + factory RevId({ + $fixnum.Int64? value, + }) { + final _result = create(); + if (value != null) { + _result.value = value; + } + return _result; + } + factory RevId.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory RevId.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + RevId clone() => RevId()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + RevId copyWith(void Function(RevId) updates) => super.copyWith((message) => updates(message as RevId)) as RevId; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static RevId create() => RevId._(); + RevId createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static RevId getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static RevId? _defaultInstance; + + @$pb.TagNumber(1) + $fixnum.Int64 get value => $_getI64(0); + @$pb.TagNumber(1) + set value($fixnum.Int64 v) { $_setInt64(0, v); } + @$pb.TagNumber(1) + $core.bool hasValue() => $_has(0); + @$pb.TagNumber(1) + void clearValue() => clearField(1); +} + class RevisionRange extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'RevisionRange', createEmptyInstance: create) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'docId') diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/revision.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/model.pbenum.dart similarity index 97% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/revision.pbenum.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/model.pbenum.dart index 0921ea3229..cd22cc9f89 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/revision.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/model.pbenum.dart @@ -1,6 +1,6 @@ /// // Generated code. Do not modify. -// source: revision.proto +// source: model.proto // // @dart = 2.12 // ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/revision.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/model.pbjson.dart similarity index 99% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/revision.pbjson.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/model.pbjson.dart index 08933d02c7..8b52c2439e 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/revision.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/model.pbjson.dart @@ -1,6 +1,6 @@ /// // Generated code. Do not modify. -// source: revision.proto +// source: model.proto // // @dart = 2.12 // ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package @@ -19,16 +19,6 @@ const RevType$json = const { /// Descriptor for `RevType`. Decode as a `google.protobuf.EnumDescriptorProto`. final $typed_data.Uint8List revTypeDescriptor = $convert.base64Decode('CgdSZXZUeXBlEgkKBUxvY2FsEAASCgoGUmVtb3RlEAE='); -@$core.Deprecated('Use revIdDescriptor instead') -const RevId$json = const { - '1': 'RevId', - '2': const [ - const {'1': 'value', '3': 1, '4': 1, '5': 3, '10': 'value'}, - ], -}; - -/// Descriptor for `RevId`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List revIdDescriptor = $convert.base64Decode('CgVSZXZJZBIUCgV2YWx1ZRgBIAEoA1IFdmFsdWU='); @$core.Deprecated('Use revisionDescriptor instead') const Revision$json = const { '1': 'Revision', @@ -44,6 +34,16 @@ const Revision$json = const { /// Descriptor for `Revision`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List revisionDescriptor = $convert.base64Decode('CghSZXZpc2lvbhIeCgtiYXNlX3Jldl9pZBgBIAEoA1IJYmFzZVJldklkEhUKBnJldl9pZBgCIAEoA1IFcmV2SWQSHQoKZGVsdGFfZGF0YRgDIAEoDFIJZGVsdGFEYXRhEhAKA21kNRgEIAEoCVIDbWQ1EhUKBmRvY19pZBgFIAEoCVIFZG9jSWQSGAoCdHkYBiABKA4yCC5SZXZUeXBlUgJ0eQ=='); +@$core.Deprecated('Use revIdDescriptor instead') +const RevId$json = const { + '1': 'RevId', + '2': const [ + const {'1': 'value', '3': 1, '4': 1, '5': 3, '10': 'value'}, + ], +}; + +/// Descriptor for `RevId`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List revIdDescriptor = $convert.base64Decode('CgVSZXZJZBIUCgV2YWx1ZRgBIAEoA1IFdmFsdWU='); @$core.Deprecated('Use revisionRangeDescriptor instead') const RevisionRange$json = const { '1': 'RevisionRange', diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/revision.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/model.pbserver.dart similarity index 85% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/revision.pbserver.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/model.pbserver.dart index 4797cc3361..0a058aba64 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/revision.pbserver.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/model.pbserver.dart @@ -1,9 +1,9 @@ /// // Generated code. Do not modify. -// source: revision.proto +// source: model.proto // // @dart = 2.12 // ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package -export 'revision.pb.dart'; +export 'model.pb.dart'; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/protobuf.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/protobuf.dart new file mode 100644 index 0000000000..f524faf0c8 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/protobuf.dart @@ -0,0 +1,2 @@ +// Auto-generated, do not edit +export './model.pb.dart'; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs index 56560b18d8..119a2335cf 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs @@ -11,7 +11,7 @@ use flowy_database::ConnectionPool; use flowy_document_infra::{ core::history::UndoResult, entities::{ - doc::{DocDelta, RevId, RevType, Revision, RevisionRange}, + doc::DocDelta, ws::{WsDataType, WsDocumentData}, }, errors::DocumentResult, @@ -19,6 +19,7 @@ use flowy_document_infra::{ use lib_infra::retry::{ExponentialBackoff, Retry}; use lib_ot::{ core::Interval, + revision::{RevId, RevType, Revision, RevisionRange}, rich_text::{RichTextAttribute, RichTextDelta}, }; use lib_ws::WsConnectState; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/model.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/model.rs index 62bbb76da4..2916dce85a 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/model.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/model.rs @@ -1,7 +1,8 @@ use crate::{errors::DocError, services::ws::DocumentWebSocket}; -use flowy_document_infra::entities::doc::{NewDocUser, RevId}; +use flowy_document_infra::entities::doc::NewDocUser; use futures::future::BoxFuture; use lib_infra::retry::Action; +use lib_ot::revision::RevId; use std::{future, sync::Arc}; pub(crate) struct OpenDocAction { diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs index d5a2dc10dd..5e9c94dd10 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs @@ -2,12 +2,12 @@ use async_stream::stream; use bytes::Bytes; use flowy_document_infra::{ core::{history::UndoResult, Document}, - entities::doc::{RevId, Revision}, errors::DocumentError, }; use futures::stream::StreamExt; use lib_ot::{ core::{Interval, OperationTransformable}, + revision::{RevId, Revision}, rich_text::{RichTextAttribute, RichTextDelta}, }; use std::{convert::TryFrom, sync::Arc}; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs index c765b4bbfa..84f9679227 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs @@ -3,12 +3,13 @@ use crate::{ services::doc::revision::RevisionStore, }; use flowy_database::ConnectionPool; -use flowy_document_infra::{ - entities::doc::{Doc, RevId, RevType, Revision, RevisionRange}, - util::RevIdCounter, -}; +use flowy_document_infra::{entities::doc::Doc, util::RevIdCounter}; use lib_infra::future::ResultFuture; -use lib_ot::{core::OperationTransformable, rich_text::RichTextDelta}; +use lib_ot::{ + core::OperationTransformable, + revision::{RevId, RevType, Revision, RevisionRange}, + rich_text::RichTextDelta, +}; use std::sync::Arc; use tokio::sync::mpsc; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/model.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/model.rs index 2922a04383..51e2d68fe3 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/model.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/model.rs @@ -1,48 +1,13 @@ use crate::{ errors::{internal_error, DocError, DocResult}, - sql_tables::{RevState, RevTableSql}, + sql_tables::{RevTableSql, SqlRevState}, }; use flowy_database::ConnectionPool; -use flowy_document_infra::entities::doc::{Revision, RevisionRange}; use lib_infra::future::ResultFuture; +use lib_ot::revision::{Revision, RevisionRange}; use std::sync::Arc; use tokio::sync::broadcast; -pub type RevIdReceiver = broadcast::Receiver; -pub type RevIdSender = broadcast::Sender; - -pub struct RevisionRecord { - pub revision: Revision, - pub state: RevState, -} - -impl RevisionRecord { - pub fn new(revision: Revision) -> Self { - Self { - revision, - state: RevState::Local, - } - } -} - -pub(crate) struct PendingRevId { - pub rev_id: i64, - pub sender: RevIdSender, -} - -impl PendingRevId { - pub(crate) fn new(rev_id: i64, sender: RevIdSender) -> Self { Self { rev_id, sender } } - - pub(crate) fn finish(&self, rev_id: i64) -> bool { - if self.rev_id > rev_id { - false - } else { - let _ = self.sender.send(self.rev_id); - true - } - } -} - pub(crate) struct Persistence { pub(crate) rev_sql: Arc, pub(crate) pool: Arc, @@ -54,7 +19,7 @@ impl Persistence { Self { rev_sql, pool } } - pub(crate) fn create_revs(&self, revisions: Vec<(Revision, RevState)>) -> DocResult<()> { + pub(crate) fn create_revs(&self, revisions: Vec<(Revision, SqlRevState)>) -> DocResult<()> { let conn = &*self.pool.get().map_err(internal_error)?; conn.immediate_transaction::<_, DocError, _>(|| { let _ = self.rev_sql.create_rev_table(revisions, conn)?; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/persistence.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/persistence.rs index 6c0f808726..5b866181a9 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/persistence.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/persistence.rs @@ -1,16 +1,17 @@ use crate::{ errors::{internal_error, DocError, DocResult}, services::doc::revision::{model::*, RevisionServer}, - sql_tables::RevState, + sql_tables::SqlRevState, }; use async_stream::stream; use dashmap::DashMap; use flowy_database::{ConnectionPool, SqliteConnection}; -use flowy_document_infra::entities::doc::{revision_from_doc, Doc, RevId, RevType, Revision, RevisionRange}; +use flowy_document_infra::entities::doc::Doc; use futures::stream::StreamExt; use lib_infra::future::ResultFuture; use lib_ot::{ core::{Operation, OperationTransformable}, + revision::{PendingRevId, RevId, RevIdReceiver, RevType, Revision, RevisionRange, RevisionRecord}, rich_text::RichTextDelta, }; use std::{collections::VecDeque, sync::Arc, time::Duration}; @@ -52,7 +53,7 @@ impl RevisionStore { server, }); - tokio::spawn(RevisionStream::new(store.clone(), pending_rx, ws_revision_sender).run()); + tokio::spawn(RevisionUploadStream::new(store.clone(), pending_rx, ws_revision_sender).run()); store } @@ -70,7 +71,7 @@ impl RevisionStore { if let Ok(rev_id) = rx.recv().await { match revs_map.get_mut(&rev_id) { None => {}, - Some(mut rev) => rev.value_mut().state = RevState::Acked, + Some(mut rev) => rev.value_mut().state = SqlRevState::Acked.into(), } } }); @@ -113,7 +114,7 @@ impl RevisionStore { let revisions_state = revs_map .iter() .map(|kv| (kv.revision.clone(), kv.state)) - .collect::>(); + .collect::>(); match persistence.create_revs(revisions_state.clone()) { Ok(_) => { @@ -157,11 +158,16 @@ impl RevisionStore { let doc = self.server.fetch_document_from_remote(&self.doc_id).await?; let revision = revision_from_doc(doc.clone(), RevType::Remote); - let _ = self.persistence.create_revs(vec![(revision, RevState::Acked)])?; + let _ = self.persistence.create_revs(vec![(revision, SqlRevState::Acked)])?; Ok(doc) } } +pub fn revision_from_doc(doc: Doc, ty: RevType) -> Revision { + let delta_data = doc.data.as_bytes(); + Revision::new(doc.base_rev_id, doc.rev_id, delta_data.to_owned(), &doc.id, ty) +} + impl RevisionIterator for RevisionStore { fn next(&self) -> ResultFuture, DocError> { let pending_revs = self.pending_revs.clone(); @@ -316,13 +322,13 @@ pub(crate) enum PendingMsg { pub(crate) type PendingSender = mpsc::UnboundedSender; pub(crate) type PendingReceiver = mpsc::UnboundedReceiver; -pub(crate) struct RevisionStream { +pub(crate) struct RevisionUploadStream { revisions: Arc, receiver: Option, ws_revision_sender: mpsc::UnboundedSender, } -impl RevisionStream { +impl RevisionUploadStream { pub(crate) fn new( revisions: Arc, pending_rx: PendingReceiver, diff --git a/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_sql.rs b/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_sql.rs index cc5d15a463..2098693535 100644 --- a/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_sql.rs +++ b/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_sql.rs @@ -1,17 +1,17 @@ use crate::{ errors::DocError, - sql_tables::{doc::RevTable, RevChangeset, RevState, RevTableType}, + sql_tables::{doc::RevTable, RevChangeset, RevTableType, SqlRevState}, }; use diesel::update; use flowy_database::{insert_or_ignore_into, prelude::*, schema::rev_table::dsl, SqliteConnection}; -use flowy_document_infra::entities::doc::{Revision, RevisionRange}; +use lib_ot::revision::{Revision, RevisionRange}; pub struct RevTableSql {} impl RevTableSql { pub(crate) fn create_rev_table( &self, - revisions: Vec<(Revision, RevState)>, + revisions: Vec<(Revision, SqlRevState)>, conn: &SqliteConnection, ) -> Result<(), DocError> { // Batch insert: https://diesel.rs/guides/all-about-inserts.html diff --git a/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_table.rs b/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_table.rs index 6294168744..6d5ff19052 100644 --- a/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_table.rs +++ b/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_table.rs @@ -1,9 +1,7 @@ use diesel::sql_types::Integer; use flowy_database::schema::rev_table; -use flowy_document_infra::{ - entities::doc::{RevId, RevType, Revision}, - util::md5, -}; +use flowy_document_infra::util::md5; +use lib_ot::revision::{RevId, RevState, RevType, Revision}; #[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable, Associations)] #[table_name = "rev_table"] @@ -13,39 +11,49 @@ pub(crate) struct RevTable { pub(crate) base_rev_id: i64, pub(crate) rev_id: i64, pub(crate) data: Vec, - pub(crate) state: RevState, + pub(crate) state: SqlRevState, pub(crate) ty: RevTableType, } #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, FromSqlRow, AsExpression)] #[repr(i32)] #[sql_type = "Integer"] -pub enum RevState { +pub enum SqlRevState { Local = 0, Acked = 1, } -impl std::default::Default for RevState { - fn default() -> Self { RevState::Local } +impl std::default::Default for SqlRevState { + fn default() -> Self { SqlRevState::Local } } -impl std::convert::From for RevState { +impl std::convert::From for SqlRevState { fn from(value: i32) -> Self { match value { - 0 => RevState::Local, - 1 => RevState::Acked, + 0 => SqlRevState::Local, + 1 => SqlRevState::Acked, o => { log::error!("Unsupported rev state {}, fallback to RevState::Local", o); - RevState::Local + SqlRevState::Local }, } } } -impl RevState { + +impl SqlRevState { pub fn value(&self) -> i32 { *self as i32 } } impl_sql_integer_expression!(RevState); +impl std::convert::From for RevState { + fn from(s: SqlRevState) -> Self { + match s { + SqlRevState::Local => RevState.Local, + SqlRevState::Acked => RevState.Acked, + } + } +} + impl std::convert::From for Revision { fn from(table: RevTable) -> Self { let md5 = md5(&table.data); @@ -111,5 +119,5 @@ impl_sql_integer_expression!(RevTableType); pub(crate) struct RevChangeset { pub(crate) doc_id: String, pub(crate) rev_id: RevId, - pub(crate) state: RevState, + pub(crate) state: SqlRevState, } diff --git a/shared-lib/Cargo.lock b/shared-lib/Cargo.lock index b6c108e131..eafd1ca8d7 100644 --- a/shared-lib/Cargo.lock +++ b/shared-lib/Cargo.lock @@ -1128,13 +1128,18 @@ version = "0.1.0" dependencies = [ "bytecount", "bytes", + "dashmap", "derive_more", + "flowy-derive", "lazy_static", "log", + "md5", + "protobuf", "serde", "serde_json", "strum", "strum_macros", + "tokio", "tracing", ] diff --git a/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs b/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs index bbb6284bf4..f5f90b2b79 100644 --- a/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs +++ b/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs @@ -63,12 +63,12 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { | "DocDelta" | "NewDocUser" | "DocIdentifier" - | "RevId" - | "Revision" - | "RevisionRange" | "WsDocumentData" | "WsError" | "WsMessage" + | "Revision" + | "RevId" + | "RevisionRange" | "SignInRequest" | "SignInParams" | "SignInResponse" @@ -91,9 +91,9 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { | "TrashType" | "ViewType" | "ExportType" - | "RevType" | "WsDataType" | "WsModule" + | "RevType" => TypeCategory::Enum, "Option" => TypeCategory::Opt, diff --git a/shared-lib/flowy-document-infra/src/entities/doc/mod.rs b/shared-lib/flowy-document-infra/src/entities/doc/mod.rs index 3bfe846c63..ef2ed9076d 100644 --- a/shared-lib/flowy-document-infra/src/entities/doc/mod.rs +++ b/shared-lib/flowy-document-infra/src/entities/doc/mod.rs @@ -1,7 +1,5 @@ #![allow(clippy::module_inception)] mod doc; pub mod parser; -mod revision; pub use doc::*; -pub use revision::*; diff --git a/shared-lib/flowy-document-infra/src/entities/ws/ws.rs b/shared-lib/flowy-document-infra/src/entities/ws/ws.rs index b332a0f79c..c7457eaf12 100644 --- a/shared-lib/flowy-document-infra/src/entities/ws/ws.rs +++ b/shared-lib/flowy-document-infra/src/entities/ws/ws.rs @@ -1,9 +1,7 @@ -use crate::{ - entities::doc::{NewDocUser, Revision}, - errors::DocumentError, -}; +use crate::{entities::doc::NewDocUser, errors::DocumentError}; use bytes::Bytes; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; +use lib_ot::revision::Revision; use std::convert::{TryFrom, TryInto}; #[derive(Debug, Clone, ProtoBuf_Enum, Eq, PartialEq, Hash)] diff --git a/shared-lib/flowy-document-infra/src/protobuf/model/mod.rs b/shared-lib/flowy-document-infra/src/protobuf/model/mod.rs index 28f1c42882..8989e8fbdf 100644 --- a/shared-lib/flowy-document-infra/src/protobuf/model/mod.rs +++ b/shared-lib/flowy-document-infra/src/protobuf/model/mod.rs @@ -4,8 +4,5 @@ mod ws; pub use ws::*; -mod revision; -pub use revision::*; - mod doc; pub use doc::*; diff --git a/shared-lib/lib-ot/Cargo.toml b/shared-lib/lib-ot/Cargo.toml index 2fa2437165..d6b99d19e2 100644 --- a/shared-lib/lib-ot/Cargo.toml +++ b/shared-lib/lib-ot/Cargo.toml @@ -8,6 +8,12 @@ edition = "2018" [dependencies] bytecount = "0.6.0" serde = { version = "1.0", features = ["derive"] } +protobuf = {version = "2.18.0"} +flowy-derive = { path = "../flowy-derive" } +tokio = {version = "1", features = ["sync"]} +dashmap = "4.0" +md5 = "0.7.0" + serde_json = {version = "1.0"} derive_more = {version = "0.99", features = ["display"]} log = "0.4" diff --git a/shared-lib/lib-ot/Flowy.toml b/shared-lib/lib-ot/Flowy.toml new file mode 100644 index 0000000000..cd4d90ffd0 --- /dev/null +++ b/shared-lib/lib-ot/Flowy.toml @@ -0,0 +1,3 @@ + +proto_crates = ["src/revision"] +event_files = [] \ No newline at end of file diff --git a/shared-lib/lib-ot/src/errors.rs b/shared-lib/lib-ot/src/errors.rs index b7ae81150e..5f67d699ac 100644 --- a/shared-lib/lib-ot/src/errors.rs +++ b/shared-lib/lib-ot/src/errors.rs @@ -1,4 +1,4 @@ -use std::{error::Error, fmt, str::Utf8Error}; +use std::{error::Error, fmt, fmt::Debug, str::Utf8Error}; #[derive(Clone, Debug)] pub struct OTError { @@ -6,6 +6,22 @@ pub struct OTError { pub msg: String, } +macro_rules! static_ot_error { + ($name:ident, $code:expr) => { + #[allow(non_snake_case, missing_docs)] + pub fn $name() -> OTError { $code.into() } + }; +} + +impl std::convert::From for OTError { + fn from(code: OTErrorCode) -> Self { + OTError { + code: code.clone(), + msg: format!("{:?}", code), + } + } +} + impl OTError { pub fn new(code: OTErrorCode, msg: &str) -> OTError { Self { @@ -13,6 +29,13 @@ impl OTError { msg: msg.to_owned(), } } + + pub fn context(mut self, error: T) -> Self { + self.msg = format!("{:?}", error); + self + } + + static_ot_error!(duplicate_revision, OTErrorCode::DuplicatedRevision); } impl fmt::Display for OTError { @@ -42,6 +65,7 @@ pub enum OTErrorCode { UndoFail, RedoFail, SerdeError, + DuplicatedRevision, } pub struct ErrorBuilder { diff --git a/shared-lib/lib-ot/src/lib.rs b/shared-lib/lib-ot/src/lib.rs index 5a3be0ede7..f66fdabd84 100644 --- a/shared-lib/lib-ot/src/lib.rs +++ b/shared-lib/lib-ot/src/lib.rs @@ -1,3 +1,5 @@ pub mod core; pub mod errors; +pub mod protobuf; +pub mod revision; pub mod rich_text; diff --git a/shared-lib/lib-ot/src/protobuf/mod.rs b/shared-lib/lib-ot/src/protobuf/mod.rs new file mode 100644 index 0000000000..da97aad28a --- /dev/null +++ b/shared-lib/lib-ot/src/protobuf/mod.rs @@ -0,0 +1,4 @@ +#![cfg_attr(rustfmt, rustfmt::skip)] +// Auto-generated, do not edit +mod model; +pub use model::*; \ No newline at end of file diff --git a/shared-lib/lib-ot/src/protobuf/model/mod.rs b/shared-lib/lib-ot/src/protobuf/model/mod.rs new file mode 100644 index 0000000000..d30d09866a --- /dev/null +++ b/shared-lib/lib-ot/src/protobuf/model/mod.rs @@ -0,0 +1,5 @@ +#![cfg_attr(rustfmt, rustfmt::skip)] +// Auto-generated, do not edit + +mod model; +pub use model::*; diff --git a/shared-lib/flowy-document-infra/src/protobuf/model/revision.rs b/shared-lib/lib-ot/src/protobuf/model/model.rs similarity index 87% rename from shared-lib/flowy-document-infra/src/protobuf/model/revision.rs rename to shared-lib/lib-ot/src/protobuf/model/model.rs index 83bd5e7ad0..125f1cc78c 100644 --- a/shared-lib/flowy-document-infra/src/protobuf/model/revision.rs +++ b/shared-lib/lib-ot/src/protobuf/model/model.rs @@ -17,164 +17,12 @@ #![allow(trivial_casts)] #![allow(unused_imports)] #![allow(unused_results)] -//! Generated file from `revision.proto` +//! Generated file from `model.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 RevId { - // message fields - pub value: i64, - // special fields - pub unknown_fields: ::protobuf::UnknownFields, - pub cached_size: ::protobuf::CachedSize, -} - -impl<'a> ::std::default::Default for &'a RevId { - fn default() -> &'a RevId { - ::default_instance() - } -} - -impl RevId { - pub fn new() -> RevId { - ::std::default::Default::default() - } - - // int64 value = 1; - - - pub fn get_value(&self) -> i64 { - self.value - } - pub fn clear_value(&mut self) { - self.value = 0; - } - - // Param is passed by value, moved - pub fn set_value(&mut self, v: i64) { - self.value = v; - } -} - -impl ::protobuf::Message for RevId { - 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_int64()?; - self.value = tmp; - }, - _ => { - ::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.value != 0 { - my_size += ::protobuf::rt::value_size(1, self.value, ::protobuf::wire_format::WireTypeVarint); - } - 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.value != 0 { - os.write_int64(1, self.value)?; - } - 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) -> ::std::boxed::Box { - self - } - - fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { - Self::descriptor_static() - } - - fn new() -> RevId { - RevId::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::ProtobufTypeInt64>( - "value", - |m: &RevId| { &m.value }, - |m: &mut RevId| { &mut m.value }, - )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "RevId", - fields, - file_descriptor_proto() - ) - }) - } - - fn default_instance() -> &'static RevId { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(RevId::new) - } -} - -impl ::protobuf::Clear for RevId { - fn clear(&mut self) { - self.value = 0; - self.unknown_fields.clear(); - } -} - -impl ::std::fmt::Debug for RevId { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - ::protobuf::text_format::fmt(self, f) - } -} - -impl ::protobuf::reflect::ProtobufValue for RevId { - fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { - ::protobuf::reflect::ReflectValueRef::Message(self) - } -} - #[derive(PartialEq,Clone,Default)] pub struct Revision { // message fields @@ -519,6 +367,158 @@ impl ::protobuf::reflect::ProtobufValue for Revision { } } +#[derive(PartialEq,Clone,Default)] +pub struct RevId { + // message fields + pub value: i64, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a RevId { + fn default() -> &'a RevId { + ::default_instance() + } +} + +impl RevId { + pub fn new() -> RevId { + ::std::default::Default::default() + } + + // int64 value = 1; + + + pub fn get_value(&self) -> i64 { + self.value + } + pub fn clear_value(&mut self) { + self.value = 0; + } + + // Param is passed by value, moved + pub fn set_value(&mut self, v: i64) { + self.value = v; + } +} + +impl ::protobuf::Message for RevId { + 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_int64()?; + self.value = tmp; + }, + _ => { + ::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.value != 0 { + my_size += ::protobuf::rt::value_size(1, self.value, ::protobuf::wire_format::WireTypeVarint); + } + 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.value != 0 { + os.write_int64(1, self.value)?; + } + 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) -> ::std::boxed::Box { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + Self::descriptor_static() + } + + fn new() -> RevId { + RevId::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::ProtobufTypeInt64>( + "value", + |m: &RevId| { &m.value }, + |m: &mut RevId| { &mut m.value }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "RevId", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static RevId { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(RevId::new) + } +} + +impl ::protobuf::Clear for RevId { + fn clear(&mut self) { + self.value = 0; + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for RevId { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for RevId { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + #[derive(PartialEq,Clone,Default)] pub struct RevisionRange { // message fields @@ -799,53 +799,52 @@ impl ::protobuf::reflect::ProtobufValue for RevType { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x0erevision.proto\"\x1d\n\x05RevId\x12\x14\n\x05value\x18\x01\x20\x01\ - (\x03R\x05value\"\xa3\x01\n\x08Revision\x12\x1e\n\x0bbase_rev_id\x18\x01\ - \x20\x01(\x03R\tbaseRevId\x12\x15\n\x06rev_id\x18\x02\x20\x01(\x03R\x05r\ - evId\x12\x1d\n\ndelta_data\x18\x03\x20\x01(\x0cR\tdeltaData\x12\x10\n\ - \x03md5\x18\x04\x20\x01(\tR\x03md5\x12\x15\n\x06doc_id\x18\x05\x20\x01(\ - \tR\x05docId\x12\x18\n\x02ty\x18\x06\x20\x01(\x0e2\x08.RevTypeR\x02ty\"N\ - \n\rRevisionRange\x12\x15\n\x06doc_id\x18\x01\x20\x01(\tR\x05docId\x12\ - \x14\n\x05start\x18\x02\x20\x01(\x03R\x05start\x12\x10\n\x03end\x18\x03\ - \x20\x01(\x03R\x03end*\x20\n\x07RevType\x12\t\n\x05Local\x10\0\x12\n\n\ - \x06Remote\x10\x01J\xea\x05\n\x06\x12\x04\0\0\x15\x01\n\x08\n\x01\x0c\ - \x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x04\x01\n\n\n\x03\x04\0\ - \x01\x12\x03\x02\x08\r\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x14\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\x0f\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x12\x13\n\n\n\x02\ - \x04\x01\x12\x04\x05\0\x0c\x01\n\n\n\x03\x04\x01\x01\x12\x03\x05\x08\x10\ - \n\x0b\n\x04\x04\x01\x02\0\x12\x03\x06\x04\x1a\n\x0c\n\x05\x04\x01\x02\0\ - \x05\x12\x03\x06\x04\t\n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03\x06\n\x15\n\ - \x0c\n\x05\x04\x01\x02\0\x03\x12\x03\x06\x18\x19\n\x0b\n\x04\x04\x01\x02\ - \x01\x12\x03\x07\x04\x15\n\x0c\n\x05\x04\x01\x02\x01\x05\x12\x03\x07\x04\ - \t\n\x0c\n\x05\x04\x01\x02\x01\x01\x12\x03\x07\n\x10\n\x0c\n\x05\x04\x01\ - \x02\x01\x03\x12\x03\x07\x13\x14\n\x0b\n\x04\x04\x01\x02\x02\x12\x03\x08\ - \x04\x19\n\x0c\n\x05\x04\x01\x02\x02\x05\x12\x03\x08\x04\t\n\x0c\n\x05\ - \x04\x01\x02\x02\x01\x12\x03\x08\n\x14\n\x0c\n\x05\x04\x01\x02\x02\x03\ - \x12\x03\x08\x17\x18\n\x0b\n\x04\x04\x01\x02\x03\x12\x03\t\x04\x13\n\x0c\ - \n\x05\x04\x01\x02\x03\x05\x12\x03\t\x04\n\n\x0c\n\x05\x04\x01\x02\x03\ - \x01\x12\x03\t\x0b\x0e\n\x0c\n\x05\x04\x01\x02\x03\x03\x12\x03\t\x11\x12\ - \n\x0b\n\x04\x04\x01\x02\x04\x12\x03\n\x04\x16\n\x0c\n\x05\x04\x01\x02\ - \x04\x05\x12\x03\n\x04\n\n\x0c\n\x05\x04\x01\x02\x04\x01\x12\x03\n\x0b\ - \x11\n\x0c\n\x05\x04\x01\x02\x04\x03\x12\x03\n\x14\x15\n\x0b\n\x04\x04\ - \x01\x02\x05\x12\x03\x0b\x04\x13\n\x0c\n\x05\x04\x01\x02\x05\x06\x12\x03\ - \x0b\x04\x0b\n\x0c\n\x05\x04\x01\x02\x05\x01\x12\x03\x0b\x0c\x0e\n\x0c\n\ - \x05\x04\x01\x02\x05\x03\x12\x03\x0b\x11\x12\n\n\n\x02\x04\x02\x12\x04\r\ - \0\x11\x01\n\n\n\x03\x04\x02\x01\x12\x03\r\x08\x15\n\x0b\n\x04\x04\x02\ - \x02\0\x12\x03\x0e\x04\x16\n\x0c\n\x05\x04\x02\x02\0\x05\x12\x03\x0e\x04\ - \n\n\x0c\n\x05\x04\x02\x02\0\x01\x12\x03\x0e\x0b\x11\n\x0c\n\x05\x04\x02\ - \x02\0\x03\x12\x03\x0e\x14\x15\n\x0b\n\x04\x04\x02\x02\x01\x12\x03\x0f\ - \x04\x14\n\x0c\n\x05\x04\x02\x02\x01\x05\x12\x03\x0f\x04\t\n\x0c\n\x05\ - \x04\x02\x02\x01\x01\x12\x03\x0f\n\x0f\n\x0c\n\x05\x04\x02\x02\x01\x03\ - \x12\x03\x0f\x12\x13\n\x0b\n\x04\x04\x02\x02\x02\x12\x03\x10\x04\x12\n\ - \x0c\n\x05\x04\x02\x02\x02\x05\x12\x03\x10\x04\t\n\x0c\n\x05\x04\x02\x02\ - \x02\x01\x12\x03\x10\n\r\n\x0c\n\x05\x04\x02\x02\x02\x03\x12\x03\x10\x10\ - \x11\n\n\n\x02\x05\0\x12\x04\x12\0\x15\x01\n\n\n\x03\x05\0\x01\x12\x03\ - \x12\x05\x0c\n\x0b\n\x04\x05\0\x02\0\x12\x03\x13\x04\x0e\n\x0c\n\x05\x05\ - \0\x02\0\x01\x12\x03\x13\x04\t\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x13\ - \x0c\r\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x14\x04\x0f\n\x0c\n\x05\x05\0\ - \x02\x01\x01\x12\x03\x14\x04\n\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x14\ - \r\x0eb\x06proto3\ + \n\x0bmodel.proto\"\xa3\x01\n\x08Revision\x12\x1e\n\x0bbase_rev_id\x18\ + \x01\x20\x01(\x03R\tbaseRevId\x12\x15\n\x06rev_id\x18\x02\x20\x01(\x03R\ + \x05revId\x12\x1d\n\ndelta_data\x18\x03\x20\x01(\x0cR\tdeltaData\x12\x10\ + \n\x03md5\x18\x04\x20\x01(\tR\x03md5\x12\x15\n\x06doc_id\x18\x05\x20\x01\ + (\tR\x05docId\x12\x18\n\x02ty\x18\x06\x20\x01(\x0e2\x08.RevTypeR\x02ty\"\ + \x1d\n\x05RevId\x12\x14\n\x05value\x18\x01\x20\x01(\x03R\x05value\"N\n\r\ + RevisionRange\x12\x15\n\x06doc_id\x18\x01\x20\x01(\tR\x05docId\x12\x14\n\ + \x05start\x18\x02\x20\x01(\x03R\x05start\x12\x10\n\x03end\x18\x03\x20\ + \x01(\x03R\x03end*\x20\n\x07RevType\x12\t\n\x05Local\x10\0\x12\n\n\x06Re\ + mote\x10\x01J\xea\x05\n\x06\x12\x04\0\0\x15\x01\n\x08\n\x01\x0c\x12\x03\ + \0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\t\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\x1a\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\ + \x15\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x18\x19\n\x0b\n\x04\x04\0\ + \x02\x01\x12\x03\x04\x04\x15\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\ + \x04\t\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\n\x10\n\x0c\n\x05\x04\0\ + \x02\x01\x03\x12\x03\x04\x13\x14\n\x0b\n\x04\x04\0\x02\x02\x12\x03\x05\ + \x04\x19\n\x0c\n\x05\x04\0\x02\x02\x05\x12\x03\x05\x04\t\n\x0c\n\x05\x04\ + \0\x02\x02\x01\x12\x03\x05\n\x14\n\x0c\n\x05\x04\0\x02\x02\x03\x12\x03\ + \x05\x17\x18\n\x0b\n\x04\x04\0\x02\x03\x12\x03\x06\x04\x13\n\x0c\n\x05\ + \x04\0\x02\x03\x05\x12\x03\x06\x04\n\n\x0c\n\x05\x04\0\x02\x03\x01\x12\ + \x03\x06\x0b\x0e\n\x0c\n\x05\x04\0\x02\x03\x03\x12\x03\x06\x11\x12\n\x0b\ + \n\x04\x04\0\x02\x04\x12\x03\x07\x04\x16\n\x0c\n\x05\x04\0\x02\x04\x05\ + \x12\x03\x07\x04\n\n\x0c\n\x05\x04\0\x02\x04\x01\x12\x03\x07\x0b\x11\n\ + \x0c\n\x05\x04\0\x02\x04\x03\x12\x03\x07\x14\x15\n\x0b\n\x04\x04\0\x02\ + \x05\x12\x03\x08\x04\x13\n\x0c\n\x05\x04\0\x02\x05\x06\x12\x03\x08\x04\ + \x0b\n\x0c\n\x05\x04\0\x02\x05\x01\x12\x03\x08\x0c\x0e\n\x0c\n\x05\x04\0\ + \x02\x05\x03\x12\x03\x08\x11\x12\n\n\n\x02\x04\x01\x12\x04\n\0\x0c\x01\n\ + \n\n\x03\x04\x01\x01\x12\x03\n\x08\r\n\x0b\n\x04\x04\x01\x02\0\x12\x03\ + \x0b\x04\x14\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03\x0b\x04\t\n\x0c\n\x05\ + \x04\x01\x02\0\x01\x12\x03\x0b\n\x0f\n\x0c\n\x05\x04\x01\x02\0\x03\x12\ + \x03\x0b\x12\x13\n\n\n\x02\x04\x02\x12\x04\r\0\x11\x01\n\n\n\x03\x04\x02\ + \x01\x12\x03\r\x08\x15\n\x0b\n\x04\x04\x02\x02\0\x12\x03\x0e\x04\x16\n\ + \x0c\n\x05\x04\x02\x02\0\x05\x12\x03\x0e\x04\n\n\x0c\n\x05\x04\x02\x02\0\ + \x01\x12\x03\x0e\x0b\x11\n\x0c\n\x05\x04\x02\x02\0\x03\x12\x03\x0e\x14\ + \x15\n\x0b\n\x04\x04\x02\x02\x01\x12\x03\x0f\x04\x14\n\x0c\n\x05\x04\x02\ + \x02\x01\x05\x12\x03\x0f\x04\t\n\x0c\n\x05\x04\x02\x02\x01\x01\x12\x03\ + \x0f\n\x0f\n\x0c\n\x05\x04\x02\x02\x01\x03\x12\x03\x0f\x12\x13\n\x0b\n\ + \x04\x04\x02\x02\x02\x12\x03\x10\x04\x12\n\x0c\n\x05\x04\x02\x02\x02\x05\ + \x12\x03\x10\x04\t\n\x0c\n\x05\x04\x02\x02\x02\x01\x12\x03\x10\n\r\n\x0c\ + \n\x05\x04\x02\x02\x02\x03\x12\x03\x10\x10\x11\n\n\n\x02\x05\0\x12\x04\ + \x12\0\x15\x01\n\n\n\x03\x05\0\x01\x12\x03\x12\x05\x0c\n\x0b\n\x04\x05\0\ + \x02\0\x12\x03\x13\x04\x0e\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\x13\x04\t\ + \n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x13\x0c\r\n\x0b\n\x04\x05\0\x02\x01\ + \x12\x03\x14\x04\x0f\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x14\x04\n\n\ + \x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x14\r\x0eb\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/shared-lib/flowy-document-infra/src/protobuf/proto/revision.proto b/shared-lib/lib-ot/src/protobuf/proto/model.proto similarity index 100% rename from shared-lib/flowy-document-infra/src/protobuf/proto/revision.proto rename to shared-lib/lib-ot/src/protobuf/proto/model.proto index 44a3137bc1..9ed4f2ea15 100644 --- a/shared-lib/flowy-document-infra/src/protobuf/proto/revision.proto +++ b/shared-lib/lib-ot/src/protobuf/proto/model.proto @@ -1,8 +1,5 @@ syntax = "proto3"; -message RevId { - int64 value = 1; -} message Revision { int64 base_rev_id = 1; int64 rev_id = 2; @@ -11,6 +8,9 @@ message Revision { string doc_id = 5; RevType ty = 6; } +message RevId { + int64 value = 1; +} message RevisionRange { string doc_id = 1; int64 start = 2; diff --git a/shared-lib/lib-ot/src/revision/cache.rs b/shared-lib/lib-ot/src/revision/cache.rs new file mode 100644 index 0000000000..0a4023b4d5 --- /dev/null +++ b/shared-lib/lib-ot/src/revision/cache.rs @@ -0,0 +1,109 @@ +use crate::{ + errors::OTError, + revision::{RevId, Revision, RevisionRange}, +}; +use dashmap::{mapref::one::RefMut, DashMap}; +use std::{collections::VecDeque, sync::Arc}; +use tokio::sync::{broadcast, RwLock}; + +pub trait RevisionDiskCache { + fn create_revision(&self, revision: &Revision) -> Result<(), OTError>; + fn revisions_in_range(&self, range: RevisionRange) -> Result>, OTError>; + fn read_revision(&self, rev_id: i64) -> Result, OTError>; +} + +pub struct RevisionMemoryCache { + revs_map: Arc>, + pending_revs: Arc>>, +} + +impl std::default::Default for RevisionMemoryCache { + fn default() -> Self { + let pending_revs = Arc::new(RwLock::new(VecDeque::new())); + RevisionMemoryCache { + revs_map: Arc::new(DashMap::new()), + pending_revs, + } + } +} + +impl RevisionMemoryCache { + pub fn new() -> Self { RevisionMemoryCache::default() } + + pub async fn add_revision(&self, revision: Revision) -> Result<(), OTError> { + if self.revs_map.contains_key(&revision.rev_id) { + return Err(OTError::duplicate_revision().context(format!("Duplicate revision id: {}", revision.rev_id))); + } + + self.pending_revs.write().await.push_back(revision.rev_id); + self.revs_map.insert(revision.rev_id, RevisionRecord::new(revision)); + Ok(()) + } + + pub async fn mut_revision(&self, rev_id: i64, f: F) + where + F: Fn(RefMut), + { + if let Some(m_revision) = self.revs_map.get_mut(&rev_id) { + f(m_revision) + } else { + log::error!("Can't find revision with id {}", rev_id); + } + } + + pub async fn revisions_in_range(&self, range: RevisionRange) -> Result>, OTError> { + let revs = range + .iter() + .flat_map(|rev_id| match self.revs_map.get(&rev_id) { + None => None, + Some(rev) => Some(rev.revision.clone()), + }) + .collect::>(); + + if revs.len() == range.len() as usize { + Ok(Some(revs)) + } else { + Ok(None) + } + } +} + +pub type RevIdReceiver = broadcast::Receiver; +pub type RevIdSender = broadcast::Sender; + +pub enum RevState { + Local = 0, + Acked = 1, +} + +pub struct RevisionRecord { + pub revision: Revision, + pub state: RevState, +} + +impl RevisionRecord { + pub fn new(revision: Revision) -> Self { + Self { + revision, + state: RevState::Local, + } + } +} + +pub struct PendingRevId { + pub rev_id: i64, + pub sender: RevIdSender, +} + +impl PendingRevId { + pub fn new(rev_id: i64, sender: RevIdSender) -> Self { Self { rev_id, sender } } + + pub fn finish(&self, rev_id: i64) -> bool { + if self.rev_id > rev_id { + false + } else { + let _ = self.sender.send(self.rev_id); + true + } + } +} diff --git a/shared-lib/lib-ot/src/revision/mod.rs b/shared-lib/lib-ot/src/revision/mod.rs new file mode 100644 index 0000000000..9848b59af1 --- /dev/null +++ b/shared-lib/lib-ot/src/revision/mod.rs @@ -0,0 +1,5 @@ +mod cache; +mod model; + +pub use cache::*; +pub use model::*; diff --git a/shared-lib/flowy-document-infra/src/entities/doc/revision.rs b/shared-lib/lib-ot/src/revision/model.rs similarity index 79% rename from shared-lib/flowy-document-infra/src/entities/doc/revision.rs rename to shared-lib/lib-ot/src/revision/model.rs index cb0ea3ce25..7b17e85699 100644 --- a/shared-lib/flowy-document-infra/src/entities/doc/revision.rs +++ b/shared-lib/lib-ot/src/revision/model.rs @@ -1,62 +1,7 @@ -use crate::{entities::doc::Doc, util::md5}; +use crate::rich_text::RichTextDelta; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; -use lib_ot::rich_text::RichTextDelta; use std::{fmt::Formatter, ops::RangeInclusive}; -#[derive(Debug, ProtoBuf_Enum, Clone, Eq, PartialEq)] -pub enum RevType { - Local = 0, - Remote = 1, -} - -impl RevType { - pub fn is_local(&self) -> bool { self == &RevType::Local } -} - -impl std::default::Default for RevType { - fn default() -> Self { RevType::Local } -} - -// [[i64 to bytes]] -// use byteorder::{BigEndian, ReadBytesExt}; -// use std::{io::Cursor}; -// impl std::convert::TryFrom for RevId { -// type Error = DocError; -// -// fn try_from(bytes: Bytes) -> Result { -// // let mut wtr = vec![]; -// // let _ = wtr.write_i64::(revision.rev_id); -// -// let mut rdr = Cursor::new(bytes); -// match rdr.read_i64::() { -// Ok(rev_id) => Ok(RevId(rev_id)), -// Err(e) => Err(DocError::internal().context(e)), -// } -// } -// } - -#[derive(Clone, Debug, ProtoBuf, Default)] -pub struct RevId { - #[pb(index = 1)] - pub value: i64, -} - -impl AsRef for RevId { - fn as_ref(&self) -> &i64 { &self.value } -} - -impl std::convert::From for i64 { - fn from(rev_id: RevId) -> Self { rev_id.value } -} - -impl std::convert::From for RevId { - fn from(value: i64) -> Self { RevId { value } } -} - -impl std::fmt::Display for RevId { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.write_fmt(format_args!("{}", self.value)) } -} - #[derive(PartialEq, Eq, Clone, Default, ProtoBuf)] pub struct Revision { #[pb(index = 1)] @@ -127,9 +72,40 @@ impl Revision { } } -pub fn revision_from_doc(doc: Doc, ty: RevType) -> Revision { - let delta_data = doc.data.as_bytes(); - Revision::new(doc.base_rev_id, doc.rev_id, delta_data.to_owned(), &doc.id, ty) +#[derive(Clone, Debug, ProtoBuf, Default)] +pub struct RevId { + #[pb(index = 1)] + pub value: i64, +} + +impl AsRef for RevId { + fn as_ref(&self) -> &i64 { &self.value } +} + +impl std::convert::From for i64 { + fn from(rev_id: RevId) -> Self { rev_id.value } +} + +impl std::convert::From for RevId { + fn from(value: i64) -> Self { RevId { value } } +} + +impl std::fmt::Display for RevId { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.write_fmt(format_args!("{}", self.value)) } +} + +#[derive(Debug, ProtoBuf_Enum, Clone, Eq, PartialEq)] +pub enum RevType { + Local = 0, + Remote = 1, +} + +impl RevType { + pub fn is_local(&self) -> bool { self == &RevType::Local } +} + +impl std::default::Default for RevType { + fn default() -> Self { RevType::Local } } #[derive(Debug, Clone, Default, ProtoBuf)] @@ -161,3 +137,9 @@ impl RevisionRange { RangeInclusive::new(self.start, self.end) } } + +#[inline] +pub fn md5>(data: T) -> String { + let md5 = format!("{:x}", md5::compute(data)); + md5 +} From 4450d4410b801f98c075d96d06e8b6396b7fa945 Mon Sep 17 00:00:00 2001 From: appflowy Date: Wed, 8 Dec 2021 14:17:40 +0800 Subject: [PATCH 08/39] send revision periodically --- backend/tests/document/helper.rs | 2 +- .../rust-lib/flowy-document/src/module.rs | 2 +- .../flowy-document/src/services/cache.rs | 2 +- .../src/services/doc/edit/editor.rs | 5 +- .../flowy-document/src/services/doc/mod.rs | 6 +- .../src/services/doc/revision/cache.rs | 263 ++++++++++++ .../src/services/doc/revision/manager.rs | 24 +- .../src/services/doc/revision/mod.rs | 7 +- .../src/services/doc/revision/model.rs | 45 --- .../src/services/doc/revision/persistence.rs | 380 ------------------ .../src/services/doc/revision/sync.rs | 76 ++++ .../src/sql_tables/doc/rev_sql.rs | 38 +- .../src/sql_tables/doc/rev_table.rs | 39 +- shared-lib/lib-ot/src/revision/cache.rs | 56 ++- 14 files changed, 449 insertions(+), 496 deletions(-) create mode 100644 frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs delete mode 100644 frontend/rust-lib/flowy-document/src/services/doc/revision/model.rs delete mode 100644 frontend/rust-lib/flowy-document/src/services/doc/revision/persistence.rs create mode 100644 frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs diff --git a/backend/tests/document/helper.rs b/backend/tests/document/helper.rs index 3c173b2028..20e622ee14 100644 --- a/backend/tests/document/helper.rs +++ b/backend/tests/document/helper.rs @@ -2,7 +2,7 @@ #![cfg_attr(rustfmt, rustfmt::skip)] use actix_web::web::Data; use backend::services::doc::{crud::update_doc, manager::DocManager}; -use flowy_document::services::doc::ClientDocEditor as ClientEditDocContext; +use flowy_document::services::doc::edit::ClientDocEditor as ClientEditDocContext; use flowy_test::{workspace::ViewTest, FlowyTest}; use flowy_user::services::user::UserSession; use futures_util::{stream, stream::StreamExt}; diff --git a/frontend/rust-lib/flowy-document/src/module.rs b/frontend/rust-lib/flowy-document/src/module.rs index b696b97b30..27a4fa62d2 100644 --- a/frontend/rust-lib/flowy-document/src/module.rs +++ b/frontend/rust-lib/flowy-document/src/module.rs @@ -1,7 +1,7 @@ use crate::{ errors::DocError, services::{ - doc::{doc_controller::DocController, ClientDocEditor}, + doc::{doc_controller::DocController, edit::ClientDocEditor}, server::construct_doc_server, ws::WsDocumentManager, }, diff --git a/frontend/rust-lib/flowy-document/src/services/cache.rs b/frontend/rust-lib/flowy-document/src/services/cache.rs index 6b633dc338..712cde6774 100644 --- a/frontend/rust-lib/flowy-document/src/services/cache.rs +++ b/frontend/rust-lib/flowy-document/src/services/cache.rs @@ -4,7 +4,7 @@ use dashmap::DashMap; use crate::{ errors::DocError, - services::doc::{ClientDocEditor, DocId}, + services::doc::edit::{ClientDocEditor, DocId}, }; pub(crate) struct DocCache { diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs index 119a2335cf..4b2e5cb1c0 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs @@ -2,7 +2,10 @@ use crate::{ errors::{internal_error, DocError, DocResult}, module::DocumentUser, services::{ - doc::{EditCommand, EditCommandQueue, OpenDocAction, RevisionManager, RevisionServer, TransformDeltas}, + doc::{ + edit::{EditCommand, EditCommandQueue, OpenDocAction, TransformDeltas}, + revision::{RevisionManager, RevisionServer}, + }, ws::{DocumentWebSocket, WsDocumentHandler}, }, }; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/mod.rs b/frontend/rust-lib/flowy-document/src/services/doc/mod.rs index 31583599f1..48a4bbd187 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/mod.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/mod.rs @@ -1,6 +1,4 @@ -mod edit; -mod revision; +pub mod edit; +pub mod revision; pub(crate) mod doc_controller; -pub use edit::*; -pub(crate) use revision::*; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs new file mode 100644 index 0000000000..8117178e11 --- /dev/null +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs @@ -0,0 +1,263 @@ +use crate::{ + errors::{internal_error, DocError, DocResult}, + services::doc::revision::RevisionServer, + sql_tables::RevTableSql, +}; +use flowy_database::ConnectionPool; +use flowy_document_infra::entities::doc::Doc; +use lib_infra::future::ResultFuture; +use lib_ot::{ + core::{Operation, OperationTransformable}, + revision::{ + RevId, + RevState, + RevType, + Revision, + RevisionDiskCache, + RevisionMemoryCache, + RevisionRange, + RevisionRecord, + }, + rich_text::RichTextDelta, +}; +use std::{sync::Arc, time::Duration}; +use tokio::{ + sync::RwLock, + task::{spawn_blocking, JoinHandle}, +}; + +pub trait RevisionIterator: Send + Sync { + fn next(&self) -> ResultFuture, DocError>; +} + +type DocRevisionDeskCache = dyn RevisionDiskCache; + +pub struct RevisionCache { + doc_id: String, + dish_cache: Arc, + memory_cache: Arc, + defer_save: RwLock>>, + server: Arc, +} + +impl RevisionCache { + pub fn new(doc_id: &str, pool: Arc, server: Arc) -> RevisionCache { + let doc_id = doc_id.to_owned(); + let dish_cache = Arc::new(Persistence::new(pool)); + let memory_cache = Arc::new(RevisionMemoryCache::new()); + Self { + doc_id, + dish_cache, + memory_cache, + defer_save: RwLock::new(None), + server, + } + } + + #[tracing::instrument(level = "debug", skip(self, revision))] + pub async fn add_revision(&self, revision: Revision) -> DocResult<()> { + if self.memory_cache.contains(&revision.rev_id) { + return Err(DocError::duplicate_rev().context(format!("Duplicate revision id: {}", revision.rev_id))); + } + self.memory_cache.add_revision(revision.clone()).await?; + self.save_revisions().await; + Ok(()) + } + + #[tracing::instrument(level = "debug", skip(self, rev_id), fields(rev_id = %rev_id.as_ref()))] + pub async fn ack_revision(&self, rev_id: RevId) { + let rev_id = rev_id.value; + self.memory_cache.mut_revision(&rev_id, |mut rev| rev.value_mut().ack()); + self.save_revisions().await; + } + + async fn save_revisions(&self) { + if let Some(handler) = self.defer_save.write().await.take() { + handler.abort(); + } + + if self.memory_cache.is_empty() { + return; + } + + let memory_cache = self.memory_cache.clone(); + let disk_cache = self.dish_cache.clone(); + *self.defer_save.write().await = Some(tokio::spawn(async move { + tokio::time::sleep(Duration::from_millis(300)).await; + let (ids, records) = memory_cache.revisions(); + match disk_cache.create_revisions(records) { + Ok(_) => { + memory_cache.remove_revisions(ids); + }, + Err(e) => log::error!("Save revision failed: {:?}", e), + } + })); + } + + pub async fn revisions_in_range(&self, range: RevisionRange) -> DocResult> { + let revs = self.memory_cache.revisions_in_range(&range).await?; + if revs.len() == range.len() as usize { + Ok(revs) + } else { + let doc_id = self.doc_id.clone(); + let disk_cache = self.dish_cache.clone(); + spawn_blocking(move || disk_cache.revisions_in_range(&doc_id, &range)) + .await + .map_err(internal_error)? + } + } + + pub async fn fetch_document(&self) -> DocResult { + let result = fetch_from_local(&self.doc_id, self.dish_cache.clone()).await; + if result.is_ok() { + return result; + } + + let doc = self.server.fetch_document_from_remote(&self.doc_id).await?; + let delta_data = doc.data.as_bytes(); + let revision = Revision::new( + doc.base_rev_id, + doc.rev_id, + delta_data.to_owned(), + &doc.id, + RevType::Remote, + ); + let record = RevisionRecord { + revision, + state: RevState::Acked, + }; + let _ = self.dish_cache.create_revisions(vec![record])?; + Ok(doc) + } +} + +impl RevisionIterator for RevisionCache { + fn next(&self) -> ResultFuture, DocError> { + let memory_cache = self.memory_cache.clone(); + let disk_cache = self.dish_cache.clone(); + let doc_id = self.doc_id.clone(); + ResultFuture::new(async move { + match memory_cache.front_revision().await { + None => { + // + match memory_cache.front_rev_id().await { + None => Ok(None), + Some(rev_id) => match disk_cache.read_revision(&doc_id, rev_id)? { + None => Ok(None), + Some(revision) => Ok(Some(RevisionRecord::new(revision))), + }, + } + }, + Some((_, record)) => Ok(Some(record)), + } + }) + } +} + +async fn fetch_from_local(doc_id: &str, disk_cache: Arc) -> DocResult { + let doc_id = doc_id.to_owned(); + spawn_blocking(move || { + let revisions = disk_cache.read_revisions(&doc_id)?; + if revisions.is_empty() { + return Err(DocError::record_not_found().context("Local doesn't have this document")); + } + + let base_rev_id: RevId = revisions.last().unwrap().base_rev_id.into(); + let rev_id: RevId = revisions.last().unwrap().rev_id.into(); + let mut delta = RichTextDelta::new(); + for (_, revision) in revisions.into_iter().enumerate() { + match RichTextDelta::from_bytes(revision.delta_data) { + Ok(local_delta) => { + delta = delta.compose(&local_delta)?; + }, + Err(e) => { + log::error!("Deserialize delta from revision failed: {}", e); + }, + } + } + + #[cfg(debug_assertions)] + validate_delta(&doc_id, disk_cache, &delta); + + match delta.ops.last() { + None => {}, + Some(op) => { + let data = op.get_data(); + if !data.ends_with('\n') { + delta.ops.push(Operation::Insert("\n".into())) + } + }, + } + + Result::::Ok(Doc { + id: doc_id, + data: delta.to_json(), + rev_id: rev_id.into(), + base_rev_id: base_rev_id.into(), + }) + }) + .await + .map_err(internal_error)? +} + +#[cfg(debug_assertions)] +fn validate_delta(doc_id: &str, disk_cache: Arc, delta: &RichTextDelta) { + if delta.ops.last().is_none() { + return; + } + + let data = delta.ops.last().as_ref().unwrap().get_data(); + if !data.ends_with('\n') { + log::error!("The op must end with newline"); + let result = || { + let revisions = disk_cache.read_revisions(&doc_id)?; + for revision in revisions { + let delta = RichTextDelta::from_bytes(revision.delta_data)?; + log::error!("Invalid revision: {}:{}", revision.rev_id, delta.to_json()); + } + Ok::<(), DocError>(()) + }; + match result() { + Ok(_) => {}, + Err(e) => log::error!("{}", e), + } + } +} + +pub(crate) struct Persistence { + pub(crate) pool: Arc, +} + +impl RevisionDiskCache for Persistence { + type Error = DocError; + + fn create_revisions(&self, revisions: Vec) -> Result<(), Self::Error> { + let conn = &*self.pool.get().map_err(internal_error)?; + conn.immediate_transaction::<_, DocError, _>(|| { + let _ = RevTableSql::create_rev_table(revisions, conn)?; + Ok(()) + }) + } + + fn revisions_in_range(&self, doc_id: &str, range: &RevisionRange) -> Result, Self::Error> { + let conn = &*self.pool.get().map_err(internal_error).unwrap(); + let revisions = RevTableSql::read_rev_tables_with_range(doc_id, range.clone(), conn)?; + Ok(revisions) + } + + fn read_revision(&self, doc_id: &str, rev_id: i64) -> Result, Self::Error> { + let conn = self.pool.get().map_err(internal_error)?; + let some = RevTableSql::read_rev_table(doc_id, &rev_id, &*conn)?; + Ok(some) + } + + fn read_revisions(&self, doc_id: &str) -> Result, Self::Error> { + let conn = self.pool.get().map_err(internal_error)?; + let some = RevTableSql::read_rev_tables(doc_id, &*conn)?; + Ok(some) + } +} + +impl Persistence { + pub(crate) fn new(pool: Arc) -> Self { Self { pool } } +} diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs index 84f9679227..1ff1f4bd86 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs @@ -1,6 +1,6 @@ use crate::{ errors::{DocError, DocResult}, - services::doc::revision::RevisionStore, + services::doc::revision::{RevisionCache, RevisionUploadStream}, }; use flowy_database::ConnectionPool; use flowy_document_infra::{entities::doc::Doc, util::RevIdCounter}; @@ -20,7 +20,7 @@ pub trait RevisionServer: Send + Sync { pub struct RevisionManager { doc_id: String, rev_id_counter: RevIdCounter, - rev_store: Arc, + cache: Arc, } impl RevisionManager { @@ -28,30 +28,32 @@ impl RevisionManager { doc_id: &str, pool: Arc, server: Arc, - pending_rev_sender: mpsc::UnboundedSender, + ws_sender: mpsc::UnboundedSender, ) -> Self { - let rev_store = RevisionStore::new(doc_id, pool, server, pending_rev_sender); + let cache = Arc::new(RevisionCache::new(doc_id, pool, server)); + spawn_upload_stream(cache.clone(), ws_sender); let rev_id_counter = RevIdCounter::new(0); Self { doc_id: doc_id.to_string(), rev_id_counter, - rev_store, + cache, } } pub async fn load_document(&mut self) -> DocResult { - let doc = self.rev_store.fetch_document().await?; + let doc = self.cache.fetch_document().await?; self.update_rev_id_counter_value(doc.rev_id); Ok(doc.delta()?) } pub async fn add_revision(&self, revision: &Revision) -> Result<(), DocError> { - let _ = self.rev_store.add_revision(revision.clone()).await?; + let _ = self.cache.add_revision(revision.clone()).await?; + Ok(()) } pub async fn ack_revision(&self, rev_id: RevId) -> Result<(), DocError> { - self.rev_store.ack_revision(rev_id).await; + self.cache.ack_revision(rev_id).await; Ok(()) } @@ -67,7 +69,7 @@ impl RevisionManager { pub async fn mk_revisions(&self, range: RevisionRange) -> Result { debug_assert!(range.doc_id == self.doc_id); - let revisions = self.rev_store.revs_in_range(range.clone()).await?; + let revisions = self.cache.revisions_in_range(range.clone()).await?; let mut new_delta = RichTextDelta::new(); for revision in revisions { match RichTextDelta::from_bytes(revision.delta_data) { @@ -90,3 +92,7 @@ impl RevisionManager { Ok(revision) } } + +fn spawn_upload_stream(cache: Arc, ws_sender: mpsc::UnboundedSender) { + tokio::spawn(RevisionUploadStream::new(cache, ws_sender).run()); +} diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/mod.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/mod.rs index 7288a5301b..867c30173c 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/mod.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/mod.rs @@ -1,6 +1,7 @@ +mod cache; mod manager; -mod model; -mod persistence; +mod sync; +pub use cache::*; pub use manager::*; -pub use persistence::*; +pub(crate) use sync::*; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/model.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/model.rs deleted file mode 100644 index 51e2d68fe3..0000000000 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/model.rs +++ /dev/null @@ -1,45 +0,0 @@ -use crate::{ - errors::{internal_error, DocError, DocResult}, - sql_tables::{RevTableSql, SqlRevState}, -}; -use flowy_database::ConnectionPool; -use lib_infra::future::ResultFuture; -use lib_ot::revision::{Revision, RevisionRange}; -use std::sync::Arc; -use tokio::sync::broadcast; - -pub(crate) struct Persistence { - pub(crate) rev_sql: Arc, - pub(crate) pool: Arc, -} - -impl Persistence { - pub(crate) fn new(pool: Arc) -> Self { - let rev_sql = Arc::new(RevTableSql {}); - Self { rev_sql, pool } - } - - pub(crate) fn create_revs(&self, revisions: Vec<(Revision, SqlRevState)>) -> DocResult<()> { - let conn = &*self.pool.get().map_err(internal_error)?; - conn.immediate_transaction::<_, DocError, _>(|| { - let _ = self.rev_sql.create_rev_table(revisions, conn)?; - Ok(()) - }) - } - - pub(crate) fn read_rev_with_range(&self, doc_id: &str, range: RevisionRange) -> DocResult> { - let conn = &*self.pool.get().map_err(internal_error).unwrap(); - let revisions = self.rev_sql.read_rev_tables_with_range(doc_id, range, conn)?; - Ok(revisions) - } - - pub(crate) fn read_rev(&self, doc_id: &str, rev_id: &i64) -> DocResult> { - let conn = self.pool.get().map_err(internal_error)?; - let some = self.rev_sql.read_rev_table(&doc_id, rev_id, &*conn)?; - Ok(some) - } -} - -pub trait RevisionIterator: Send + Sync { - fn next(&self) -> ResultFuture, DocError>; -} diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/persistence.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/persistence.rs deleted file mode 100644 index 5b866181a9..0000000000 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/persistence.rs +++ /dev/null @@ -1,380 +0,0 @@ -use crate::{ - errors::{internal_error, DocError, DocResult}, - services::doc::revision::{model::*, RevisionServer}, - sql_tables::SqlRevState, -}; -use async_stream::stream; -use dashmap::DashMap; -use flowy_database::{ConnectionPool, SqliteConnection}; -use flowy_document_infra::entities::doc::Doc; -use futures::stream::StreamExt; -use lib_infra::future::ResultFuture; -use lib_ot::{ - core::{Operation, OperationTransformable}, - revision::{PendingRevId, RevId, RevIdReceiver, RevType, Revision, RevisionRange, RevisionRecord}, - rich_text::RichTextDelta, -}; -use std::{collections::VecDeque, sync::Arc, time::Duration}; -use tokio::{ - sync::{broadcast, mpsc, RwLock}, - task::{spawn_blocking, JoinHandle}, -}; - -pub struct RevisionStore { - doc_id: String, - persistence: Arc, - revs_map: Arc>, - pending_tx: PendingSender, - pending_revs: Arc>>, - defer_save: RwLock>>, - server: Arc, -} - -impl RevisionStore { - pub fn new( - doc_id: &str, - pool: Arc, - server: Arc, - ws_revision_sender: mpsc::UnboundedSender, - ) -> Arc { - let doc_id = doc_id.to_owned(); - let persistence = Arc::new(Persistence::new(pool)); - let revs_map = Arc::new(DashMap::new()); - let (pending_tx, pending_rx) = mpsc::unbounded_channel(); - let pending_revs = Arc::new(RwLock::new(VecDeque::new())); - - let store = Arc::new(Self { - doc_id, - persistence, - revs_map, - pending_revs, - pending_tx, - defer_save: RwLock::new(None), - server, - }); - - tokio::spawn(RevisionUploadStream::new(store.clone(), pending_rx, ws_revision_sender).run()); - - store - } - - #[tracing::instrument(level = "debug", skip(self, revision))] - pub async fn add_revision(&self, revision: Revision) -> DocResult<()> { - if self.revs_map.contains_key(&revision.rev_id) { - return Err(DocError::duplicate_rev().context(format!("Duplicate revision id: {}", revision.rev_id))); - } - - let (sender, receiver) = broadcast::channel(2); - let revs_map = self.revs_map.clone(); - let mut rx = sender.subscribe(); - tokio::spawn(async move { - if let Ok(rev_id) = rx.recv().await { - match revs_map.get_mut(&rev_id) { - None => {}, - Some(mut rev) => rev.value_mut().state = SqlRevState::Acked.into(), - } - } - }); - - let pending_rev = PendingRevId::new(revision.rev_id, sender); - self.pending_revs.write().await.push_back(pending_rev); - self.revs_map.insert(revision.rev_id, RevisionRecord::new(revision)); - - let _ = self.pending_tx.send(PendingMsg::Revision { ret: receiver }); - self.save_revisions().await; - Ok(()) - } - - #[tracing::instrument(level = "debug", skip(self, rev_id), fields(rev_id = %rev_id.as_ref()))] - pub async fn ack_revision(&self, rev_id: RevId) { - let rev_id = rev_id.value; - self.pending_revs - .write() - .await - .retain(|pending| !pending.finish(rev_id)); - - self.save_revisions().await; - } - - async fn save_revisions(&self) { - if let Some(handler) = self.defer_save.write().await.take() { - handler.abort(); - } - - if self.revs_map.is_empty() { - return; - } - - let revs_map = self.revs_map.clone(); - let persistence = self.persistence.clone(); - - *self.defer_save.write().await = Some(tokio::spawn(async move { - tokio::time::sleep(Duration::from_millis(300)).await; - let ids = revs_map.iter().map(|kv| *kv.key()).collect::>(); - let revisions_state = revs_map - .iter() - .map(|kv| (kv.revision.clone(), kv.state)) - .collect::>(); - - match persistence.create_revs(revisions_state.clone()) { - Ok(_) => { - tracing::debug!( - "Revision State Changed: {:?}", - revisions_state.iter().map(|s| (s.0.rev_id, s.1)).collect::>() - ); - revs_map.retain(|k, _| !ids.contains(k)); - }, - Err(e) => log::error!("Save revision failed: {:?}", e), - } - })); - } - - pub async fn revs_in_range(&self, range: RevisionRange) -> DocResult> { - let revs = range - .iter() - .flat_map(|rev_id| match self.revs_map.get(&rev_id) { - None => None, - Some(rev) => Some(rev.revision.clone()), - }) - .collect::>(); - - if revs.len() == range.len() as usize { - Ok(revs) - } else { - let doc_id = self.doc_id.clone(); - let persistence = self.persistence.clone(); - let result = spawn_blocking(move || persistence.read_rev_with_range(&doc_id, range)) - .await - .map_err(internal_error)?; - result - } - } - - pub async fn fetch_document(&self) -> DocResult { - let result = fetch_from_local(&self.doc_id, self.persistence.clone()).await; - if result.is_ok() { - return result; - } - - let doc = self.server.fetch_document_from_remote(&self.doc_id).await?; - let revision = revision_from_doc(doc.clone(), RevType::Remote); - let _ = self.persistence.create_revs(vec![(revision, SqlRevState::Acked)])?; - Ok(doc) - } -} - -pub fn revision_from_doc(doc: Doc, ty: RevType) -> Revision { - let delta_data = doc.data.as_bytes(); - Revision::new(doc.base_rev_id, doc.rev_id, delta_data.to_owned(), &doc.id, ty) -} - -impl RevisionIterator for RevisionStore { - fn next(&self) -> ResultFuture, DocError> { - let pending_revs = self.pending_revs.clone(); - let revs_map = self.revs_map.clone(); - let persistence = self.persistence.clone(); - let doc_id = self.doc_id.clone(); - ResultFuture::new(async move { - match pending_revs.read().await.front() { - None => Ok(None), - Some(pending) => match revs_map.get(&pending.rev_id) { - None => persistence.read_rev(&doc_id, &pending.rev_id), - Some(context) => Ok(Some(context.revision.clone())), - }, - } - }) - } -} - -async fn fetch_from_local(doc_id: &str, persistence: Arc) -> DocResult { - let doc_id = doc_id.to_owned(); - spawn_blocking(move || { - let conn = &*persistence.pool.get().map_err(internal_error)?; - let revisions = persistence.rev_sql.read_rev_tables(&doc_id, conn)?; - if revisions.is_empty() { - return Err(DocError::record_not_found().context("Local doesn't have this document")); - } - - let base_rev_id: RevId = revisions.last().unwrap().base_rev_id.into(); - let rev_id: RevId = revisions.last().unwrap().rev_id.into(); - let mut delta = RichTextDelta::new(); - for (_, revision) in revisions.into_iter().enumerate() { - match RichTextDelta::from_bytes(revision.delta_data) { - Ok(local_delta) => { - delta = delta.compose(&local_delta)?; - }, - Err(e) => { - log::error!("Deserialize delta from revision failed: {}", e); - }, - } - } - - #[cfg(debug_assertions)] - validate_delta(&doc_id, persistence, conn, &delta); - - match delta.ops.last() { - None => {}, - Some(op) => { - let data = op.get_data(); - if !data.ends_with('\n') { - delta.ops.push(Operation::Insert("\n".into())) - } - }, - } - - Result::::Ok(Doc { - id: doc_id, - data: delta.to_json(), - rev_id: rev_id.into(), - base_rev_id: base_rev_id.into(), - }) - }) - .await - .map_err(internal_error)? -} - -#[cfg(debug_assertions)] -fn validate_delta(doc_id: &str, persistence: Arc, conn: &SqliteConnection, delta: &RichTextDelta) { - if delta.ops.last().is_none() { - return; - } - - let data = delta.ops.last().as_ref().unwrap().get_data(); - if !data.ends_with('\n') { - log::error!("The op must end with newline"); - let result = || { - let revisions = persistence.rev_sql.read_rev_tables(&doc_id, conn)?; - for revision in revisions { - let delta = RichTextDelta::from_bytes(revision.delta_data)?; - log::error!("Invalid revision: {}:{}", revision.rev_id, delta.to_json()); - } - Ok::<(), DocError>(()) - }; - match result() { - Ok(_) => {}, - Err(e) => log::error!("{}", e), - } - } -} - -// fn update_revisions(&self) { -// let rev_ids = self -// .revs -// .iter() -// .flat_map(|kv| match kv.state == RevState::Acked { -// true => None, -// false => Some(kv.key().clone()), -// }) -// .collect::>(); -// -// if rev_ids.is_empty() { -// return; -// } -// -// tracing::debug!("Try to update {:?} state", rev_ids); -// match self.update(&rev_ids) { -// Ok(_) => { -// self.revs.retain(|k, _| !rev_ids.contains(k)); -// }, -// Err(e) => log::error!("Save revision failed: {:?}", e), -// } -// } -// -// fn update(&self, rev_ids: &Vec) -> Result<(), DocError> { -// let conn = &*self.pool.get().map_err(internal_error).unwrap(); -// let result = conn.immediate_transaction::<_, DocError, _>(|| { -// for rev_id in rev_ids { -// let changeset = RevChangeset { -// doc_id: self.doc_id.clone(), -// rev_id: rev_id.clone(), -// state: RevState::Acked, -// }; -// let _ = self.op_sql.update_rev_table(changeset, conn)?; -// } -// Ok(()) -// }); -// -// result -// } - -// fn delete_revision(&self, rev_id: RevId) { -// let op_sql = self.op_sql.clone(); -// let pool = self.pool.clone(); -// let doc_id = self.doc_id.clone(); -// tokio::spawn(async move { -// let conn = &*pool.get().map_err(internal_error).unwrap(); -// let result = conn.immediate_transaction::<_, DocError, _>(|| { -// let _ = op_sql.delete_rev_table(&doc_id, rev_id, conn)?; -// Ok(()) -// }); -// -// match result { -// Ok(_) => {}, -// Err(e) => log::error!("Delete revision failed: {:?}", e), -// } -// }); -// } - -pub(crate) enum PendingMsg { - Revision { ret: RevIdReceiver }, -} - -pub(crate) type PendingSender = mpsc::UnboundedSender; -pub(crate) type PendingReceiver = mpsc::UnboundedReceiver; - -pub(crate) struct RevisionUploadStream { - revisions: Arc, - receiver: Option, - ws_revision_sender: mpsc::UnboundedSender, -} - -impl RevisionUploadStream { - pub(crate) fn new( - revisions: Arc, - pending_rx: PendingReceiver, - ws_revision_sender: mpsc::UnboundedSender, - ) -> Self { - Self { - revisions, - receiver: Some(pending_rx), - ws_revision_sender, - } - } - - pub async fn run(mut self) { - let mut receiver = self.receiver.take().expect("Should only call once"); - let stream = stream! { - loop { - match receiver.recv().await { - Some(msg) => yield msg, - None => break, - } - } - }; - stream - .for_each(|msg| async { - match self.handle_msg(msg).await { - Ok(_) => {}, - Err(e) => log::error!("{:?}", e), - } - }) - .await; - } - - async fn handle_msg(&self, msg: PendingMsg) -> DocResult<()> { - match msg { - PendingMsg::Revision { ret } => self.prepare_next_pending_rev(ret).await, - } - } - - async fn prepare_next_pending_rev(&self, mut ret: RevIdReceiver) -> DocResult<()> { - match self.revisions.next().await? { - None => Ok(()), - Some(revision) => { - let _ = self.ws_revision_sender.send(revision).map_err(internal_error); - let _ = tokio::time::timeout(Duration::from_millis(2000), ret.recv()).await; - Ok(()) - }, - } - } -} diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs new file mode 100644 index 0000000000..ac225ce9a0 --- /dev/null +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs @@ -0,0 +1,76 @@ +use crate::{ + errors::{internal_error, DocResult}, + services::doc::revision::RevisionIterator, +}; +use async_stream::stream; +use futures::stream::StreamExt; +use lib_ot::revision::Revision; +use std::sync::Arc; +use tokio::{ + sync::mpsc, + time::{interval, Duration}, +}; + +pub(crate) enum RevisionMsg { + Tick, +} + +pub(crate) struct RevisionUploadStream { + revisions: Arc, + ws_sender: mpsc::UnboundedSender, +} + +impl RevisionUploadStream { + pub(crate) fn new(revisions: Arc, ws_sender: mpsc::UnboundedSender) -> Self { + Self { revisions, ws_sender } + } + + pub async fn run(self) { + let (tx, mut rx) = mpsc::unbounded_channel(); + tokio::spawn(tick(tx)); + let stream = stream! { + loop { + match rx.recv().await { + Some(msg) => yield msg, + None => break, + } + } + }; + stream + .for_each(|msg| async { + match self.handle_msg(msg).await { + Ok(_) => {}, + Err(e) => log::error!("{:?}", e), + } + }) + .await; + } + + async fn handle_msg(&self, msg: RevisionMsg) -> DocResult<()> { + match msg { + RevisionMsg::Tick => self.send_next_revision().await, + } + } + + async fn send_next_revision(&self) -> DocResult<()> { + match self.revisions.next().await? { + None => Ok(()), + Some(record) => { + let _ = self.ws_sender.send(record.revision).map_err(internal_error); + // let _ = tokio::time::timeout(Duration::from_millis(2000), ret.recv()).await; + Ok(()) + }, + } + } +} + +async fn tick(sender: mpsc::UnboundedSender) { + let mut i = interval(Duration::from_secs(2)); + loop { + match sender.send(RevisionMsg::Tick) { + Ok(_) => {}, + Err(e) => log::error!("RevisionUploadStream tick error: {}", e), + } + i.tick().await; + } +} diff --git a/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_sql.rs b/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_sql.rs index 2098693535..051473048c 100644 --- a/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_sql.rs +++ b/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_sql.rs @@ -1,30 +1,27 @@ use crate::{ errors::DocError, - sql_tables::{doc::RevTable, RevChangeset, RevTableType, SqlRevState}, + sql_tables::{doc::RevTable, RevChangeset, RevTableState, RevTableType}, }; use diesel::update; use flowy_database::{insert_or_ignore_into, prelude::*, schema::rev_table::dsl, SqliteConnection}; -use lib_ot::revision::{Revision, RevisionRange}; +use lib_ot::revision::{Revision, RevisionRange, RevisionRecord}; pub struct RevTableSql {} impl RevTableSql { - pub(crate) fn create_rev_table( - &self, - revisions: Vec<(Revision, SqlRevState)>, - conn: &SqliteConnection, - ) -> Result<(), DocError> { + pub(crate) fn create_rev_table(revisions: Vec, conn: &SqliteConnection) -> Result<(), DocError> { // Batch insert: https://diesel.rs/guides/all-about-inserts.html let records = revisions .into_iter() - .map(|(revision, new_state)| { - let rev_ty: RevTableType = revision.ty.into(); + .map(|record| { + let rev_ty: RevTableType = record.revision.ty.into(); + let rev_state: RevTableState = record.state.into(); ( - dsl::doc_id.eq(revision.doc_id), - dsl::base_rev_id.eq(revision.base_rev_id), - dsl::rev_id.eq(revision.rev_id), - dsl::data.eq(revision.delta_data), - dsl::state.eq(new_state), + dsl::doc_id.eq(record.revision.doc_id), + dsl::base_rev_id.eq(record.revision.base_rev_id), + dsl::rev_id.eq(record.revision.rev_id), + dsl::data.eq(record.revision.delta_data), + dsl::state.eq(rev_state), dsl::ty.eq(rev_ty), ) }) @@ -35,7 +32,7 @@ impl RevTableSql { } #[allow(dead_code)] - pub(crate) fn update_rev_table(&self, changeset: RevChangeset, conn: &SqliteConnection) -> Result<(), DocError> { + pub(crate) fn update_rev_table(changeset: RevChangeset, conn: &SqliteConnection) -> Result<(), DocError> { let filter = dsl::rev_table .filter(dsl::rev_id.eq(changeset.rev_id.as_ref())) .filter(dsl::doc_id.eq(changeset.doc_id)); @@ -44,7 +41,7 @@ impl RevTableSql { Ok(()) } - pub(crate) fn read_rev_tables(&self, doc_id: &str, conn: &SqliteConnection) -> Result, DocError> { + pub(crate) fn read_rev_tables(doc_id: &str, conn: &SqliteConnection) -> Result, DocError> { let filter = dsl::rev_table .filter(dsl::doc_id.eq(doc_id)) .order(dsl::rev_id.asc()) @@ -58,7 +55,6 @@ impl RevTableSql { } pub(crate) fn read_rev_table( - &self, doc_id: &str, revision_id: &i64, conn: &SqliteConnection, @@ -76,7 +72,6 @@ impl RevTableSql { } pub(crate) fn read_rev_tables_with_range( - &self, doc_id_s: &str, range: RevisionRange, conn: &SqliteConnection, @@ -96,12 +91,7 @@ impl RevTableSql { } #[allow(dead_code)] - pub(crate) fn delete_rev_table( - &self, - 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<(), DocError> { let filter = dsl::rev_table .filter(dsl::rev_id.eq(rev_id_s)) .filter(dsl::doc_id.eq(doc_id_s)); diff --git a/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_table.rs b/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_table.rs index 6d5ff19052..d652833978 100644 --- a/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_table.rs +++ b/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_table.rs @@ -11,45 +11,54 @@ pub(crate) struct RevTable { pub(crate) base_rev_id: i64, pub(crate) rev_id: i64, pub(crate) data: Vec, - pub(crate) state: SqlRevState, + pub(crate) state: RevTableState, pub(crate) ty: RevTableType, } #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, FromSqlRow, AsExpression)] #[repr(i32)] #[sql_type = "Integer"] -pub enum SqlRevState { +pub enum RevTableState { Local = 0, Acked = 1, } -impl std::default::Default for SqlRevState { - fn default() -> Self { SqlRevState::Local } +impl std::default::Default for RevTableState { + fn default() -> Self { RevTableState::Local } } -impl std::convert::From for SqlRevState { +impl std::convert::From for RevTableState { fn from(value: i32) -> Self { match value { - 0 => SqlRevState::Local, - 1 => SqlRevState::Acked, + 0 => RevTableState::Local, + 1 => RevTableState::Acked, o => { log::error!("Unsupported rev state {}, fallback to RevState::Local", o); - SqlRevState::Local + RevTableState::Local }, } } } -impl SqlRevState { +impl RevTableState { pub fn value(&self) -> i32 { *self as i32 } } -impl_sql_integer_expression!(RevState); +impl_sql_integer_expression!(RevTableState); -impl std::convert::From for RevState { - fn from(s: SqlRevState) -> Self { +impl std::convert::From for RevState { + fn from(s: RevTableState) -> Self { match s { - SqlRevState::Local => RevState.Local, - SqlRevState::Acked => RevState.Acked, + RevTableState::Local => RevState::Local, + RevTableState::Acked => RevState::Acked, + } + } +} + +impl std::convert::From for RevTableState { + fn from(s: RevState) -> Self { + match s { + RevState::Local => RevTableState::Local, + RevState::Acked => RevTableState::Acked, } } } @@ -119,5 +128,5 @@ impl_sql_integer_expression!(RevTableType); pub(crate) struct RevChangeset { pub(crate) doc_id: String, pub(crate) rev_id: RevId, - pub(crate) state: SqlRevState, + pub(crate) state: RevTableState, } diff --git a/shared-lib/lib-ot/src/revision/cache.rs b/shared-lib/lib-ot/src/revision/cache.rs index 0a4023b4d5..ede3a4298c 100644 --- a/shared-lib/lib-ot/src/revision/cache.rs +++ b/shared-lib/lib-ot/src/revision/cache.rs @@ -1,15 +1,17 @@ use crate::{ errors::OTError, - revision::{RevId, Revision, RevisionRange}, + revision::{Revision, RevisionRange}, }; use dashmap::{mapref::one::RefMut, DashMap}; -use std::{collections::VecDeque, sync::Arc}; +use std::{collections::VecDeque, fmt::Debug, sync::Arc}; use tokio::sync::{broadcast, RwLock}; -pub trait RevisionDiskCache { - fn create_revision(&self, revision: &Revision) -> Result<(), OTError>; - fn revisions_in_range(&self, range: RevisionRange) -> Result>, OTError>; - fn read_revision(&self, rev_id: i64) -> Result, OTError>; +pub trait RevisionDiskCache: Sync + Send { + type Error: Debug; + fn create_revisions(&self, revisions: Vec) -> Result<(), Self::Error>; + fn revisions_in_range(&self, doc_id: &str, range: &RevisionRange) -> Result, Self::Error>; + fn read_revision(&self, doc_id: &str, rev_id: i64) -> Result, Self::Error>; + fn read_revisions(&self, doc_id: &str) -> Result, Self::Error>; } pub struct RevisionMemoryCache { @@ -32,7 +34,7 @@ impl RevisionMemoryCache { pub async fn add_revision(&self, revision: Revision) -> Result<(), OTError> { if self.revs_map.contains_key(&revision.rev_id) { - return Err(OTError::duplicate_revision().context(format!("Duplicate revision id: {}", revision.rev_id))); + return Ok(()); } self.pending_revs.write().await.push_back(revision.rev_id); @@ -40,18 +42,20 @@ impl RevisionMemoryCache { Ok(()) } - pub async fn mut_revision(&self, rev_id: i64, f: F) + pub fn remove_revisions(&self, ids: Vec) { self.revs_map.retain(|k, _| !ids.contains(k)); } + + pub fn mut_revision(&self, rev_id: &i64, f: F) where F: Fn(RefMut), { - if let Some(m_revision) = self.revs_map.get_mut(&rev_id) { + if let Some(m_revision) = self.revs_map.get_mut(rev_id) { f(m_revision) } else { log::error!("Can't find revision with id {}", rev_id); } } - pub async fn revisions_in_range(&self, range: RevisionRange) -> Result>, OTError> { + pub async fn revisions_in_range(&self, range: &RevisionRange) -> Result, OTError> { let revs = range .iter() .flat_map(|rev_id| match self.revs_map.get(&rev_id) { @@ -61,21 +65,47 @@ impl RevisionMemoryCache { .collect::>(); if revs.len() == range.len() as usize { - Ok(Some(revs)) + Ok(revs) } else { - Ok(None) + Ok(vec![]) } } + + pub fn contains(&self, rev_id: &i64) -> bool { self.revs_map.contains_key(rev_id) } + + pub fn is_empty(&self) -> bool { self.revs_map.is_empty() } + + pub fn revisions(&self) -> (Vec, Vec) { + let mut records: Vec = vec![]; + let mut ids: Vec = vec![]; + + self.revs_map.iter().for_each(|kv| { + records.push(kv.value().clone()); + ids.push(*kv.key()); + }); + (ids, records) + } + + pub async fn front_revision(&self) -> Option<(i64, RevisionRecord)> { + match self.pending_revs.read().await.front() { + None => None, + Some(rev_id) => self.revs_map.get(rev_id).map(|r| (*r.key(), r.value().clone())), + } + } + + pub async fn front_rev_id(&self) -> Option { self.pending_revs.read().await.front().copied() } } pub type RevIdReceiver = broadcast::Receiver; pub type RevIdSender = broadcast::Sender; +#[derive(Clone, Eq, PartialEq)] pub enum RevState { Local = 0, Acked = 1, } +#[derive(Clone)] pub struct RevisionRecord { pub revision: Revision, pub state: RevState, @@ -88,6 +118,8 @@ impl RevisionRecord { state: RevState::Local, } } + + pub fn ack(&mut self) { self.state = RevState::Acked; } } pub struct PendingRevId { From 7ac55f29db7bdf5a38fb305a259549fd9310cbe9 Mon Sep 17 00:00:00 2001 From: appflowy Date: Wed, 8 Dec 2021 17:33:22 +0800 Subject: [PATCH 09/39] refactor tests --- backend/Cargo.lock | 1 + backend/tests/document/helper.rs | 20 +- .../flowy-core/tests/workspace/app_test.rs | 2 +- .../flowy-core/tests/workspace/view_test.rs | 12 +- .../tests/workspace/workspace_test.rs | 10 +- frontend/rust-lib/flowy-document/Cargo.toml | 1 + .../rust-lib/flowy-document/src/errors.rs | 4 +- .../rust-lib/flowy-document/src/module.rs | 2 +- .../flowy-document/src/services/cache.rs | 2 +- .../doc/{doc_controller.rs => controller.rs} | 4 +- .../src/services/doc/edit/editor.rs | 4 +- .../src/services/doc/edit/queue.rs | 4 +- .../flowy-document/src/services/doc/mod.rs | 2 +- .../src/services/doc/revision/cache.rs | 78 +++-- .../src/services/doc/revision/manager.rs | 4 +- .../src/services/doc/revision/sync.rs | 1 + .../flowy-document/tests/editor/mod.rs | 1 + .../tests/editor/revision_test.rs | 8 + frontend/rust-lib/flowy-test/src/editor.rs | 22 ++ .../src/{builder.rs => event_builder.rs} | 31 +- frontend/rust-lib/flowy-test/src/helper.rs | 275 ++++++++++++++++- frontend/rust-lib/flowy-test/src/lib.rs | 48 +-- frontend/rust-lib/flowy-test/src/workspace.rs | 276 ------------------ .../flowy-user/tests/event/auth_test.rs | 24 +- .../rust-lib/flowy-user/tests/event/helper.rs | 2 +- .../tests/event/user_profile_test.rs | 50 ++-- .../src/entities/ws/ws.rs | 3 + shared-lib/lib-ot/src/errors.rs | 2 + shared-lib/lib-ot/src/revision/cache.rs | 26 +- shared-lib/lib-ot/src/revision/model.rs | 2 + 30 files changed, 467 insertions(+), 454 deletions(-) rename frontend/rust-lib/flowy-document/src/services/doc/{doc_controller.rs => controller.rs} (96%) create mode 100644 frontend/rust-lib/flowy-document/tests/editor/revision_test.rs create mode 100644 frontend/rust-lib/flowy-test/src/editor.rs rename frontend/rust-lib/flowy-test/src/{builder.rs => event_builder.rs} (84%) delete mode 100644 frontend/rust-lib/flowy-test/src/workspace.rs diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 2b3c3bd2c3..0da8aaa84e 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -1272,6 +1272,7 @@ dependencies = [ "flowy-document-infra", "futures", "futures-core", + "futures-util", "lazy_static", "lib-dispatch", "lib-infra", diff --git a/backend/tests/document/helper.rs b/backend/tests/document/helper.rs index 20e622ee14..3dcfd74edf 100644 --- a/backend/tests/document/helper.rs +++ b/backend/tests/document/helper.rs @@ -3,7 +3,7 @@ use actix_web::web::Data; use backend::services::doc::{crud::update_doc, manager::DocManager}; use flowy_document::services::doc::edit::ClientDocEditor as ClientEditDocContext; -use flowy_test::{workspace::ViewTest, FlowyTest}; +use flowy_test::{helper::ViewTest, FlowySDKTest}; use flowy_user::services::user::UserSession; use futures_util::{stream, stream::StreamExt}; use sqlx::PgPool; @@ -18,7 +18,7 @@ use lib_ot::core::Interval; pub struct DocumentTest { server: TestServer, - flowy_test: FlowyTest, + flowy_test: FlowySDKTest, } #[derive(Clone)] pub enum DocScript { @@ -34,7 +34,7 @@ pub enum DocScript { impl DocumentTest { pub async fn new() -> Self { let server = spawn_server().await; - let flowy_test = FlowyTest::setup_with(server.client_server_config.clone()); + let flowy_test = FlowySDKTest::setup_with(server.client_server_config.clone()); Self { server, flowy_test } } @@ -50,7 +50,7 @@ impl DocumentTest { #[derive(Clone)] struct ScriptContext { client_edit_context: Option>, - flowy_test: FlowyTest, + client_sdk: FlowySDKTest, client_user_session: Arc, server_doc_manager: Arc, server_pg_pool: Data, @@ -58,13 +58,13 @@ struct ScriptContext { } impl ScriptContext { - async fn new(flowy_test: FlowyTest, server: TestServer) -> Self { - let user_session = flowy_test.sdk.user_session.clone(); - let doc_id = create_doc(&flowy_test).await; + async fn new(client_sdk: FlowySDKTest, server: TestServer) -> Self { + let user_session = client_sdk.user_session.clone(); + let doc_id = create_doc(&client_sdk).await; Self { client_edit_context: None, - flowy_test, + client_sdk, client_user_session: user_session, server_doc_manager: server.app_ctx.doc_biz.manager.clone(), server_pg_pool: Data::new(server.pg_pool.clone()), @@ -73,7 +73,7 @@ impl ScriptContext { } async fn open_doc(&mut self) { - let flowy_document = self.flowy_test.sdk.flowy_document.clone(); + let flowy_document = self.client_sdk.flowy_document.clone(); let doc_id = self.doc_id.clone(); let edit_context = flowy_document.open(DocIdentifier { doc_id }).await.unwrap(); @@ -161,7 +161,7 @@ fn assert_eq(expect: &str, receive: &str) { assert_eq!(target_delta, expected_delta); } -async fn create_doc(flowy_test: &FlowyTest) -> String { +async fn create_doc(flowy_test: &FlowySDKTest) -> String { let view_test = ViewTest::new(flowy_test).await; view_test.view.id } diff --git a/frontend/rust-lib/flowy-core/tests/workspace/app_test.rs b/frontend/rust-lib/flowy-core/tests/workspace/app_test.rs index 74521bd0d3..9da73fba3d 100644 --- a/frontend/rust-lib/flowy-core/tests/workspace/app_test.rs +++ b/frontend/rust-lib/flowy-core/tests/workspace/app_test.rs @@ -3,7 +3,7 @@ use flowy_core::entities::{ trash::{TrashIdentifier, TrashType}, view::*, }; -use flowy_test::workspace::*; +use flowy_test::helper::*; #[tokio::test] #[should_panic] diff --git a/frontend/rust-lib/flowy-core/tests/workspace/view_test.rs b/frontend/rust-lib/flowy-core/tests/workspace/view_test.rs index 220d0aeb70..42c49d503b 100644 --- a/frontend/rust-lib/flowy-core/tests/workspace/view_test.rs +++ b/frontend/rust-lib/flowy-core/tests/workspace/view_test.rs @@ -3,12 +3,12 @@ use flowy_core::entities::{ trash::{TrashIdentifier, TrashType}, view::*, }; -use flowy_test::{workspace::*, FlowyTest}; +use flowy_test::{helper::*, FlowySDKTest}; #[tokio::test] #[should_panic] async fn view_delete() { - let test = FlowyTest::setup(); + let test = FlowySDKTest::setup(); let _ = test.init_user().await; let test = ViewTest::new(&test).await; @@ -21,7 +21,7 @@ async fn view_delete() { #[tokio::test] async fn view_delete_then_putback() { - let test = FlowyTest::setup(); + let test = FlowySDKTest::setup(); let _ = test.init_user().await; let test = ViewTest::new(&test).await; @@ -44,7 +44,7 @@ async fn view_delete_then_putback() { #[tokio::test] async fn view_delete_all() { - let test = FlowyTest::setup(); + let test = FlowySDKTest::setup(); let _ = test.init_user().await; let test = ViewTest::new(&test).await; @@ -66,7 +66,7 @@ async fn view_delete_all() { #[tokio::test] async fn view_delete_all_permanent() { - let test = FlowyTest::setup(); + let test = FlowySDKTest::setup(); let _ = test.init_user().await; let test = ViewTest::new(&test).await; @@ -85,7 +85,7 @@ async fn view_delete_all_permanent() { #[tokio::test] async fn view_open_doc() { - let test = FlowyTest::setup(); + let test = FlowySDKTest::setup(); let _ = test.init_user().await; let test = ViewTest::new(&test).await; diff --git a/frontend/rust-lib/flowy-core/tests/workspace/workspace_test.rs b/frontend/rust-lib/flowy-core/tests/workspace/workspace_test.rs index 62f8bbdfa5..1fde2ff4b7 100644 --- a/frontend/rust-lib/flowy-core/tests/workspace/workspace_test.rs +++ b/frontend/rust-lib/flowy-core/tests/workspace/workspace_test.rs @@ -3,7 +3,7 @@ use flowy_core::{ event::WorkspaceEvent::*, prelude::*, }; -use flowy_test::{builder::*, workspace::*, FlowyTest}; +use flowy_test::{event_builder::*, helper::*, FlowySDKTest}; #[tokio::test] async fn workspace_read_all() { @@ -42,13 +42,13 @@ async fn workspace_create_with_apps() { #[tokio::test] async fn workspace_create_with_invalid_name() { for (name, code) in invalid_workspace_name_test_case() { - let sdk = FlowyTest::setup().sdk; + let sdk = FlowySDKTest::setup(); let request = CreateWorkspaceRequest { name, desc: "".to_owned(), }; assert_eq!( - FlowyWorkspaceTest::new(sdk) + CoreModuleEventBuilder::new(sdk) .event(CreateWorkspace) .request(request) .async_send() @@ -62,14 +62,14 @@ async fn workspace_create_with_invalid_name() { #[tokio::test] async fn workspace_update_with_invalid_name() { - let sdk = FlowyTest::setup().sdk; + let sdk = FlowySDKTest::setup(); for (name, code) in invalid_workspace_name_test_case() { let request = CreateWorkspaceRequest { name, desc: "".to_owned(), }; assert_eq!( - FlowyWorkspaceTest::new(sdk.clone()) + CoreModuleEventBuilder::new(sdk.clone()) .event(CreateWorkspace) .request(request) .async_send() diff --git a/frontend/rust-lib/flowy-document/Cargo.toml b/frontend/rust-lib/flowy-document/Cargo.toml index f7985d871f..fe7525b272 100644 --- a/frontend/rust-lib/flowy-document/Cargo.toml +++ b/frontend/rust-lib/flowy-document/Cargo.toml @@ -39,6 +39,7 @@ serde = { version = "1.0", features = ["derive"] } serde_json = {version = "1.0"} chrono = "0.4.19" futures-core = { version = "0.3", default-features = false } +futures-util = "0.3.15" byteorder = {version = "1.3.4"} async-stream = "0.3.2" futures = "0.3.15" diff --git a/frontend/rust-lib/flowy-document/src/errors.rs b/frontend/rust-lib/flowy-document/src/errors.rs index a737c44665..d55f5d430f 100644 --- a/frontend/rust-lib/flowy-document/src/errors.rs +++ b/frontend/rust-lib/flowy-document/src/errors.rs @@ -46,7 +46,7 @@ impl DocError { static_doc_error!(ws, ErrorCode::WsConnectError); static_doc_error!(internal, ErrorCode::InternalError); static_doc_error!(unauthorized, ErrorCode::UserUnauthorized); - static_doc_error!(record_not_found, ErrorCode::DocNotfound); + static_doc_error!(doc_not_found, ErrorCode::DocNotfound); static_doc_error!(duplicate_rev, ErrorCode::DuplicateRevision); } @@ -82,7 +82,7 @@ impl std::default::Default for ErrorCode { impl std::convert::From for DocError { fn from(error: flowy_database::Error) -> Self { match error { - flowy_database::Error::NotFound => DocError::record_not_found().context(error), + flowy_database::Error::NotFound => DocError::doc_not_found().context(error), _ => DocError::internal().context(error), } } diff --git a/frontend/rust-lib/flowy-document/src/module.rs b/frontend/rust-lib/flowy-document/src/module.rs index 27a4fa62d2..582beba1e5 100644 --- a/frontend/rust-lib/flowy-document/src/module.rs +++ b/frontend/rust-lib/flowy-document/src/module.rs @@ -1,7 +1,7 @@ use crate::{ errors::DocError, services::{ - doc::{doc_controller::DocController, edit::ClientDocEditor}, + doc::{controller::DocController, edit::ClientDocEditor}, server::construct_doc_server, ws::WsDocumentManager, }, diff --git a/frontend/rust-lib/flowy-document/src/services/cache.rs b/frontend/rust-lib/flowy-document/src/services/cache.rs index 712cde6774..dce3a006b7 100644 --- a/frontend/rust-lib/flowy-document/src/services/cache.rs +++ b/frontend/rust-lib/flowy-document/src/services/cache.rs @@ -46,4 +46,4 @@ impl DocCache { } } -fn doc_not_found() -> DocError { DocError::record_not_found().context("Doc is close or you should call open first") } +fn doc_not_found() -> DocError { DocError::doc_not_found().context("Doc is close or you should call open first") } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/doc_controller.rs b/frontend/rust-lib/flowy-document/src/services/doc/controller.rs similarity index 96% rename from frontend/rust-lib/flowy-document/src/services/doc/doc_controller.rs rename to frontend/rust-lib/flowy-document/src/services/doc/controller.rs index e7d33fd186..f7a502d41f 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/doc_controller.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/controller.rs @@ -122,7 +122,7 @@ struct RevisionServerImpl { impl RevisionServer for RevisionServerImpl { #[tracing::instrument(level = "debug", skip(self))] - fn fetch_document_from_remote(&self, doc_id: &str) -> ResultFuture { + fn fetch_document(&self, doc_id: &str) -> ResultFuture { let params = DocIdentifier { doc_id: doc_id.to_string(), }; @@ -131,7 +131,7 @@ impl RevisionServer for RevisionServerImpl { ResultFuture::new(async move { match server.read_doc(&token, params).await? { - None => Err(DocError::record_not_found().context("Remote doesn't have this document")), + None => Err(DocError::doc_not_found().context("Remote doesn't have this document")), Some(doc) => Ok(doc), } }) diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs index 4b2e5cb1c0..a3162eb979 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs @@ -209,7 +209,7 @@ impl ClientDocEditor { async fn handle_push_rev(&self, bytes: Bytes) -> DocResult<()> { // Transform the revision let (ret, rx) = oneshot::channel::>(); - let _ = self.edit_tx.send(EditCommand::RemoteRevision { bytes, ret }); + let _ = self.edit_tx.send(EditCommand::ProcessRemoteRevision { bytes, ret }); let TransformDeltas { client_prime, server_prime, @@ -268,12 +268,12 @@ impl ClientDocEditor { let revision = self.rev_manager.mk_revisions(range).await?; let _ = self.ws.send(revision.into()); }, - WsDataType::NewDocUser => {}, WsDataType::Acked => { let rev_id = RevId::try_from(bytes)?; let _ = self.rev_manager.ack_revision(rev_id).await?; }, WsDataType::Conflict => {}, + WsDataType::NewDocUser => {}, } Ok(()) } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs index 5e9c94dd10..b466c0a147 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs @@ -55,7 +55,7 @@ impl EditCommandQueue { let result = self.composed_delta(delta).await; let _ = ret.send(result); }, - EditCommand::RemoteRevision { bytes, ret } => { + EditCommand::ProcessRemoteRevision { bytes, ret } => { let revision = Revision::try_from(bytes)?; let delta = RichTextDelta::from_bytes(&revision.delta_data)?; let rev_id: RevId = revision.rev_id.into(); @@ -131,7 +131,7 @@ pub(crate) enum EditCommand { delta: RichTextDelta, ret: Ret<()>, }, - RemoteRevision { + ProcessRemoteRevision { bytes: Bytes, ret: Ret, }, diff --git a/frontend/rust-lib/flowy-document/src/services/doc/mod.rs b/frontend/rust-lib/flowy-document/src/services/doc/mod.rs index 48a4bbd187..9b554e2e17 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/mod.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/mod.rs @@ -1,4 +1,4 @@ pub mod edit; pub mod revision; -pub(crate) mod doc_controller; +pub(crate) mod controller; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs index 8117178e11..a6e7d0a80b 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs @@ -22,7 +22,7 @@ use lib_ot::{ }; use std::{sync::Arc, time::Duration}; use tokio::{ - sync::RwLock, + sync::{mpsc, RwLock}, task::{spawn_blocking, JoinHandle}, }; @@ -107,13 +107,15 @@ impl RevisionCache { } } - pub async fn fetch_document(&self) -> DocResult { - let result = fetch_from_local(&self.doc_id, self.dish_cache.clone()).await; + pub async fn load_document(&self) -> DocResult { + // 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() { return result; } - let doc = self.server.fetch_document_from_remote(&self.doc_id).await?; + // The document doesn't exist in local. Try load from server + let doc = self.server.fetch_document(&self.doc_id).await?; let delta_data = doc.data.as_bytes(); let revision = Revision::new( doc.base_rev_id, @@ -154,21 +156,30 @@ impl RevisionIterator for RevisionCache { } } -async fn fetch_from_local(doc_id: &str, disk_cache: Arc) -> DocResult { +async fn load_from_disk( + doc_id: &str, + memory_cache: Arc, + disk_cache: Arc, +) -> DocResult { let doc_id = doc_id.to_owned(); - spawn_blocking(move || { + let (tx, mut rx) = mpsc::channel(2); + let doc = spawn_blocking(move || { let revisions = disk_cache.read_revisions(&doc_id)?; if revisions.is_empty() { - return Err(DocError::record_not_found().context("Local doesn't have this document")); + return Err(DocError::doc_not_found().context("Local doesn't have this document")); } - let base_rev_id: RevId = revisions.last().unwrap().base_rev_id.into(); - let rev_id: RevId = revisions.last().unwrap().rev_id.into(); + let (base_rev_id, rev_id) = revisions.last().unwrap().pair_rev_id(); let mut delta = RichTextDelta::new(); for (_, revision) in revisions.into_iter().enumerate() { - match RichTextDelta::from_bytes(revision.delta_data) { + // Opti: revision's clone may cause memory issues + match RichTextDelta::from_bytes(revision.clone().delta_data) { Ok(local_delta) => { delta = delta.compose(&local_delta)?; + match tx.blocking_send(revision) { + Ok(_) => {}, + Err(e) => log::error!("Load document from disk error: {}", e), + } }, Err(e) => { log::error!("Deserialize delta from revision failed: {}", e); @@ -176,51 +187,36 @@ async fn fetch_from_local(doc_id: &str, disk_cache: Arc) - } } - #[cfg(debug_assertions)] - validate_delta(&doc_id, disk_cache, &delta); - - match delta.ops.last() { - None => {}, - Some(op) => { - let data = op.get_data(); - if !data.ends_with('\n') { - delta.ops.push(Operation::Insert("\n".into())) - } - }, - } - + correct_delta_if_need(&mut delta); Result::::Ok(Doc { id: doc_id, data: delta.to_json(), - rev_id: rev_id.into(), - base_rev_id: base_rev_id.into(), + rev_id, + base_rev_id, }) }) .await - .map_err(internal_error)? + .map_err(internal_error)?; + + while let Some(revision) = rx.recv().await { + match memory_cache.add_revision(revision).await { + Ok(_) => {}, + Err(e) => log::error!("{:?}", e), + } + } + + doc } -#[cfg(debug_assertions)] -fn validate_delta(doc_id: &str, disk_cache: Arc, delta: &RichTextDelta) { +fn correct_delta_if_need(delta: &mut RichTextDelta) { if delta.ops.last().is_none() { return; } let data = delta.ops.last().as_ref().unwrap().get_data(); if !data.ends_with('\n') { - log::error!("The op must end with newline"); - let result = || { - let revisions = disk_cache.read_revisions(&doc_id)?; - for revision in revisions { - let delta = RichTextDelta::from_bytes(revision.delta_data)?; - log::error!("Invalid revision: {}:{}", revision.rev_id, delta.to_json()); - } - Ok::<(), DocError>(()) - }; - match result() { - Ok(_) => {}, - Err(e) => log::error!("{}", e), - } + log::error!("The op must end with newline. Correcting it by inserting newline op"); + delta.ops.push(Operation::Insert("\n".into())); } } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs index 1ff1f4bd86..62e20e98ac 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs @@ -14,7 +14,7 @@ use std::sync::Arc; use tokio::sync::mpsc; pub trait RevisionServer: Send + Sync { - fn fetch_document_from_remote(&self, doc_id: &str) -> ResultFuture; + fn fetch_document(&self, doc_id: &str) -> ResultFuture; } pub struct RevisionManager { @@ -41,7 +41,7 @@ impl RevisionManager { } pub async fn load_document(&mut self) -> DocResult { - let doc = self.cache.fetch_document().await?; + let doc = self.cache.load_document().await?; self.update_rev_id_counter_value(doc.rev_id); Ok(doc.delta()?) } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs index ac225ce9a0..deafc670a9 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs @@ -53,6 +53,7 @@ impl RevisionUploadStream { } async fn send_next_revision(&self) -> DocResult<()> { + log::debug!("😁Tick"); match self.revisions.next().await? { None => Ok(()), Some(record) => { diff --git a/frontend/rust-lib/flowy-document/tests/editor/mod.rs b/frontend/rust-lib/flowy-document/tests/editor/mod.rs index a6fb4624b5..83afcda353 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/mod.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/mod.rs @@ -1,6 +1,7 @@ #![allow(clippy::module_inception)] mod attribute_test; mod op_test; +mod revision_test; mod serde_test; mod undo_redo_test; diff --git a/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs b/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs new file mode 100644 index 0000000000..e3e3d15222 --- /dev/null +++ b/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs @@ -0,0 +1,8 @@ +use flowy_test::editor::*; + +#[tokio::test] +async fn create_doc() { + let test = EditorTest::new().await; + let _editor = test.create_doc().await; + println!("123"); +} diff --git a/frontend/rust-lib/flowy-test/src/editor.rs b/frontend/rust-lib/flowy-test/src/editor.rs new file mode 100644 index 0000000000..7764e698ac --- /dev/null +++ b/frontend/rust-lib/flowy-test/src/editor.rs @@ -0,0 +1,22 @@ +use crate::{helper::ViewTest, FlowySDKTest}; +use flowy_document::services::doc::edit::ClientDocEditor; +use flowy_document_infra::entities::doc::DocIdentifier; +use std::sync::Arc; + +pub struct EditorTest { + pub sdk: FlowySDKTest, +} + +impl EditorTest { + pub async fn new() -> Self { + let sdk = FlowySDKTest::setup(); + let _ = sdk.init_user().await; + Self { sdk } + } + + pub async fn create_doc(&self) -> Arc { + let test = ViewTest::new(&self.sdk).await; + let doc_identifier: DocIdentifier = test.view.id.clone().into(); + self.sdk.flowy_document.open(doc_identifier).await.unwrap() + } +} diff --git a/frontend/rust-lib/flowy-test/src/builder.rs b/frontend/rust-lib/flowy-test/src/event_builder.rs similarity index 84% rename from frontend/rust-lib/flowy-test/src/builder.rs rename to frontend/rust-lib/flowy-test/src/event_builder.rs index 5e23f331a4..0cacef01af 100644 --- a/frontend/rust-lib/flowy-test/src/builder.rs +++ b/frontend/rust-lib/flowy-test/src/event_builder.rs @@ -5,37 +5,36 @@ use std::{ hash::Hash, }; -use crate::FlowyTestSDK; -use lib_dispatch::prelude::*; - +use crate::FlowySDKTest; use flowy_core::errors::WorkspaceError; -use flowy_sdk::*; + use flowy_user::errors::UserError; +use lib_dispatch::prelude::*; use std::{convert::TryFrom, marker::PhantomData, sync::Arc}; -pub type FlowyWorkspaceTest = Builder; -impl FlowyWorkspaceTest { - pub fn new(sdk: FlowyTestSDK) -> Self { Builder::test(TestContext::new(sdk)) } +pub type CoreModuleEventBuilder = EventBuilder; +impl CoreModuleEventBuilder { + pub fn new(sdk: FlowySDKTest) -> Self { EventBuilder::test(TestContext::new(sdk)) } } -pub type UserTest = Builder; -impl UserTest { - pub fn new(sdk: FlowyTestSDK) -> Self { Builder::test(TestContext::new(sdk)) } +pub type UserModuleEventBuilder = EventBuilder; +impl UserModuleEventBuilder { + pub fn new(sdk: FlowySDKTest) -> Self { EventBuilder::test(TestContext::new(sdk)) } pub fn user_profile(&self) -> &Option { &self.user_profile } } #[derive(Clone)] -pub struct Builder { +pub struct EventBuilder { context: TestContext, user_profile: Option, err_phantom: PhantomData, } -impl Builder +impl EventBuilder where E: FromBytes + Debug, { - pub(crate) fn test(context: TestContext) -> Self { + fn test(context: TestContext) -> Self { Self { context, user_profile: None, @@ -111,8 +110,6 @@ where self } - pub fn sdk(&self) -> FlowySDK { self.context.sdk.clone() } - fn dispatch(&self) -> Arc { self.context.sdk.dispatcher() } fn get_response(&self) -> EventResponse { @@ -128,13 +125,13 @@ where #[derive(Clone)] pub struct TestContext { - sdk: FlowyTestSDK, + pub sdk: FlowySDKTest, request: Option, response: Option, } impl TestContext { - pub fn new(sdk: FlowyTestSDK) -> Self { + pub fn new(sdk: FlowySDKTest) -> Self { Self { sdk, request: None, diff --git a/frontend/rust-lib/flowy-test/src/helper.rs b/frontend/rust-lib/flowy-test/src/helper.rs index aa84fd583c..340bef8ad4 100644 --- a/frontend/rust-lib/flowy-test/src/helper.rs +++ b/frontend/rust-lib/flowy-test/src/helper.rs @@ -1,19 +1,282 @@ +use crate::prelude::*; use bytes::Bytes; -use lib_dispatch::prelude::{EventDispatcher, ModuleRequest, ToBytes}; -use lib_infra::{kv::KV, uuid}; - use flowy_core::{ - entities::workspace::{CreateWorkspaceRequest, QueryWorkspaceRequest, Workspace}, - errors::WorkspaceError, - event::WorkspaceEvent::{CreateWorkspace, OpenWorkspace}, + entities::{ + app::*, + trash::{RepeatedTrash, TrashIdentifier}, + view::*, + workspace::{CreateWorkspaceRequest, QueryWorkspaceRequest, Workspace, *}, + }, + errors::{ErrorCode, WorkspaceError}, + event::WorkspaceEvent::{CreateWorkspace, OpenWorkspace, *}, }; +use flowy_document_infra::entities::doc::Doc; use flowy_user::{ entities::{SignInRequest, SignUpRequest, UserProfile}, errors::UserError, event::UserEvent::{SignIn, SignOut, SignUp}, }; +use lib_dispatch::prelude::{EventDispatcher, ModuleRequest, ToBytes}; +use lib_infra::{kv::KV, uuid}; use std::{fs, path::PathBuf, sync::Arc}; +pub struct WorkspaceTest { + pub sdk: FlowySDKTest, + pub workspace: Workspace, +} + +impl WorkspaceTest { + pub async fn new() -> Self { + let sdk = FlowySDKTest::setup(); + let _ = sdk.init_user().await; + let workspace = create_workspace(&sdk, "Workspace", "").await; + open_workspace(&sdk, &workspace.id).await; + + Self { sdk, workspace } + } +} + +pub struct AppTest { + pub sdk: FlowySDKTest, + pub workspace: Workspace, + pub app: App, +} + +impl AppTest { + pub async fn new() -> Self { + let sdk = FlowySDKTest::setup(); + let _ = sdk.init_user().await; + let workspace = create_workspace(&sdk, "Workspace", "").await; + open_workspace(&sdk, &workspace.id).await; + let app = create_app(&sdk, "App", "AppFlowy GitHub Project", &workspace.id).await; + Self { sdk, workspace, app } + } + + pub async fn move_app_to_trash(&self) { + let request = UpdateAppRequest { + app_id: self.app.id.clone(), + name: None, + desc: None, + color_style: None, + is_trash: Some(true), + }; + update_app(&self.sdk, request).await; + } +} + +pub struct ViewTest { + pub sdk: FlowySDKTest, + pub workspace: Workspace, + pub app: App, + pub view: View, +} + +impl ViewTest { + pub async fn new(sdk: &FlowySDKTest) -> Self { + let workspace = create_workspace(&sdk, "Workspace", "").await; + open_workspace(&sdk, &workspace.id).await; + let app = create_app(&sdk, "App", "AppFlowy GitHub Project", &workspace.id).await; + let view = create_view(&sdk, &app.id).await; + Self { + sdk: sdk.clone(), + workspace, + app, + view, + } + } + + pub async fn delete_views(&self, view_ids: Vec) { + let request = QueryViewRequest { view_ids }; + delete_view(&self.sdk, request).await; + } + + pub async fn delete_views_permanent(&self, view_ids: Vec) { + let request = QueryViewRequest { view_ids }; + delete_view(&self.sdk, request).await; + + CoreModuleEventBuilder::new(self.sdk.clone()) + .event(DeleteAll) + .async_send() + .await; + } +} + +pub fn invalid_workspace_name_test_case() -> Vec<(String, ErrorCode)> { + vec![ + ("".to_owned(), ErrorCode::WorkspaceNameInvalid), + ("1234".repeat(100), ErrorCode::WorkspaceNameTooLong), + ] +} + +pub async fn create_workspace(sdk: &FlowySDKTest, name: &str, desc: &str) -> Workspace { + let request = CreateWorkspaceRequest { + name: name.to_owned(), + desc: desc.to_owned(), + }; + + let workspace = CoreModuleEventBuilder::new(sdk.clone()) + .event(CreateWorkspace) + .request(request) + .async_send() + .await + .parse::(); + workspace +} + +async fn open_workspace(sdk: &FlowySDKTest, workspace_id: &str) { + let request = QueryWorkspaceRequest { + workspace_id: Some(workspace_id.to_owned()), + }; + let _ = CoreModuleEventBuilder::new(sdk.clone()) + .event(OpenWorkspace) + .request(request) + .async_send() + .await; +} + +pub async fn read_workspace(sdk: &FlowySDKTest, request: QueryWorkspaceRequest) -> Vec { + let repeated_workspace = CoreModuleEventBuilder::new(sdk.clone()) + .event(ReadWorkspaces) + .request(request.clone()) + .async_send() + .await + .parse::(); + + let workspaces; + if let Some(workspace_id) = &request.workspace_id { + workspaces = repeated_workspace + .into_inner() + .into_iter() + .filter(|workspace| &workspace.id == workspace_id) + .collect::>(); + debug_assert_eq!(workspaces.len(), 1); + } else { + workspaces = repeated_workspace.items; + } + + workspaces +} + +pub async fn create_app(sdk: &FlowySDKTest, name: &str, desc: &str, workspace_id: &str) -> App { + let create_app_request = CreateAppRequest { + workspace_id: workspace_id.to_owned(), + name: name.to_string(), + desc: desc.to_string(), + color_style: Default::default(), + }; + + let app = CoreModuleEventBuilder::new(sdk.clone()) + .event(CreateApp) + .request(create_app_request) + .async_send() + .await + .parse::(); + app +} + +pub async fn delete_app(sdk: &FlowySDKTest, app_id: &str) { + let delete_app_request = AppIdentifier { + app_id: app_id.to_string(), + }; + + CoreModuleEventBuilder::new(sdk.clone()) + .event(DeleteApp) + .request(delete_app_request) + .async_send() + .await; +} + +pub async fn update_app(sdk: &FlowySDKTest, request: UpdateAppRequest) { + CoreModuleEventBuilder::new(sdk.clone()) + .event(UpdateApp) + .request(request) + .async_send() + .await; +} + +pub async fn read_app(sdk: &FlowySDKTest, request: QueryAppRequest) -> App { + let app = CoreModuleEventBuilder::new(sdk.clone()) + .event(ReadApp) + .request(request) + .async_send() + .await + .parse::(); + + app +} + +pub async fn create_view_with_request(sdk: &FlowySDKTest, request: CreateViewRequest) -> View { + let view = CoreModuleEventBuilder::new(sdk.clone()) + .event(CreateView) + .request(request) + .async_send() + .await + .parse::(); + view +} + +pub async fn create_view(sdk: &FlowySDKTest, app_id: &str) -> View { + let request = CreateViewRequest { + belong_to_id: app_id.to_string(), + name: "View A".to_string(), + desc: "".to_string(), + thumbnail: Some("http://1.png".to_string()), + view_type: ViewType::Doc, + }; + + create_view_with_request(sdk, request).await +} + +pub async fn update_view(sdk: &FlowySDKTest, request: UpdateViewRequest) { + CoreModuleEventBuilder::new(sdk.clone()) + .event(UpdateView) + .request(request) + .async_send() + .await; +} + +pub async fn read_view(sdk: &FlowySDKTest, request: QueryViewRequest) -> View { + CoreModuleEventBuilder::new(sdk.clone()) + .event(ReadView) + .request(request) + .async_send() + .await + .parse::() +} + +pub async fn delete_view(sdk: &FlowySDKTest, request: QueryViewRequest) { + CoreModuleEventBuilder::new(sdk.clone()) + .event(DeleteView) + .request(request) + .async_send() + .await; +} + +pub async fn read_trash(sdk: &FlowySDKTest) -> RepeatedTrash { + CoreModuleEventBuilder::new(sdk.clone()) + .event(ReadTrash) + .async_send() + .await + .parse::() +} + +pub async fn putback_trash(sdk: &FlowySDKTest, id: TrashIdentifier) { + CoreModuleEventBuilder::new(sdk.clone()) + .event(PutbackTrash) + .request(id) + .async_send() + .await; +} + +pub async fn open_view(sdk: &FlowySDKTest, request: QueryViewRequest) -> Doc { + CoreModuleEventBuilder::new(sdk.clone()) + .event(OpenView) + .request(request) + .async_send() + .await + .parse::() +} + pub fn root_dir() -> String { // https://doc.rust-lang.org/cargo/reference/environment-variables.html let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| "./".to_owned()); diff --git a/frontend/rust-lib/flowy-test/src/lib.rs b/frontend/rust-lib/flowy-test/src/lib.rs index 01bd9a88c7..492d5d3b1d 100644 --- a/frontend/rust-lib/flowy-test/src/lib.rs +++ b/frontend/rust-lib/flowy-test/src/lib.rs @@ -1,6 +1,6 @@ -pub mod builder; -mod helper; -pub mod workspace; +pub mod editor; +pub mod event_builder; +pub mod helper; use crate::helper::*; use backend_service::configuration::{get_client_server_configuration, ClientServerConfiguration}; @@ -9,40 +9,40 @@ use flowy_user::entities::UserProfile; use lib_infra::uuid; pub mod prelude { - pub use crate::{builder::*, helper::*, *}; + pub use crate::{event_builder::*, helper::*, *}; pub use lib_dispatch::prelude::*; } -pub type FlowyTestSDK = FlowySDK; - #[derive(Clone)] -pub struct FlowyTest { - pub sdk: FlowyTestSDK, +pub struct FlowySDKTest(pub FlowySDK); + +impl std::ops::Deref for FlowySDKTest { + type Target = FlowySDK; + + fn deref(&self) -> &Self::Target { &self.0 } } -impl FlowyTest { +impl FlowySDKTest { pub fn setup() -> Self { let server_config = get_client_server_configuration().unwrap(); - let test = Self::setup_with(server_config); - std::mem::forget(test.sdk.dispatcher()); - test - } - - pub async fn sign_up(&self) -> SignUpContext { - let context = async_sign_up(self.sdk.dispatcher()).await; - context - } - - pub async fn init_user(&self) -> UserProfile { - let context = async_sign_up(self.sdk.dispatcher()).await; - context.user_profile + let sdk = Self::setup_with(server_config); + std::mem::forget(sdk.dispatcher()); + sdk } pub fn setup_with(server_config: ClientServerConfiguration) -> Self { let config = FlowySDKConfig::new(&root_dir(), server_config, &uuid()).log_filter("debug"); let sdk = FlowySDK::new(config); - Self { sdk } + Self(sdk) } - pub fn sdk(&self) -> FlowyTestSDK { self.sdk.clone() } + pub async fn sign_up(&self) -> SignUpContext { + let context = async_sign_up(self.0.dispatcher()).await; + context + } + + pub async fn init_user(&self) -> UserProfile { + let context = async_sign_up(self.0.dispatcher()).await; + context.user_profile + } } diff --git a/frontend/rust-lib/flowy-test/src/workspace.rs b/frontend/rust-lib/flowy-test/src/workspace.rs deleted file mode 100644 index d2c2f77b48..0000000000 --- a/frontend/rust-lib/flowy-test/src/workspace.rs +++ /dev/null @@ -1,276 +0,0 @@ -use crate::prelude::*; -use flowy_core::{ - entities::{ - app::*, - trash::{RepeatedTrash, TrashIdentifier}, - view::*, - workspace::*, - }, - errors::ErrorCode, - event::WorkspaceEvent::*, -}; -use flowy_document_infra::entities::doc::Doc; - -pub struct WorkspaceTest { - pub sdk: FlowyTestSDK, - pub workspace: Workspace, -} - -impl WorkspaceTest { - pub async fn new() -> Self { - let test = FlowyTest::setup(); - let _ = test.init_user().await; - let workspace = create_workspace(&test.sdk, "Workspace", "").await; - open_workspace(&test.sdk, &workspace.id).await; - - Self { - sdk: test.sdk, - workspace, - } - } -} - -pub struct AppTest { - pub sdk: FlowyTestSDK, - pub workspace: Workspace, - pub app: App, -} - -impl AppTest { - pub async fn new() -> Self { - let test = FlowyTest::setup(); - let _ = test.init_user().await; - let workspace = create_workspace(&test.sdk, "Workspace", "").await; - open_workspace(&test.sdk, &workspace.id).await; - let app = create_app(&test.sdk, "App", "AppFlowy GitHub Project", &workspace.id).await; - Self { - sdk: test.sdk, - workspace, - app, - } - } - - pub async fn move_app_to_trash(&self) { - let request = UpdateAppRequest { - app_id: self.app.id.clone(), - name: None, - desc: None, - color_style: None, - is_trash: Some(true), - }; - update_app(&self.sdk, request).await; - } -} - -pub struct ViewTest { - pub sdk: FlowyTestSDK, - pub workspace: Workspace, - pub app: App, - pub view: View, -} - -impl ViewTest { - pub async fn new(test: &FlowyTest) -> Self { - let workspace = create_workspace(&test.sdk, "Workspace", "").await; - open_workspace(&test.sdk, &workspace.id).await; - let app = create_app(&test.sdk, "App", "AppFlowy GitHub Project", &workspace.id).await; - let view = create_view(&test.sdk, &app.id).await; - Self { - sdk: test.sdk.clone(), - workspace, - app, - view, - } - } - - pub async fn delete_views(&self, view_ids: Vec) { - let request = QueryViewRequest { view_ids }; - delete_view(&self.sdk, request).await; - } - - pub async fn delete_views_permanent(&self, view_ids: Vec) { - let request = QueryViewRequest { view_ids }; - delete_view(&self.sdk, request).await; - - FlowyWorkspaceTest::new(self.sdk.clone()) - .event(DeleteAll) - .async_send() - .await; - } -} - -pub fn invalid_workspace_name_test_case() -> Vec<(String, ErrorCode)> { - vec![ - ("".to_owned(), ErrorCode::WorkspaceNameInvalid), - ("1234".repeat(100), ErrorCode::WorkspaceNameTooLong), - ] -} - -pub async fn create_workspace(sdk: &FlowyTestSDK, name: &str, desc: &str) -> Workspace { - let request = CreateWorkspaceRequest { - name: name.to_owned(), - desc: desc.to_owned(), - }; - - let workspace = FlowyWorkspaceTest::new(sdk.clone()) - .event(CreateWorkspace) - .request(request) - .async_send() - .await - .parse::(); - workspace -} - -async fn open_workspace(sdk: &FlowyTestSDK, workspace_id: &str) { - let request = QueryWorkspaceRequest { - workspace_id: Some(workspace_id.to_owned()), - }; - let _ = FlowyWorkspaceTest::new(sdk.clone()) - .event(OpenWorkspace) - .request(request) - .async_send() - .await; -} - -pub async fn read_workspace(sdk: &FlowyTestSDK, request: QueryWorkspaceRequest) -> Vec { - let repeated_workspace = FlowyWorkspaceTest::new(sdk.clone()) - .event(ReadWorkspaces) - .request(request.clone()) - .async_send() - .await - .parse::(); - - let workspaces; - if let Some(workspace_id) = &request.workspace_id { - workspaces = repeated_workspace - .into_inner() - .into_iter() - .filter(|workspace| &workspace.id == workspace_id) - .collect::>(); - debug_assert_eq!(workspaces.len(), 1); - } else { - workspaces = repeated_workspace.items; - } - - workspaces -} - -pub async fn create_app(sdk: &FlowyTestSDK, name: &str, desc: &str, workspace_id: &str) -> App { - let create_app_request = CreateAppRequest { - workspace_id: workspace_id.to_owned(), - name: name.to_string(), - desc: desc.to_string(), - color_style: Default::default(), - }; - - let app = FlowyWorkspaceTest::new(sdk.clone()) - .event(CreateApp) - .request(create_app_request) - .async_send() - .await - .parse::(); - app -} - -pub async fn delete_app(sdk: &FlowyTestSDK, app_id: &str) { - let delete_app_request = AppIdentifier { - app_id: app_id.to_string(), - }; - - FlowyWorkspaceTest::new(sdk.clone()) - .event(DeleteApp) - .request(delete_app_request) - .async_send() - .await; -} - -pub async fn update_app(sdk: &FlowyTestSDK, request: UpdateAppRequest) { - FlowyWorkspaceTest::new(sdk.clone()) - .event(UpdateApp) - .request(request) - .async_send() - .await; -} - -pub async fn read_app(sdk: &FlowyTestSDK, request: QueryAppRequest) -> App { - let app = FlowyWorkspaceTest::new(sdk.clone()) - .event(ReadApp) - .request(request) - .async_send() - .await - .parse::(); - - app -} - -pub async fn create_view_with_request(sdk: &FlowyTestSDK, request: CreateViewRequest) -> View { - let view = FlowyWorkspaceTest::new(sdk.clone()) - .event(CreateView) - .request(request) - .async_send() - .await - .parse::(); - view -} - -pub async fn create_view(sdk: &FlowyTestSDK, app_id: &str) -> View { - let request = CreateViewRequest { - belong_to_id: app_id.to_string(), - name: "View A".to_string(), - desc: "".to_string(), - thumbnail: Some("http://1.png".to_string()), - view_type: ViewType::Doc, - }; - - create_view_with_request(sdk, request).await -} - -pub async fn update_view(sdk: &FlowyTestSDK, request: UpdateViewRequest) { - FlowyWorkspaceTest::new(sdk.clone()) - .event(UpdateView) - .request(request) - .async_send() - .await; -} - -pub async fn read_view(sdk: &FlowyTestSDK, request: QueryViewRequest) -> View { - FlowyWorkspaceTest::new(sdk.clone()) - .event(ReadView) - .request(request) - .async_send() - .await - .parse::() -} - -pub async fn delete_view(sdk: &FlowyTestSDK, request: QueryViewRequest) { - FlowyWorkspaceTest::new(sdk.clone()) - .event(DeleteView) - .request(request) - .async_send() - .await; -} - -pub async fn read_trash(sdk: &FlowyTestSDK) -> RepeatedTrash { - FlowyWorkspaceTest::new(sdk.clone()) - .event(ReadTrash) - .async_send() - .await - .parse::() -} - -pub async fn putback_trash(sdk: &FlowyTestSDK, id: TrashIdentifier) { - FlowyWorkspaceTest::new(sdk.clone()) - .event(PutbackTrash) - .request(id) - .async_send() - .await; -} - -pub async fn open_view(sdk: &FlowyTestSDK, request: QueryViewRequest) -> Doc { - FlowyWorkspaceTest::new(sdk.clone()) - .event(OpenView) - .request(request) - .async_send() - .await - .parse::() -} diff --git a/frontend/rust-lib/flowy-user/tests/event/auth_test.rs b/frontend/rust-lib/flowy-user/tests/event/auth_test.rs index b78a414a59..a0490927af 100644 --- a/frontend/rust-lib/flowy-user/tests/event/auth_test.rs +++ b/frontend/rust-lib/flowy-user/tests/event/auth_test.rs @@ -1,11 +1,11 @@ use crate::helper::*; -use flowy_test::{builder::UserTest, FlowyTest}; +use flowy_test::{event_builder::UserModuleEventBuilder, FlowySDKTest}; use flowy_user::{errors::ErrorCode, event::UserEvent::*, prelude::*}; #[tokio::test] async fn sign_up_with_invalid_email() { for email in invalid_email_test_case() { - let test = FlowyTest::setup(); + let sdk = FlowySDKTest::setup(); let request = SignUpRequest { email: email.to_string(), name: valid_name(), @@ -13,7 +13,7 @@ async fn sign_up_with_invalid_email() { }; assert_eq!( - UserTest::new(test.sdk) + UserModuleEventBuilder::new(sdk) .event(SignUp) .request(request) .async_send() @@ -27,14 +27,14 @@ async fn sign_up_with_invalid_email() { #[tokio::test] async fn sign_up_with_invalid_password() { for password in invalid_password_test_case() { - let test = FlowyTest::setup(); + let sdk = FlowySDKTest::setup(); let request = SignUpRequest { email: random_email(), name: valid_name(), password, }; - UserTest::new(test.sdk) + UserModuleEventBuilder::new(sdk) .event(SignUp) .request(request) .async_send() @@ -45,8 +45,8 @@ async fn sign_up_with_invalid_password() { #[tokio::test] async fn sign_in_success() { - let test = FlowyTest::setup(); - let _ = UserTest::new(test.sdk()).event(SignOut).sync_send(); + let test = FlowySDKTest::setup(); + let _ = UserModuleEventBuilder::new(test.clone()).event(SignOut).sync_send(); let sign_up_context = test.sign_up().await; let request = SignInRequest { @@ -55,7 +55,7 @@ async fn sign_in_success() { name: "".to_string(), }; - let response = UserTest::new(test.sdk()) + let response = UserModuleEventBuilder::new(test.clone()) .event(SignIn) .request(request) .async_send() @@ -67,7 +67,7 @@ async fn sign_in_success() { #[tokio::test] async fn sign_in_with_invalid_email() { for email in invalid_email_test_case() { - let test = FlowyTest::setup(); + let sdk = FlowySDKTest::setup(); let request = SignInRequest { email: email.to_string(), password: login_password(), @@ -75,7 +75,7 @@ async fn sign_in_with_invalid_email() { }; assert_eq!( - UserTest::new(test.sdk) + UserModuleEventBuilder::new(sdk) .event(SignIn) .request(request) .async_send() @@ -90,7 +90,7 @@ async fn sign_in_with_invalid_email() { #[tokio::test] async fn sign_in_with_invalid_password() { for password in invalid_password_test_case() { - let test = FlowyTest::setup(); + let sdk = FlowySDKTest::setup(); let request = SignInRequest { email: random_email(), @@ -98,7 +98,7 @@ async fn sign_in_with_invalid_password() { name: "".to_string(), }; - UserTest::new(test.sdk) + UserModuleEventBuilder::new(sdk) .event(SignIn) .request(request) .async_send() diff --git a/frontend/rust-lib/flowy-user/tests/event/helper.rs b/frontend/rust-lib/flowy-user/tests/event/helper.rs index 2afc5b8a01..ed1fe6ede8 100644 --- a/frontend/rust-lib/flowy-user/tests/event/helper.rs +++ b/frontend/rust-lib/flowy-user/tests/event/helper.rs @@ -1,5 +1,5 @@ pub use flowy_test::{ - builder::*, + event_builder::*, prelude::{login_password, random_email}, }; diff --git a/frontend/rust-lib/flowy-user/tests/event/user_profile_test.rs b/frontend/rust-lib/flowy-user/tests/event/user_profile_test.rs index 8ef97e6fe6..e3c2a4de09 100644 --- a/frontend/rust-lib/flowy-user/tests/event/user_profile_test.rs +++ b/frontend/rust-lib/flowy-user/tests/event/user_profile_test.rs @@ -1,13 +1,13 @@ use crate::helper::*; -use flowy_test::{builder::UserTest, FlowyTest}; +use flowy_test::{event_builder::UserModuleEventBuilder, FlowySDKTest}; use flowy_user::{errors::ErrorCode, event::UserEvent::*, prelude::*}; use lib_infra::uuid; use serial_test::*; #[tokio::test] async fn user_profile_get_failed() { - let test = FlowyTest::setup(); - let result = UserTest::new(test.sdk) + let sdk = FlowySDKTest::setup(); + let result = UserModuleEventBuilder::new(sdk) .event(GetUserProfile) .assert_error() .async_send() @@ -18,9 +18,9 @@ async fn user_profile_get_failed() { #[tokio::test] #[serial] async fn user_profile_get() { - let test = FlowyTest::setup(); + let test = FlowySDKTest::setup(); let user_profile = test.init_user().await; - let user = UserTest::new(test.sdk.clone()) + let user = UserModuleEventBuilder::new(test.clone()) .event(GetUserProfile) .sync_send() .parse::(); @@ -30,13 +30,16 @@ async fn user_profile_get() { #[tokio::test] #[serial] async fn user_update_with_name() { - let test = FlowyTest::setup(); - let user = test.init_user().await; + let sdk = FlowySDKTest::setup(); + let user = sdk.init_user().await; let new_name = "hello_world".to_owned(); let request = UpdateUserRequest::new(&user.id).name(&new_name); - let _ = UserTest::new(test.sdk()).event(UpdateUser).request(request).sync_send(); + let _ = UserModuleEventBuilder::new(sdk.clone()) + .event(UpdateUser) + .request(request) + .sync_send(); - let user_profile = UserTest::new(test.sdk()) + let user_profile = UserModuleEventBuilder::new(sdk.clone()) .event(GetUserProfile) .assert_error() .sync_send() @@ -48,12 +51,15 @@ async fn user_update_with_name() { #[tokio::test] #[serial] async fn user_update_with_email() { - let test = FlowyTest::setup(); - let user = test.init_user().await; + let sdk = FlowySDKTest::setup(); + let user = sdk.init_user().await; let new_email = format!("{}@gmail.com", uuid()); let request = UpdateUserRequest::new(&user.id).email(&new_email); - let _ = UserTest::new(test.sdk()).event(UpdateUser).request(request).sync_send(); - let user_profile = UserTest::new(test.sdk()) + let _ = UserModuleEventBuilder::new(sdk.clone()) + .event(UpdateUser) + .request(request) + .sync_send(); + let user_profile = UserModuleEventBuilder::new(sdk.clone()) .event(GetUserProfile) .assert_error() .sync_send() @@ -65,12 +71,12 @@ async fn user_update_with_email() { #[tokio::test] #[serial] async fn user_update_with_password() { - let test = FlowyTest::setup(); - let user = test.init_user().await; + let sdk = FlowySDKTest::setup(); + let user = sdk.init_user().await; let new_password = "H123world!".to_owned(); let request = UpdateUserRequest::new(&user.id).password(&new_password); - let _ = UserTest::new(test.sdk()) + let _ = UserModuleEventBuilder::new(sdk.clone()) .event(UpdateUser) .request(request) .sync_send() @@ -80,12 +86,12 @@ async fn user_update_with_password() { #[tokio::test] #[serial] async fn user_update_with_invalid_email() { - let test = FlowyTest::setup(); + let test = FlowySDKTest::setup(); let user = test.init_user().await; for email in invalid_email_test_case() { let request = UpdateUserRequest::new(&user.id).email(&email); assert_eq!( - UserTest::new(test.sdk()) + UserModuleEventBuilder::new(test.clone()) .event(UpdateUser) .request(request) .sync_send() @@ -99,12 +105,12 @@ async fn user_update_with_invalid_email() { #[tokio::test] #[serial] async fn user_update_with_invalid_password() { - let test = FlowyTest::setup(); + let test = FlowySDKTest::setup(); let user = test.init_user().await; for password in invalid_password_test_case() { let request = UpdateUserRequest::new(&user.id).password(&password); - UserTest::new(test.sdk()) + UserModuleEventBuilder::new(test.clone()) .event(UpdateUser) .request(request) .sync_send() @@ -115,10 +121,10 @@ async fn user_update_with_invalid_password() { #[tokio::test] #[serial] async fn user_update_with_invalid_name() { - let test = FlowyTest::setup(); + let test = FlowySDKTest::setup(); let user = test.init_user().await; let request = UpdateUserRequest::new(&user.id).name(""); - UserTest::new(test.sdk()) + UserModuleEventBuilder::new(test.clone()) .event(UpdateUser) .request(request) .sync_send() diff --git a/shared-lib/flowy-document-infra/src/entities/ws/ws.rs b/shared-lib/flowy-document-infra/src/entities/ws/ws.rs index c7457eaf12..422f6591b3 100644 --- a/shared-lib/flowy-document-infra/src/entities/ws/ws.rs +++ b/shared-lib/flowy-document-infra/src/entities/ws/ws.rs @@ -6,8 +6,11 @@ use std::convert::{TryFrom, TryInto}; #[derive(Debug, Clone, ProtoBuf_Enum, Eq, PartialEq, Hash)] pub enum WsDataType { + // The frontend receives the Acked means the backend has accepted the revision Acked = 0, + // The frontend receives the PushRev event means the backend is pushing the new revision to frontend PushRev = 1, + // The fronted receives the PullRev event means the backend try to pull the revision from frontend PullRev = 2, // data should be Revision Conflict = 3, NewDocUser = 4, diff --git a/shared-lib/lib-ot/src/errors.rs b/shared-lib/lib-ot/src/errors.rs index 5f67d699ac..fde37f2c42 100644 --- a/shared-lib/lib-ot/src/errors.rs +++ b/shared-lib/lib-ot/src/errors.rs @@ -36,6 +36,7 @@ impl OTError { } static_ot_error!(duplicate_revision, OTErrorCode::DuplicatedRevision); + static_ot_error!(revision_id_conflict, OTErrorCode::RevisionIDConflict); } impl fmt::Display for OTError { @@ -66,6 +67,7 @@ pub enum OTErrorCode { RedoFail, SerdeError, DuplicatedRevision, + RevisionIDConflict, } pub struct ErrorBuilder { diff --git a/shared-lib/lib-ot/src/revision/cache.rs b/shared-lib/lib-ot/src/revision/cache.rs index ede3a4298c..4a09b7bceb 100644 --- a/shared-lib/lib-ot/src/revision/cache.rs +++ b/shared-lib/lib-ot/src/revision/cache.rs @@ -33,8 +33,12 @@ impl RevisionMemoryCache { pub fn new() -> Self { RevisionMemoryCache::default() } pub async fn add_revision(&self, revision: Revision) -> Result<(), OTError> { - if self.revs_map.contains_key(&revision.rev_id) { - return Ok(()); + // The last revision's rev_id must be greater than the new one. + if let Some(rev_id) = self.pending_revs.read().await.back() { + if *rev_id >= revision.rev_id { + return Err(OTError::revision_id_conflict() + .context(format!("The new revision's id must be greater than {}", rev_id))); + } } self.pending_revs.write().await.push_back(revision.rev_id); @@ -121,21 +125,3 @@ impl RevisionRecord { pub fn ack(&mut self) { self.state = RevState::Acked; } } - -pub struct PendingRevId { - pub rev_id: i64, - pub sender: RevIdSender, -} - -impl PendingRevId { - pub fn new(rev_id: i64, sender: RevIdSender) -> Self { Self { rev_id, sender } } - - pub fn finish(&self, rev_id: i64) -> bool { - if self.rev_id > rev_id { - false - } else { - let _ = self.sender.send(self.rev_id); - true - } - } -} diff --git a/shared-lib/lib-ot/src/revision/model.rs b/shared-lib/lib-ot/src/revision/model.rs index 7b17e85699..818eb9886c 100644 --- a/shared-lib/lib-ot/src/revision/model.rs +++ b/shared-lib/lib-ot/src/revision/model.rs @@ -25,6 +25,8 @@ pub struct Revision { impl Revision { pub fn is_empty(&self) -> bool { self.base_rev_id == self.rev_id } + + pub fn pair_rev_id(&self) -> (i64, i64) { (self.base_rev_id, self.rev_id) } } impl std::fmt::Debug for Revision { From 6b338d4cc55479df6caa0dba41148cf097aefe5a Mon Sep 17 00:00:00 2001 From: appflowy Date: Wed, 8 Dec 2021 21:51:06 +0800 Subject: [PATCH 10/39] add feature flowy_unit_test --- backend/Cargo.toml | 2 +- frontend/rust-lib/flowy-document/Cargo.toml | 3 +- .../src/services/doc/controller.rs | 29 +++-- .../src/services/doc/edit/editor.rs | 108 ++++++++--------- .../src/services/doc/revision/cache.rs | 7 ++ .../src/services/doc/revision/manager.rs | 27 +++-- .../src/services/doc/revision/sync.rs | 112 +++++++++++++++--- .../tests/editor/revision_test.rs | 14 ++- frontend/rust-lib/flowy-test/src/editor.rs | 10 ++ frontend/rust-lib/lib-infra/src/kv/kv.rs | 2 +- shared-lib/lib-ot/Cargo.toml | 2 + shared-lib/lib-ot/src/revision/cache.rs | 6 + 12 files changed, 217 insertions(+), 105 deletions(-) diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 4c92fa296f..357575b127 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -100,6 +100,6 @@ futures-util = "0.3.15" backend = { path = ".", features = ["flowy_test"]} flowy-sdk = { path = "../frontend/rust-lib/flowy-sdk", features = ["http_server"] } flowy-user = { path = "../frontend/rust-lib/flowy-user", features = ["http_server"] } -flowy-document = { path = "../frontend/rust-lib/flowy-document", features = ["flowy_test", "http_server"] } +flowy-document = { path = "../frontend/rust-lib/flowy-document", features = ["flowy_unit_test", "http_server"] } flowy-test = { path = "../frontend/rust-lib/flowy-test" } diff --git a/frontend/rust-lib/flowy-document/Cargo.toml b/frontend/rust-lib/flowy-document/Cargo.toml index fe7525b272..8eab79e1b8 100644 --- a/frontend/rust-lib/flowy-document/Cargo.toml +++ b/frontend/rust-lib/flowy-document/Cargo.toml @@ -47,6 +47,7 @@ pin-project = "1.0.0" [dev-dependencies] flowy-test = { path = "../flowy-test" } +flowy-document = { path = "../flowy-document", features = ["flowy_unit_test"]} color-eyre = { version = "0.5", default-features = false } criterion = "0.3" rand = "0.7.3" @@ -55,4 +56,4 @@ env_logger = "0.8.2" [features] http_server = [] -flowy_test = [] \ No newline at end of file +flowy_unit_test = ["lib-ot/flowy_unit_test"] \ No newline at end of file diff --git a/frontend/rust-lib/flowy-document/src/services/doc/controller.rs b/frontend/rust-lib/flowy-document/src/services/doc/controller.rs index f7a502d41f..8aab7424c8 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/controller.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/controller.rs @@ -5,7 +5,7 @@ use crate::{ cache::DocCache, doc::{ edit::{ClientDocEditor, EditDocWsHandler}, - revision::RevisionServer, + revision::{RevisionCache, RevisionManager, RevisionServer}, }, server::Server, ws::WsDocumentManager, @@ -96,23 +96,28 @@ impl DocController { doc_id: &str, pool: Arc, ) -> Result, DocError> { - // 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?; - let ws = self.ws_manager.ws(); - let token = self.user.token()?; let user = self.user.clone(); - let server = Arc::new(RevisionServerImpl { - token, - server: self.server.clone(), - }); - - let edit_ctx = Arc::new(ClientDocEditor::new(doc_id, pool, ws, server, user).await?); + 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?; let ws_handler = Arc::new(EditDocWsHandler(edit_ctx.clone())); self.ws_manager.register_handler(doc_id, ws_handler); self.cache.set(edit_ctx.clone()); Ok(edit_ctx) } + + fn make_rev_manager(&self, doc_id: &str, pool: Arc) -> Result { + // 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?; + let ws_sender = self.ws_manager.ws(); + let token = self.user.token()?; + let server = Arc::new(RevisionServerImpl { + token, + server: self.server.clone(), + }); + let cache = Arc::new(RevisionCache::new(doc_id, pool, server)); + Ok(RevisionManager::new(doc_id, cache, ws_sender)) + } } struct RevisionServerImpl { diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs index a3162eb979..5d67fe34a3 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs @@ -4,7 +4,7 @@ use crate::{ services::{ doc::{ edit::{EditCommand, EditCommandQueue, OpenDocAction, TransformDeltas}, - revision::{RevisionManager, RevisionServer}, + revision::{RevisionDownStream, RevisionManager}, }, ws::{DocumentWebSocket, WsDocumentHandler}, }, @@ -13,20 +13,17 @@ use bytes::Bytes; use flowy_database::ConnectionPool; use flowy_document_infra::{ core::history::UndoResult, - entities::{ - doc::DocDelta, - ws::{WsDataType, WsDocumentData}, - }, + entities::{doc::DocDelta, ws::WsDocumentData}, errors::DocumentResult, }; use lib_infra::retry::{ExponentialBackoff, Retry}; use lib_ot::{ core::Interval, - revision::{RevId, RevType, Revision, RevisionRange}, + revision::{RevId, RevType, Revision}, rich_text::{RichTextAttribute, RichTextDelta}, }; use lib_ws::WsConnectState; -use std::{convert::TryFrom, sync::Arc}; +use std::sync::Arc; use tokio::sync::{mpsc, mpsc::UnboundedSender, oneshot}; pub type DocId = String; @@ -35,34 +32,48 @@ pub struct ClientDocEditor { pub doc_id: DocId, rev_manager: Arc, edit_tx: UnboundedSender, - ws: Arc, + ws_sender: Arc, user: Arc, + ws_msg_tx: UnboundedSender, +} + +#[cfg(feature = "flowy_unit_test")] +impl ClientDocEditor { + pub async fn doc_json(&self) -> DocResult { + let (ret, rx) = oneshot::channel::>(); + let msg = EditCommand::ReadDoc { ret }; + let _ = self.edit_tx.send(msg); + let s = rx.await.map_err(internal_error)??; + Ok(s) + } + + pub fn rev_manager(&self) -> Arc { self.rev_manager.clone() } } impl ClientDocEditor { pub(crate) async fn new( doc_id: &str, - pool: Arc, - ws: Arc, - server: Arc, user: Arc, - ) -> DocResult { - let (sender, receiver) = mpsc::unbounded_channel(); - let mut rev_manager = RevisionManager::new(doc_id, pool.clone(), server.clone(), sender); - spawn_rev_receiver(receiver, ws.clone()); - + pool: Arc, + mut rev_manager: RevisionManager, + ws_sender: Arc, + ) -> DocResult> { let delta = rev_manager.load_document().await?; let edit_queue_tx = spawn_edit_queue(doc_id, delta, pool.clone()); let doc_id = doc_id.to_string(); let rev_manager = Arc::new(rev_manager); - let edit_doc = Self { + let (ws_msg_tx, ws_msg_rx) = mpsc::unbounded_channel(); + let edit_doc = Arc::new(Self { doc_id, rev_manager, edit_tx: edit_queue_tx, - ws, user, - }; + ws_msg_tx, + ws_sender, + }); edit_doc.notify_open_doc(); + + start_sync(edit_doc.clone(), ws_msg_rx); Ok(edit_doc) } @@ -180,20 +191,11 @@ impl ClientDocEditor { Ok(()) } - #[cfg(feature = "flowy_test")] - pub async fn doc_json(&self) -> DocResult { - let (ret, rx) = oneshot::channel::>(); - let msg = EditCommand::ReadDoc { ret }; - let _ = self.edit_tx.send(msg); - let s = rx.await.map_err(internal_error)??; - Ok(s) - } - #[tracing::instrument(level = "debug", skip(self))] fn notify_open_doc(&self) { let rev_id: RevId = self.rev_manager.rev_id().into(); if let Ok(user_id) = self.user.user_id() { - let action = OpenDocAction::new(&user_id, &self.doc_id, &rev_id, &self.ws); + let action = OpenDocAction::new(&user_id, &self.doc_id, &rev_id, &self.ws_sender); let strategy = ExponentialBackoff::from_millis(50).take(3); let retry = Retry::spawn(strategy, action); tokio::spawn(async move { @@ -206,7 +208,7 @@ impl ClientDocEditor { } #[tracing::instrument(level = "debug", skip(self))] - async fn handle_push_rev(&self, bytes: Bytes) -> DocResult<()> { + pub(crate) async fn handle_push_rev(&self, bytes: Bytes) -> DocResult<()> { // Transform the revision let (ret, rx) = oneshot::channel::>(); let _ = self.edit_tx.send(EditCommand::ProcessRemoteRevision { bytes, ret }); @@ -253,27 +255,14 @@ impl ClientDocEditor { &self.doc_id, RevType::Remote, ); - let _ = self.ws.send(revision.into()); + let _ = self.ws_sender.send(revision.into()); Ok(()) } async fn handle_ws_message(&self, doc_data: WsDocumentData) -> DocResult<()> { - let bytes = Bytes::from(doc_data.data); - match doc_data.ty { - WsDataType::PushRev => { - let _ = self.handle_push_rev(bytes).await?; - }, - WsDataType::PullRev => { - let range = RevisionRange::try_from(bytes)?; - let revision = self.rev_manager.mk_revisions(range).await?; - let _ = self.ws.send(revision.into()); - }, - WsDataType::Acked => { - let rev_id = RevId::try_from(bytes)?; - let _ = self.rev_manager.ack_revision(rev_id).await?; - }, - WsDataType::Conflict => {}, - WsDataType::NewDocUser => {}, + match self.ws_msg_tx.send(doc_data) { + Ok(_) => {}, + Err(e) => log::error!("Propagate ws message data failed. {}", e), } Ok(()) } @@ -307,23 +296,20 @@ impl WsDocumentHandler for EditDocWsHandler { } } -fn spawn_rev_receiver(mut receiver: mpsc::UnboundedReceiver, ws: Arc) { - tokio::spawn(async move { - loop { - while let Some(revision) = receiver.recv().await { - // tracing::debug!("Send revision:{} to server", revision.rev_id); - match ws.send(revision.into()) { - Ok(_) => {}, - Err(e) => log::error!("Send revision failed: {:?}", e), - }; - } - } - }); -} - fn spawn_edit_queue(doc_id: &str, delta: RichTextDelta, _pool: Arc) -> UnboundedSender { let (sender, receiver) = mpsc::unbounded_channel::(); let actor = EditCommandQueue::new(doc_id, delta, receiver); tokio::spawn(actor.run()); sender } + +fn start_sync(editor: Arc, ws_msg_rx: mpsc::UnboundedReceiver) { + let rev_manager = editor.rev_manager.clone(); + let ws_sender = editor.ws_sender.clone(); + + let up_stream = editor.rev_manager.make_up_stream(); + let down_stream = RevisionDownStream::new(editor, rev_manager, ws_msg_rx, ws_sender); + + tokio::spawn(up_stream.run()); + tokio::spawn(down_stream.run()); +} diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs index a6e7d0a80b..4649acbdb4 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs @@ -257,3 +257,10 @@ impl RevisionDiskCache for Persistence { impl Persistence { pub(crate) fn new(pool: Arc) -> Self { Self { pool } } } + +#[cfg(feature = "flowy_unit_test")] +impl RevisionCache { + pub fn dish_cache(&self) -> Arc { self.dish_cache.clone() } + + pub fn memory_cache(&self) -> Arc { self.memory_cache.clone() } +} diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs index 62e20e98ac..a152104d4d 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs @@ -1,8 +1,10 @@ use crate::{ errors::{DocError, DocResult}, - services::doc::revision::{RevisionCache, RevisionUploadStream}, + services::{ + doc::revision::{RevisionCache, RevisionUpStream}, + ws::DocumentWebSocket, + }, }; -use flowy_database::ConnectionPool; use flowy_document_infra::{entities::doc::Doc, util::RevIdCounter}; use lib_infra::future::ResultFuture; use lib_ot::{ @@ -11,7 +13,6 @@ use lib_ot::{ rich_text::RichTextDelta, }; use std::sync::Arc; -use tokio::sync::mpsc; pub trait RevisionServer: Send + Sync { fn fetch_document(&self, doc_id: &str) -> ResultFuture; @@ -21,22 +22,17 @@ pub struct RevisionManager { doc_id: String, rev_id_counter: RevIdCounter, cache: Arc, + ws_sender: Arc, } impl RevisionManager { - pub fn new( - doc_id: &str, - pool: Arc, - server: Arc, - ws_sender: mpsc::UnboundedSender, - ) -> Self { - let cache = Arc::new(RevisionCache::new(doc_id, pool, server)); - spawn_upload_stream(cache.clone(), ws_sender); + pub fn new(doc_id: &str, cache: Arc, ws_sender: Arc) -> Self { let rev_id_counter = RevIdCounter::new(0); Self { doc_id: doc_id.to_string(), rev_id_counter, cache, + ws_sender, } } @@ -91,8 +87,13 @@ impl RevisionManager { Ok(revision) } + + pub(crate) fn make_up_stream(&self) -> RevisionUpStream { + RevisionUpStream::new(self.cache.clone(), self.ws_sender.clone()) + } } -fn spawn_upload_stream(cache: Arc, ws_sender: mpsc::UnboundedSender) { - tokio::spawn(RevisionUploadStream::new(cache, ws_sender).run()); +#[cfg(feature = "flowy_unit_test")] +impl RevisionManager { + pub fn revision_cache(&self) -> Arc { self.cache.clone() } } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs index deafc670a9..b25482f0cd 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs @@ -1,27 +1,107 @@ use crate::{ errors::{internal_error, DocResult}, - services::doc::revision::RevisionIterator, + services::{ + doc::{ + edit::ClientDocEditor, + revision::{RevisionIterator, RevisionManager}, + }, + ws::DocumentWebSocket, + }, }; use async_stream::stream; +use bytes::Bytes; +use flowy_document_infra::entities::ws::{WsDataType, WsDocumentData}; use futures::stream::StreamExt; -use lib_ot::revision::Revision; -use std::sync::Arc; +use lib_ot::revision::{RevId, RevisionRange}; +use std::{convert::TryFrom, sync::Arc}; use tokio::{ sync::mpsc, + task::spawn_blocking, time::{interval, Duration}, }; -pub(crate) enum RevisionMsg { +pub(crate) struct RevisionDownStream { + editor: Arc, + rev_manager: Arc, + receiver: Option>, + ws_sender: Arc, +} + +impl RevisionDownStream { + pub(crate) fn new( + editor: Arc, + rev_manager: Arc, + receiver: mpsc::UnboundedReceiver, + ws_sender: Arc, + ) -> Self { + RevisionDownStream { + editor, + rev_manager, + receiver: Some(receiver), + ws_sender, + } + } + + pub async fn run(mut self) { + let mut receiver = self.receiver.take().expect("Only take once"); + let stream = stream! { + loop { + match receiver.recv().await { + Some(msg) => yield msg, + None => break, + } + } + }; + stream + .for_each(|msg| async { + match self.handle_message(msg).await { + Ok(_) => {}, + Err(e) => log::error!("RevisionDownStream error: {}", e), + } + }) + .await; + } + + async fn handle_message(&self, msg: WsDocumentData) -> DocResult<()> { + let WsDocumentData { doc_id: _, ty, data } = msg; + let bytes = spawn_blocking(move || Bytes::from(data)) + .await + .map_err(internal_error)?; + log::debug!("[RevisionDownStream]: receives new message: {:?}", ty); + + match ty { + WsDataType::PushRev => { + let _ = self.editor.handle_push_rev(bytes).await?; + }, + WsDataType::PullRev => { + let range = RevisionRange::try_from(bytes)?; + let revision = self.rev_manager.mk_revisions(range).await?; + let _ = self.ws_sender.send(revision.into()); + }, + WsDataType::Acked => { + let rev_id = RevId::try_from(bytes)?; + let _ = self.rev_manager.ack_revision(rev_id).await?; + }, + WsDataType::Conflict => {}, + WsDataType::NewDocUser => {}, + } + + Ok(()) + } +} + +// RevisionUpStream +pub(crate) enum UpStreamMsg { Tick, } -pub(crate) struct RevisionUploadStream { +pub(crate) struct RevisionUpStream { revisions: Arc, - ws_sender: mpsc::UnboundedSender, + ws_sender: Arc, } -impl RevisionUploadStream { - pub(crate) fn new(revisions: Arc, ws_sender: mpsc::UnboundedSender) -> Self { +impl RevisionUpStream { + pub(crate) fn new(revisions: Arc, ws_sender: Arc) -> Self { Self { revisions, ws_sender } } @@ -46,18 +126,22 @@ impl RevisionUploadStream { .await; } - async fn handle_msg(&self, msg: RevisionMsg) -> DocResult<()> { + async fn handle_msg(&self, msg: UpStreamMsg) -> DocResult<()> { match msg { - RevisionMsg::Tick => self.send_next_revision().await, + UpStreamMsg::Tick => self.send_next_revision().await, } } async fn send_next_revision(&self) -> DocResult<()> { - log::debug!("😁Tick"); match self.revisions.next().await? { None => Ok(()), Some(record) => { - let _ = self.ws_sender.send(record.revision).map_err(internal_error); + log::debug!( + "[RevisionUpStream]: processes revision: {}:{:?}", + record.revision.doc_id, + record.revision.rev_id + ); + let _ = self.ws_sender.send(record.revision.into()).map_err(internal_error); // let _ = tokio::time::timeout(Duration::from_millis(2000), ret.recv()).await; Ok(()) }, @@ -65,10 +149,10 @@ impl RevisionUploadStream { } } -async fn tick(sender: mpsc::UnboundedSender) { +async fn tick(sender: mpsc::UnboundedSender) { let mut i = interval(Duration::from_secs(2)); loop { - match sender.send(RevisionMsg::Tick) { + match sender.send(UpStreamMsg::Tick) { Ok(_) => {}, Err(e) => log::error!("RevisionUploadStream tick error: {}", e), } diff --git a/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs b/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs index e3e3d15222..85a15191da 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs @@ -3,6 +3,16 @@ use flowy_test::editor::*; #[tokio::test] async fn create_doc() { let test = EditorTest::new().await; - let _editor = test.create_doc().await; - println!("123"); + let editor = test.create_doc().await; + let rev_manager = editor.rev_manager(); + assert_eq!(rev_manager.rev_id(), 0); + + let json = editor.doc_json().await.unwrap(); + assert_eq!(json, r#"[{"insert":"\n"}]"#); + + editor.insert(0, "123").await.unwrap(); + assert_eq!(rev_manager.rev_id(), 1); + + editor.insert(0, "456").await.unwrap(); + assert_eq!(rev_manager.rev_id(), 2); } diff --git a/frontend/rust-lib/flowy-test/src/editor.rs b/frontend/rust-lib/flowy-test/src/editor.rs index 7764e698ac..3f2edd37c2 100644 --- a/frontend/rust-lib/flowy-test/src/editor.rs +++ b/frontend/rust-lib/flowy-test/src/editor.rs @@ -2,6 +2,7 @@ use crate::{helper::ViewTest, FlowySDKTest}; use flowy_document::services::doc::edit::ClientDocEditor; use flowy_document_infra::entities::doc::DocIdentifier; use std::sync::Arc; +use tokio::time::Interval; pub struct EditorTest { pub sdk: FlowySDKTest, @@ -20,3 +21,12 @@ impl EditorTest { self.sdk.flowy_document.open(doc_identifier).await.unwrap() } } + +pub enum EditAction { + InsertText(&'static str, usize), + Delete(Interval), + Replace(Interval, &'static str), + Undo(), + Redo(), + AssertJson(&'static str), +} diff --git a/frontend/rust-lib/lib-infra/src/kv/kv.rs b/frontend/rust-lib/lib-infra/src/kv/kv.rs index 59f60f66c1..c9303e7520 100644 --- a/frontend/rust-lib/lib-infra/src/kv/kv.rs +++ b/frontend/rust-lib/lib-infra/src/kv/kv.rs @@ -25,7 +25,7 @@ impl KV { } fn set(value: KeyValue) -> Result<(), String> { - log::debug!("set value: {:?}", value); + log::trace!("[KV]: set value: {:?}", value); update_cache(value.clone()); let _ = diesel::replace_into(kv_table::table) diff --git a/shared-lib/lib-ot/Cargo.toml b/shared-lib/lib-ot/Cargo.toml index d6b99d19e2..5959371483 100644 --- a/shared-lib/lib-ot/Cargo.toml +++ b/shared-lib/lib-ot/Cargo.toml @@ -24,5 +24,7 @@ strum_macros = "0.21" bytes = "1.0" +[features] +flowy_unit_test = [] diff --git a/shared-lib/lib-ot/src/revision/cache.rs b/shared-lib/lib-ot/src/revision/cache.rs index 4a09b7bceb..4013ca7337 100644 --- a/shared-lib/lib-ot/src/revision/cache.rs +++ b/shared-lib/lib-ot/src/revision/cache.rs @@ -125,3 +125,9 @@ impl RevisionRecord { pub fn ack(&mut self) { self.state = RevState::Acked; } } + +#[cfg(feature = "flowy_unit_test")] +impl RevisionMemoryCache { + pub fn revs_map(&self) -> Arc> { self.revs_map.clone() } + pub fn pending_revs(&self) -> Arc>> { self.pending_revs.clone() } +} From 0172fc71db8a6a7f4fc2a4668090e7e738030248 Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 9 Dec 2021 11:00:05 +0800 Subject: [PATCH 11/39] stop sync after close the view --- backend/Cargo.lock | 2 + backend/src/services/doc/crud.rs | 2 +- .../flowy-core/src/core/core_context.rs | 4 +- .../flowy-document/src/services/cache.rs | 4 + .../src/services/doc/controller.rs | 1 + .../src/services/doc/edit/editor.rs | 60 ++++++++----- .../src/services/doc/edit/queue.rs | 7 ++ .../src/services/doc/revision/manager.rs | 6 +- .../src/services/doc/revision/sync.rs | 55 +++++++++--- .../tests/editor/attribute_test.rs | 84 +++++++++---------- .../flowy-document/tests/editor/mod.rs | 4 +- .../flowy-document/tests/editor/op_test.rs | 28 +++---- .../tests/editor/revision_test.rs | 23 ++--- .../tests/editor/undo_redo_test.rs | 42 +++++----- frontend/rust-lib/flowy-test/Cargo.toml | 3 +- frontend/rust-lib/flowy-test/src/editor.rs | 64 ++++++++++++-- 16 files changed, 252 insertions(+), 137 deletions(-) diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 0da8aaa84e..912210f77b 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -1350,9 +1350,11 @@ dependencies = [ "futures-util", "lib-dispatch", "lib-infra", + "lib-ot", "log", "protobuf", "serde", + "serde_json", "thread-id", "tokio", ] diff --git a/backend/src/services/doc/crud.rs b/backend/src/services/doc/crud.rs index 18377c71c7..a2c5a00864 100644 --- a/backend/src/services/doc/crud.rs +++ b/backend/src/services/doc/crud.rs @@ -59,7 +59,7 @@ pub async fn update_doc(pool: &PgPool, mut params: UpdateDocParams) -> Result<() let data = Some(params.take_data()); - tracing::Span::current().record("result", &data.as_ref().unwrap_or(&"".to_owned()).as_str()); + tracing::Span::current().record("delta", &data.as_ref().unwrap_or(&"".to_owned()).as_str()); let (sql, args) = SqlBuilder::update(DOC_TABLE) .add_some_arg("data", data) diff --git a/frontend/rust-lib/flowy-core/src/core/core_context.rs b/frontend/rust-lib/flowy-core/src/core/core_context.rs index c00dbd19f1..e29ddb0a4c 100644 --- a/frontend/rust-lib/flowy-core/src/core/core_context.rs +++ b/frontend/rust-lib/flowy-core/src/core/core_context.rs @@ -93,8 +93,10 @@ impl CoreContext { data: delta.to_json(), }; let _ = self.view_controller.apply_doc_delta(doc_delta).await?; - self.view_controller.set_latest_view(&view); + + // Close the view after initialize + self.view_controller.close_view(view.id.clone().into()).await?; } let _ = self.view_controller.create_view(view).await?; } diff --git a/frontend/rust-lib/flowy-document/src/services/cache.rs b/frontend/rust-lib/flowy-document/src/services/cache.rs index dce3a006b7..dae1fa7338 100644 --- a/frontend/rust-lib/flowy-document/src/services/cache.rs +++ b/frontend/rust-lib/flowy-document/src/services/cache.rs @@ -42,6 +42,10 @@ impl DocCache { pub(crate) fn remove(&self, id: &str) { let doc_id: DocId = id.into(); + match self.get(id) { + Ok(editor) => editor.stop_sync(), + Err(e) => log::error!("{}", e), + } self.inner.remove(&doc_id); } } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/controller.rs b/frontend/rust-lib/flowy-document/src/services/doc/controller.rs index 8aab7424c8..e5489db2ff 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/controller.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/controller.rs @@ -56,6 +56,7 @@ impl DocController { } pub(crate) fn close(&self, doc_id: &str) -> Result<(), DocError> { + log::debug!("Close doc {}", doc_id); self.cache.remove(doc_id); self.ws_manager.remove_handler(doc_id); Ok(()) diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs index 5d67fe34a3..30cd310933 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs @@ -4,7 +4,7 @@ use crate::{ services::{ doc::{ edit::{EditCommand, EditCommandQueue, OpenDocAction, TransformDeltas}, - revision::{RevisionDownStream, RevisionManager}, + revision::{RevisionDownStream, RevisionManager, SteamStopRx, SteamStopTx}, }, ws::{DocumentWebSocket, WsDocumentHandler}, }, @@ -35,19 +35,7 @@ pub struct ClientDocEditor { ws_sender: Arc, user: Arc, ws_msg_tx: UnboundedSender, -} - -#[cfg(feature = "flowy_unit_test")] -impl ClientDocEditor { - pub async fn doc_json(&self) -> DocResult { - let (ret, rx) = oneshot::channel::>(); - let msg = EditCommand::ReadDoc { ret }; - let _ = self.edit_tx.send(msg); - let s = rx.await.map_err(internal_error)??; - Ok(s) - } - - pub fn rev_manager(&self) -> Arc { self.rev_manager.clone() } + stop_sync_tx: tokio::sync::broadcast::Sender<()>, } impl ClientDocEditor { @@ -63,6 +51,8 @@ impl ClientDocEditor { let doc_id = doc_id.to_string(); let rev_manager = Arc::new(rev_manager); let (ws_msg_tx, ws_msg_rx) = mpsc::unbounded_channel(); + let (stop_sync_tx, _) = tokio::sync::broadcast::channel(2); + let cloned_stop_sync_tx = stop_sync_tx.clone(); let edit_doc = Arc::new(Self { doc_id, rev_manager, @@ -70,10 +60,11 @@ impl ClientDocEditor { user, ws_msg_tx, ws_sender, + stop_sync_tx, }); edit_doc.notify_open_doc(); - start_sync(edit_doc.clone(), ws_msg_rx); + start_sync(edit_doc.clone(), ws_msg_rx, cloned_stop_sync_tx); Ok(edit_doc) } @@ -112,7 +103,7 @@ impl ClientDocEditor { Ok(()) } - pub async fn replace(&mut self, interval: Interval, data: T) -> Result<(), DocError> { + pub async fn replace(&self, interval: Interval, data: T) -> Result<(), DocError> { let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::Replace { interval, @@ -191,6 +182,12 @@ impl ClientDocEditor { Ok(()) } + #[tracing::instrument(level = "debug", skip(self), fields(doc_id))] + pub fn stop_sync(&self) { + tracing::Span::current().record("doc_id", &self.doc_id.as_str()); + let _ = self.stop_sync_tx.send(()); + } + #[tracing::instrument(level = "debug", skip(self))] fn notify_open_doc(&self) { let rev_id: RevId = self.rev_manager.rev_id().into(); @@ -303,13 +300,38 @@ fn spawn_edit_queue(doc_id: &str, delta: RichTextDelta, _pool: Arc, ws_msg_rx: mpsc::UnboundedReceiver) { +fn start_sync( + editor: Arc, + ws_msg_rx: mpsc::UnboundedReceiver, + stop_sync_tx: SteamStopTx, +) { let rev_manager = editor.rev_manager.clone(); let ws_sender = editor.ws_sender.clone(); - let up_stream = editor.rev_manager.make_up_stream(); - let down_stream = RevisionDownStream::new(editor, rev_manager, ws_msg_rx, ws_sender); + let up_stream = editor.rev_manager.make_up_stream(stop_sync_tx.subscribe()); + let down_stream = RevisionDownStream::new(editor, rev_manager, ws_msg_rx, ws_sender, stop_sync_tx.subscribe()); tokio::spawn(up_stream.run()); tokio::spawn(down_stream.run()); } + +#[cfg(feature = "flowy_unit_test")] +impl ClientDocEditor { + pub async fn doc_json(&self) -> DocResult { + let (ret, rx) = oneshot::channel::>(); + let msg = EditCommand::ReadDoc { ret }; + let _ = self.edit_tx.send(msg); + let s = rx.await.map_err(internal_error)??; + Ok(s) + } + + pub async fn doc_delta(&self) -> DocResult { + let (ret, rx) = oneshot::channel::>(); + let msg = EditCommand::ReadDocDelta { ret }; + let _ = self.edit_tx.send(msg); + let delta = rx.await.map_err(internal_error)??; + Ok(delta) + } + + pub fn rev_manager(&self) -> Arc { self.rev_manager.clone() } +} diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs index b466c0a147..24b9c177fb 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs @@ -105,6 +105,10 @@ impl EditCommandQueue { let data = self.document.read().await.to_json(); let _ = ret.send(Ok(data)); }, + EditCommand::ReadDocDelta { ret } => { + let delta = self.document.read().await.delta().clone(); + let _ = ret.send(Ok(delta)); + }, } Ok(()) } @@ -170,6 +174,9 @@ pub(crate) enum EditCommand { ReadDoc { ret: Ret, }, + ReadDocDelta { + ret: Ret, + }, } pub(crate) struct TransformDeltas { diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs index a152104d4d..5b28ada95c 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs @@ -1,7 +1,7 @@ use crate::{ errors::{DocError, DocResult}, services::{ - doc::revision::{RevisionCache, RevisionUpStream}, + doc::revision::{RevisionCache, RevisionUpStream, SteamStopRx}, ws::DocumentWebSocket, }, }; @@ -88,8 +88,8 @@ impl RevisionManager { Ok(revision) } - pub(crate) fn make_up_stream(&self) -> RevisionUpStream { - RevisionUpStream::new(self.cache.clone(), self.ws_sender.clone()) + pub(crate) fn make_up_stream(&self, stop_rx: SteamStopRx) -> RevisionUpStream { + RevisionUpStream::new(self.cache.clone(), self.ws_sender.clone(), stop_rx) } } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs index b25482f0cd..315dcc1f8c 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs @@ -15,7 +15,7 @@ use futures::stream::StreamExt; use lib_ot::revision::{RevId, RevisionRange}; use std::{convert::TryFrom, sync::Arc}; use tokio::{ - sync::mpsc, + sync::{broadcast, mpsc}, task::spawn_blocking, time::{interval, Duration}, }; @@ -25,6 +25,7 @@ pub(crate) struct RevisionDownStream { rev_manager: Arc, receiver: Option>, ws_sender: Arc, + stop_rx: Option, } impl RevisionDownStream { @@ -33,23 +34,35 @@ impl RevisionDownStream { rev_manager: Arc, receiver: mpsc::UnboundedReceiver, ws_sender: Arc, + stop_rx: SteamStopRx, ) -> Self { RevisionDownStream { editor, rev_manager, receiver: Some(receiver), ws_sender, + stop_rx: Some(stop_rx), } } pub async fn run(mut self) { let mut receiver = self.receiver.take().expect("Only take once"); + let mut stop_rx = self.stop_rx.take().expect("Only take once"); let stream = stream! { loop { - match receiver.recv().await { - Some(msg) => yield msg, - None => break, - } + // match receiver.recv().await { + // Some(msg) => yield msg, + // None => break, + // } + tokio::select! { + result = receiver.recv() => { + match result { + Some(msg) => yield msg, + None => break, + } + }, + _ = stop_rx.recv() => break, + }; } }; stream @@ -95,25 +108,43 @@ pub(crate) enum UpStreamMsg { Tick, } +pub type SteamStopRx = broadcast::Receiver<()>; +pub type SteamStopTx = broadcast::Sender<()>; + pub(crate) struct RevisionUpStream { revisions: Arc, ws_sender: Arc, + stop_rx: Option, } impl RevisionUpStream { - pub(crate) fn new(revisions: Arc, ws_sender: Arc) -> Self { - Self { revisions, ws_sender } + pub(crate) fn new( + revisions: Arc, + ws_sender: Arc, + stop_rx: SteamStopRx, + ) -> Self { + Self { + revisions, + ws_sender, + stop_rx: Some(stop_rx), + } } - pub async fn run(self) { + pub async fn run(mut self) { let (tx, mut rx) = mpsc::unbounded_channel(); + let mut stop_rx = self.stop_rx.take().expect("Only take once"); tokio::spawn(tick(tx)); let stream = stream! { loop { - match rx.recv().await { - Some(msg) => yield msg, - None => break, - } + tokio::select! { + result = rx.recv() => { + match result { + Some(msg) => yield msg, + None => break, + } + }, + _ = stop_rx.recv() => break, + }; } }; stream diff --git a/frontend/rust-lib/flowy-document/tests/editor/attribute_test.rs b/frontend/rust-lib/flowy-document/tests/editor/attribute_test.rs index 957d03d2ef..d740eee324 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/attribute_test.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/attribute_test.rs @@ -19,7 +19,7 @@ fn attributes_bold_added() { ]"#, ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -31,7 +31,7 @@ fn attributes_bold_added_and_invert_all() { Bold(0, Interval::new(0, 3), false), AssertDocJson(0, r#"[{"insert":"123"}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -43,7 +43,7 @@ fn attributes_bold_added_and_invert_partial_suffix() { Bold(0, Interval::new(2, 4), false), AssertDocJson(0, r#"[{"insert":"12","attributes":{"bold":"true"}},{"insert":"34"}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -57,7 +57,7 @@ fn attributes_bold_added_and_invert_partial_suffix2() { Bold(0, Interval::new(2, 4), true), AssertDocJson(0, r#"[{"insert":"1234","attributes":{"bold":"true"}}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -85,7 +85,7 @@ fn attributes_bold_added_with_new_line() { r#"[{"insert":"123","attributes":{"bold":"true"}},{"insert":"\na\n"},{"insert":"456","attributes":{"bold":"true"}},{"insert":"\n"}]"#, ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -97,7 +97,7 @@ fn attributes_bold_added_and_invert_partial_prefix() { Bold(0, Interval::new(0, 2), false), AssertDocJson(0, r#"[{"insert":"12"},{"insert":"34","attributes":{"bold":"true"}}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -109,7 +109,7 @@ fn attributes_bold_added_consecutive() { Bold(0, Interval::new(1, 2), true), AssertDocJson(0, r#"[{"insert":"12","attributes":{"bold":"true"}},{"insert":"34"}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -128,7 +128,7 @@ fn attributes_bold_added_italic() { r#"[{"insert":"12345678","attributes":{"bold":"true","italic":"true"}},{"insert":"\n"}]"#, ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -156,7 +156,7 @@ fn attributes_bold_added_italic2() { ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -193,7 +193,7 @@ fn attributes_bold_added_italic3() { ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -229,7 +229,7 @@ fn attributes_bold_added_italic_delete() { AssertDocJson(0, r#"[{"insert":"67"},{"insert":"89","attributes":{"bold":"true"}}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -240,7 +240,7 @@ fn attributes_merge_inserted_text_with_same_attribute() { InsertBold(0, "456", Interval::new(3, 6)), AssertDocJson(0, r#"[{"insert":"123456","attributes":{"bold":"true"}}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -255,7 +255,7 @@ fn attributes_compose_attr_attributes_with_attr_attributes_test() { AssertDocJson(1, r#"[{"insert":"1234567","attributes":{"bold":"true"}}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -296,7 +296,7 @@ fn attributes_compose_attr_attributes_with_attr_attributes_test2() { ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -312,7 +312,7 @@ fn attributes_compose_attr_attributes_with_no_attr_attributes_test() { AssertDocJson(0, expected), AssertDocJson(1, expected), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -324,7 +324,7 @@ fn attributes_replace_heading() { AssertDocJson(0, r#"[{"insert":"3456","attributes":{"bold":"true"}}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -336,7 +336,7 @@ fn attributes_replace_trailing() { AssertDocJson(0, r#"[{"insert":"12345","attributes":{"bold":"true"}}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -350,7 +350,7 @@ fn attributes_replace_middle() { AssertDocJson(0, r#"[{"insert":"34","attributes":{"bold":"true"}}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -362,7 +362,7 @@ fn attributes_replace_all() { AssertDocJson(0, r#"[]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -374,7 +374,7 @@ fn attributes_replace_with_text() { AssertDocJson(0, r#"[{"insert":"ab"},{"insert":"456","attributes":{"bold":"true"}}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -390,7 +390,7 @@ fn attributes_header_insert_newline_at_middle() { ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -415,7 +415,7 @@ fn attributes_header_insert_double_newline_at_middle() { ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -430,7 +430,7 @@ fn attributes_header_insert_newline_at_trailing() { ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -446,7 +446,7 @@ fn attributes_header_insert_double_newline_at_trailing() { ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -460,7 +460,7 @@ fn attributes_link_added() { ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -479,7 +479,7 @@ fn attributes_link_format_with_bold() { ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -498,7 +498,7 @@ fn attributes_link_insert_char_at_head() { ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -513,7 +513,7 @@ fn attributes_link_insert_char_at_middle() { ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -532,7 +532,7 @@ fn attributes_link_insert_char_at_trailing() { ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -547,7 +547,7 @@ fn attributes_link_insert_newline_at_middle() { ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -563,7 +563,7 @@ fn attributes_link_auto_format() { ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -579,7 +579,7 @@ fn attributes_link_auto_format_exist() { ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -595,7 +595,7 @@ fn attributes_link_auto_format_exist2() { ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -606,7 +606,7 @@ fn attributes_bullet_added() { AssertDocJson(0, r#"[{"insert":"12"},{"insert":"\n","attributes":{"list":"bullet"}}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -627,7 +627,7 @@ fn attributes_bullet_added_2() { ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -644,7 +644,7 @@ fn attributes_bullet_remove_partial() { ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -660,7 +660,7 @@ fn attributes_bullet_auto_exit() { ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -700,7 +700,7 @@ fn attributes_preserve_block_when_insert_newline_inside() { ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -717,7 +717,7 @@ fn attributes_preserve_header_format_on_merge() { AssertDocJson(0, r#"[{"insert":"123456"},{"insert":"\n","attributes":{"header":1}}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -736,7 +736,7 @@ fn attributes_format_emoji() { r#"[{"insert":"👋 "},{"insert":"\n","attributes":{"header":1}}]"#, ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -756,7 +756,7 @@ fn attributes_preserve_list_format_on_merge() { ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -795,5 +795,5 @@ fn delta_compose() { ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } diff --git a/frontend/rust-lib/flowy-document/tests/editor/mod.rs b/frontend/rust-lib/flowy-document/tests/editor/mod.rs index 83afcda353..02a947beea 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/mod.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/mod.rs @@ -267,11 +267,11 @@ impl TestBuilder { } } - pub fn run_script(mut self, script: Vec) { + pub fn run_scripts(mut self, scripts: Vec) { self.documents = vec![Document::new::(), Document::new::()]; self.primes = vec![None, None]; self.deltas = vec![None, None]; - for (_i, op) in script.iter().enumerate() { + for (_i, op) in scripts.iter().enumerate() { self.run_op(op); } } diff --git a/frontend/rust-lib/flowy-document/tests/editor/op_test.rs b/frontend/rust-lib/flowy-document/tests/editor/op_test.rs index 7968de167b..c1b8c4496b 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/op_test.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/op_test.rs @@ -13,7 +13,7 @@ fn attributes_insert_text() { Insert(0, "456", 3), AssertDocJson(0, r#"[{"insert":"123456"}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -23,7 +23,7 @@ fn attributes_insert_text_at_head() { Insert(0, "456", 0), AssertDocJson(0, r#"[{"insert":"456123"}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -33,7 +33,7 @@ fn attributes_insert_text_at_middle() { Insert(0, "456", 1), AssertDocJson(0, r#"[{"insert":"145623"}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -523,7 +523,7 @@ fn transform_two_plain_delta_test() { AssertDocJson(0, r#"[{"insert":"123456"}]"#), AssertDocJson(1, r#"[{"insert":"123456"}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -537,7 +537,7 @@ fn transform_two_plain_delta_test2() { AssertDocJson(0, r#"[{"insert":"123456"}]"#), AssertDocJson(1, r#"[{"insert":"123456"}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -555,7 +555,7 @@ fn transform_two_non_seq_delta() { AssertDocJson(0, r#"[{"insert":"123456"}]"#), AssertDocJson(1, r#"[{"insert":"123456789"}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -570,7 +570,7 @@ fn transform_two_conflict_non_seq_delta() { AssertDocJson(0, r#"[{"insert":"123456"}]"#), AssertDocJson(1, r#"[{"insert":"12378456"}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -597,7 +597,7 @@ fn delta_invert_no_attribute_delta2() { Invert(0, 1), AssertDocJson(0, r#"[{"insert":"123"}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -610,7 +610,7 @@ fn delta_invert_attribute_delta_with_no_attribute_delta() { Invert(0, 1), AssertDocJson(0, r#"[{"insert":"123","attributes":{"bold":"true"}}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -645,7 +645,7 @@ fn delta_invert_attribute_delta_with_no_attribute_delta2() { ]"#, ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -658,7 +658,7 @@ fn delta_invert_no_attribute_delta_with_attribute_delta() { Invert(0, 1), AssertDocJson(0, r#"[{"insert":"123"}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -677,7 +677,7 @@ fn delta_invert_no_attribute_delta_with_attribute_delta2() { Invert(0, 1), AssertDocJson(0, r#"[{"insert":"123"}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -718,7 +718,7 @@ fn delta_invert_attribute_delta_with_attribute_delta() { ]"#, ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -731,5 +731,5 @@ fn delta_compose_with_missing_delta() { AssertDocJson(0, r#"[{"insert":"1234\n"}]"#), AssertStr(1, r#"4\n"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } diff --git a/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs b/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs index 85a15191da..12a4c73945 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs @@ -1,18 +1,13 @@ -use flowy_test::editor::*; +use flowy_test::editor::{EditorScript::*, *}; #[tokio::test] async fn create_doc() { - let test = EditorTest::new().await; - let editor = test.create_doc().await; - let rev_manager = editor.rev_manager(); - assert_eq!(rev_manager.rev_id(), 0); - - let json = editor.doc_json().await.unwrap(); - assert_eq!(json, r#"[{"insert":"\n"}]"#); - - editor.insert(0, "123").await.unwrap(); - assert_eq!(rev_manager.rev_id(), 1); - - editor.insert(0, "456").await.unwrap(); - assert_eq!(rev_manager.rev_id(), 2); + let scripts = vec![ + InsertText("123", 0), + AssertRevId(1), + InsertText("456", 3), + AssertRevId(2), + AssertJson(r#"[{"insert":"123456\n"}]"#), + ]; + EditorTest::new().await.run_scripts(scripts).await; } diff --git a/frontend/rust-lib/flowy-document/tests/editor/undo_redo_test.rs b/frontend/rust-lib/flowy-document/tests/editor/undo_redo_test.rs index 355121fc2e..95def758ab 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/undo_redo_test.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/undo_redo_test.rs @@ -5,7 +5,7 @@ use lib_ot::core::{Interval, NEW_LINE, WHITESPACE}; #[test] fn history_insert_undo() { let ops = vec![Insert(0, "123", 0), Undo(0), AssertDocJson(0, r#"[{"insert":"\n"}]"#)]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -19,7 +19,7 @@ fn history_insert_undo_with_lagging() { Undo(0), AssertDocJson(0, r#"[{"insert":"\n"}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -32,7 +32,7 @@ fn history_insert_redo() { Redo(0), AssertDocJson(0, r#"[{"insert":"123\n"}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -51,7 +51,7 @@ fn history_insert_redo_with_lagging() { Undo(0), AssertDocJson(0, r#"[{"insert":"123\n"}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -62,7 +62,7 @@ fn history_bold_undo() { Undo(0), AssertDocJson(0, r#"[{"insert":"\n"}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -74,7 +74,7 @@ fn history_bold_undo_with_lagging() { Undo(0), AssertDocJson(0, r#"[{"insert":"123\n"}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -87,7 +87,7 @@ fn history_bold_redo() { Redo(0), AssertDocJson(0, r#" [{"insert":"123","attributes":{"bold":"true"}},{"insert":"\n"}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -101,7 +101,7 @@ fn history_bold_redo_with_lagging() { Redo(0), AssertDocJson(0, r#"[{"insert":"123","attributes":{"bold":"true"}},{"insert":"\n"}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -114,7 +114,7 @@ fn history_delete_undo() { Undo(0), AssertDocJson(0, r#"[{"insert":"123"}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -133,7 +133,7 @@ fn history_delete_undo_2() { Undo(0), AssertDocJson(0, r#"[{"insert":"\n"}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -160,7 +160,7 @@ fn history_delete_undo_with_lagging() { "#, ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -174,7 +174,7 @@ fn history_delete_redo() { Redo(0), AssertDocJson(0, r#"[{"insert":"\n"}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -193,7 +193,7 @@ fn history_replace_undo() { Undo(0), AssertDocJson(0, r#"[{"insert":"\n"}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -214,7 +214,7 @@ fn history_replace_undo_with_lagging() { Undo(0), AssertDocJson(0, r#"[{"insert":"123","attributes":{"bold":"true"}},{"insert":"\n"}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -233,7 +233,7 @@ fn history_replace_redo() { "#, ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -252,7 +252,7 @@ fn history_header_added_undo() { ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -271,7 +271,7 @@ fn history_link_added_undo() { ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -290,7 +290,7 @@ fn history_link_auto_format_undo_with_lagging() { AssertDocJson(0, r#"[{"insert":"https://appflowy.io\n"}]"#), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -313,7 +313,7 @@ fn history_bullet_undo() { ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -341,7 +341,7 @@ fn history_bullet_undo_with_lagging() { ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } #[test] @@ -368,5 +368,5 @@ fn history_undo_attribute_on_merge_between_line() { ), ]; - TestBuilder::new().run_script::(ops); + TestBuilder::new().run_scripts::(ops); } diff --git a/frontend/rust-lib/flowy-test/Cargo.toml b/frontend/rust-lib/flowy-test/Cargo.toml index f94de9e574..fc59336c48 100644 --- a/frontend/rust-lib/flowy-test/Cargo.toml +++ b/frontend/rust-lib/flowy-test/Cargo.toml @@ -15,9 +15,10 @@ lib-infra = { path = "../lib-infra" } flowy-document-infra = { path = "../../../shared-lib/flowy-document-infra" } backend-service = { path = "../../../shared-lib/backend-service" } - +lib-ot = { path = "../../../shared-lib/lib-ot" } serde = { version = "1.0", features = ["derive"] } +serde_json = {version = "1.0"} bincode = { version = "1.3"} protobuf = {version = "2.24.1"} claim = "0.5.0" diff --git a/frontend/rust-lib/flowy-test/src/editor.rs b/frontend/rust-lib/flowy-test/src/editor.rs index 3f2edd37c2..45eaf35a58 100644 --- a/frontend/rust-lib/flowy-test/src/editor.rs +++ b/frontend/rust-lib/flowy-test/src/editor.rs @@ -1,32 +1,82 @@ use crate::{helper::ViewTest, FlowySDKTest}; use flowy_document::services::doc::edit::ClientDocEditor; use flowy_document_infra::entities::doc::DocIdentifier; +use lib_ot::{core::Interval, revision::RevState, rich_text::RichTextDelta}; use std::sync::Arc; -use tokio::time::Interval; +use tokio::time::{sleep, Duration}; pub struct EditorTest { pub sdk: FlowySDKTest, + pub editor: Arc, } impl EditorTest { pub async fn new() -> Self { let sdk = FlowySDKTest::setup(); let _ = sdk.init_user().await; - Self { sdk } + let test = ViewTest::new(&sdk).await; + let doc_identifier: DocIdentifier = test.view.id.clone().into(); + let editor = sdk.flowy_document.open(doc_identifier).await.unwrap(); + Self { sdk, editor } } - pub async fn create_doc(&self) -> Arc { - let test = ViewTest::new(&self.sdk).await; - let doc_identifier: DocIdentifier = test.view.id.clone().into(); - self.sdk.flowy_document.open(doc_identifier).await.unwrap() + pub async fn run_scripts(mut self, scripts: Vec) { + for script in scripts { + self.run_script(script).await; + } + + sleep(Duration::from_secs(10)).await; + } + + async fn run_script(&mut self, script: EditorScript) { + let rev_manager = self.editor.rev_manager(); + let cache = rev_manager.revision_cache(); + let memory_cache = cache.memory_cache(); + let disk_cache = cache.dish_cache(); + + match script { + EditorScript::InsertText(s, offset) => { + self.editor.insert(offset, s).await.unwrap(); + }, + EditorScript::Delete(interval) => { + self.editor.delete(interval).await.unwrap(); + }, + EditorScript::Replace(interval, s) => { + self.editor.replace(interval, s).await.unwrap(); + }, + EditorScript::Undo() => { + self.editor.undo().await.unwrap(); + }, + EditorScript::Redo() => { + self.editor.redo().await.unwrap(); + }, + EditorScript::AssertRevisionState(rev_id, state) => {}, + EditorScript::AssertNextSentRevision(rev_id, state) => {}, + EditorScript::AssertRevId(rev_id) => { + assert_eq!(self.editor.rev_manager().rev_id(), rev_id); + }, + EditorScript::AssertJson(expected) => { + let expected_delta: RichTextDelta = serde_json::from_str(expected).unwrap(); + let delta = self.editor.doc_delta().await.unwrap(); + + if expected_delta != delta { + eprintln!("✅ expect: {}", expected,); + eprintln!("❌ receive: {}", delta.to_json()); + } + assert_eq!(expected_delta, delta); + }, + } } } -pub enum EditAction { +pub enum EditorScript { InsertText(&'static str, usize), Delete(Interval), Replace(Interval, &'static str), Undo(), Redo(), + AssertRevisionState(i64, RevState), + AssertNextSentRevision(i64, RevState), + AssertRevId(i64), AssertJson(&'static str), } From 909406bf08ef3f669d7b1205d16677102b69532e Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 9 Dec 2021 19:01:58 +0800 Subject: [PATCH 12/39] fix bugs & add unit test --- .../src/services/doc/edit/editor.rs | 51 ++++++++++--------- .../src/services/doc/revision/cache.rs | 22 +++----- .../src/services/doc/revision/manager.rs | 4 +- .../src/services/doc/revision/sync.rs | 35 ++++++++----- .../tests/editor/revision_test.rs | 36 +++++++++++-- frontend/rust-lib/flowy-test/src/editor.rs | 48 +++++++++++++---- .../src/entities/ws/ws.rs | 39 ++++++++++++-- shared-lib/lib-ot/src/revision/cache.rs | 23 ++++++--- 8 files changed, 177 insertions(+), 81 deletions(-) diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs index 30cd310933..a1554afe4b 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs @@ -4,7 +4,7 @@ use crate::{ services::{ doc::{ edit::{EditCommand, EditCommandQueue, OpenDocAction, TransformDeltas}, - revision::{RevisionDownStream, RevisionManager, SteamStopRx, SteamStopTx}, + revision::{RevisionDownStream, RevisionManager, SteamStopTx}, }, ws::{DocumentWebSocket, WsDocumentHandler}, }, @@ -31,7 +31,7 @@ pub type DocId = String; pub struct ClientDocEditor { pub doc_id: DocId, rev_manager: Arc, - edit_tx: UnboundedSender, + edit_cmd_tx: UnboundedSender, ws_sender: Arc, user: Arc, ws_msg_tx: UnboundedSender, @@ -47,7 +47,7 @@ impl ClientDocEditor { ws_sender: Arc, ) -> DocResult> { let delta = rev_manager.load_document().await?; - let edit_queue_tx = spawn_edit_queue(doc_id, delta, pool.clone()); + let edit_cmd_tx = spawn_edit_queue(doc_id, delta, pool.clone()); let doc_id = doc_id.to_string(); let rev_manager = Arc::new(rev_manager); let (ws_msg_tx, ws_msg_rx) = mpsc::unbounded_channel(); @@ -56,12 +56,13 @@ impl ClientDocEditor { let edit_doc = Arc::new(Self { doc_id, rev_manager, - edit_tx: edit_queue_tx, + edit_cmd_tx, + ws_sender, user, ws_msg_tx, - ws_sender, stop_sync_tx, }); + edit_doc.notify_open_doc(); start_sync(edit_doc.clone(), ws_msg_rx, cloned_stop_sync_tx); @@ -75,7 +76,7 @@ impl ClientDocEditor { data: data.to_string(), ret, }; - let _ = self.edit_tx.send(msg); + let _ = self.edit_cmd_tx.send(msg); let delta = rx.await.map_err(internal_error)??; let _ = self.save_local_delta(delta).await?; Ok(()) @@ -84,7 +85,7 @@ impl ClientDocEditor { pub async fn delete(&self, interval: Interval) -> Result<(), DocError> { let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::Delete { interval, ret }; - let _ = self.edit_tx.send(msg); + let _ = self.edit_cmd_tx.send(msg); let delta = rx.await.map_err(internal_error)??; let _ = self.save_local_delta(delta).await?; Ok(()) @@ -97,7 +98,7 @@ impl ClientDocEditor { attribute, ret, }; - let _ = self.edit_tx.send(msg); + let _ = self.edit_cmd_tx.send(msg); let delta = rx.await.map_err(internal_error)??; let _ = self.save_local_delta(delta).await?; Ok(()) @@ -110,7 +111,7 @@ impl ClientDocEditor { data: data.to_string(), ret, }; - let _ = self.edit_tx.send(msg); + let _ = self.edit_cmd_tx.send(msg); let delta = rx.await.map_err(internal_error)??; let _ = self.save_local_delta(delta).await?; Ok(()) @@ -119,21 +120,21 @@ impl ClientDocEditor { pub async fn can_undo(&self) -> bool { let (ret, rx) = oneshot::channel::(); let msg = EditCommand::CanUndo { ret }; - let _ = self.edit_tx.send(msg); + let _ = self.edit_cmd_tx.send(msg); rx.await.unwrap_or(false) } pub async fn can_redo(&self) -> bool { let (ret, rx) = oneshot::channel::(); let msg = EditCommand::CanRedo { ret }; - let _ = self.edit_tx.send(msg); + let _ = self.edit_cmd_tx.send(msg); rx.await.unwrap_or(false) } pub async fn undo(&self) -> Result { let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::Undo { ret }; - let _ = self.edit_tx.send(msg); + let _ = self.edit_cmd_tx.send(msg); let r = rx.await.map_err(internal_error)??; Ok(r) } @@ -141,7 +142,7 @@ impl ClientDocEditor { pub async fn redo(&self) -> Result { let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::Redo { ret }; - let _ = self.edit_tx.send(msg); + let _ = self.edit_cmd_tx.send(msg); let r = rx.await.map_err(internal_error)??; Ok(r) } @@ -149,7 +150,7 @@ impl ClientDocEditor { pub async fn delta(&self) -> DocResult { let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::ReadDoc { ret }; - let _ = self.edit_tx.send(msg); + let _ = self.edit_cmd_tx.send(msg); let data = rx.await.map_err(internal_error)??; Ok(DocDelta { @@ -175,16 +176,16 @@ impl ClientDocEditor { delta: delta.clone(), ret, }; - let _ = self.edit_tx.send(msg); + let _ = self.edit_cmd_tx.send(msg); let _ = rx.await.map_err(internal_error)??; let _ = self.save_local_delta(delta).await?; Ok(()) } - #[tracing::instrument(level = "debug", skip(self), fields(doc_id))] + #[tracing::instrument(level = "debug", skip(self))] pub fn stop_sync(&self) { - tracing::Span::current().record("doc_id", &self.doc_id.as_str()); + tracing::debug!("{} stop sync", self.doc_id); let _ = self.stop_sync_tx.send(()); } @@ -208,7 +209,7 @@ impl ClientDocEditor { pub(crate) async fn handle_push_rev(&self, bytes: Bytes) -> DocResult<()> { // Transform the revision let (ret, rx) = oneshot::channel::>(); - let _ = self.edit_tx.send(EditCommand::ProcessRemoteRevision { bytes, ret }); + let _ = self.edit_cmd_tx.send(EditCommand::ProcessRemoteRevision { bytes, ret }); let TransformDeltas { client_prime, server_prime, @@ -226,7 +227,7 @@ impl ClientDocEditor { delta: client_prime.clone(), ret, }; - let _ = self.edit_tx.send(msg); + let _ = self.edit_cmd_tx.send(msg); let _ = rx.await.map_err(internal_error)??; // update rev id @@ -256,10 +257,12 @@ impl ClientDocEditor { Ok(()) } - async fn handle_ws_message(&self, doc_data: WsDocumentData) -> DocResult<()> { + pub async fn handle_ws_message(&self, doc_data: WsDocumentData) -> DocResult<()> { match self.ws_msg_tx.send(doc_data) { - Ok(_) => {}, - Err(e) => log::error!("Propagate ws message data failed. {}", e), + Ok(_) => { + tracing::debug!("Propagate ws message data success") + }, + Err(e) => tracing::error!("Propagate ws message data failed. {}", e), } Ok(()) } @@ -320,7 +323,7 @@ impl ClientDocEditor { pub async fn doc_json(&self) -> DocResult { let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::ReadDoc { ret }; - let _ = self.edit_tx.send(msg); + let _ = self.edit_cmd_tx.send(msg); let s = rx.await.map_err(internal_error)??; Ok(s) } @@ -328,7 +331,7 @@ impl ClientDocEditor { pub async fn doc_delta(&self) -> DocResult { let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::ReadDocDelta { ret }; - let _ = self.edit_tx.send(msg); + let _ = self.edit_cmd_tx.send(msg); let delta = rx.await.map_err(internal_error)??; Ok(delta) } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs index 4649acbdb4..c45de3f26c 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs @@ -8,16 +8,7 @@ use flowy_document_infra::entities::doc::Doc; use lib_infra::future::ResultFuture; use lib_ot::{ core::{Operation, OperationTransformable}, - revision::{ - RevId, - RevState, - RevType, - Revision, - RevisionDiskCache, - RevisionMemoryCache, - RevisionRange, - RevisionRecord, - }, + revision::{RevState, RevType, Revision, RevisionDiskCache, RevisionMemoryCache, RevisionRange, RevisionRecord}, rich_text::RichTextDelta, }; use std::{sync::Arc, time::Duration}; @@ -64,13 +55,16 @@ impl RevisionCache { Ok(()) } - #[tracing::instrument(level = "debug", skip(self, rev_id), fields(rev_id = %rev_id.as_ref()))] - pub async fn ack_revision(&self, rev_id: RevId) { - let rev_id = rev_id.value; - self.memory_cache.mut_revision(&rev_id, |mut rev| rev.value_mut().ack()); + #[tracing::instrument(level = "debug", skip(self, rev_id), fields(rev_id = %rev_id))] + pub async fn ack_revision(&self, rev_id: i64) { + self.memory_cache.ack_revision(&rev_id).await; self.save_revisions().await; } + pub async fn query_revision(&self, rev_id: i64) -> Option { + self.memory_cache.query_revision(&rev_id).await + } + async fn save_revisions(&self) { if let Some(handler) = self.defer_save.write().await.take() { handler.abort(); diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs index 5b28ada95c..699046efa1 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs @@ -49,7 +49,7 @@ impl RevisionManager { } pub async fn ack_revision(&self, rev_id: RevId) -> Result<(), DocError> { - self.cache.ack_revision(rev_id).await; + self.cache.ack_revision(rev_id.into()).await; Ok(()) } @@ -89,7 +89,7 @@ impl RevisionManager { } pub(crate) fn make_up_stream(&self, stop_rx: SteamStopRx) -> RevisionUpStream { - RevisionUpStream::new(self.cache.clone(), self.ws_sender.clone(), stop_rx) + RevisionUpStream::new(&self.doc_id, self.cache.clone(), self.ws_sender.clone(), stop_rx) } } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs index 315dcc1f8c..68f39d5590 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs @@ -23,7 +23,7 @@ use tokio::{ pub(crate) struct RevisionDownStream { editor: Arc, rev_manager: Arc, - receiver: Option>, + ws_msg_rx: Option>, ws_sender: Arc, stop_rx: Option, } @@ -32,36 +32,36 @@ impl RevisionDownStream { pub(crate) fn new( editor: Arc, rev_manager: Arc, - receiver: mpsc::UnboundedReceiver, + ws_msg_rx: mpsc::UnboundedReceiver, ws_sender: Arc, stop_rx: SteamStopRx, ) -> Self { RevisionDownStream { editor, rev_manager, - receiver: Some(receiver), + ws_msg_rx: Some(ws_msg_rx), ws_sender, stop_rx: Some(stop_rx), } } pub async fn run(mut self) { - let mut receiver = self.receiver.take().expect("Only take once"); + let mut receiver = self.ws_msg_rx.take().expect("Only take once"); let mut stop_rx = self.stop_rx.take().expect("Only take once"); + let doc_id = self.editor.doc_id.clone(); let stream = stream! { loop { - // match receiver.recv().await { - // Some(msg) => yield msg, - // None => break, - // } tokio::select! { result = receiver.recv() => { match result { Some(msg) => yield msg, - None => break, + None => {}, } }, - _ = stop_rx.recv() => break, + _ = stop_rx.recv() => { + tracing::debug!("[RevisionDownStream:{}] loop exit", doc_id); + break + }, }; } }; @@ -80,8 +80,8 @@ impl RevisionDownStream { let bytes = spawn_blocking(move || Bytes::from(data)) .await .map_err(internal_error)?; - log::debug!("[RevisionDownStream]: receives new message: {:?}", ty); + log::debug!("[RevisionDownStream]: receives new message: {:?}", ty); match ty { WsDataType::PushRev => { let _ = self.editor.handle_push_rev(bytes).await?; @@ -115,10 +115,12 @@ pub(crate) struct RevisionUpStream { revisions: Arc, ws_sender: Arc, stop_rx: Option, + doc_id: String, } impl RevisionUpStream { pub(crate) fn new( + doc_id: &str, revisions: Arc, ws_sender: Arc, stop_rx: SteamStopRx, @@ -127,12 +129,14 @@ impl RevisionUpStream { revisions, ws_sender, stop_rx: Some(stop_rx), + doc_id: doc_id.to_owned(), } } pub async fn run(mut self) { let (tx, mut rx) = mpsc::unbounded_channel(); let mut stop_rx = self.stop_rx.take().expect("Only take once"); + let doc_id = self.doc_id.clone(); tokio::spawn(tick(tx)); let stream = stream! { loop { @@ -140,10 +144,13 @@ impl RevisionUpStream { result = rx.recv() => { match result { Some(msg) => yield msg, - None => break, + None => {}, } }, - _ = stop_rx.recv() => break, + _ = stop_rx.recv() => { + tracing::debug!("[RevisionUpStream:{}] loop exit", doc_id); + break + }, }; } }; @@ -167,7 +174,7 @@ impl RevisionUpStream { match self.revisions.next().await? { None => Ok(()), Some(record) => { - log::debug!( + tracing::debug!( "[RevisionUpStream]: processes revision: {}:{:?}", record.revision.doc_id, record.revision.rev_id diff --git a/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs b/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs index 12a4c73945..2a005c7426 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs @@ -1,13 +1,39 @@ use flowy_test::editor::{EditorScript::*, *}; +use lib_ot::revision::RevState; #[tokio::test] -async fn create_doc() { +async fn doc_rev_state_test1() { let scripts = vec![ InsertText("123", 0), - AssertRevId(1), - InsertText("456", 3), - AssertRevId(2), - AssertJson(r#"[{"insert":"123456\n"}]"#), + AssertCurrentRevId(1), + AssertRevisionState(1, RevState::Local), + SimulateAckedMessage(1), + AssertRevisionState(1, RevState::Acked), + AssertNextSendingRevision(None), + AssertJson(r#"[{"insert":"123\n"}]"#), + ]; + EditorTest::new().await.run_scripts(scripts).await; +} + +#[tokio::test] +async fn doc_rev_state_test2() { + let scripts = vec![ + InsertText("1", 0), + InsertText("2", 1), + InsertText("3", 2), + AssertCurrentRevId(3), + AssertRevisionState(1, RevState::Local), + AssertRevisionState(2, RevState::Local), + AssertRevisionState(3, RevState::Local), + SimulateAckedMessage(1), + AssertRevisionState(1, RevState::Acked), + AssertNextSendingRevision(Some(2)), + SimulateAckedMessage(2), + AssertRevisionState(2, RevState::Acked), + // + AssertNextSendingRevision(Some(3)), + AssertRevisionState(3, RevState::Local), + AssertJson(r#"[{"insert":"123\n"}]"#), ]; EditorTest::new().await.run_scripts(scripts).await; } diff --git a/frontend/rust-lib/flowy-test/src/editor.rs b/frontend/rust-lib/flowy-test/src/editor.rs index 45eaf35a58..414ae555d1 100644 --- a/frontend/rust-lib/flowy-test/src/editor.rs +++ b/frontend/rust-lib/flowy-test/src/editor.rs @@ -1,7 +1,11 @@ use crate::{helper::ViewTest, FlowySDKTest}; -use flowy_document::services::doc::edit::ClientDocEditor; -use flowy_document_infra::entities::doc::DocIdentifier; -use lib_ot::{core::Interval, revision::RevState, rich_text::RichTextDelta}; +use flowy_document::services::doc::{edit::ClientDocEditor, revision::RevisionIterator}; +use flowy_document_infra::entities::{doc::DocIdentifier, ws::WsDocumentDataBuilder}; +use lib_ot::{ + core::Interval, + revision::{RevState, Revision, RevisionRange}, + rich_text::RichTextDelta, +}; use std::sync::Arc; use tokio::time::{sleep, Duration}; @@ -25,14 +29,15 @@ impl EditorTest { self.run_script(script).await; } - sleep(Duration::from_secs(10)).await; + sleep(Duration::from_secs(5)).await; } async fn run_script(&mut self, script: EditorScript) { let rev_manager = self.editor.rev_manager(); let cache = rev_manager.revision_cache(); - let memory_cache = cache.memory_cache(); - let disk_cache = cache.dish_cache(); + let _memory_cache = cache.memory_cache(); + let _disk_cache = cache.dish_cache(); + let doc_id = self.editor.doc_id.clone(); match script { EditorScript::InsertText(s, offset) => { @@ -50,11 +55,29 @@ impl EditorTest { EditorScript::Redo() => { self.editor.redo().await.unwrap(); }, - EditorScript::AssertRevisionState(rev_id, state) => {}, - EditorScript::AssertNextSentRevision(rev_id, state) => {}, - EditorScript::AssertRevId(rev_id) => { + EditorScript::AssertRevisionState(rev_id, state) => { + let record = cache.query_revision(rev_id).await.unwrap(); + assert_eq!(record.state, state); + }, + EditorScript::AssertCurrentRevId(rev_id) => { assert_eq!(self.editor.rev_manager().rev_id(), rev_id); }, + EditorScript::AssertNextSendingRevision(rev_id) => { + let next_revision = cache.next().await.unwrap(); + if rev_id.is_none() { + assert_eq!(next_revision.is_none(), true); + } + + let next_revision = next_revision.unwrap(); + assert_eq!(next_revision.revision.rev_id, rev_id.unwrap()); + }, + EditorScript::SimulatePushRevisionMessage(_revision) => {}, + EditorScript::SimulatePullRevisionMessage(_range) => {}, + EditorScript::SimulateAckedMessage(i64) => { + let data = WsDocumentDataBuilder::build_acked_message(&doc_id, i64); + self.editor.handle_ws_message(data).await.unwrap(); + sleep(Duration::from_millis(200)).await; + }, EditorScript::AssertJson(expected) => { let expected_delta: RichTextDelta = serde_json::from_str(expected).unwrap(); let delta = self.editor.doc_delta().await.unwrap(); @@ -75,8 +98,11 @@ pub enum EditorScript { Replace(Interval, &'static str), Undo(), Redo(), + SimulatePushRevisionMessage(Revision), + SimulatePullRevisionMessage(RevisionRange), + SimulateAckedMessage(i64), AssertRevisionState(i64, RevState), - AssertNextSentRevision(i64, RevState), - AssertRevId(i64), + AssertNextSendingRevision(Option), + AssertCurrentRevId(i64), AssertJson(&'static str), } diff --git a/shared-lib/flowy-document-infra/src/entities/ws/ws.rs b/shared-lib/flowy-document-infra/src/entities/ws/ws.rs index 422f6591b3..6b3555ce16 100644 --- a/shared-lib/flowy-document-infra/src/entities/ws/ws.rs +++ b/shared-lib/flowy-document-infra/src/entities/ws/ws.rs @@ -1,7 +1,7 @@ use crate::{entities::doc::NewDocUser, errors::DocumentError}; use bytes::Bytes; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; -use lib_ot::revision::Revision; +use lib_ot::revision::{RevId, Revision, RevisionRange}; use std::convert::{TryFrom, TryInto}; #[derive(Debug, Clone, ProtoBuf_Enum, Eq, PartialEq, Hash)] @@ -11,7 +11,7 @@ pub enum WsDataType { // The frontend receives the PushRev event means the backend is pushing the new revision to frontend PushRev = 1, // The fronted receives the PullRev event means the backend try to pull the revision from frontend - PullRev = 2, // data should be Revision + PullRev = 2, Conflict = 3, NewDocUser = 4, } @@ -37,7 +37,6 @@ pub struct WsDocumentData { #[pb(index = 2)] pub ty: WsDataType, - // Opti: parse the data with type constraints #[pb(index = 3)] pub data: Vec, } @@ -65,3 +64,37 @@ impl std::convert::From for WsDocumentData { } } } + +pub struct WsDocumentDataBuilder(); +impl WsDocumentDataBuilder { + // WsDataType::PushRev -> Revision + pub fn build_push_rev_message(doc_id: &str, revision: Revision) -> WsDocumentData { + let bytes: Bytes = revision.try_into().unwrap(); + WsDocumentData { + doc_id: doc_id.to_string(), + ty: WsDataType::PushRev, + data: bytes.to_vec(), + } + } + + // WsDataType::PullRev -> RevisionRange + pub fn build_push_pull_message(doc_id: &str, range: RevisionRange) -> WsDocumentData { + let bytes: Bytes = range.try_into().unwrap(); + WsDocumentData { + doc_id: doc_id.to_string(), + ty: WsDataType::PullRev, + data: bytes.to_vec(), + } + } + + // WsDataType::Acked -> RevId + pub fn build_acked_message(doc_id: &str, rev_id: i64) -> WsDocumentData { + let rev_id: RevId = rev_id.into(); + let bytes: Bytes = rev_id.try_into().unwrap(); + WsDocumentData { + doc_id: doc_id.to_string(), + ty: WsDataType::Acked, + data: bytes.to_vec(), + } + } +} diff --git a/shared-lib/lib-ot/src/revision/cache.rs b/shared-lib/lib-ot/src/revision/cache.rs index 4013ca7337..4e2dd40673 100644 --- a/shared-lib/lib-ot/src/revision/cache.rs +++ b/shared-lib/lib-ot/src/revision/cache.rs @@ -2,7 +2,7 @@ use crate::{ errors::OTError, revision::{Revision, RevisionRange}, }; -use dashmap::{mapref::one::RefMut, DashMap}; +use dashmap::DashMap; use std::{collections::VecDeque, fmt::Debug, sync::Arc}; use tokio::sync::{broadcast, RwLock}; @@ -48,12 +48,15 @@ impl RevisionMemoryCache { pub fn remove_revisions(&self, ids: Vec) { self.revs_map.retain(|k, _| !ids.contains(k)); } - pub fn mut_revision(&self, rev_id: &i64, f: F) - where - F: Fn(RefMut), - { - if let Some(m_revision) = self.revs_map.get_mut(rev_id) { - f(m_revision) + pub async fn ack_revision(&self, rev_id: &i64) { + if let Some(mut m_revision) = self.revs_map.get_mut(rev_id) { + m_revision.value_mut().ack(); + match self.pending_revs.write().await.pop_front() { + None => log::error!("The pending_revs should not be empty"), + Some(cache_rev_id) => { + assert_eq!(&cache_rev_id, rev_id); + }, + } } else { log::error!("Can't find revision with id {}", rev_id); } @@ -90,6 +93,10 @@ impl RevisionMemoryCache { (ids, records) } + pub async fn query_revision(&self, rev_id: &i64) -> Option { + self.revs_map.get(&rev_id).map(|r| r.value().clone()) + } + pub async fn front_revision(&self) -> Option<(i64, RevisionRecord)> { match self.pending_revs.read().await.front() { None => None, @@ -103,7 +110,7 @@ impl RevisionMemoryCache { pub type RevIdReceiver = broadcast::Receiver; pub type RevIdSender = broadcast::Sender; -#[derive(Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq)] pub enum RevState { Local = 0, Acked = 1, From 3fa0f97e748a899d7db23fb5dfed6c0cc72176c5 Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 9 Dec 2021 21:39:53 +0800 Subject: [PATCH 13/39] add pb generation log --- .../lib/protobuf/lib-ot/cache.pb.dart | 11 +++ .../lib/protobuf/lib-ot/cache.pbenum.dart | 26 +++++ .../lib/protobuf/lib-ot/cache.pbjson.dart | 21 ++++ .../lib/protobuf/lib-ot/cache.pbserver.dart | 9 ++ .../lib/protobuf/lib-ot/protobuf.dart | 1 + .../src/services/doc/edit/queue.rs | 29 +++--- .../src/services/doc/revision/sync.rs | 3 +- .../tests/editor/revision_test.rs | 15 ++- frontend/rust-lib/flowy-test/src/editor.rs | 59 +++++++---- .../src/services/user/user_session.rs | 36 +++++-- shared-lib/flowy-ast/src/ast.rs | 8 +- shared-lib/flowy-ast/src/ty_ext.rs | 48 ++++----- .../flowy-derive/src/proto_buf/deserialize.rs | 8 +- .../flowy-derive/src/proto_buf/serialize.rs | 34 ++++++- .../src/entities/ws/ws.rs | 11 +++ shared-lib/lib-ot/Flowy.toml | 2 +- shared-lib/lib-ot/src/protobuf/model/cache.rs | 97 +++++++++++++++++++ shared-lib/lib-ot/src/protobuf/model/mod.rs | 3 + .../lib-ot/src/protobuf/proto/cache.proto | 6 ++ shared-lib/lib-ot/src/rich_text/delta.rs | 6 +- 20 files changed, 353 insertions(+), 80 deletions(-) create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pb.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pbenum.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pbjson.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pbserver.dart create mode 100644 shared-lib/lib-ot/src/protobuf/model/cache.rs create mode 100644 shared-lib/lib-ot/src/protobuf/proto/cache.proto diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pb.dart new file mode 100644 index 0000000000..e9456cbd1a --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pb.dart @@ -0,0 +1,11 @@ +/// +// Generated code. Do not modify. +// source: cache.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields + +import 'dart:core' as $core; + +export 'cache.pbenum.dart'; + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pbenum.dart new file mode 100644 index 0000000000..176438ae6f --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pbenum.dart @@ -0,0 +1,26 @@ +/// +// Generated code. Do not modify. +// source: cache.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields + +// ignore_for_file: UNDEFINED_SHOWN_NAME +import 'dart:core' as $core; +import 'package:protobuf/protobuf.dart' as $pb; + +class RevState extends $pb.ProtobufEnum { + static const RevState Local = RevState._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Local'); + static const RevState Acked = RevState._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Acked'); + + static const $core.List values = [ + Local, + Acked, + ]; + + static final $core.Map<$core.int, RevState> _byValue = $pb.ProtobufEnum.initByValue(values); + static RevState? valueOf($core.int value) => _byValue[value]; + + const RevState._($core.int v, $core.String n) : super(v, n); +} + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pbjson.dart new file mode 100644 index 0000000000..43aeaa15e4 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pbjson.dart @@ -0,0 +1,21 @@ +/// +// Generated code. Do not modify. +// source: cache.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package + +import 'dart:core' as $core; +import 'dart:convert' as $convert; +import 'dart:typed_data' as $typed_data; +@$core.Deprecated('Use revStateDescriptor instead') +const RevState$json = const { + '1': 'RevState', + '2': const [ + const {'1': 'Local', '2': 0}, + const {'1': 'Acked', '2': 1}, + ], +}; + +/// Descriptor for `RevState`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List revStateDescriptor = $convert.base64Decode('CghSZXZTdGF0ZRIJCgVMb2NhbBAAEgkKBUFja2VkEAE='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pbserver.dart new file mode 100644 index 0000000000..0bdfceba59 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pbserver.dart @@ -0,0 +1,9 @@ +/// +// Generated code. Do not modify. +// source: cache.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package + +export 'cache.pb.dart'; + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/protobuf.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/protobuf.dart index f524faf0c8..53ea90df40 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/protobuf.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/protobuf.dart @@ -1,2 +1,3 @@ // Auto-generated, do not edit +export './cache.pb.dart'; export './model.pb.dart'; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs index 24b9c177fb..01a2927d26 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs @@ -41,31 +41,31 @@ impl EditCommandQueue { }; stream .for_each(|msg| async { - match self.handle_message(msg).await { - Ok(_) => {}, - Err(e) => log::error!("{:?}", e), - } + self.handle_message(msg).await; }) .await; } - async fn handle_message(&self, msg: EditCommand) -> Result<(), DocumentError> { + async fn handle_message(&self, msg: EditCommand) { match msg { EditCommand::ComposeDelta { delta, ret } => { let result = self.composed_delta(delta).await; let _ = ret.send(result); }, EditCommand::ProcessRemoteRevision { bytes, ret } => { - let revision = Revision::try_from(bytes)?; - let delta = RichTextDelta::from_bytes(&revision.delta_data)?; - let rev_id: RevId = revision.rev_id.into(); - let (server_prime, client_prime) = self.document.read().await.delta().transform(&delta)?; - let transform_delta = TransformDeltas { - client_prime, - server_prime, - server_rev_id: rev_id, + let f = || async { + let revision = Revision::try_from(bytes)?; + let delta = RichTextDelta::from_bytes(&revision.delta_data)?; + let rev_id: RevId = revision.rev_id.into(); + let (server_prime, client_prime) = self.document.read().await.delta().transform(&delta)?; + let transform_delta = TransformDeltas { + client_prime, + server_prime, + server_rev_id: rev_id, + }; + Ok::(transform_delta) }; - let _ = ret.send(Ok(transform_delta)); + let _ = ret.send(f().await); }, EditCommand::Insert { index, data, ret } => { let delta = self.document.write().await.insert(index, data); @@ -110,7 +110,6 @@ impl EditCommandQueue { let _ = ret.send(Ok(delta)); }, } - Ok(()) } #[tracing::instrument(level = "debug", skip(self, delta), fields(compose_result), err)] diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs index 68f39d5590..ecf7a72c89 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs @@ -65,11 +65,12 @@ impl RevisionDownStream { }; } }; + stream .for_each(|msg| async { match self.handle_message(msg).await { Ok(_) => {}, - Err(e) => log::error!("RevisionDownStream error: {}", e), + Err(e) => log::error!("[RevisionDownStream:{}] error: {}", self.editor.doc_id, e), } }) .await; diff --git a/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs b/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs index 2a005c7426..d2993538a6 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs @@ -1,5 +1,5 @@ use flowy_test::editor::{EditorScript::*, *}; -use lib_ot::revision::RevState; +use lib_ot::{core::DeltaBuilder, revision::RevState, rich_text::RichTextDeltaBuilder}; #[tokio::test] async fn doc_rev_state_test1() { @@ -37,3 +37,16 @@ async fn doc_rev_state_test2() { ]; EditorTest::new().await.run_scripts(scripts).await; } + +#[tokio::test] +async fn doc_push_test() { + let delta = RichTextDeltaBuilder::new().insert("abc\n").build(); + let scripts = vec![ + InsertText("1", 0), + InsertText("2", 1), + InsertText("3", 2), + SimulatePushRevisionMessageWithDelta(delta), + AssertJson(r#"[{"insert":"123\nabc\n"}]"#), + ]; + EditorTest::new().await.run_scripts(scripts).await; +} diff --git a/frontend/rust-lib/flowy-test/src/editor.rs b/frontend/rust-lib/flowy-test/src/editor.rs index 414ae555d1..4d0033ffb8 100644 --- a/frontend/rust-lib/flowy-test/src/editor.rs +++ b/frontend/rust-lib/flowy-test/src/editor.rs @@ -1,14 +1,32 @@ use crate::{helper::ViewTest, FlowySDKTest}; use flowy_document::services::doc::{edit::ClientDocEditor, revision::RevisionIterator}; -use flowy_document_infra::entities::{doc::DocIdentifier, ws::WsDocumentDataBuilder}; +use flowy_document_infra::entities::{ + doc::DocIdentifier, + ws::{WsDocumentData, WsDocumentDataBuilder}, +}; use lib_ot::{ core::Interval, - revision::{RevState, Revision, RevisionRange}, + revision::{RevState, RevType, Revision, RevisionRange}, rich_text::RichTextDelta, }; -use std::sync::Arc; +use std::{str::FromStr, sync::Arc}; use tokio::time::{sleep, Duration}; +pub enum EditorScript { + InsertText(&'static str, usize), + Delete(Interval), + Replace(Interval, &'static str), + Undo(), + Redo(), + SimulatePushRevisionMessageWithDelta(RichTextDelta), + SimulatePullRevisionMessage(RevisionRange), + SimulateAckedMessage(i64), + AssertRevisionState(i64, RevState), + AssertNextSendingRevision(Option), + AssertCurrentRevId(i64), + AssertJson(&'static str), +} + pub struct EditorTest { pub sdk: FlowySDKTest, pub editor: Arc, @@ -71,12 +89,23 @@ impl EditorTest { let next_revision = next_revision.unwrap(); assert_eq!(next_revision.revision.rev_id, rev_id.unwrap()); }, - EditorScript::SimulatePushRevisionMessage(_revision) => {}, + EditorScript::SimulatePushRevisionMessageWithDelta(delta) => { + let local_base_rev_id = rev_manager.rev_id(); + let local_rev_id = local_base_rev_id + 1; + let revision = Revision::new( + local_base_rev_id, + local_rev_id, + delta.to_bytes().to_vec(), + &doc_id, + RevType::Remote, + ); + let data = WsDocumentDataBuilder::build_push_rev_message(&doc_id, revision); + self.send_ws_message(data).await; + }, EditorScript::SimulatePullRevisionMessage(_range) => {}, EditorScript::SimulateAckedMessage(i64) => { let data = WsDocumentDataBuilder::build_acked_message(&doc_id, i64); - self.editor.handle_ws_message(data).await.unwrap(); - sleep(Duration::from_millis(200)).await; + self.send_ws_message(data).await; }, EditorScript::AssertJson(expected) => { let expected_delta: RichTextDelta = serde_json::from_str(expected).unwrap(); @@ -90,19 +119,9 @@ impl EditorTest { }, } } -} -pub enum EditorScript { - InsertText(&'static str, usize), - Delete(Interval), - Replace(Interval, &'static str), - Undo(), - Redo(), - SimulatePushRevisionMessage(Revision), - SimulatePullRevisionMessage(RevisionRange), - SimulateAckedMessage(i64), - AssertRevisionState(i64, RevState), - AssertNextSendingRevision(Option), - AssertCurrentRevId(i64), - AssertJson(&'static str), + async fn send_ws_message(&self, data: WsDocumentData) { + self.editor.handle_ws_message(data).await.unwrap(); + sleep(Duration::from_millis(200)).await; + } } diff --git a/frontend/rust-lib/flowy-user/src/services/user/user_session.rs b/frontend/rust-lib/flowy-user/src/services/user/user_session.rs index e8078bde1a..cecbc6becd 100644 --- a/frontend/rust-lib/flowy-user/src/services/user/user_session.rs +++ b/frontend/rust-lib/flowy-user/src/services/user/user_session.rs @@ -20,6 +20,7 @@ use flowy_database::{ ExpressionMethods, UserDatabaseConnection, }; +use flowy_user_infra::entities::{SignInResponse, SignUpResponse}; use lib_infra::{entities::network_state::NetworkState, kv::KV}; use lib_sqlite::ConnectionPool; use lib_ws::{WsConnectState, WsMessageHandler, WsSender}; @@ -98,7 +99,7 @@ impl UserSession { self.user_profile().await } else { let resp = self.server.sign_in(params).await?; - let session = Session::new(&resp.user_id, &resp.token, &resp.email); + let session: Session = resp.clone().into(); let _ = self.set_session(Some(session))?; let user_table = self.save_user(resp.into()).await?; let user_profile: UserProfile = user_table.into(); @@ -113,7 +114,7 @@ impl UserSession { self.user_profile().await } else { let resp = self.server.sign_up(params).await?; - let session = Session::new(&resp.user_id, &resp.token, &resp.email); + let session: Session = resp.clone().into(); let _ = self.set_session(Some(session))?; let user_table = self.save_user(resp.into()).await?; let user_profile: UserProfile = user_table.into(); @@ -326,17 +327,32 @@ struct Session { user_id: String, token: String, email: String, + name: String, +} + +impl std::convert::From for Session { + fn from(resp: SignInResponse) -> Self { + Session { + user_id: resp.user_id, + token: resp.token, + email: resp.email, + name: resp.name, + } + } +} + +impl std::convert::From for Session { + fn from(resp: SignUpResponse) -> Self { + Session { + user_id: resp.user_id, + token: resp.token, + email: resp.email, + name: resp.name, + } + } } impl Session { - pub fn new(user_id: &str, token: &str, email: &str) -> Self { - Self { - user_id: user_id.to_owned(), - token: token.to_owned(), - email: email.to_owned(), - } - } - pub fn into_part(self) -> (String, String) { (self.user_id, self.token) } } diff --git a/shared-lib/flowy-ast/src/ast.rs b/shared-lib/flowy-ast/src/ast.rs index 48968d4fc7..b5c0208c01 100644 --- a/shared-lib/flowy-ast/src/ast.rs +++ b/shared-lib/flowy-ast/src/ast.rs @@ -115,7 +115,7 @@ impl<'a> ASTField<'a> { let mut bracket_ty = None; let mut bracket_category = Some(BracketCategory::Other); match parse_ty(cx, &field.ty) { - Some(inner) => { + Ok(Some(inner)) => { match inner.primitive_ty { PrimitiveTy::Map(map_info) => { bracket_category = Some(BracketCategory::Map((map_info.key.clone(), map_info.value))) @@ -141,9 +141,13 @@ impl<'a> ASTField<'a> { }, } }, - None => { + Ok(None) => { cx.error_spanned_by(&field.ty, "fail to get the ty inner type"); }, + Err(e) => { + eprintln!("ASTField parser failed: {:?} with error: {}", field, e); + panic!() + }, } ASTField { diff --git a/shared-lib/flowy-ast/src/ty_ext.rs b/shared-lib/flowy-ast/src/ty_ext.rs index 940eb99535..769643f51c 100644 --- a/shared-lib/flowy-ast/src/ty_ext.rs +++ b/shared-lib/flowy-ast/src/ty_ext.rs @@ -39,17 +39,17 @@ impl<'a> TyInfo<'a> { } } -pub fn parse_ty<'a>(ctxt: &Ctxt, ty: &'a syn::Type) -> Option> { +pub fn parse_ty<'a>(ctxt: &Ctxt, ty: &'a syn::Type) -> Result>, String> { // Type -> TypePath -> Path -> PathSegment -> PathArguments -> // AngleBracketedGenericArguments -> GenericArgument -> Type. if let syn::Type::Path(ref p) = ty { if p.path.segments.len() != 1 { - return None; + return Ok(None); } let seg = match p.path.segments.last() { Some(seg) => seg, - None => return None, + None => return Ok(None), }; let _is_option = seg.ident == "Option"; @@ -60,20 +60,20 @@ pub fn parse_ty<'a>(ctxt: &Ctxt, ty: &'a syn::Type) -> Option> { "Vec" => generate_vec_ty_info(ctxt, seg, bracketed), "Option" => generate_option_ty_info(ctxt, ty, seg, bracketed), _ => { - panic!("Unsupported ty {}", seg.ident.to_string()) + return Err(format!("Unsupported ty {}", seg.ident.to_string())); }, } } else { - return Some(TyInfo { + return Ok(Some(TyInfo { ident: &seg.ident, ty, primitive_ty: PrimitiveTy::Other, bracket_ty_info: Box::new(None), - }); + })); }; } ctxt.error_spanned_by(ty, "Unsupported inner type, get inner type fail".to_string()); - None + Ok(None) } fn parse_bracketed(bracketed: &AngleBracketedGenericArguments) -> Vec<&syn::Type> { @@ -95,21 +95,21 @@ pub fn generate_hashmap_ty_info<'a>( ty: &'a syn::Type, path_segment: &'a PathSegment, bracketed: &'a AngleBracketedGenericArguments, -) -> Option> { +) -> Result>, String> { // The args of map must greater than 2 if bracketed.args.len() != 2 { - return None; + return Ok(None); } let types = parse_bracketed(bracketed); - let key = parse_ty(ctxt, types[0]).unwrap().ident.to_string(); - let value = parse_ty(ctxt, types[1]).unwrap().ident.to_string(); - let bracket_ty_info = Box::new(parse_ty(ctxt, &types[1])); - Some(TyInfo { + let key = parse_ty(ctxt, types[0])?.unwrap().ident.to_string(); + let value = parse_ty(ctxt, types[1])?.unwrap().ident.to_string(); + let bracket_ty_info = Box::new(parse_ty(ctxt, &types[1])?); + Ok(Some(TyInfo { ident: &path_segment.ident, ty, primitive_ty: PrimitiveTy::Map(MapInfo::new(key, value)), bracket_ty_info, - }) + })) } fn generate_option_ty_info<'a>( @@ -117,34 +117,34 @@ fn generate_option_ty_info<'a>( ty: &'a syn::Type, path_segment: &'a PathSegment, bracketed: &'a AngleBracketedGenericArguments, -) -> Option> { +) -> Result>, String> { assert_eq!(path_segment.ident.to_string(), "Option".to_string()); let types = parse_bracketed(bracketed); - let bracket_ty_info = Box::new(parse_ty(ctxt, &types[0])); - Some(TyInfo { + let bracket_ty_info = Box::new(parse_ty(ctxt, &types[0])?); + Ok(Some(TyInfo { ident: &path_segment.ident, ty, primitive_ty: PrimitiveTy::Opt, bracket_ty_info, - }) + })) } fn generate_vec_ty_info<'a>( ctxt: &Ctxt, path_segment: &'a PathSegment, bracketed: &'a AngleBracketedGenericArguments, -) -> Option> { +) -> Result>, String> { if bracketed.args.len() != 1 { - return None; + return Ok(None); } if let syn::GenericArgument::Type(ref bracketed_type) = bracketed.args.first().unwrap() { - let bracketed_ty_info = Box::new(parse_ty(ctxt, &bracketed_type)); - return Some(TyInfo { + let bracketed_ty_info = Box::new(parse_ty(ctxt, &bracketed_type)?); + return Ok(Some(TyInfo { ident: &path_segment.ident, ty: bracketed_type, primitive_ty: PrimitiveTy::Vec, bracket_ty_info: bracketed_ty_info, - }); + })); } - None + Ok(None) } diff --git a/shared-lib/flowy-derive/src/proto_buf/deserialize.rs b/shared-lib/flowy-derive/src/proto_buf/deserialize.rs index ba6810d923..4c864aa2af 100644 --- a/shared-lib/flowy-derive/src/proto_buf/deserialize.rs +++ b/shared-lib/flowy-derive/src/proto_buf/deserialize.rs @@ -103,7 +103,13 @@ fn token_stream_for_one_of(ctxt: &Ctxt, field: &ASTField) -> Option fn token_stream_for_field(ctxt: &Ctxt, member: &syn::Member, ty: &syn::Type, is_option: bool) -> Option { let ident = get_member_ident(ctxt, member)?; - let ty_info = parse_ty(ctxt, ty)?; + let ty_info = match parse_ty(ctxt, ty) { + Ok(ty_info) => ty_info, + Err(e) => { + eprintln!("token_stream_for_field: {:?} with error: {}", member, e); + panic!() + }, + }?; match ident_category(ty_info.ident) { TypeCategory::Array => { assert_bracket_ty_is_some(ctxt, &ty_info); diff --git a/shared-lib/flowy-derive/src/proto_buf/serialize.rs b/shared-lib/flowy-derive/src/proto_buf/serialize.rs index 9e838a5aa3..3a9f32bb93 100644 --- a/shared-lib/flowy-derive/src/proto_buf/serialize.rs +++ b/shared-lib/flowy-derive/src/proto_buf/serialize.rs @@ -54,7 +54,14 @@ fn se_token_stream_for_field(ctxt: &Ctxt, field: &ASTField, _take: bool) -> Opti fn token_stream_for_one_of(ctxt: &Ctxt, field: &ASTField) -> Option { let member = &field.member; let ident = get_member_ident(ctxt, member)?; - let ty_info = parse_ty(ctxt, &field.ty)?; + let ty_info = match parse_ty(ctxt, &field.ty) { + Ok(ty_info) => ty_info, + Err(e) => { + eprintln!("token_stream_for_one_of failed: {:?} with error: {}", member, e); + panic!(); + }, + }?; + let bracketed_ty_info = ty_info.bracket_ty_info.as_ref().as_ref(); let set_func = format_ident!("set_{}", ident.to_string()); @@ -76,7 +83,13 @@ fn token_stream_for_one_of(ctxt: &Ctxt, field: &ASTField) -> Option } fn gen_token_stream(ctxt: &Ctxt, member: &syn::Member, ty: &syn::Type, is_option: bool) -> Option { - let ty_info = parse_ty(ctxt, ty)?; + let ty_info = match parse_ty(ctxt, ty) { + Ok(ty_info) => ty_info, + Err(e) => { + eprintln!("gen_token_stream failed: {:?} with error: {}", member, e); + panic!(); + }, + }?; match ident_category(ty_info.ident) { TypeCategory::Array => token_stream_for_vec(ctxt, &member, &ty_info.ty), TypeCategory::Map => token_stream_for_map(ctxt, &member, &ty_info.bracket_ty_info.unwrap().ty), @@ -111,7 +124,14 @@ fn gen_token_stream(ctxt: &Ctxt, member: &syn::Member, ty: &syn::Type, is_option // e.g. pub cells: Vec, the memeber will be cells, ty would be Vec fn token_stream_for_vec(ctxt: &Ctxt, member: &syn::Member, ty: &syn::Type) -> Option { - let ty_info = parse_ty(ctxt, ty)?; + let ty_info = match parse_ty(ctxt, ty) { + Ok(ty_info) => ty_info, + Err(e) => { + eprintln!("token_stream_for_vec failed: {:?} with error: {}", member, e); + panic!(); + }, + }?; + match ident_category(ty_info.ident) { TypeCategory::Protobuf => Some(quote! { pb.#member = ::protobuf::RepeatedField::from_vec( @@ -132,7 +152,13 @@ fn token_stream_for_vec(ctxt: &Ctxt, member: &syn::Member, ty: &syn::Type) -> Op fn token_stream_for_map(ctxt: &Ctxt, member: &syn::Member, ty: &syn::Type) -> Option { // The key of the hashmap must be string let flowy_protobuf = format_ident!("flowy_protobuf"); - let ty_info = parse_ty(ctxt, ty)?; + let ty_info = match parse_ty(ctxt, ty) { + Ok(ty_info) => ty_info, + Err(e) => { + eprintln!("token_stream_for_map failed: {:?} with error: {}", member, e); + panic!(); + }, + }?; match ident_category(ty_info.ident) { TypeCategory::Protobuf => { let value_type = ty_info.ident; diff --git a/shared-lib/flowy-document-infra/src/entities/ws/ws.rs b/shared-lib/flowy-document-infra/src/entities/ws/ws.rs index 6b3555ce16..fc9f90d3f0 100644 --- a/shared-lib/flowy-document-infra/src/entities/ws/ws.rs +++ b/shared-lib/flowy-document-infra/src/entities/ws/ws.rs @@ -29,6 +29,15 @@ impl std::default::Default for WsDataType { fn default() -> Self { WsDataType::Acked } } +// #[derive(ProtoBuf, Default, Debug, Clone)] +// pub struct WsDocumentUser { +// #[pb(index = 1)] +// pub user_id: String, +// +// #[pb(index = 2)] +// pub name: String, +// } + #[derive(ProtoBuf, Default, Debug, Clone)] pub struct WsDocumentData { #[pb(index = 1)] @@ -39,6 +48,8 @@ pub struct WsDocumentData { #[pb(index = 3)] pub data: Vec, + /* #[pb(index = 4)] + * pub user: WsDocumentUser, */ } impl std::convert::From for WsDocumentData { diff --git a/shared-lib/lib-ot/Flowy.toml b/shared-lib/lib-ot/Flowy.toml index cd4d90ffd0..d11f71bcd6 100644 --- a/shared-lib/lib-ot/Flowy.toml +++ b/shared-lib/lib-ot/Flowy.toml @@ -1,3 +1,3 @@ -proto_crates = ["src/revision"] +proto_crates = ["src/revision/model.rs"] event_files = [] \ No newline at end of file diff --git a/shared-lib/lib-ot/src/protobuf/model/cache.rs b/shared-lib/lib-ot/src/protobuf/model/cache.rs new file mode 100644 index 0000000000..d173ff7ef2 --- /dev/null +++ b/shared-lib/lib-ot/src/protobuf/model/cache.rs @@ -0,0 +1,97 @@ +// 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 `cache.proto` + +/// Generated files are compatible only with the same version +/// of protobuf runtime. +// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_22_1; + +#[derive(Clone,PartialEq,Eq,Debug,Hash)] +pub enum RevState { + Local = 0, + Acked = 1, +} + +impl ::protobuf::ProtobufEnum for RevState { + fn value(&self) -> i32 { + *self as i32 + } + + fn from_i32(value: i32) -> ::std::option::Option { + match value { + 0 => ::std::option::Option::Some(RevState::Local), + 1 => ::std::option::Option::Some(RevState::Acked), + _ => ::std::option::Option::None + } + } + + fn values() -> &'static [Self] { + static values: &'static [RevState] = &[ + RevState::Local, + RevState::Acked, + ]; + 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::("RevState", file_descriptor_proto()) + }) + } +} + +impl ::std::marker::Copy for RevState { +} + +impl ::std::default::Default for RevState { + fn default() -> Self { + RevState::Local + } +} + +impl ::protobuf::reflect::ProtobufValue for RevState { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self)) + } +} + +static file_descriptor_proto_data: &'static [u8] = b"\ + \n\x0bcache.proto*\x20\n\x08RevState\x12\t\n\x05Local\x10\0\x12\t\n\x05A\ + cked\x10\x01J|\n\x06\x12\x04\0\0\x05\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\ + \n\n\n\x02\x05\0\x12\x04\x02\0\x05\x01\n\n\n\x03\x05\0\x01\x12\x03\x02\ + \x05\r\n\x0b\n\x04\x05\0\x02\0\x12\x03\x03\x04\x0e\n\x0c\n\x05\x05\0\x02\ + \0\x01\x12\x03\x03\x04\t\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x03\x0c\r\n\ + \x0b\n\x04\x05\0\x02\x01\x12\x03\x04\x04\x0e\n\x0c\n\x05\x05\0\x02\x01\ + \x01\x12\x03\x04\x04\t\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x04\x0c\rb\ + \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() + }) +} diff --git a/shared-lib/lib-ot/src/protobuf/model/mod.rs b/shared-lib/lib-ot/src/protobuf/model/mod.rs index d30d09866a..86c4fd5276 100644 --- a/shared-lib/lib-ot/src/protobuf/model/mod.rs +++ b/shared-lib/lib-ot/src/protobuf/model/mod.rs @@ -1,5 +1,8 @@ #![cfg_attr(rustfmt, rustfmt::skip)] // Auto-generated, do not edit +mod cache; +pub use cache::*; + mod model; pub use model::*; diff --git a/shared-lib/lib-ot/src/protobuf/proto/cache.proto b/shared-lib/lib-ot/src/protobuf/proto/cache.proto new file mode 100644 index 0000000000..9ff05aac2a --- /dev/null +++ b/shared-lib/lib-ot/src/protobuf/proto/cache.proto @@ -0,0 +1,6 @@ +syntax = "proto3"; + +enum RevState { + Local = 0; + Acked = 1; +} diff --git a/shared-lib/lib-ot/src/rich_text/delta.rs b/shared-lib/lib-ot/src/rich_text/delta.rs index 03f3b2479f..99cb35f2bc 100644 --- a/shared-lib/lib-ot/src/rich_text/delta.rs +++ b/shared-lib/lib-ot/src/rich_text/delta.rs @@ -1,3 +1,7 @@ -use crate::{core::Delta, rich_text::RichTextAttributes}; +use crate::{ + core::{Delta, DeltaBuilder}, + rich_text::RichTextAttributes, +}; pub type RichTextDelta = Delta; +pub type RichTextDeltaBuilder = DeltaBuilder; From 45d9a0918fc76ab216f7361db1e41aea97a515f0 Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 9 Dec 2021 22:28:11 +0800 Subject: [PATCH 14/39] add user_id in revision --- .../lib/protobuf/lib-ot/model.pb.dart | 14 ++ .../lib/protobuf/lib-ot/model.pbjson.dart | 3 +- .../src/services/doc/controller.rs | 5 +- .../src/services/doc/edit/editor.rs | 7 +- .../src/services/doc/revision/cache.rs | 26 +++- .../src/services/doc/revision/manager.rs | 5 +- .../src/sql_tables/doc/rev_sql.rs | 20 ++- .../src/sql_tables/doc/rev_table.rs | 22 +-- .../tests/editor/revision_test.rs | 2 +- frontend/rust-lib/flowy-test/src/editor.rs | 5 +- .../src/services/user/user_session.rs | 2 + .../flowy-derive/src/proto_buf/deserialize.rs | 8 +- .../flowy-document-infra/src/core/document.rs | 2 +- .../flowy-document-infra/src/core/view.rs | 2 +- .../src/entities/ws/ws.rs | 11 -- .../flowy-user-infra/src/entities/auth.rs | 4 +- shared-lib/lib-ot/src/protobuf/model/model.rs | 132 ++++++++++++------ .../lib-ot/src/protobuf/proto/model.proto | 1 + shared-lib/lib-ot/src/revision/model.rs | 6 +- 19 files changed, 186 insertions(+), 91 deletions(-) diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/model.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/model.pb.dart index a19ab537be..85a13ba547 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/model.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/model.pb.dart @@ -22,6 +22,7 @@ class Revision extends $pb.GeneratedMessage { ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'md5') ..aOS(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'docId') ..e(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'ty', $pb.PbFieldType.OE, defaultOrMaker: RevType.Local, valueOf: RevType.valueOf, enumValues: RevType.values) + ..aOS(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'userId') ..hasRequiredFields = false ; @@ -33,6 +34,7 @@ class Revision extends $pb.GeneratedMessage { $core.String? md5, $core.String? docId, RevType? ty, + $core.String? userId, }) { final _result = create(); if (baseRevId != null) { @@ -53,6 +55,9 @@ class Revision extends $pb.GeneratedMessage { if (ty != null) { _result.ty = ty; } + if (userId != null) { + _result.userId = userId; + } return _result; } factory Revision.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); @@ -129,6 +134,15 @@ class Revision extends $pb.GeneratedMessage { $core.bool hasTy() => $_has(5); @$pb.TagNumber(6) void clearTy() => clearField(6); + + @$pb.TagNumber(7) + $core.String get userId => $_getSZ(6); + @$pb.TagNumber(7) + set userId($core.String v) { $_setString(6, v); } + @$pb.TagNumber(7) + $core.bool hasUserId() => $_has(6); + @$pb.TagNumber(7) + void clearUserId() => clearField(7); } class RevId extends $pb.GeneratedMessage { diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/model.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/model.pbjson.dart index 8b52c2439e..5cc16b7fec 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/model.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/model.pbjson.dart @@ -29,11 +29,12 @@ const Revision$json = const { const {'1': 'md5', '3': 4, '4': 1, '5': 9, '10': 'md5'}, const {'1': 'doc_id', '3': 5, '4': 1, '5': 9, '10': 'docId'}, const {'1': 'ty', '3': 6, '4': 1, '5': 14, '6': '.RevType', '10': 'ty'}, + const {'1': 'user_id', '3': 7, '4': 1, '5': 9, '10': 'userId'}, ], }; /// Descriptor for `Revision`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List revisionDescriptor = $convert.base64Decode('CghSZXZpc2lvbhIeCgtiYXNlX3Jldl9pZBgBIAEoA1IJYmFzZVJldklkEhUKBnJldl9pZBgCIAEoA1IFcmV2SWQSHQoKZGVsdGFfZGF0YRgDIAEoDFIJZGVsdGFEYXRhEhAKA21kNRgEIAEoCVIDbWQ1EhUKBmRvY19pZBgFIAEoCVIFZG9jSWQSGAoCdHkYBiABKA4yCC5SZXZUeXBlUgJ0eQ=='); +final $typed_data.Uint8List revisionDescriptor = $convert.base64Decode('CghSZXZpc2lvbhIeCgtiYXNlX3Jldl9pZBgBIAEoA1IJYmFzZVJldklkEhUKBnJldl9pZBgCIAEoA1IFcmV2SWQSHQoKZGVsdGFfZGF0YRgDIAEoDFIJZGVsdGFEYXRhEhAKA21kNRgEIAEoCVIDbWQ1EhUKBmRvY19pZBgFIAEoCVIFZG9jSWQSGAoCdHkYBiABKA4yCC5SZXZUeXBlUgJ0eRIXCgd1c2VyX2lkGAcgASgJUgZ1c2VySWQ='); @$core.Deprecated('Use revIdDescriptor instead') const RevId$json = const { '1': 'RevId', diff --git a/frontend/rust-lib/flowy-document/src/services/doc/controller.rs b/frontend/rust-lib/flowy-document/src/services/doc/controller.rs index e5489db2ff..fabc15668b 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/controller.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/controller.rs @@ -112,12 +112,13 @@ impl DocController { // let doc = self.read_doc(doc_id, pool.clone()).await?; let ws_sender = self.ws_manager.ws(); let token = self.user.token()?; + let user_id = self.user.user_id()?; let server = Arc::new(RevisionServerImpl { token, server: self.server.clone(), }); - let cache = Arc::new(RevisionCache::new(doc_id, pool, server)); - Ok(RevisionManager::new(doc_id, cache, ws_sender)) + let cache = Arc::new(RevisionCache::new(&user_id, doc_id, pool, server)); + Ok(RevisionManager::new(&user_id, doc_id, cache, ws_sender)) } } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs index a1554afe4b..58242d778b 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs @@ -163,7 +163,8 @@ impl ClientDocEditor { 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(); - let revision = Revision::new(base_rev_id, rev_id, delta_data, &self.doc_id, RevType::Local); + let user_id = self.user.user_id()?; + let revision = Revision::new(base_rev_id, rev_id, delta_data, &self.doc_id, RevType::Local, user_id); let _ = self.rev_manager.add_revision(&revision).await?; Ok(rev_id.into()) } @@ -236,22 +237,26 @@ impl ClientDocEditor { let (local_base_rev_id, local_rev_id) = self.rev_manager.next_rev_id(); // save the revision + let user_id = self.user.user_id()?; let revision = Revision::new( local_base_rev_id, local_rev_id, client_prime.to_bytes().to_vec(), &self.doc_id, RevType::Remote, + user_id, ); let _ = self.rev_manager.add_revision(&revision).await?; // send the server_prime delta + let user_id = self.user.user_id()?; let revision = Revision::new( local_base_rev_id, local_rev_id, server_prime.to_bytes().to_vec(), &self.doc_id, RevType::Remote, + user_id, ); let _ = self.ws_sender.send(revision.into()); Ok(()) diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs index c45de3f26c..77e8cc649a 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs @@ -24,6 +24,7 @@ pub trait RevisionIterator: Send + Sync { type DocRevisionDeskCache = dyn RevisionDiskCache; pub struct RevisionCache { + user_id: String, doc_id: String, dish_cache: Arc, memory_cache: Arc, @@ -32,11 +33,17 @@ pub struct RevisionCache { } impl RevisionCache { - pub fn new(doc_id: &str, pool: Arc, server: Arc) -> RevisionCache { + pub fn new( + user_id: &str, + doc_id: &str, + pool: Arc, + server: Arc, + ) -> RevisionCache { let doc_id = doc_id.to_owned(); - let dish_cache = Arc::new(Persistence::new(pool)); + let dish_cache = Arc::new(Persistence::new(user_id, pool)); let memory_cache = Arc::new(RevisionMemoryCache::new()); Self { + user_id: user_id.to_owned(), doc_id, dish_cache, memory_cache, @@ -117,6 +124,7 @@ impl RevisionCache { delta_data.to_owned(), &doc.id, RevType::Remote, + self.user_id.clone(), ); let record = RevisionRecord { revision, @@ -215,6 +223,7 @@ fn correct_delta_if_need(delta: &mut RichTextDelta) { } pub(crate) struct Persistence { + user_id: String, pub(crate) pool: Arc, } @@ -231,25 +240,30 @@ impl RevisionDiskCache for Persistence { fn revisions_in_range(&self, doc_id: &str, range: &RevisionRange) -> Result, Self::Error> { let conn = &*self.pool.get().map_err(internal_error).unwrap(); - let revisions = RevTableSql::read_rev_tables_with_range(doc_id, range.clone(), conn)?; + let revisions = RevTableSql::read_rev_tables_with_range(&self.user_id, doc_id, range.clone(), conn)?; Ok(revisions) } fn read_revision(&self, doc_id: &str, rev_id: i64) -> Result, Self::Error> { let conn = self.pool.get().map_err(internal_error)?; - let some = RevTableSql::read_rev_table(doc_id, &rev_id, &*conn)?; + let some = RevTableSql::read_rev_table(&self.user_id, doc_id, &rev_id, &*conn)?; Ok(some) } fn read_revisions(&self, doc_id: &str) -> Result, Self::Error> { let conn = self.pool.get().map_err(internal_error)?; - let some = RevTableSql::read_rev_tables(doc_id, &*conn)?; + let some = RevTableSql::read_rev_tables(&self.user_id, doc_id, &*conn)?; Ok(some) } } impl Persistence { - pub(crate) fn new(pool: Arc) -> Self { Self { pool } } + pub(crate) fn new(user_id: &str, pool: Arc) -> Self { + Self { + user_id: user_id.to_owned(), + pool, + } + } } #[cfg(feature = "flowy_unit_test")] diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs index 699046efa1..30f372be28 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs @@ -20,16 +20,18 @@ pub trait RevisionServer: Send + Sync { pub struct RevisionManager { doc_id: String, + user_id: String, rev_id_counter: RevIdCounter, cache: Arc, ws_sender: Arc, } impl RevisionManager { - pub fn new(doc_id: &str, cache: Arc, ws_sender: Arc) -> Self { + pub fn new(user_id: &str, doc_id: &str, cache: Arc, ws_sender: Arc) -> Self { let rev_id_counter = RevIdCounter::new(0); Self { doc_id: doc_id.to_string(), + user_id: user_id.to_owned(), rev_id_counter, cache, ws_sender, @@ -83,6 +85,7 @@ impl RevisionManager { delta_data.to_vec(), &self.doc_id, RevType::Remote, + self.user_id.clone(), ); Ok(revision) diff --git a/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_sql.rs b/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_sql.rs index 051473048c..28cd06895c 100644 --- a/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_sql.rs +++ b/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_sql.rs @@ -1,6 +1,6 @@ use crate::{ errors::DocError, - sql_tables::{doc::RevTable, RevChangeset, RevTableState, RevTableType}, + sql_tables::{doc::RevTable, mk_revision_from_table, RevChangeset, RevTableState, RevTableType}, }; use diesel::update; use flowy_database::{insert_or_ignore_into, prelude::*, schema::rev_table::dsl, SqliteConnection}; @@ -41,7 +41,11 @@ impl RevTableSql { Ok(()) } - pub(crate) fn read_rev_tables(doc_id: &str, conn: &SqliteConnection) -> Result, DocError> { + pub(crate) fn read_rev_tables( + user_id: &str, + doc_id: &str, + conn: &SqliteConnection, + ) -> Result, DocError> { let filter = dsl::rev_table .filter(dsl::doc_id.eq(doc_id)) .order(dsl::rev_id.asc()) @@ -49,12 +53,13 @@ impl RevTableSql { let rev_tables = filter.load::(conn)?; let revisions = rev_tables .into_iter() - .map(|table| table.into()) + .map(|table| mk_revision_from_table(user_id, table)) .collect::>(); Ok(revisions) } pub(crate) fn read_rev_table( + user_id: &str, doc_id: &str, revision_id: &i64, conn: &SqliteConnection, @@ -67,25 +72,26 @@ impl RevTableSql { if Err(diesel::NotFound) == result { Ok(None) } else { - Ok(Some(result?.into())) + Ok(Some(mk_revision_from_table(user_id, result?))) } } pub(crate) fn read_rev_tables_with_range( - doc_id_s: &str, + user_id: &str, + doc_id: &str, range: RevisionRange, conn: &SqliteConnection, ) -> Result, DocError> { let rev_tables = dsl::rev_table .filter(dsl::rev_id.ge(range.start)) .filter(dsl::rev_id.le(range.end)) - .filter(dsl::doc_id.eq(doc_id_s)) + .filter(dsl::doc_id.eq(doc_id)) .order(dsl::rev_id.asc()) .load::(conn)?; let revisions = rev_tables .into_iter() - .map(|table| table.into()) + .map(|table| mk_revision_from_table(user_id, table)) .collect::>(); Ok(revisions) } diff --git a/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_table.rs b/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_table.rs index d652833978..2dcdf9b368 100644 --- a/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_table.rs +++ b/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_table.rs @@ -1,5 +1,6 @@ use diesel::sql_types::Integer; use flowy_database::schema::rev_table; + use flowy_document_infra::util::md5; use lib_ot::revision::{RevId, RevState, RevType, Revision}; @@ -63,17 +64,16 @@ impl std::convert::From for RevTableState { } } -impl std::convert::From for Revision { - fn from(table: RevTable) -> Self { - let md5 = md5(&table.data); - Revision { - base_rev_id: table.base_rev_id, - rev_id: table.rev_id, - delta_data: table.data, - md5, - doc_id: table.doc_id, - ty: table.ty.into(), - } +pub(crate) fn mk_revision_from_table(user_id: &str, table: RevTable) -> Revision { + let md5 = md5(&table.data); + Revision { + base_rev_id: table.base_rev_id, + rev_id: table.rev_id, + delta_data: table.data, + md5, + doc_id: table.doc_id, + ty: table.ty.into(), + user_id: user_id.to_owned(), } } diff --git a/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs b/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs index d2993538a6..81c23b3f86 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs @@ -1,5 +1,5 @@ use flowy_test::editor::{EditorScript::*, *}; -use lib_ot::{core::DeltaBuilder, revision::RevState, rich_text::RichTextDeltaBuilder}; +use lib_ot::{revision::RevState, rich_text::RichTextDeltaBuilder}; #[tokio::test] async fn doc_rev_state_test1() { diff --git a/frontend/rust-lib/flowy-test/src/editor.rs b/frontend/rust-lib/flowy-test/src/editor.rs index 4d0033ffb8..3dd4b6de5d 100644 --- a/frontend/rust-lib/flowy-test/src/editor.rs +++ b/frontend/rust-lib/flowy-test/src/editor.rs @@ -9,7 +9,7 @@ use lib_ot::{ revision::{RevState, RevType, Revision, RevisionRange}, rich_text::RichTextDelta, }; -use std::{str::FromStr, sync::Arc}; +use std::sync::Arc; use tokio::time::{sleep, Duration}; pub enum EditorScript { @@ -56,10 +56,12 @@ impl EditorTest { let _memory_cache = cache.memory_cache(); let _disk_cache = cache.dish_cache(); let doc_id = self.editor.doc_id.clone(); + let user_id = self.sdk.user_session.user_id().unwrap(); match script { EditorScript::InsertText(s, offset) => { self.editor.insert(offset, s).await.unwrap(); + sleep(Duration::from_millis(200)).await; }, EditorScript::Delete(interval) => { self.editor.delete(interval).await.unwrap(); @@ -98,6 +100,7 @@ impl EditorTest { delta.to_bytes().to_vec(), &doc_id, RevType::Remote, + user_id, ); let data = WsDocumentDataBuilder::build_push_rev_message(&doc_id, revision); self.send_ws_message(data).await; diff --git a/frontend/rust-lib/flowy-user/src/services/user/user_session.rs b/frontend/rust-lib/flowy-user/src/services/user/user_session.rs index cecbc6becd..32bbba4a25 100644 --- a/frontend/rust-lib/flowy-user/src/services/user/user_session.rs +++ b/frontend/rust-lib/flowy-user/src/services/user/user_session.rs @@ -184,6 +184,8 @@ impl UserSession { pub fn user_id(&self) -> Result { Ok(self.get_session()?.user_id) } + pub fn user_name(&self) -> Result { Ok(self.get_session()?.name) } + pub fn token(&self) -> Result { Ok(self.get_session()?.token) } pub fn add_ws_handler(&self, handler: Arc) { let _ = self.ws_manager.add_handler(handler); } diff --git a/shared-lib/flowy-derive/src/proto_buf/deserialize.rs b/shared-lib/flowy-derive/src/proto_buf/deserialize.rs index 4c864aa2af..775670b6bc 100644 --- a/shared-lib/flowy-derive/src/proto_buf/deserialize.rs +++ b/shared-lib/flowy-derive/src/proto_buf/deserialize.rs @@ -47,7 +47,13 @@ pub fn make_de_token_steam(ctxt: &Ctxt, ast: &ASTContainer) -> Option Option { let member = &field.member; let ident = get_member_ident(ctxt, member)?; - let ty_info = parse_ty(ctxt, &field.ty)?; + let ty_info = match parse_ty(ctxt, &field.ty) { + Ok(ty_info) => ty_info, + Err(e) => { + eprintln!("token_stream_for_one_of failed: {:?} with error: {}", member, e); + panic!(); + } + }?; let bracketed_ty_info = ty_info.bracket_ty_info.as_ref().as_ref(); let has_func = format_ident!("has_{}", ident.to_string()); diff --git a/shared-lib/flowy-document-infra/src/core/document.rs b/shared-lib/flowy-document-infra/src/core/document.rs index 0618f56ee4..0d17222d0e 100644 --- a/shared-lib/flowy-document-infra/src/core/document.rs +++ b/shared-lib/flowy-document-infra/src/core/document.rs @@ -109,7 +109,7 @@ impl Document { let text = data.to_string(); let delta = self.view.insert(&self.delta, &text, interval)?; - tracing::trace!("👉 receive change: {}", delta); + tracing::debug!("👉 receive change: {}", delta); self.compose_delta(delta.clone())?; Ok(delta) } diff --git a/shared-lib/flowy-document-infra/src/core/view.rs b/shared-lib/flowy-document-infra/src/core/view.rs index 9f5335def5..ee752abb6f 100644 --- a/shared-lib/flowy-document-infra/src/core/view.rs +++ b/shared-lib/flowy-document-infra/src/core/view.rs @@ -32,7 +32,7 @@ impl View { for ext in &self.insert_exts { if let Some(mut delta) = ext.apply(delta, interval.size(), text, interval.start) { trim(&mut delta); - tracing::trace!("[{}]: applied, delta: {}", ext.ext_name(), delta); + tracing::debug!("[{}]: applied, delta: {}", ext.ext_name(), delta); new_delta = Some(delta); break; } diff --git a/shared-lib/flowy-document-infra/src/entities/ws/ws.rs b/shared-lib/flowy-document-infra/src/entities/ws/ws.rs index fc9f90d3f0..6b3555ce16 100644 --- a/shared-lib/flowy-document-infra/src/entities/ws/ws.rs +++ b/shared-lib/flowy-document-infra/src/entities/ws/ws.rs @@ -29,15 +29,6 @@ impl std::default::Default for WsDataType { fn default() -> Self { WsDataType::Acked } } -// #[derive(ProtoBuf, Default, Debug, Clone)] -// pub struct WsDocumentUser { -// #[pb(index = 1)] -// pub user_id: String, -// -// #[pb(index = 2)] -// pub name: String, -// } - #[derive(ProtoBuf, Default, Debug, Clone)] pub struct WsDocumentData { #[pb(index = 1)] @@ -48,8 +39,6 @@ pub struct WsDocumentData { #[pb(index = 3)] pub data: Vec, - /* #[pb(index = 4)] - * pub user: WsDocumentUser, */ } impl std::convert::From for WsDocumentData { diff --git a/shared-lib/flowy-user-infra/src/entities/auth.rs b/shared-lib/flowy-user-infra/src/entities/auth.rs index ca0f76ddd0..0b4fda73ef 100644 --- a/shared-lib/flowy-user-infra/src/entities/auth.rs +++ b/shared-lib/flowy-user-infra/src/entities/auth.rs @@ -28,7 +28,7 @@ pub struct SignInParams { pub name: String, } -#[derive(Debug, Default, ProtoBuf)] +#[derive(Debug, Default, ProtoBuf, Clone)] pub struct SignInResponse { #[pb(index = 1)] pub user_id: String, @@ -97,7 +97,7 @@ pub struct SignUpParams { pub password: String, } -#[derive(ProtoBuf, Debug, Default)] +#[derive(ProtoBuf, Debug, Default, Clone)] pub struct SignUpResponse { #[pb(index = 1)] pub user_id: String, diff --git a/shared-lib/lib-ot/src/protobuf/model/model.rs b/shared-lib/lib-ot/src/protobuf/model/model.rs index 125f1cc78c..6bf8f5490a 100644 --- a/shared-lib/lib-ot/src/protobuf/model/model.rs +++ b/shared-lib/lib-ot/src/protobuf/model/model.rs @@ -32,6 +32,7 @@ pub struct Revision { pub md5: ::std::string::String, pub doc_id: ::std::string::String, pub ty: RevType, + pub user_id: ::std::string::String, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, @@ -170,6 +171,32 @@ impl Revision { pub fn set_ty(&mut self, v: RevType) { self.ty = v; } + + // string user_id = 7; + + + pub fn get_user_id(&self) -> &str { + &self.user_id + } + pub fn clear_user_id(&mut self) { + self.user_id.clear(); + } + + // Param is passed by value, moved + pub fn set_user_id(&mut self, v: ::std::string::String) { + self.user_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_user_id(&mut self) -> &mut ::std::string::String { + &mut self.user_id + } + + // Take field + pub fn take_user_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.user_id, ::std::string::String::new()) + } } impl ::protobuf::Message for Revision { @@ -207,6 +234,9 @@ impl ::protobuf::Message for Revision { 6 => { ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.ty, 6, &mut self.unknown_fields)? }, + 7 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.user_id)?; + }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; }, @@ -237,6 +267,9 @@ impl ::protobuf::Message for Revision { if self.ty != RevType::Local { my_size += ::protobuf::rt::enum_size(6, self.ty); } + if !self.user_id.is_empty() { + my_size += ::protobuf::rt::string_size(7, &self.user_id); + } my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); self.cached_size.set(my_size); my_size @@ -261,6 +294,9 @@ impl ::protobuf::Message for Revision { if self.ty != RevType::Local { os.write_enum(6, ::protobuf::ProtobufEnum::value(&self.ty))?; } + if !self.user_id.is_empty() { + os.write_string(7, &self.user_id)?; + } os.write_unknown_fields(self.get_unknown_fields())?; ::std::result::Result::Ok(()) } @@ -329,6 +365,11 @@ impl ::protobuf::Message for Revision { |m: &Revision| { &m.ty }, |m: &mut Revision| { &mut m.ty }, )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "user_id", + |m: &Revision| { &m.user_id }, + |m: &mut Revision| { &mut m.user_id }, + )); ::protobuf::reflect::MessageDescriptor::new_pb_name::( "Revision", fields, @@ -351,6 +392,7 @@ impl ::protobuf::Clear for Revision { self.md5.clear(); self.doc_id.clear(); self.ty = RevType::Local; + self.user_id.clear(); self.unknown_fields.clear(); } } @@ -799,52 +841,56 @@ impl ::protobuf::reflect::ProtobufValue for RevType { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x0bmodel.proto\"\xa3\x01\n\x08Revision\x12\x1e\n\x0bbase_rev_id\x18\ + \n\x0bmodel.proto\"\xbc\x01\n\x08Revision\x12\x1e\n\x0bbase_rev_id\x18\ \x01\x20\x01(\x03R\tbaseRevId\x12\x15\n\x06rev_id\x18\x02\x20\x01(\x03R\ \x05revId\x12\x1d\n\ndelta_data\x18\x03\x20\x01(\x0cR\tdeltaData\x12\x10\ \n\x03md5\x18\x04\x20\x01(\tR\x03md5\x12\x15\n\x06doc_id\x18\x05\x20\x01\ - (\tR\x05docId\x12\x18\n\x02ty\x18\x06\x20\x01(\x0e2\x08.RevTypeR\x02ty\"\ - \x1d\n\x05RevId\x12\x14\n\x05value\x18\x01\x20\x01(\x03R\x05value\"N\n\r\ - RevisionRange\x12\x15\n\x06doc_id\x18\x01\x20\x01(\tR\x05docId\x12\x14\n\ - \x05start\x18\x02\x20\x01(\x03R\x05start\x12\x10\n\x03end\x18\x03\x20\ - \x01(\x03R\x03end*\x20\n\x07RevType\x12\t\n\x05Local\x10\0\x12\n\n\x06Re\ - mote\x10\x01J\xea\x05\n\x06\x12\x04\0\0\x15\x01\n\x08\n\x01\x0c\x12\x03\ - \0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\t\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\x1a\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\ - \x15\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x18\x19\n\x0b\n\x04\x04\0\ - \x02\x01\x12\x03\x04\x04\x15\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\ - \x04\t\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\n\x10\n\x0c\n\x05\x04\0\ - \x02\x01\x03\x12\x03\x04\x13\x14\n\x0b\n\x04\x04\0\x02\x02\x12\x03\x05\ - \x04\x19\n\x0c\n\x05\x04\0\x02\x02\x05\x12\x03\x05\x04\t\n\x0c\n\x05\x04\ - \0\x02\x02\x01\x12\x03\x05\n\x14\n\x0c\n\x05\x04\0\x02\x02\x03\x12\x03\ - \x05\x17\x18\n\x0b\n\x04\x04\0\x02\x03\x12\x03\x06\x04\x13\n\x0c\n\x05\ - \x04\0\x02\x03\x05\x12\x03\x06\x04\n\n\x0c\n\x05\x04\0\x02\x03\x01\x12\ - \x03\x06\x0b\x0e\n\x0c\n\x05\x04\0\x02\x03\x03\x12\x03\x06\x11\x12\n\x0b\ - \n\x04\x04\0\x02\x04\x12\x03\x07\x04\x16\n\x0c\n\x05\x04\0\x02\x04\x05\ - \x12\x03\x07\x04\n\n\x0c\n\x05\x04\0\x02\x04\x01\x12\x03\x07\x0b\x11\n\ - \x0c\n\x05\x04\0\x02\x04\x03\x12\x03\x07\x14\x15\n\x0b\n\x04\x04\0\x02\ - \x05\x12\x03\x08\x04\x13\n\x0c\n\x05\x04\0\x02\x05\x06\x12\x03\x08\x04\ - \x0b\n\x0c\n\x05\x04\0\x02\x05\x01\x12\x03\x08\x0c\x0e\n\x0c\n\x05\x04\0\ - \x02\x05\x03\x12\x03\x08\x11\x12\n\n\n\x02\x04\x01\x12\x04\n\0\x0c\x01\n\ - \n\n\x03\x04\x01\x01\x12\x03\n\x08\r\n\x0b\n\x04\x04\x01\x02\0\x12\x03\ - \x0b\x04\x14\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03\x0b\x04\t\n\x0c\n\x05\ - \x04\x01\x02\0\x01\x12\x03\x0b\n\x0f\n\x0c\n\x05\x04\x01\x02\0\x03\x12\ - \x03\x0b\x12\x13\n\n\n\x02\x04\x02\x12\x04\r\0\x11\x01\n\n\n\x03\x04\x02\ - \x01\x12\x03\r\x08\x15\n\x0b\n\x04\x04\x02\x02\0\x12\x03\x0e\x04\x16\n\ - \x0c\n\x05\x04\x02\x02\0\x05\x12\x03\x0e\x04\n\n\x0c\n\x05\x04\x02\x02\0\ - \x01\x12\x03\x0e\x0b\x11\n\x0c\n\x05\x04\x02\x02\0\x03\x12\x03\x0e\x14\ - \x15\n\x0b\n\x04\x04\x02\x02\x01\x12\x03\x0f\x04\x14\n\x0c\n\x05\x04\x02\ - \x02\x01\x05\x12\x03\x0f\x04\t\n\x0c\n\x05\x04\x02\x02\x01\x01\x12\x03\ - \x0f\n\x0f\n\x0c\n\x05\x04\x02\x02\x01\x03\x12\x03\x0f\x12\x13\n\x0b\n\ - \x04\x04\x02\x02\x02\x12\x03\x10\x04\x12\n\x0c\n\x05\x04\x02\x02\x02\x05\ - \x12\x03\x10\x04\t\n\x0c\n\x05\x04\x02\x02\x02\x01\x12\x03\x10\n\r\n\x0c\ - \n\x05\x04\x02\x02\x02\x03\x12\x03\x10\x10\x11\n\n\n\x02\x05\0\x12\x04\ - \x12\0\x15\x01\n\n\n\x03\x05\0\x01\x12\x03\x12\x05\x0c\n\x0b\n\x04\x05\0\ - \x02\0\x12\x03\x13\x04\x0e\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\x13\x04\t\ - \n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x13\x0c\r\n\x0b\n\x04\x05\0\x02\x01\ - \x12\x03\x14\x04\x0f\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x14\x04\n\n\ - \x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x14\r\x0eb\x06proto3\ + (\tR\x05docId\x12\x18\n\x02ty\x18\x06\x20\x01(\x0e2\x08.RevTypeR\x02ty\ + \x12\x17\n\x07user_id\x18\x07\x20\x01(\tR\x06userId\"\x1d\n\x05RevId\x12\ + \x14\n\x05value\x18\x01\x20\x01(\x03R\x05value\"N\n\rRevisionRange\x12\ + \x15\n\x06doc_id\x18\x01\x20\x01(\tR\x05docId\x12\x14\n\x05start\x18\x02\ + \x20\x01(\x03R\x05start\x12\x10\n\x03end\x18\x03\x20\x01(\x03R\x03end*\ + \x20\n\x07RevType\x12\t\n\x05Local\x10\0\x12\n\n\x06Remote\x10\x01J\xa1\ + \x06\n\x06\x12\x04\0\0\x16\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\ + \x04\0\x12\x04\x02\0\n\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\x1a\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\x15\n\x0c\n\x05\ + \x04\0\x02\0\x03\x12\x03\x03\x18\x19\n\x0b\n\x04\x04\0\x02\x01\x12\x03\ + \x04\x04\x15\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\x04\t\n\x0c\n\x05\ + \x04\0\x02\x01\x01\x12\x03\x04\n\x10\n\x0c\n\x05\x04\0\x02\x01\x03\x12\ + \x03\x04\x13\x14\n\x0b\n\x04\x04\0\x02\x02\x12\x03\x05\x04\x19\n\x0c\n\ + \x05\x04\0\x02\x02\x05\x12\x03\x05\x04\t\n\x0c\n\x05\x04\0\x02\x02\x01\ + \x12\x03\x05\n\x14\n\x0c\n\x05\x04\0\x02\x02\x03\x12\x03\x05\x17\x18\n\ + \x0b\n\x04\x04\0\x02\x03\x12\x03\x06\x04\x13\n\x0c\n\x05\x04\0\x02\x03\ + \x05\x12\x03\x06\x04\n\n\x0c\n\x05\x04\0\x02\x03\x01\x12\x03\x06\x0b\x0e\ + \n\x0c\n\x05\x04\0\x02\x03\x03\x12\x03\x06\x11\x12\n\x0b\n\x04\x04\0\x02\ + \x04\x12\x03\x07\x04\x16\n\x0c\n\x05\x04\0\x02\x04\x05\x12\x03\x07\x04\n\ + \n\x0c\n\x05\x04\0\x02\x04\x01\x12\x03\x07\x0b\x11\n\x0c\n\x05\x04\0\x02\ + \x04\x03\x12\x03\x07\x14\x15\n\x0b\n\x04\x04\0\x02\x05\x12\x03\x08\x04\ + \x13\n\x0c\n\x05\x04\0\x02\x05\x06\x12\x03\x08\x04\x0b\n\x0c\n\x05\x04\0\ + \x02\x05\x01\x12\x03\x08\x0c\x0e\n\x0c\n\x05\x04\0\x02\x05\x03\x12\x03\ + \x08\x11\x12\n\x0b\n\x04\x04\0\x02\x06\x12\x03\t\x04\x17\n\x0c\n\x05\x04\ + \0\x02\x06\x05\x12\x03\t\x04\n\n\x0c\n\x05\x04\0\x02\x06\x01\x12\x03\t\ + \x0b\x12\n\x0c\n\x05\x04\0\x02\x06\x03\x12\x03\t\x15\x16\n\n\n\x02\x04\ + \x01\x12\x04\x0b\0\r\x01\n\n\n\x03\x04\x01\x01\x12\x03\x0b\x08\r\n\x0b\n\ + \x04\x04\x01\x02\0\x12\x03\x0c\x04\x14\n\x0c\n\x05\x04\x01\x02\0\x05\x12\ + \x03\x0c\x04\t\n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03\x0c\n\x0f\n\x0c\n\ + \x05\x04\x01\x02\0\x03\x12\x03\x0c\x12\x13\n\n\n\x02\x04\x02\x12\x04\x0e\ + \0\x12\x01\n\n\n\x03\x04\x02\x01\x12\x03\x0e\x08\x15\n\x0b\n\x04\x04\x02\ + \x02\0\x12\x03\x0f\x04\x16\n\x0c\n\x05\x04\x02\x02\0\x05\x12\x03\x0f\x04\ + \n\n\x0c\n\x05\x04\x02\x02\0\x01\x12\x03\x0f\x0b\x11\n\x0c\n\x05\x04\x02\ + \x02\0\x03\x12\x03\x0f\x14\x15\n\x0b\n\x04\x04\x02\x02\x01\x12\x03\x10\ + \x04\x14\n\x0c\n\x05\x04\x02\x02\x01\x05\x12\x03\x10\x04\t\n\x0c\n\x05\ + \x04\x02\x02\x01\x01\x12\x03\x10\n\x0f\n\x0c\n\x05\x04\x02\x02\x01\x03\ + \x12\x03\x10\x12\x13\n\x0b\n\x04\x04\x02\x02\x02\x12\x03\x11\x04\x12\n\ + \x0c\n\x05\x04\x02\x02\x02\x05\x12\x03\x11\x04\t\n\x0c\n\x05\x04\x02\x02\ + \x02\x01\x12\x03\x11\n\r\n\x0c\n\x05\x04\x02\x02\x02\x03\x12\x03\x11\x10\ + \x11\n\n\n\x02\x05\0\x12\x04\x13\0\x16\x01\n\n\n\x03\x05\0\x01\x12\x03\ + \x13\x05\x0c\n\x0b\n\x04\x05\0\x02\0\x12\x03\x14\x04\x0e\n\x0c\n\x05\x05\ + \0\x02\0\x01\x12\x03\x14\x04\t\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x14\ + \x0c\r\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x15\x04\x0f\n\x0c\n\x05\x05\0\ + \x02\x01\x01\x12\x03\x15\x04\n\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x15\ + \r\x0eb\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/shared-lib/lib-ot/src/protobuf/proto/model.proto b/shared-lib/lib-ot/src/protobuf/proto/model.proto index 9ed4f2ea15..f9c9f12bc2 100644 --- a/shared-lib/lib-ot/src/protobuf/proto/model.proto +++ b/shared-lib/lib-ot/src/protobuf/proto/model.proto @@ -7,6 +7,7 @@ message Revision { string md5 = 4; string doc_id = 5; RevType ty = 6; + string user_id = 7; } message RevId { int64 value = 1; diff --git a/shared-lib/lib-ot/src/revision/model.rs b/shared-lib/lib-ot/src/revision/model.rs index 818eb9886c..79c9ed7bff 100644 --- a/shared-lib/lib-ot/src/revision/model.rs +++ b/shared-lib/lib-ot/src/revision/model.rs @@ -21,6 +21,9 @@ pub struct Revision { #[pb(index = 6)] pub ty: RevType, + + #[pb(index = 7)] + pub user_id: String, } impl Revision { @@ -47,7 +50,7 @@ impl std::fmt::Debug for Revision { } impl Revision { - pub fn new(base_rev_id: T1, rev_id: T2, delta: D, doc_id: &str, ty: RevType) -> Revision + pub fn new(base_rev_id: T1, rev_id: T2, delta: D, doc_id: &str, ty: RevType, user_id: String) -> Revision where T1: Into, T2: Into, @@ -70,6 +73,7 @@ impl Revision { md5, doc_id, ty, + user_id, } } } From 34441ee07642a0399b6d1c5ddf0e25135878a283 Mon Sep 17 00:00:00 2001 From: appflowy Date: Fri, 10 Dec 2021 11:05:23 +0800 Subject: [PATCH 15/39] add test --- backend/src/application.rs | 2 +- backend/src/context.rs | 10 +-- backend/src/services/doc/manager.rs | 45 ++++++++----- backend/src/services/doc/ws_actor.rs | 4 +- backend/src/services/view/router.rs | 4 +- .../flowy-document/src/services/cache.rs | 53 --------------- .../src/services/doc/controller.rs | 66 +++++++++++++------ .../src/services/doc/edit/queue.rs | 1 + .../flowy-document/src/services/mod.rs | 1 - .../tests/editor/revision_test.rs | 14 ++++ frontend/rust-lib/flowy-test/src/editor.rs | 2 +- 11 files changed, 102 insertions(+), 100 deletions(-) delete mode 100644 frontend/rust-lib/flowy-document/src/services/cache.rs diff --git a/backend/src/application.rs b/backend/src/application.rs index f05b44767d..b4958a76d4 100644 --- a/backend/src/application.rs +++ b/backend/src/application.rs @@ -59,7 +59,7 @@ pub fn run(listener: TcpListener, app_ctx: AppContext) -> Result>, pub pg_pool: Data, pub ws_bizs: Data, - pub doc_biz: Data>, + pub document_core: Data>, } impl AppContext { @@ -22,14 +22,14 @@ impl AppContext { let pg_pool = Data::new(db_pool); let mut ws_bizs = WsBizHandlers::new(); - let doc_biz = Arc::new(DocBiz::new(pg_pool.clone())); - ws_bizs.register(WsModule::Doc, doc_biz.clone()); + let document_core = Arc::new(DocumentCore::new(pg_pool.clone())); + ws_bizs.register(WsModule::Doc, document_core.clone()); AppContext { ws_server, pg_pool, ws_bizs: Data::new(ws_bizs), - doc_biz: Data::new(doc_biz), + document_core: Data::new(document_core), } } } diff --git a/backend/src/services/doc/manager.rs b/backend/src/services/doc/manager.rs index f0de848da1..4b3159f9f9 100644 --- a/backend/src/services/doc/manager.rs +++ b/backend/src/services/doc/manager.rs @@ -18,30 +18,34 @@ use tokio::{ task::spawn_blocking, }; -pub struct DocBiz { +#[rustfmt::skip] +// ┌──────────────┐ ┌────────────┐ 1 n ┌───────────────┐ +// │ DocumentCore │────▶│ DocManager │─────▶│ OpenDocHandle │ +// └──────────────┘ └────────────┘ └───────────────┘ +pub struct DocumentCore { pub manager: Arc, - sender: mpsc::Sender, + ws_sender: mpsc::Sender, pg_pool: Data, } -impl DocBiz { +impl DocumentCore { pub fn new(pg_pool: Data) -> Self { let manager = Arc::new(DocManager::new()); - let (tx, rx) = mpsc::channel(100); + let (ws_sender, rx) = mpsc::channel(100); let actor = DocWsActor::new(rx, manager.clone()); tokio::task::spawn(actor.run()); Self { manager, - sender: tx, + ws_sender, pg_pool, } } } -impl WsBizHandler for DocBiz { +impl WsBizHandler for DocumentCore { fn receive_data(&self, client_data: WsClientData) { let (ret, rx) = oneshot::channel(); - let sender = self.sender.clone(); + let sender = self.ws_sender.clone(); let pool = self.pg_pool.clone(); actix_rt::spawn(async move { @@ -58,14 +62,25 @@ impl WsBizHandler for DocBiz { } } +#[rustfmt::skip] +// EditDocActor +// ┌────────────────────────────────────┐ +// │ ServerDocEditor │ +// │ ┌──────────────────────────────┐ │ +// ┌────────────┐ 1 n ┌───────────────┐ │ │ ┌──────────┐ ┌──────────┐ │ │ +// │ DocManager │─────▶│ OpenDocHandle │──────▶│ │ │ Document │ │ Users │ │ │ +// └────────────┘ └───────────────┘ │ │ └──────────┘ └──────────┘ │ │ +// │ └──────────────────────────────┘ │ +// │ │ +// └────────────────────────────────────┘ pub struct DocManager { - docs_map: DashMap>, + open_doc_map: DashMap>, } impl std::default::Default for DocManager { fn default() -> Self { Self { - docs_map: DashMap::new(), + open_doc_map: DashMap::new(), } } } @@ -73,19 +88,19 @@ impl std::default::Default for DocManager { impl DocManager { pub fn new() -> Self { DocManager::default() } - pub async fn get(&self, doc_id: &str, pg_pool: Data) -> Result>, ServerError> { - match self.docs_map.get(doc_id) { + pub async fn get(&self, doc_id: &str, pg_pool: Data) -> Result>, ServerError> { + match self.open_doc_map.get(doc_id) { None => { let params = DocIdentifier { doc_id: doc_id.to_string(), ..Default::default() }; let doc = read_doc(pg_pool.get_ref(), params).await?; - let handle = spawn_blocking(|| DocOpenHandle::new(doc, pg_pool)) + let handle = spawn_blocking(|| OpenDocHandle::new(doc, pg_pool)) .await .map_err(internal_error)?; let handle = Arc::new(handle?); - self.docs_map.insert(doc_id.to_string(), handle.clone()); + self.open_doc_map.insert(doc_id.to_string(), handle.clone()); Ok(Some(handle)) }, Some(ctx) => Ok(Some(ctx.clone())), @@ -93,11 +108,11 @@ impl DocManager { } } -pub struct DocOpenHandle { +pub struct OpenDocHandle { pub sender: mpsc::Sender, } -impl DocOpenHandle { +impl OpenDocHandle { pub fn new(doc: Doc, pg_pool: Data) -> Result { let (sender, receiver) = mpsc::channel(100); let actor = EditDocActor::new(receiver, doc, pg_pool)?; diff --git a/backend/src/services/doc/ws_actor.rs b/backend/src/services/doc/ws_actor.rs index 1a8fa60de0..b6542588d5 100644 --- a/backend/src/services/doc/ws_actor.rs +++ b/backend/src/services/doc/ws_actor.rs @@ -1,6 +1,6 @@ use crate::{ services::{ - doc::manager::{DocManager, DocOpenHandle}, + doc::manager::{DocManager, OpenDocHandle}, util::{md5, parse_from_bytes}, }, web_socket::{entities::Socket, WsClientData, WsUser}, @@ -122,7 +122,7 @@ impl DocWsActor { Ok(()) } - async fn find_doc_handle(&self, doc_id: &str, pool: Data) -> Option> { + async fn find_doc_handle(&self, doc_id: &str, pool: Data) -> Option> { match self.doc_manager.get(doc_id, pool).await { Ok(Some(edit_doc)) => Some(edit_doc), Ok(None) => { diff --git a/backend/src/services/view/router.rs b/backend/src/services/view/router.rs index ee67637973..c4a4ddd69d 100644 --- a/backend/src/services/view/router.rs +++ b/backend/src/services/view/router.rs @@ -1,5 +1,5 @@ use crate::services::{ - doc::manager::DocBiz, + doc::manager::DocumentCore, user::LoggedUser, util::parse_from_payload, view::{create_view, delete_view, read_view, sql_builder::check_view_ids, update_view}, @@ -23,7 +23,7 @@ use std::sync::Arc; pub async fn create_handler( payload: Payload, pool: Data, - _doc_biz: Data>, + _doc_biz: Data>, ) -> Result { let params: CreateViewParams = parse_from_payload(payload).await?; let mut transaction = pool diff --git a/frontend/rust-lib/flowy-document/src/services/cache.rs b/frontend/rust-lib/flowy-document/src/services/cache.rs deleted file mode 100644 index dae1fa7338..0000000000 --- a/frontend/rust-lib/flowy-document/src/services/cache.rs +++ /dev/null @@ -1,53 +0,0 @@ -use std::sync::Arc; - -use dashmap::DashMap; - -use crate::{ - errors::DocError, - services::doc::edit::{ClientDocEditor, DocId}, -}; - -pub(crate) struct DocCache { - inner: DashMap>, -} - -impl DocCache { - pub(crate) fn new() -> Self { Self { inner: DashMap::new() } } - - #[allow(dead_code)] - pub(crate) fn all_docs(&self) -> Vec> { - self.inner - .iter() - .map(|kv| kv.value().clone()) - .collect::>>() - } - - pub(crate) fn set(&self, doc: Arc) { - let doc_id = doc.doc_id.clone(); - if self.inner.contains_key(&doc_id) { - log::warn!("Doc:{} already exists in cache", &doc_id); - } - self.inner.insert(doc_id, doc); - } - - 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, DocError> { - if !self.contains(&doc_id) { - return Err(doc_not_found()); - } - let opened_doc = self.inner.get(doc_id).unwrap(); - Ok(opened_doc.clone()) - } - - pub(crate) fn remove(&self, id: &str) { - let doc_id: DocId = id.into(); - match self.get(id) { - Ok(editor) => editor.stop_sync(), - Err(e) => log::error!("{}", e), - } - self.inner.remove(&doc_id); - } -} - -fn doc_not_found() -> DocError { DocError::doc_not_found().context("Doc is close or you should call open first") } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/controller.rs b/frontend/rust-lib/flowy-document/src/services/doc/controller.rs index fabc15668b..2a1fd5db46 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/controller.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/controller.rs @@ -2,7 +2,6 @@ use crate::{ errors::{DocError, DocResult}, module::DocumentUser, services::{ - cache::DocCache, doc::{ edit::{ClientDocEditor, EditDocWsHandler}, revision::{RevisionCache, RevisionManager, RevisionServer}, @@ -12,6 +11,7 @@ use crate::{ }, }; use bytes::Bytes; +use dashmap::DashMap; use flowy_database::ConnectionPool; use flowy_document_infra::entities::doc::{Doc, DocDelta, DocIdentifier}; use lib_infra::future::{wrap_future, FnFuture, ResultFuture}; @@ -21,18 +21,18 @@ use tokio::time::{interval, Duration}; pub(crate) struct DocController { server: Server, ws_manager: Arc, - cache: Arc, + open_cache: Arc, user: Arc, } impl DocController { pub(crate) fn new(server: Server, user: Arc, ws: Arc) -> Self { - let cache = Arc::new(DocCache::new()); + let open_cache = Arc::new(OpenDocCache::new()); Self { server, user, ws_manager: ws, - cache, + open_cache, } } @@ -46,18 +46,18 @@ impl DocController { params: DocIdentifier, pool: Arc, ) -> Result, DocError> { - if !self.cache.contains(¶ms.doc_id) { + 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); } - let edit_doc_ctx = self.cache.get(¶ms.doc_id)?; + let edit_doc_ctx = self.open_cache.get(¶ms.doc_id)?; Ok(edit_doc_ctx) } pub(crate) fn close(&self, doc_id: &str) -> Result<(), DocError> { log::debug!("Close doc {}", doc_id); - self.cache.remove(doc_id); + self.open_cache.remove(doc_id); self.ws_manager.remove_handler(doc_id); Ok(()) } @@ -65,7 +65,7 @@ impl DocController { #[tracing::instrument(level = "debug", skip(self), err)] pub(crate) fn delete(&self, params: DocIdentifier) -> Result<(), DocError> { let doc_id = ¶ms.doc_id; - self.cache.remove(doc_id); + self.open_cache.remove(doc_id); self.ws_manager.remove_handler(doc_id); Ok(()) } @@ -80,12 +80,12 @@ impl DocController { delta: DocDelta, db_pool: Arc, ) -> Result { - if !self.cache.contains(&delta.doc_id) { + 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?; } - let edit_doc_ctx = self.cache.get(&delta.doc_id)?; + let edit_doc_ctx = self.open_cache.get(&delta.doc_id)?; let _ = edit_doc_ctx.composing_local_delta(Bytes::from(delta.data)).await?; Ok(edit_doc_ctx.delta().await?) } @@ -102,7 +102,7 @@ impl DocController { let edit_ctx = ClientDocEditor::new(doc_id, user, pool, rev_manager, self.ws_manager.ws()).await?; let ws_handler = Arc::new(EditDocWsHandler(edit_ctx.clone())); self.ws_manager.register_handler(doc_id, ws_handler); - self.cache.set(edit_ctx.clone()); + self.open_cache.set(edit_ctx.clone()); Ok(edit_ctx) } @@ -145,13 +145,39 @@ impl RevisionServer for RevisionServerImpl { } } -#[allow(dead_code)] -fn event_loop(_cache: Arc) -> FnFuture<()> { - let mut i = interval(Duration::from_secs(3)); - wrap_future(async move { - loop { - // cache.all_docs().iter().for_each(|doc| doc.tick()); - i.tick().await; - } - }) +pub struct OpenDocCache { + inner: DashMap>, } + +impl OpenDocCache { + fn new() -> Self { Self { inner: DashMap::new() } } + + pub(crate) fn set(&self, doc: Arc) { + let doc_id = doc.doc_id.clone(); + if self.inner.contains_key(&doc_id) { + log::warn!("Doc:{} already exists in cache", &doc_id); + } + self.inner.insert(doc_id, doc); + } + + 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, DocError> { + if !self.contains(&doc_id) { + return Err(doc_not_found()); + } + let opened_doc = self.inner.get(doc_id).unwrap(); + Ok(opened_doc.clone()) + } + + pub(crate) fn remove(&self, id: &str) { + let doc_id = id.to_string(); + match self.get(id) { + Ok(editor) => editor.stop_sync(), + Err(e) => log::error!("{}", e), + } + self.inner.remove(&doc_id); + } +} + +fn doc_not_found() -> DocError { DocError::doc_not_found().context("Doc is close or you should call open first") } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs index 01a2927d26..ed65d9ccf5 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs @@ -129,6 +129,7 @@ impl EditCommandQueue { } pub(crate) type Ret = oneshot::Sender>; +#[allow(dead_code)] pub(crate) enum EditCommand { ComposeDelta { delta: RichTextDelta, diff --git a/frontend/rust-lib/flowy-document/src/services/mod.rs b/frontend/rust-lib/flowy-document/src/services/mod.rs index c26732203a..a9a801a0b8 100644 --- a/frontend/rust-lib/flowy-document/src/services/mod.rs +++ b/frontend/rust-lib/flowy-document/src/services/mod.rs @@ -1,4 +1,3 @@ -mod cache; pub mod doc; pub mod server; pub mod ws; diff --git a/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs b/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs index 81c23b3f86..d565e2a109 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs @@ -1,3 +1,4 @@ +use flowy_document_infra::core::{Document, FlowyDoc}; use flowy_test::editor::{EditorScript::*, *}; use lib_ot::{revision::RevState, rich_text::RichTextDeltaBuilder}; @@ -50,3 +51,16 @@ async fn doc_push_test() { ]; EditorTest::new().await.run_scripts(scripts).await; } + +#[tokio::test] +async fn doc_push_test2() { + let mut document = Document::new::(); + let delta_1 = document.insert(0, "123").unwrap(); + let json = document.to_json(); + + let scripts = vec![ + SimulatePushRevisionMessageWithDelta(delta_1), + AssertJson(r#"[{"insert":"\n123"}]"#), + ]; + EditorTest::new().await.run_scripts(scripts).await; +} diff --git a/frontend/rust-lib/flowy-test/src/editor.rs b/frontend/rust-lib/flowy-test/src/editor.rs index 3dd4b6de5d..7953577b89 100644 --- a/frontend/rust-lib/flowy-test/src/editor.rs +++ b/frontend/rust-lib/flowy-test/src/editor.rs @@ -47,7 +47,7 @@ impl EditorTest { self.run_script(script).await; } - sleep(Duration::from_secs(5)).await; + sleep(Duration::from_secs(10)).await; } async fn run_script(&mut self, script: EditorScript) { From aeb448c4de65bf12b9bc6635993d17481a2f641d Mon Sep 17 00:00:00 2001 From: appflowy Date: Fri, 10 Dec 2021 22:18:44 +0800 Subject: [PATCH 16/39] mock websocket --- backend/Cargo.lock | 1 + backend/tests/document/helper.rs | 2 +- .../src/services/doc/controller.rs | 3 +- .../src/services/doc/revision/manager.rs | 1 - .../src/services/ws/ws_manager.rs | 2 +- .../tests/editor/revision_test.rs | 14 -- .../src/deps_resolve/document_deps.rs | 24 ++- frontend/rust-lib/flowy-user/Cargo.toml | 1 + .../src/services/user/user_session.rs | 17 +- .../src/services/user/ws_manager.rs | 164 ++++++++++++++++-- shared-lib/lib-ws/src/ws.rs | 2 +- 11 files changed, 175 insertions(+), 56 deletions(-) diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 912210f77b..e41d5e680b 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -1366,6 +1366,7 @@ dependencies = [ "backend-service", "bytes", "dart-notify", + "dashmap", "derive_more", "diesel", "diesel_derives", diff --git a/backend/tests/document/helper.rs b/backend/tests/document/helper.rs index 3dcfd74edf..b153ea6571 100644 --- a/backend/tests/document/helper.rs +++ b/backend/tests/document/helper.rs @@ -66,7 +66,7 @@ impl ScriptContext { client_edit_context: None, client_sdk, client_user_session: user_session, - server_doc_manager: server.app_ctx.doc_biz.manager.clone(), + server_doc_manager: server.app_ctx.document_core.manager.clone(), server_pg_pool: Data::new(server.pg_pool.clone()), doc_id, } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/controller.rs b/frontend/rust-lib/flowy-document/src/services/doc/controller.rs index 2a1fd5db46..9996054fe3 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/controller.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/controller.rs @@ -14,9 +14,8 @@ use bytes::Bytes; use dashmap::DashMap; use flowy_database::ConnectionPool; use flowy_document_infra::entities::doc::{Doc, DocDelta, DocIdentifier}; -use lib_infra::future::{wrap_future, FnFuture, ResultFuture}; +use lib_infra::future::ResultFuture; use std::sync::Arc; -use tokio::time::{interval, Duration}; pub(crate) struct DocController { server: Server, diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs index 30f372be28..20d10ef639 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs @@ -46,7 +46,6 @@ impl RevisionManager { pub async fn add_revision(&self, revision: &Revision) -> Result<(), DocError> { let _ = self.cache.add_revision(revision.clone()).await?; - Ok(()) } diff --git a/frontend/rust-lib/flowy-document/src/services/ws/ws_manager.rs b/frontend/rust-lib/flowy-document/src/services/ws/ws_manager.rs index 414bd3045a..f5678e6934 100644 --- a/frontend/rust-lib/flowy-document/src/services/ws/ws_manager.rs +++ b/frontend/rust-lib/flowy-document/src/services/ws/ws_manager.rs @@ -39,7 +39,7 @@ impl WsDocumentManager { pub(crate) fn remove_handler(&self, id: &str) { self.handlers.remove(id); } - pub fn handle_ws_data(&self, data: Bytes) { + pub fn did_receive_ws_data(&self, data: Bytes) { let data: WsDocumentData = data.try_into().unwrap(); match self.handlers.get(&data.doc_id) { None => { diff --git a/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs b/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs index d565e2a109..81c23b3f86 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs @@ -1,4 +1,3 @@ -use flowy_document_infra::core::{Document, FlowyDoc}; use flowy_test::editor::{EditorScript::*, *}; use lib_ot::{revision::RevState, rich_text::RichTextDeltaBuilder}; @@ -51,16 +50,3 @@ async fn doc_push_test() { ]; EditorTest::new().await.run_scripts(scripts).await; } - -#[tokio::test] -async fn doc_push_test2() { - let mut document = Document::new::(); - let delta_1 = document.insert(0, "123").unwrap(); - let json = document.to_json(); - - let scripts = vec![ - SimulatePushRevisionMessageWithDelta(delta_1), - AssertJson(r#"[{"insert":"\n123"}]"#), - ]; - EditorTest::new().await.run_scripts(scripts).await; -} diff --git a/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs b/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs index 9eeca54c99..90bbbe64a0 100644 --- a/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs +++ b/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs @@ -29,7 +29,7 @@ impl DocumentDepsResolver { user: self.user_session.clone(), }); let ws_manager = Arc::new(WsDocumentManager::new(sender)); - let ws_handler = Arc::new(WsDocumentReceiver { + let ws_handler = Arc::new(DocumentWsMessageReceiver { inner: ws_manager.clone(), }); self.user_session.add_ws_handler(ws_handler); @@ -74,15 +74,13 @@ struct WsSenderImpl { impl DocumentWebSocket for WsSenderImpl { fn send(&self, data: WsDocumentData) -> Result<(), DocError> { - if cfg!(feature = "http_server") { - let bytes: Bytes = data.try_into().unwrap(); - let msg = WsMessage { - module: WsModule::Doc, - data: bytes.to_vec(), - }; - let sender = self.user.ws_sender().map_err(internal_error)?; - sender.send_msg(msg).map_err(internal_error)?; - } + let bytes: Bytes = data.try_into().unwrap(); + let msg = WsMessage { + module: WsModule::Doc, + data: bytes.to_vec(), + }; + let sender = self.user.ws_sender().map_err(internal_error)?; + sender.send(msg).map_err(internal_error)?; Ok(()) } @@ -90,15 +88,15 @@ impl DocumentWebSocket for WsSenderImpl { fn state_notify(&self) -> WsStateReceiver { self.user.ws_state_notifier() } } -struct WsDocumentReceiver { +struct DocumentWsMessageReceiver { inner: Arc, } -impl WsMessageHandler for WsDocumentReceiver { +impl WsMessageHandler for DocumentWsMessageReceiver { fn source(&self) -> WsModule { WsModule::Doc } fn receive_message(&self, msg: WsMessage) { let data = Bytes::from(msg.data); - self.inner.handle_ws_data(data); + self.inner.did_receive_ws_data(data); } } diff --git a/frontend/rust-lib/flowy-user/Cargo.toml b/frontend/rust-lib/flowy-user/Cargo.toml index ae70823d25..4a907f98b1 100644 --- a/frontend/rust-lib/flowy-user/Cargo.toml +++ b/frontend/rust-lib/flowy-user/Cargo.toml @@ -37,6 +37,7 @@ tokio = { version = "1", features = ["rt"] } pin-project = "1.0.0" futures-core = { version = "0.3", default-features = false } r2d2 = "0.8.9" +dashmap = "4.0" [dev-dependencies] flowy-test = { path = "../flowy-test" } diff --git a/frontend/rust-lib/flowy-user/src/services/user/user_session.rs b/frontend/rust-lib/flowy-user/src/services/user/user_session.rs index 32bbba4a25..010e462801 100644 --- a/frontend/rust-lib/flowy-user/src/services/user/user_session.rs +++ b/frontend/rust-lib/flowy-user/src/services/user/user_session.rs @@ -9,7 +9,10 @@ use crate::{ notify::*, services::{ server::{construct_user_server, Server}, - user::{notifier::UserNotifier, ws_manager::WsManager}, + user::{ + notifier::UserNotifier, + ws_manager::{FlowyWsSender, WsManager}, + }, }, }; use backend_service::configuration::ClientServerConfiguration; @@ -23,7 +26,7 @@ use flowy_database::{ use flowy_user_infra::entities::{SignInResponse, SignUpResponse}; use lib_infra::{entities::network_state::NetworkState, kv::KV}; use lib_sqlite::ConnectionPool; -use lib_ws::{WsConnectState, WsMessageHandler, WsSender}; +use lib_ws::{WsConnectState, WsMessageHandler}; use parking_lot::RwLock; use serde::{Deserialize, Serialize}; use std::sync::Arc; @@ -196,8 +199,8 @@ impl UserSession { self.notifier.update_network_type(&new_state.ty); } - pub fn ws_sender(&self) -> Result, UserError> { - let sender = self.ws_manager.sender()?; + pub fn ws_sender(&self) -> Result, UserError> { + let sender = self.ws_manager.ws_sender()?; Ok(sender) } @@ -301,10 +304,8 @@ impl UserSession { #[tracing::instrument(level = "debug", skip(self, token))] pub async fn start_ws_connection(&self, token: &str) -> Result<(), UserError> { - if cfg!(feature = "http_server") { - let addr = format!("{}/{}", self.server.ws_addr(), token); - let _ = self.ws_manager.start(addr).await?; - } + let addr = format!("{}/{}", self.server.ws_addr(), token); + let _ = self.ws_manager.start(addr).await?; Ok(()) } } diff --git a/frontend/rust-lib/flowy-user/src/services/user/ws_manager.rs b/frontend/rust-lib/flowy-user/src/services/user/ws_manager.rs index 8f3cd6e2b6..3b82e6a96d 100644 --- a/frontend/rust-lib/flowy-user/src/services/user/ws_manager.rs +++ b/frontend/rust-lib/flowy-user/src/services/user/ws_manager.rs @@ -1,12 +1,25 @@ use crate::errors::UserError; -use lib_infra::entities::network_state::NetworkType; -use lib_ws::{WsConnectState, WsController}; + +use lib_infra::{entities::network_state::NetworkType, future::ResultFuture}; +use lib_ws::{WsConnectState, WsController, WsMessage, WsMessageHandler, WsSender}; use parking_lot::RwLock; use std::sync::Arc; -use tokio::sync::broadcast; +use tokio::sync::{broadcast, broadcast::Receiver}; + +pub trait FlowyWebSocket: Send + Sync { + fn start_connect(&self, addr: String) -> ResultFuture<(), UserError>; + fn conn_state_subscribe(&self) -> broadcast::Receiver; + fn reconnect(&self, count: usize) -> ResultFuture<(), UserError>; + fn add_handler(&self, handler: Arc) -> Result<(), UserError>; + fn ws_sender(&self) -> Result, UserError>; +} + +pub trait FlowyWsSender: Send + Sync { + fn send(&self, msg: WsMessage) -> Result<(), UserError>; +} pub struct WsManager { - inner: Arc, + inner: Arc, connect_type: RwLock, } @@ -38,12 +51,10 @@ impl WsManager { } } - pub fn state_subscribe(&self) -> broadcast::Receiver { self.inner.state_subscribe() } - #[tracing::instrument(level = "debug", skip(self))] fn listen_on_websocket(&self) { - let mut notify = self.inner.state_subscribe(); - let ws_controller = self.inner.clone(); + let mut notify = self.inner.conn_state_subscribe(); + let ws = self.inner.clone(); let _ = tokio::spawn(async move { loop { match notify.recv().await { @@ -53,7 +64,7 @@ impl WsManager { WsConnectState::Init => {}, WsConnectState::Connected => {}, WsConnectState::Connecting => {}, - WsConnectState::Disconnected => retry_connect(ws_controller.clone(), 100).await, + WsConnectState::Disconnected => retry_connect(ws.clone(), 100).await, } }, Err(e) => { @@ -64,10 +75,22 @@ impl WsManager { } }); } + + pub fn state_subscribe(&self) -> broadcast::Receiver { self.inner.conn_state_subscribe() } + + pub fn add_handler(&self, handler: Arc) -> Result<(), UserError> { + let _ = self.inner.add_handler(handler)?; + Ok(()) + } + + pub fn ws_sender(&self) -> Result, UserError> { + // + self.inner.ws_sender() + } } -async fn retry_connect(ws_controller: Arc, count: usize) { - match ws_controller.retry(count).await { +async fn retry_connect(ws: Arc, count: usize) { + match ws.reconnect(count).await { Ok(_) => {}, Err(e) => { log::error!("websocket connect failed: {:?}", e); @@ -77,15 +100,126 @@ async fn retry_connect(ws_controller: Arc, count: usize) { impl std::default::Default for WsManager { fn default() -> Self { + let ws: Arc = if cfg!(feature = "http_server") { + Arc::new(Arc::new(WsController::new())) + } else { + mock::MockWebSocket::new() + }; + WsManager { - inner: Arc::new(WsController::new()), + inner: ws, connect_type: RwLock::new(NetworkType::default()), } } } -impl std::ops::Deref for WsManager { - type Target = WsController; +impl FlowyWebSocket for Arc { + fn start_connect(&self, addr: String) -> ResultFuture<(), UserError> { + let cloned_ws = self.clone(); + ResultFuture::new(async move { + let _ = cloned_ws.start(addr).await?; + Ok(()) + }) + } - fn deref(&self) -> &Self::Target { &self.inner } + fn conn_state_subscribe(&self) -> Receiver { self.state_subscribe() } + + fn reconnect(&self, count: usize) -> ResultFuture<(), UserError> { + let cloned_ws = self.clone(); + ResultFuture::new(async move { + let _ = cloned_ws.retry(count).await?; + Ok(()) + }) + } + + fn add_handler(&self, handler: Arc) -> Result<(), UserError> { + let _ = self.add_handler(handler)?; + Ok(()) + } + + fn ws_sender(&self) -> Result, UserError> { + let sender = self.sender()?; + Ok(sender) + } +} + +impl FlowyWsSender for WsSender { + fn send(&self, msg: WsMessage) -> Result<(), UserError> { + let _ = self.send_msg(msg)?; + Ok(()) + } +} + +// #[cfg(not(feature = "http_server"))] +mod mock { + use crate::{ + errors::UserError, + services::user::ws_manager::{FlowyWebSocket, FlowyWsSender}, + }; + use dashmap::DashMap; + use lib_infra::future::ResultFuture; + use lib_ws::{WsConnectState, WsMessage, WsMessageHandler, WsModule}; + use std::sync::Arc; + use tokio::sync::{broadcast, broadcast::Receiver}; + + pub struct MockWebSocket { + handlers: DashMap>, + state_sender: broadcast::Sender, + ws_sender: broadcast::Sender, + } + + impl std::default::Default for MockWebSocket { + fn default() -> Self { + let (state_sender, _) = broadcast::channel(16); + let (ws_sender, _) = broadcast::channel(16); + MockWebSocket { + handlers: DashMap::new(), + state_sender, + ws_sender, + } + } + } + + impl MockWebSocket { + pub fn new() -> Arc { + let ws = Arc::new(MockWebSocket::default()); + let mut ws_receiver = ws.ws_sender.subscribe(); + let cloned_ws = ws.clone(); + tokio::spawn(async move { + while let Ok(message) = ws_receiver.recv().await { + match cloned_ws.handlers.get(&message.module) { + None => log::error!("Can't find any handler for message: {:?}", message), + Some(handler) => handler.receive_message(message.clone()), + } + } + }); + ws + } + } + + impl FlowyWebSocket for MockWebSocket { + fn start_connect(&self, _addr: String) -> ResultFuture<(), UserError> { ResultFuture::new(async { Ok(()) }) } + + fn conn_state_subscribe(&self) -> Receiver { self.state_sender.subscribe() } + + fn reconnect(&self, _count: usize) -> ResultFuture<(), UserError> { ResultFuture::new(async { Ok(()) }) } + + fn add_handler(&self, handler: Arc) -> Result<(), UserError> { + let source = handler.source(); + if self.handlers.contains_key(&source) { + log::error!("WsSource's {:?} is already registered", source); + } + self.handlers.insert(source, handler); + Ok(()) + } + + fn ws_sender(&self) -> Result, UserError> { Ok(Arc::new(self.ws_sender.clone())) } + } + + impl FlowyWsSender for broadcast::Sender { + fn send(&self, _msg: WsMessage) -> Result<(), UserError> { + // let _ = self.send(msg).unwrap(); + Ok(()) + } + } } diff --git a/shared-lib/lib-ws/src/ws.rs b/shared-lib/lib-ws/src/ws.rs index a67c101956..8b1459ba1c 100644 --- a/shared-lib/lib-ws/src/ws.rs +++ b/shared-lib/lib-ws/src/ws.rs @@ -68,7 +68,7 @@ impl WsController { Ok(()) } - pub async fn start_connect(&self, addr: String) -> Result<(), ServerError> { + pub async fn start(&self, addr: String) -> Result<(), ServerError> { *self.addr.write() = Some(addr.clone()); let strategy = FixedInterval::from_millis(5000).take(3); From 69ee8aff55861fc24dfb781d40b66adde8d86f3f Mon Sep 17 00:00:00 2001 From: appflowy Date: Fri, 10 Dec 2021 22:48:30 +0800 Subject: [PATCH 17/39] rename flowy-workspace-infra --- backend/Cargo.lock | 40 +++++++++---------- backend/Cargo.toml | 2 +- backend/src/entities/workspace.rs | 2 +- backend/src/services/app/app.rs | 2 +- backend/src/services/app/router.rs | 4 +- backend/src/services/app/sql_builder.rs | 2 +- backend/src/services/trash/router.rs | 2 +- backend/src/services/trash/trash.rs | 2 +- backend/src/services/user/user_default.rs | 4 +- backend/src/services/view/router.rs | 2 +- backend/src/services/view/sql_builder.rs | 2 +- backend/src/services/view/view.rs | 4 +- backend/src/services/workspace/router.rs | 2 +- backend/src/services/workspace/sql_builder.rs | 2 +- backend/src/services/workspace/workspace.rs | 2 +- backend/tests/api/doc.rs | 2 +- backend/tests/api/workspace.rs | 2 +- backend/tests/util/helper.rs | 2 +- .../app_flowy/lib/user/domain/i_auth.dart | 2 +- .../app_flowy/lib/user/domain/i_splash.dart | 2 +- .../lib/user/infrastructure/i_auth_impl.dart | 2 +- .../user/infrastructure/i_splash_impl.dart | 2 +- .../user/presentation/skip_log_in_screen.dart | 2 +- .../lib/user/presentation/splash_screen.dart | 2 +- .../lib/user/presentation/welcome_screen.dart | 2 +- .../workspace/application/app/app_bloc.dart | 4 +- .../workspace/application/doc/doc_bloc.dart | 4 +- .../workspace/application/doc/share_bloc.dart | 4 +- .../application/home/home_listen_bloc.dart | 2 +- .../workspace/application/menu/menu_bloc.dart | 2 +- .../application/menu/menu_user_bloc.dart | 2 +- .../application/trash/trash_bloc.dart | 2 +- .../workspace/application/view/view_bloc.dart | 2 +- .../application/workspace/welcome_bloc.dart | 2 +- .../app_flowy/lib/workspace/domain/i_app.dart | 6 +-- .../lib/workspace/domain/i_share.dart | 2 +- .../lib/workspace/domain/i_trash.dart | 2 +- .../lib/workspace/domain/i_user.dart | 2 +- .../lib/workspace/domain/i_view.dart | 2 +- .../lib/workspace/domain/i_workspace.dart | 2 +- .../app_flowy/lib/workspace/domain/image.dart | 2 +- .../lib/workspace/domain/view_ext.dart | 2 +- .../infrastructure/deps_resolver.dart | 4 +- .../workspace/infrastructure/i_app_impl.dart | 2 +- .../infrastructure/i_share_impl.dart | 2 +- .../infrastructure/i_trash_impl.dart | 2 +- .../workspace/infrastructure/i_user_impl.dart | 2 +- .../workspace/infrastructure/i_view_impl.dart | 2 +- .../infrastructure/i_workspace_impl.dart | 2 +- .../infrastructure/repos/app_repo.dart | 10 ++--- .../infrastructure/repos/doc_repo.dart | 2 +- .../infrastructure/repos/share_repo.dart | 2 +- .../infrastructure/repos/trash_repo.dart | 2 +- .../infrastructure/repos/user_repo.dart | 4 +- .../infrastructure/repos/view_repo.dart | 6 +-- .../infrastructure/repos/workspace_repo.dart | 6 +-- .../presentation/home/home_screen.dart | 2 +- .../presentation/stack_page/doc/doc_page.dart | 2 +- .../stack_page/doc/doc_stack_page.dart | 4 +- .../stack_page/trash/widget/trash_cell.dart | 2 +- .../presentation/widgets/home_top_bar.dart | 4 +- .../presentation/widgets/menu/menu.dart | 4 +- .../menu/widget/app/header/add_button.dart | 2 +- .../menu/widget/app/header/header.dart | 2 +- .../widgets/menu/widget/app/menu_app.dart | 4 +- .../widgets/menu/widget/app/section/item.dart | 2 +- .../menu/widget/app/section/section.dart | 4 +- .../Flutter/GeneratedPluginRegistrant.swift | 2 + .../packages/flowy_sdk/example/pubspec.lock | 8 ++-- .../flowy_sdk/lib/dispatch/dispatch.dart | 3 +- .../app_create.pb.dart | 0 .../app_create.pbenum.dart | 0 .../app_create.pbjson.dart | 0 .../app_create.pbserver.dart | 0 .../app_query.pb.dart | 0 .../app_query.pbenum.dart | 0 .../app_query.pbjson.dart | 0 .../app_query.pbserver.dart | 0 .../app_update.pb.dart | 0 .../app_update.pbenum.dart | 0 .../app_update.pbjson.dart | 0 .../app_update.pbserver.dart | 0 .../errors.pb.dart | 0 .../errors.pbenum.dart | 0 .../errors.pbjson.dart | 0 .../errors.pbserver.dart | 0 .../export.pb.dart | 0 .../export.pbenum.dart | 0 .../export.pbjson.dart | 0 .../export.pbserver.dart | 0 .../protobuf.dart | 0 .../trash_create.pb.dart | 0 .../trash_create.pbenum.dart | 0 .../trash_create.pbjson.dart | 0 .../trash_create.pbserver.dart | 0 .../view_create.pb.dart | 0 .../view_create.pbenum.dart | 0 .../view_create.pbjson.dart | 0 .../view_create.pbserver.dart | 0 .../view_query.pb.dart | 0 .../view_query.pbenum.dart | 0 .../view_query.pbjson.dart | 0 .../view_query.pbserver.dart | 0 .../view_update.pb.dart | 0 .../view_update.pbenum.dart | 0 .../view_update.pbjson.dart | 0 .../view_update.pbserver.dart | 0 .../workspace_create.pb.dart | 0 .../workspace_create.pbenum.dart | 0 .../workspace_create.pbjson.dart | 0 .../workspace_create.pbserver.dart | 0 .../workspace_query.pb.dart | 0 .../workspace_query.pbenum.dart | 0 .../workspace_query.pbjson.dart | 0 .../workspace_query.pbserver.dart | 0 .../workspace_setting.pb.dart | 0 .../workspace_setting.pbenum.dart | 0 .../workspace_setting.pbjson.dart | 0 .../workspace_setting.pbserver.dart | 0 .../workspace_update.pb.dart | 0 .../workspace_update.pbenum.dart | 0 .../workspace_update.pbjson.dart | 0 .../workspace_update.pbserver.dart | 0 .../app_flowy/packages/flowy_sdk/pubspec.lock | 4 +- frontend/app_flowy/pubspec.lock | 2 +- frontend/rust-lib/flowy-core/Cargo.toml | 2 +- .../core/aggregate_tasks/workspace_task.rs | 2 +- .../flowy-core/src/core/core_context.rs | 2 +- .../flowy-core/src/core/event_handler.rs | 2 +- frontend/rust-lib/flowy-core/src/errors.rs | 2 +- frontend/rust-lib/flowy-core/src/lib.rs | 4 +- .../src/services/server/server_api.rs | 2 +- .../src/services/view/controller.rs | 2 +- .../src/services/view/event_handler.rs | 2 +- .../src/services/workspace/controller.rs | 2 +- .../src/services/workspace/event_handler.rs | 2 +- shared-lib/Cargo.lock | 36 ++++++++--------- shared-lib/Cargo.toml | 2 +- shared-lib/backend-service/Cargo.toml | 2 +- .../backend-service/src/workspace_request.rs | 2 +- .../Cargo.toml | 2 +- .../Flowy.toml | 0 .../src/entities/app/app_create.rs | 0 .../src/entities/app/app_query.rs | 0 .../src/entities/app/app_update.rs | 0 .../src/entities/app/mod.rs | 0 .../src/entities/mod.rs | 0 .../src/entities/share/export.rs | 0 .../src/entities/share/mod.rs | 0 .../src/entities/trash/mod.rs | 0 .../src/entities/trash/trash_create.rs | 0 .../src/entities/view/mod.rs | 0 .../src/entities/view/view_create.rs | 0 .../src/entities/view/view_query.rs | 0 .../src/entities/view/view_update.rs | 0 .../src/entities/workspace/mod.rs | 0 .../entities/workspace/workspace_create.rs | 0 .../src/entities/workspace/workspace_query.rs | 0 .../entities/workspace/workspace_setting.rs | 0 .../entities/workspace/workspace_update.rs | 0 .../src/errors.rs | 0 .../src/lib.rs | 0 .../src/macros.rs | 0 .../src/parser/app/app_color_style.rs | 0 .../src/parser/app/app_desc.rs | 0 .../src/parser/app/app_id.rs | 0 .../src/parser/app/app_name.rs | 0 .../src/parser/app/mod.rs | 0 .../src/parser/mod.rs | 0 .../src/parser/trash/mod.rs | 0 .../src/parser/trash/trash_id.rs | 0 .../src/parser/view/delta_data.rs | 0 .../src/parser/view/mod.rs | 0 .../src/parser/view/view_desc.rs | 0 .../src/parser/view/view_id.rs | 0 .../src/parser/view/view_name.rs | 0 .../src/parser/view/view_thumbnail.rs | 0 .../src/parser/workspace/mod.rs | 0 .../src/parser/workspace/workspace_desc.rs | 0 .../src/parser/workspace/workspace_id.rs | 0 .../src/parser/workspace/workspace_name.rs | 0 .../src/protobuf/mod.rs | 0 .../src/protobuf/model/app_create.rs | 0 .../src/protobuf/model/app_query.rs | 0 .../src/protobuf/model/app_update.rs | 0 .../src/protobuf/model/errors.rs | 0 .../src/protobuf/model/export.rs | 0 .../src/protobuf/model/mod.rs | 0 .../src/protobuf/model/trash_create.rs | 0 .../src/protobuf/model/view_create.rs | 0 .../src/protobuf/model/view_query.rs | 0 .../src/protobuf/model/view_update.rs | 0 .../src/protobuf/model/workspace_create.rs | 0 .../src/protobuf/model/workspace_query.rs | 0 .../src/protobuf/model/workspace_setting.rs | 0 .../src/protobuf/model/workspace_update.rs | 0 .../src/protobuf/proto/app_create.proto | 0 .../src/protobuf/proto/app_query.proto | 0 .../src/protobuf/proto/app_update.proto | 0 .../src/protobuf/proto/errors.proto | 0 .../src/protobuf/proto/export.proto | 0 .../src/protobuf/proto/trash_create.proto | 0 .../src/protobuf/proto/view_create.proto | 0 .../src/protobuf/proto/view_query.proto | 0 .../src/protobuf/proto/view_update.proto | 0 .../src/protobuf/proto/workspace_create.proto | 0 .../src/protobuf/proto/workspace_query.proto | 0 .../protobuf/proto/workspace_setting.proto | 0 .../src/protobuf/proto/workspace_update.proto | 0 .../src/user_default.rs | 0 .../src/derive_cache/derive_cache.rs | 16 ++++---- 211 files changed, 161 insertions(+), 160 deletions(-) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/app_create.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/app_create.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/app_create.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/app_create.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/app_query.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/app_query.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/app_query.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/app_query.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/app_update.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/app_update.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/app_update.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/app_update.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/errors.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/errors.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/errors.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/errors.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/export.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/export.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/export.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/export.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/protobuf.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/trash_create.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/trash_create.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/trash_create.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/trash_create.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/view_create.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/view_create.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/view_create.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/view_create.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/view_query.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/view_query.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/view_query.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/view_query.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/view_update.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/view_update.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/view_update.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/view_update.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/workspace_create.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/workspace_create.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/workspace_create.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/workspace_create.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/workspace_query.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/workspace_query.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/workspace_query.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/workspace_query.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/workspace_setting.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/workspace_setting.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/workspace_setting.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/workspace_setting.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/workspace_update.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/workspace_update.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/workspace_update.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-workspace-infra => flowy-core-infra}/workspace_update.pbserver.dart (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/Cargo.toml (94%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/Flowy.toml (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/entities/app/app_create.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/entities/app/app_query.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/entities/app/app_update.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/entities/app/mod.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/entities/mod.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/entities/share/export.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/entities/share/mod.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/entities/trash/mod.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/entities/trash/trash_create.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/entities/view/mod.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/entities/view/view_create.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/entities/view/view_query.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/entities/view/view_update.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/entities/workspace/mod.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/entities/workspace/workspace_create.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/entities/workspace/workspace_query.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/entities/workspace/workspace_setting.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/entities/workspace/workspace_update.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/errors.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/lib.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/macros.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/parser/app/app_color_style.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/parser/app/app_desc.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/parser/app/app_id.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/parser/app/app_name.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/parser/app/mod.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/parser/mod.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/parser/trash/mod.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/parser/trash/trash_id.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/parser/view/delta_data.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/parser/view/mod.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/parser/view/view_desc.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/parser/view/view_id.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/parser/view/view_name.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/parser/view/view_thumbnail.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/parser/workspace/mod.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/parser/workspace/workspace_desc.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/parser/workspace/workspace_id.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/parser/workspace/workspace_name.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/protobuf/mod.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/protobuf/model/app_create.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/protobuf/model/app_query.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/protobuf/model/app_update.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/protobuf/model/errors.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/protobuf/model/export.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/protobuf/model/mod.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/protobuf/model/trash_create.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/protobuf/model/view_create.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/protobuf/model/view_query.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/protobuf/model/view_update.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/protobuf/model/workspace_create.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/protobuf/model/workspace_query.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/protobuf/model/workspace_setting.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/protobuf/model/workspace_update.rs (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/protobuf/proto/app_create.proto (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/protobuf/proto/app_query.proto (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/protobuf/proto/app_update.proto (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/protobuf/proto/errors.proto (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/protobuf/proto/export.proto (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/protobuf/proto/trash_create.proto (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/protobuf/proto/view_create.proto (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/protobuf/proto/view_query.proto (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/protobuf/proto/view_update.proto (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/protobuf/proto/workspace_create.proto (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/protobuf/proto/workspace_query.proto (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/protobuf/proto/workspace_setting.proto (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/protobuf/proto/workspace_update.proto (100%) rename shared-lib/{flowy-workspace-infra => flowy-core-infra}/src/user_default.rs (100%) diff --git a/backend/Cargo.lock b/backend/Cargo.lock index e41d5e680b..32efba1a58 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -455,13 +455,13 @@ dependencies = [ "config", "dashmap", "derive_more", + "flowy-core-infra", "flowy-document", "flowy-document-infra", "flowy-sdk", "flowy-test", "flowy-user", "flowy-user-infra", - "flowy-workspace-infra", "futures", "futures-core", "futures-util", @@ -505,8 +505,8 @@ dependencies = [ "bytes", "config", "derive_more", + "flowy-core-infra", "flowy-user-infra", - "flowy-workspace-infra", "hyper", "lazy_static", "log", @@ -1209,11 +1209,11 @@ dependencies = [ "derive_more", "diesel", "diesel_derives", + "flowy-core-infra", "flowy-database", "flowy-derive", "flowy-document", "flowy-document-infra", - "flowy-workspace-infra", "futures", "futures-core", "lazy_static", @@ -1232,6 +1232,23 @@ dependencies = [ "tracing", ] +[[package]] +name = "flowy-core-infra" +version = "0.1.0" +dependencies = [ + "bytes", + "chrono", + "derive_more", + "flowy-derive", + "flowy-document-infra", + "log", + "protobuf", + "strum", + "strum_macros", + "unicode-segmentation", + "uuid", +] + [[package]] name = "flowy-database" version = "0.1.0" @@ -1410,23 +1427,6 @@ dependencies = [ "validator", ] -[[package]] -name = "flowy-workspace-infra" -version = "0.1.0" -dependencies = [ - "bytes", - "chrono", - "derive_more", - "flowy-derive", - "flowy-document-infra", - "log", - "protobuf", - "strum", - "strum_macros", - "unicode-segmentation", - "uuid", -] - [[package]] name = "fnv" version = "1.0.7" diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 357575b127..9fefaf3941 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -60,7 +60,7 @@ byteorder = {version = "1.3.4"} async-stream = "0.3.2" flowy-user-infra = { path = "../shared-lib/flowy-user-infra" } -flowy-workspace-infra = { path = "../shared-lib/flowy-workspace-infra" } +flowy-core-infra = { path = "../shared-lib/flowy-core-infra" } flowy-document-infra = { path = "../shared-lib/flowy-document-infra" } lib-ws = { path = "../shared-lib/lib-ws" } lib-ot = { path = "../shared-lib/lib-ot" } diff --git a/backend/src/entities/workspace.rs b/backend/src/entities/workspace.rs index dfb4375b8d..689ab68271 100644 --- a/backend/src/entities/workspace.rs +++ b/backend/src/entities/workspace.rs @@ -1,5 +1,5 @@ use chrono::Utc; -use flowy_workspace_infra::protobuf::{App, RepeatedView, Trash, TrashType, View, ViewType, Workspace}; +use flowy_core_infra::protobuf::{App, RepeatedView, Trash, TrashType, View, ViewType, Workspace}; use protobuf::ProtobufEnum; pub(crate) const WORKSPACE_TABLE: &str = "workspace_table"; diff --git a/backend/src/services/app/app.rs b/backend/src/services/app/app.rs index 39ed88de09..2f3f41e762 100644 --- a/backend/src/services/app/app.rs +++ b/backend/src/services/app/app.rs @@ -7,7 +7,7 @@ use crate::{ use crate::services::trash::read_trash_ids; use backend_service::errors::{invalid_params, ServerError}; use chrono::Utc; -use flowy_workspace_infra::{ +use flowy_core_infra::{ parser::{ app::{AppDesc, AppName}, workspace::WorkspaceId, diff --git a/backend/src/services/app/router.rs b/backend/src/services/app/router.rs index 7dd3fa8233..aa9820d06b 100644 --- a/backend/src/services/app/router.rs +++ b/backend/src/services/app/router.rs @@ -3,7 +3,7 @@ use actix_web::{ HttpResponse, }; use backend_service::errors::{invalid_params, ServerError}; -use flowy_workspace_infra::protobuf::{AppIdentifier, CreateAppParams, UpdateAppParams}; +use flowy_core_infra::protobuf::{AppIdentifier, CreateAppParams, UpdateAppParams}; use protobuf::Message; use sqlx::PgPool; @@ -17,7 +17,7 @@ use crate::services::{ }; use anyhow::Context; use backend_service::response::FlowyResponse; -use flowy_workspace_infra::parser::app::{AppDesc, AppName}; +use flowy_core_infra::parser::app::{AppDesc, AppName}; pub async fn create_handler( payload: Payload, diff --git a/backend/src/services/app/sql_builder.rs b/backend/src/services/app/sql_builder.rs index d2d3d7ac30..7fb6b2bcad 100644 --- a/backend/src/services/app/sql_builder.rs +++ b/backend/src/services/app/sql_builder.rs @@ -4,7 +4,7 @@ use crate::{ }; use backend_service::errors::{invalid_params, ServerError}; use chrono::{DateTime, NaiveDateTime, Utc}; -use flowy_workspace_infra::{ +use flowy_core_infra::{ parser::app::AppId, protobuf::{App, ColorStyle}, }; diff --git a/backend/src/services/trash/router.rs b/backend/src/services/trash/router.rs index 3ff7298136..6233e33fec 100644 --- a/backend/src/services/trash/router.rs +++ b/backend/src/services/trash/router.rs @@ -13,7 +13,7 @@ use backend_service::{ errors::{invalid_params, ServerError}, response::FlowyResponse, }; -use flowy_workspace_infra::{parser::trash::TrashId, protobuf::TrashIdentifiers}; +use flowy_core_infra::{parser::trash::TrashId, protobuf::TrashIdentifiers}; use sqlx::PgPool; use uuid::Uuid; diff --git a/backend/src/services/trash/trash.rs b/backend/src/services/trash/trash.rs index 6ce9892ee2..ddecb66d61 100644 --- a/backend/src/services/trash/trash.rs +++ b/backend/src/services/trash/trash.rs @@ -9,7 +9,7 @@ use crate::{ }; use ::protobuf::ProtobufEnum; use backend_service::errors::ServerError; -use flowy_workspace_infra::protobuf::{RepeatedTrash, Trash, TrashType}; +use flowy_core_infra::protobuf::{RepeatedTrash, Trash, TrashType}; use sqlx::{postgres::PgArguments, Postgres, Row}; use uuid::Uuid; diff --git a/backend/src/services/user/user_default.rs b/backend/src/services/user/user_default.rs index 4f25e82775..a70e493b69 100644 --- a/backend/src/services/user/user_default.rs +++ b/backend/src/services/user/user_default.rs @@ -9,8 +9,8 @@ use crate::{ use crate::services::view::{create_view_with_args, sql_builder::NewViewSqlBuilder}; use backend_service::errors::ServerError; use chrono::Utc; +use flowy_core_infra::protobuf::Workspace; use flowy_document_infra::user_default::doc_initial_string; -use flowy_workspace_infra::protobuf::Workspace; use std::convert::TryInto; #[allow(dead_code)] @@ -19,7 +19,7 @@ pub async fn create_default_workspace( user_id: &str, ) -> Result { let time = Utc::now(); - let workspace: Workspace = flowy_workspace_infra::user_default::create_default_workspace(time) + let workspace: Workspace = flowy_core_infra::user_default::create_default_workspace(time) .try_into() .unwrap(); diff --git a/backend/src/services/view/router.rs b/backend/src/services/view/router.rs index c4a4ddd69d..0cbd7f44ac 100644 --- a/backend/src/services/view/router.rs +++ b/backend/src/services/view/router.rs @@ -13,7 +13,7 @@ use backend_service::{ errors::{invalid_params, ServerError}, response::FlowyResponse, }; -use flowy_workspace_infra::{ +use flowy_core_infra::{ parser::view::{ViewDesc, ViewName, ViewThumbnail}, protobuf::{CreateViewParams, QueryViewRequest, UpdateViewParams, ViewIdentifier}, }; diff --git a/backend/src/services/view/sql_builder.rs b/backend/src/services/view/sql_builder.rs index a8568b4edc..6fc935d5cb 100644 --- a/backend/src/services/view/sql_builder.rs +++ b/backend/src/services/view/sql_builder.rs @@ -4,7 +4,7 @@ use crate::{ }; use backend_service::errors::{invalid_params, ServerError}; use chrono::{DateTime, NaiveDateTime, Utc}; -use flowy_workspace_infra::{ +use flowy_core_infra::{ parser::view::ViewId, protobuf::{View, ViewType}, }; diff --git a/backend/src/services/view/view.rs b/backend/src/services/view/view.rs index 543f51964f..4cb7d65b80 100644 --- a/backend/src/services/view/view.rs +++ b/backend/src/services/view/view.rs @@ -10,14 +10,14 @@ use crate::{ }; use backend_service::errors::{invalid_params, ServerError}; use chrono::Utc; -use flowy_document_infra::protobuf::CreateDocParams; -use flowy_workspace_infra::{ +use flowy_core_infra::{ parser::{ app::AppId, view::{ViewDesc, ViewName, ViewThumbnail}, }, protobuf::{CreateViewParams, RepeatedView, View}, }; +use flowy_document_infra::protobuf::CreateDocParams; use sqlx::{postgres::PgArguments, Postgres}; use uuid::Uuid; diff --git a/backend/src/services/workspace/router.rs b/backend/src/services/workspace/router.rs index b760c2912c..984a713bcb 100644 --- a/backend/src/services/workspace/router.rs +++ b/backend/src/services/workspace/router.rs @@ -18,7 +18,7 @@ use backend_service::{ errors::{invalid_params, ServerError}, response::FlowyResponse, }; -use flowy_workspace_infra::{ +use flowy_core_infra::{ parser::workspace::{WorkspaceDesc, WorkspaceName}, protobuf::{CreateWorkspaceParams, UpdateWorkspaceParams, WorkspaceIdentifier}, }; diff --git a/backend/src/services/workspace/sql_builder.rs b/backend/src/services/workspace/sql_builder.rs index 42222c169b..9f198d6234 100644 --- a/backend/src/services/workspace/sql_builder.rs +++ b/backend/src/services/workspace/sql_builder.rs @@ -4,7 +4,7 @@ use crate::{ }; use backend_service::errors::{invalid_params, ServerError}; use chrono::{DateTime, NaiveDateTime, Utc}; -use flowy_workspace_infra::{parser::workspace::WorkspaceId, protobuf::Workspace}; +use flowy_core_infra::{parser::workspace::WorkspaceId, protobuf::Workspace}; use sqlx::postgres::PgArguments; use uuid::Uuid; diff --git a/backend/src/services/workspace/workspace.rs b/backend/src/services/workspace/workspace.rs index fc7800a9ef..39a419c6fb 100644 --- a/backend/src/services/workspace/workspace.rs +++ b/backend/src/services/workspace/workspace.rs @@ -6,7 +6,7 @@ use crate::{ }; use anyhow::Context; use backend_service::errors::{invalid_params, ServerError}; -use flowy_workspace_infra::{ +use flowy_core_infra::{ parser::workspace::WorkspaceId, protobuf::{RepeatedApp, RepeatedWorkspace, Workspace}, }; diff --git a/backend/tests/api/doc.rs b/backend/tests/api/doc.rs index fe99cd43b6..571d74ac4d 100644 --- a/backend/tests/api/doc.rs +++ b/backend/tests/api/doc.rs @@ -1,6 +1,6 @@ use crate::util::helper::ViewTest; +use flowy_core_infra::entities::view::ViewIdentifiers; use flowy_document_infra::entities::doc::DocIdentifier; -use flowy_workspace_infra::entities::view::ViewIdentifiers; #[actix_rt::test] async fn doc_read() { diff --git a/backend/tests/api/workspace.rs b/backend/tests/api/workspace.rs index 8374ebda92..abfb6294c0 100644 --- a/backend/tests/api/workspace.rs +++ b/backend/tests/api/workspace.rs @@ -1,6 +1,6 @@ #![allow(clippy::all)] use crate::util::helper::*; -use flowy_workspace_infra::entities::{ +use flowy_core_infra::entities::{ app::{AppIdentifier, UpdateAppParams}, trash::{TrashIdentifier, TrashIdentifiers, TrashType}, view::{UpdateViewParams, ViewIdentifier}, diff --git a/backend/tests/util/helper.rs b/backend/tests/util/helper.rs index 93d7d6eb5c..3fb8dcd617 100644 --- a/backend/tests/util/helper.rs +++ b/backend/tests/util/helper.rs @@ -9,10 +9,10 @@ use backend_service::{ user_request::*, workspace_request::*, }; +use flowy_core_infra::entities::prelude::*; use flowy_document::services::server::read_doc_request; use flowy_document_infra::entities::doc::{Doc, DocIdentifier}; use flowy_user_infra::entities::*; -use flowy_workspace_infra::entities::prelude::*; use sqlx::{Connection, Executor, PgConnection, PgPool}; use uuid::Uuid; diff --git a/frontend/app_flowy/lib/user/domain/i_auth.dart b/frontend/app_flowy/lib/user/domain/i_auth.dart index 495218c530..3b557616e8 100644 --- a/frontend/app_flowy/lib/user/domain/i_auth.dart +++ b/frontend/app_flowy/lib/user/domain/i_auth.dart @@ -1,6 +1,6 @@ import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/protobuf.dart'; import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile; import 'package:flutter/material.dart'; diff --git a/frontend/app_flowy/lib/user/domain/i_splash.dart b/frontend/app_flowy/lib/user/domain/i_splash.dart index 8ebd5ce5c1..33781f93a8 100644 --- a/frontend/app_flowy/lib/user/domain/i_splash.dart +++ b/frontend/app_flowy/lib/user/domain/i_splash.dart @@ -1,5 +1,5 @@ import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/protobuf.dart'; import 'package:flutter/widgets.dart'; import 'auth_state.dart'; diff --git a/frontend/app_flowy/lib/user/infrastructure/i_auth_impl.dart b/frontend/app_flowy/lib/user/infrastructure/i_auth_impl.dart index 164c9895aa..b348d38c77 100644 --- a/frontend/app_flowy/lib/user/infrastructure/i_auth_impl.dart +++ b/frontend/app_flowy/lib/user/infrastructure/i_auth_impl.dart @@ -9,7 +9,7 @@ import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProf import 'package:app_flowy/user/domain/i_auth.dart'; import 'package:app_flowy/user/infrastructure/repos/auth_repo.dart'; import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/protobuf.dart'; import 'package:flutter/material.dart'; class AuthImpl extends IAuth { diff --git a/frontend/app_flowy/lib/user/infrastructure/i_splash_impl.dart b/frontend/app_flowy/lib/user/infrastructure/i_splash_impl.dart index 2f459f876b..79e8ce78e3 100644 --- a/frontend/app_flowy/lib/user/infrastructure/i_splash_impl.dart +++ b/frontend/app_flowy/lib/user/infrastructure/i_splash_impl.dart @@ -11,7 +11,7 @@ import 'package:flowy_infra/time/duration.dart'; import 'package:flowy_infra_ui/widget/route/animation.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/protobuf.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; diff --git a/frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart b/frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart index 972ee09285..f6fbfd9701 100644 --- a/frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart +++ b/frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart @@ -9,7 +9,7 @@ import 'package:flowy_infra_ui/widget/rounded_button.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/protobuf.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile; import 'package:flutter/material.dart'; diff --git a/frontend/app_flowy/lib/user/presentation/splash_screen.dart b/frontend/app_flowy/lib/user/presentation/splash_screen.dart index 4f407f849c..14f02b3ba4 100644 --- a/frontend/app_flowy/lib/user/presentation/splash_screen.dart +++ b/frontend/app_flowy/lib/user/presentation/splash_screen.dart @@ -3,7 +3,7 @@ import 'package:app_flowy/user/application/splash_bloc.dart'; import 'package:app_flowy/user/domain/auth_state.dart'; import 'package:app_flowy/user/domain/i_splash.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/errors.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/app_flowy/lib/user/presentation/welcome_screen.dart b/frontend/app_flowy/lib/user/presentation/welcome_screen.dart index 16e95e3b67..4f78c020b2 100644 --- a/frontend/app_flowy/lib/user/presentation/welcome_screen.dart +++ b/frontend/app_flowy/lib/user/presentation/welcome_screen.dart @@ -5,7 +5,7 @@ import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/widget/error_page.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/workspace_create.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart b/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart index c2af8cf871..a66eb5f56d 100644 --- a/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart @@ -1,7 +1,7 @@ import 'package:app_flowy/workspace/domain/i_app.dart'; import 'package:flowy_log/flowy_log.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/app_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/doc/doc_bloc.dart b/frontend/app_flowy/lib/workspace/application/doc/doc_bloc.dart index 67c7023c8a..0ba9405b8f 100644 --- a/frontend/app_flowy/lib/workspace/application/doc/doc_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/doc/doc_bloc.dart @@ -2,8 +2,8 @@ import 'dart:convert'; import 'package:app_flowy/workspace/domain/i_trash.dart'; import 'package:app_flowy/workspace/domain/i_view.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/trash_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/trash_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:flutter_quill/flutter_quill.dart'; import 'package:flowy_log/flowy_log.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/doc/share_bloc.dart b/frontend/app_flowy/lib/workspace/application/doc/share_bloc.dart index bfb98d2528..48582082f3 100644 --- a/frontend/app_flowy/lib/workspace/application/doc/share_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/doc/share_bloc.dart @@ -1,7 +1,7 @@ import 'package:app_flowy/workspace/domain/i_share.dart'; import 'package:app_flowy/workspace/infrastructure/markdown/delta_markdown.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/export.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/export.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/home/home_listen_bloc.dart b/frontend/app_flowy/lib/workspace/application/home/home_listen_bloc.dart index 5979fa4ca5..5e71b82380 100644 --- a/frontend/app_flowy/lib/workspace/application/home/home_listen_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/home/home_listen_bloc.dart @@ -1,5 +1,5 @@ import 'package:app_flowy/workspace/domain/i_user.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/errors.pb.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:dartz/dartz.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart b/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart index f78eef6e73..bb2c2d013b 100644 --- a/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart @@ -4,7 +4,7 @@ import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; import 'package:app_flowy/workspace/presentation/stack_page/blank/blank_page.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_log/flowy_log.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/app_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:flutter/material.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart b/frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart index bff016f9f9..5e1c4a1746 100644 --- a/frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart @@ -1,7 +1,7 @@ import 'package:app_flowy/workspace/domain/i_user.dart'; import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/workspace_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/trash/trash_bloc.dart b/frontend/app_flowy/lib/workspace/application/trash/trash_bloc.dart index 2d885d8ff9..cd20a56a97 100644 --- a/frontend/app_flowy/lib/workspace/application/trash/trash_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/trash/trash_bloc.dart @@ -1,7 +1,7 @@ import 'package:app_flowy/workspace/domain/i_trash.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_log/flowy_log.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/trash_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/trash_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/view/view_bloc.dart b/frontend/app_flowy/lib/workspace/application/view/view_bloc.dart index 59c00e44f3..579c3d4165 100644 --- a/frontend/app_flowy/lib/workspace/application/view/view_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/view/view_bloc.dart @@ -1,5 +1,5 @@ import 'package:dartz/dartz.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/workspace/welcome_bloc.dart b/frontend/app_flowy/lib/workspace/application/workspace/welcome_bloc.dart index faba9f421e..16fc9805ff 100644 --- a/frontend/app_flowy/lib/workspace/application/workspace/welcome_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/workspace/welcome_bloc.dart @@ -1,7 +1,7 @@ import 'package:app_flowy/workspace/domain/i_user.dart'; import 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart'; import 'package:flowy_log/flowy_log.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/workspace_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/domain/i_app.dart b/frontend/app_flowy/lib/workspace/domain/i_app.dart index 240ec54c55..255d1ab78a 100644 --- a/frontend/app_flowy/lib/workspace/domain/i_app.dart +++ b/frontend/app_flowy/lib/workspace/domain/i_app.dart @@ -1,6 +1,6 @@ -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/app_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/protobuf.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; diff --git a/frontend/app_flowy/lib/workspace/domain/i_share.dart b/frontend/app_flowy/lib/workspace/domain/i_share.dart index 8bf29ce153..cd24047807 100644 --- a/frontend/app_flowy/lib/workspace/domain/i_share.dart +++ b/frontend/app_flowy/lib/workspace/domain/i_share.dart @@ -1,6 +1,6 @@ import 'dart:async'; import 'package:dartz/dartz.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/protobuf.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; abstract class IShare { diff --git a/frontend/app_flowy/lib/workspace/domain/i_trash.dart b/frontend/app_flowy/lib/workspace/domain/i_trash.dart index 57de56e1c0..5ab660f081 100644 --- a/frontend/app_flowy/lib/workspace/domain/i_trash.dart +++ b/frontend/app_flowy/lib/workspace/domain/i_trash.dart @@ -1,6 +1,6 @@ import 'dart:async'; import 'package:dartz/dartz.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/trash_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/trash_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; abstract class ITrash { diff --git a/frontend/app_flowy/lib/workspace/domain/i_user.dart b/frontend/app_flowy/lib/workspace/domain/i_user.dart index 95bc9398b0..4fc5ecab1d 100644 --- a/frontend/app_flowy/lib/workspace/domain/i_user.dart +++ b/frontend/app_flowy/lib/workspace/domain/i_user.dart @@ -2,7 +2,7 @@ import 'package:dartz/dartz.dart'; import 'package:flowy_infra/notifier.dart'; import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/workspace_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; export 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart'; export 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile; diff --git a/frontend/app_flowy/lib/workspace/domain/i_view.dart b/frontend/app_flowy/lib/workspace/domain/i_view.dart index bdddbfcad3..d982baf00f 100644 --- a/frontend/app_flowy/lib/workspace/domain/i_view.dart +++ b/frontend/app_flowy/lib/workspace/domain/i_view.dart @@ -1,4 +1,4 @@ -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_infra/notifier.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; diff --git a/frontend/app_flowy/lib/workspace/domain/i_workspace.dart b/frontend/app_flowy/lib/workspace/domain/i_workspace.dart index 9837689233..beb85d0115 100644 --- a/frontend/app_flowy/lib/workspace/domain/i_workspace.dart +++ b/frontend/app_flowy/lib/workspace/domain/i_workspace.dart @@ -1,4 +1,4 @@ -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/protobuf.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; diff --git a/frontend/app_flowy/lib/workspace/domain/image.dart b/frontend/app_flowy/lib/workspace/domain/image.dart index 649f652b1d..8eaa2928f8 100644 --- a/frontend/app_flowy/lib/workspace/domain/image.dart +++ b/frontend/app_flowy/lib/workspace/domain/image.dart @@ -1,4 +1,4 @@ -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; import 'package:flutter/material.dart'; import 'package:flowy_infra/image.dart'; diff --git a/frontend/app_flowy/lib/workspace/domain/view_ext.dart b/frontend/app_flowy/lib/workspace/domain/view_ext.dart index 14858b147a..fccf9901d7 100644 --- a/frontend/app_flowy/lib/workspace/domain/view_ext.dart +++ b/frontend/app_flowy/lib/workspace/domain/view_ext.dart @@ -1,7 +1,7 @@ import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; import 'package:app_flowy/workspace/presentation/stack_page/blank/blank_page.dart'; import 'package:app_flowy/workspace/presentation/stack_page/doc/doc_stack_page.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; extension ToHomeStackContext on View { HomeStackContext stackContext() { diff --git a/frontend/app_flowy/lib/workspace/infrastructure/deps_resolver.dart b/frontend/app_flowy/lib/workspace/infrastructure/deps_resolver.dart index 060225fc18..4ad59aa75e 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/deps_resolver.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/deps_resolver.dart @@ -21,8 +21,8 @@ import 'package:app_flowy/workspace/infrastructure/repos/trash_repo.dart'; import 'package:app_flowy/workspace/infrastructure/repos/view_repo.dart'; import 'package:app_flowy/workspace/infrastructure/repos/workspace_repo.dart'; import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/app_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; import 'package:get_it/get_it.dart'; import 'i_share_impl.dart'; diff --git a/frontend/app_flowy/lib/workspace/infrastructure/i_app_impl.dart b/frontend/app_flowy/lib/workspace/infrastructure/i_app_impl.dart index 2eb71235b7..2dec77f617 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/i_app_impl.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/i_app_impl.dart @@ -1,7 +1,7 @@ import 'package:app_flowy/workspace/infrastructure/repos/app_repo.dart'; import 'package:dartz/dartz.dart'; import 'package:app_flowy/workspace/domain/i_app.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; export 'package:app_flowy/workspace/domain/i_app.dart'; diff --git a/frontend/app_flowy/lib/workspace/infrastructure/i_share_impl.dart b/frontend/app_flowy/lib/workspace/infrastructure/i_share_impl.dart index e57df7f516..12ed9722c4 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/i_share_impl.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/i_share_impl.dart @@ -1,5 +1,5 @@ import 'package:app_flowy/workspace/domain/i_share.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/protobuf.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:dartz/dartz.dart'; diff --git a/frontend/app_flowy/lib/workspace/infrastructure/i_trash_impl.dart b/frontend/app_flowy/lib/workspace/infrastructure/i_trash_impl.dart index fa73c11704..26a44ba169 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/i_trash_impl.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/i_trash_impl.dart @@ -1,7 +1,7 @@ import 'package:app_flowy/workspace/domain/i_trash.dart'; import 'package:app_flowy/workspace/infrastructure/repos/trash_repo.dart'; import 'package:dartz/dartz.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/trash_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/trash_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; class ITrashImpl implements ITrash { diff --git a/frontend/app_flowy/lib/workspace/infrastructure/i_user_impl.dart b/frontend/app_flowy/lib/workspace/infrastructure/i_user_impl.dart index d1e5ec7f42..08d7e3e12e 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/i_user_impl.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/i_user_impl.dart @@ -9,7 +9,7 @@ import 'package:flowy_sdk/protobuf/dart-notify/protobuf.dart'; import 'package:flowy_sdk/protobuf/flowy-user-infra/errors.pb.dart'; // import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart' as user_error; import 'package:flowy_sdk/protobuf/flowy-user/observable.pb.dart' as user; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/workspace_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/observable.pb.dart'; export 'package:app_flowy/workspace/domain/i_user.dart'; diff --git a/frontend/app_flowy/lib/workspace/infrastructure/i_view_impl.dart b/frontend/app_flowy/lib/workspace/infrastructure/i_view_impl.dart index c737076b4e..84bc049b33 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/i_view_impl.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/i_view_impl.dart @@ -2,7 +2,7 @@ import 'package:app_flowy/workspace/domain/i_view.dart'; import 'package:app_flowy/workspace/infrastructure/repos/view_repo.dart'; import 'package:flowy_infra/notifier.dart'; import 'package:dartz/dartz.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; class IViewImpl extends IView { diff --git a/frontend/app_flowy/lib/workspace/infrastructure/i_workspace_impl.dart b/frontend/app_flowy/lib/workspace/infrastructure/i_workspace_impl.dart index 1d1826b600..a90e9b62c3 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/i_workspace_impl.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/i_workspace_impl.dart @@ -1,7 +1,7 @@ import 'package:app_flowy/workspace/domain/i_workspace.dart'; import 'package:app_flowy/workspace/infrastructure/repos/workspace_repo.dart'; import 'package:dartz/dartz.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/app_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; export 'package:app_flowy/workspace/domain/i_workspace.dart'; diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/app_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/app_repo.dart index d915ed4487..1fe3f2e00b 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/app_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/app_repo.dart @@ -5,11 +5,11 @@ import 'package:dartz/dartz.dart'; import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/dart-notify/subject.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_query.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_update.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pbenum.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/app_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/app_query.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/app_update.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pbenum.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/observable.pb.dart'; import 'package:flowy_sdk/rust_stream.dart'; diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/doc_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/doc_repo.dart index b56afffd9f..401d469f79 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/doc_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/doc_repo.dart @@ -1,7 +1,7 @@ import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-document-infra/doc.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_query.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/view_query.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; class DocRepository { diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/share_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/share_repo.dart index 52c72912f3..85f8334316 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/share_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/share_repo.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/protobuf.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; class ShareRepo { diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/trash_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/trash_repo.dart index 67123d9264..821c1db7af 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/trash_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/trash_repo.dart @@ -5,7 +5,7 @@ import 'package:app_flowy/workspace/infrastructure/repos/helper.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/dart-notify/subject.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/trash_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/trash_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/observable.pb.dart'; import 'package:flowy_sdk/rust_stream.dart'; diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/user_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/user_repo.dart index fd613f2f6e..3adaa87006 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/user_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/user_repo.dart @@ -3,8 +3,8 @@ import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_query.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/workspace_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/workspace_query.pb.dart'; import 'package:app_flowy/workspace/domain/i_user.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/view_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/view_repo.dart index 7fd2735abe..96d19d80b8 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/view_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/view_repo.dart @@ -3,9 +3,9 @@ import 'dart:typed_data'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/dart-notify/subject.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_query.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_update.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/view_query.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/view_update.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/observable.pb.dart'; import 'package:flowy_sdk/rust_stream.dart'; diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/workspace_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/workspace_repo.dart index e7faf31091..c9d192c370 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/workspace_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/workspace_repo.dart @@ -7,9 +7,9 @@ import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/dart-notify/subject.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_query.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/app_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/workspace_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/workspace_query.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/observable.pb.dart'; import 'package:flowy_sdk/rust_stream.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart b/frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart index 50fb5827f2..2ff6b29afb 100644 --- a/frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart +++ b/frontend/app_flowy/lib/workspace/presentation/home/home_screen.dart @@ -8,7 +8,7 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_infra_ui/style_widget/container.dart'; import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/protobuf.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:styled_widget/styled_widget.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_page.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_page.dart index 61f05d4cce..ba9da95e45 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_page.dart @@ -4,7 +4,7 @@ import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flutter_quill/flutter_quill.dart' as quill; import 'package:flowy_infra_ui/widget/error_page.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:styled_widget/styled_widget.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart index d1b7f7ca8d..65ca557600 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart @@ -12,8 +12,8 @@ import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/widget/rounded_button.dart'; import 'package:flowy_log/flowy_log.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/export.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/export.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:flutter/material.dart'; import 'package:dartz/dartz.dart' as dartz; diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/widget/trash_cell.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/widget/trash_cell.dart index 7de74f9ef0..b30c61a819 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/widget/trash_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/widget/trash_cell.dart @@ -2,7 +2,7 @@ import 'package:flowy_infra/image.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/trash_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/trash_create.pb.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:fixnum/fixnum.dart' as $fixnum; diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/home_top_bar.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/home_top_bar.dart index 0af6784ef9..e7f85d3190 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/home_top_bar.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/home_top_bar.dart @@ -3,8 +3,8 @@ import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; import 'package:app_flowy/workspace/presentation/home/home_sizes.dart'; import 'package:app_flowy/workspace/presentation/home/navigation.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pbenum.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pbenum.dart'; import 'package:flutter/material.dart'; import 'package:flowy_infra_ui/style_widget/extension.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/menu.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/menu.dart index c1dabad71f..a12c524761 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/menu.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/menu.dart @@ -4,8 +4,8 @@ import 'package:flowy_infra/size.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/workspace_setting.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/workspace_setting.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:provider/provider.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/add_button.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/add_button.dart index 7a4dffe95f..17d4ae57d3 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/add_button.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/add_button.dart @@ -4,7 +4,7 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/hover.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:styled_widget/styled_widget.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart index 71396a1f7d..6d6f193736 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart @@ -6,7 +6,7 @@ import 'package:flowy_infra/flowy_icon_data_icons.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/app_create.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/menu_app.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/menu_app.dart index 3042ff3c9c..2431a3a14f 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/menu_app.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/menu_app.dart @@ -1,8 +1,8 @@ import 'package:app_flowy/workspace/presentation/widgets/menu/menu.dart'; import 'package:app_flowy/workspace/presentation/widgets/menu/widget/app/header/header.dart'; import 'package:expandable/expandable.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/app_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:app_flowy/startup/startup.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart index e361bce174..11adbed14b 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart @@ -8,7 +8,7 @@ import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/hover.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:provider/provider.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/section.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/section.dart index 26f6c3fd56..5233dc3c45 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/section.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/section.dart @@ -3,10 +3,8 @@ import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart'; import 'package:app_flowy/workspace/domain/view_ext.dart'; import 'package:app_flowy/workspace/presentation/widgets/menu/menu.dart'; import 'package:app_flowy/workspace/presentation/widgets/menu/widget/app/menu_app.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart'; -import 'package:flutter/foundation.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:provider/provider.dart'; import 'package:styled_widget/styled_widget.dart'; import 'item.dart'; diff --git a/frontend/app_flowy/macos/Flutter/GeneratedPluginRegistrant.swift b/frontend/app_flowy/macos/Flutter/GeneratedPluginRegistrant.swift index 327448375e..fcef838641 100644 --- a/frontend/app_flowy/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/frontend/app_flowy/macos/Flutter/GeneratedPluginRegistrant.swift @@ -10,6 +10,7 @@ import flowy_infra_ui import flowy_sdk import package_info_plus_macos import path_provider_macos +import shared_preferences_macos import url_launcher_macos import window_size @@ -19,6 +20,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FlowySdkPlugin.register(with: registry.registrar(forPlugin: "FlowySdkPlugin")) FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) WindowSizePlugin.register(with: registry.registrar(forPlugin: "WindowSizePlugin")) } diff --git a/frontend/app_flowy/packages/flowy_sdk/example/pubspec.lock b/frontend/app_flowy/packages/flowy_sdk/example/pubspec.lock index f297a73753..e3acc4bb72 100644 --- a/frontend/app_flowy/packages/flowy_sdk/example/pubspec.lock +++ b/frontend/app_flowy/packages/flowy_sdk/example/pubspec.lock @@ -7,7 +7,7 @@ packages: name: archive url: "https://pub.dartlang.org" source: hosted - version: "3.1.2" + version: "3.1.6" async: dependency: transitive description: @@ -214,7 +214,7 @@ packages: name: process url: "https://pub.dartlang.org" source: hosted - version: "4.2.3" + version: "4.2.4" protobuf: dependency: transitive description: @@ -289,7 +289,7 @@ packages: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.1" vm_service: dependency: transitive description: @@ -305,5 +305,5 @@ packages: source: hosted version: "3.0.0" sdks: - dart: ">=2.12.0 <3.0.0" + dart: ">=2.14.0 <3.0.0" flutter: ">=1.17.0" diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart index 0672da7200..088bfb6e4d 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart @@ -1,6 +1,7 @@ import 'dart:ffi'; import 'package:dartz/dartz.dart'; import 'package:flowy_log/flowy_log.dart'; +// ignore: unnecessary_import import 'package:flowy_sdk/protobuf/dart-ffi/ffi_response.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user/event.pb.dart'; @@ -17,7 +18,7 @@ import 'dart:typed_data'; import 'package:flowy_sdk/ffi.dart' as ffi; import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart'; import 'package:flowy_sdk/protobuf/dart-ffi/protobuf.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace-infra/protobuf.dart'; +import 'package:flowy_sdk/protobuf/flowy-core-infra/protobuf.dart'; import 'package:flowy_sdk/protobuf/flowy-document-infra/protobuf.dart'; // ignore: unused_import diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/app_create.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/app_create.pb.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/app_create.pb.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/app_create.pb.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/app_create.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/app_create.pbenum.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/app_create.pbenum.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/app_create.pbenum.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/app_create.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/app_create.pbjson.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/app_create.pbjson.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/app_create.pbjson.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/app_create.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/app_create.pbserver.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/app_create.pbserver.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/app_create.pbserver.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/app_query.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/app_query.pb.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/app_query.pb.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/app_query.pb.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/app_query.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/app_query.pbenum.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/app_query.pbenum.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/app_query.pbenum.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/app_query.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/app_query.pbjson.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/app_query.pbjson.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/app_query.pbjson.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/app_query.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/app_query.pbserver.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/app_query.pbserver.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/app_query.pbserver.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/app_update.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/app_update.pb.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/app_update.pb.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/app_update.pb.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/app_update.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/app_update.pbenum.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/app_update.pbenum.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/app_update.pbenum.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/app_update.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/app_update.pbjson.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/app_update.pbjson.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/app_update.pbjson.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/app_update.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/app_update.pbserver.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/app_update.pbserver.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/app_update.pbserver.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/errors.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/errors.pb.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/errors.pb.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/errors.pb.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/errors.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/errors.pbenum.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/errors.pbenum.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/errors.pbenum.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/errors.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/errors.pbjson.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/errors.pbjson.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/errors.pbjson.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/errors.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/errors.pbserver.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/errors.pbserver.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/errors.pbserver.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/export.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/export.pb.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/export.pb.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/export.pb.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/export.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/export.pbenum.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/export.pbenum.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/export.pbenum.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/export.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/export.pbjson.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/export.pbjson.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/export.pbjson.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/export.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/export.pbserver.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/export.pbserver.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/export.pbserver.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/protobuf.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/protobuf.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/protobuf.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/protobuf.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/trash_create.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/trash_create.pb.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/trash_create.pb.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/trash_create.pb.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/trash_create.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/trash_create.pbenum.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/trash_create.pbenum.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/trash_create.pbenum.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/trash_create.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/trash_create.pbjson.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/trash_create.pbjson.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/trash_create.pbjson.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/trash_create.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/trash_create.pbserver.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/trash_create.pbserver.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/trash_create.pbserver.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/view_create.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/view_create.pb.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/view_create.pb.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/view_create.pb.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/view_create.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/view_create.pbenum.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/view_create.pbenum.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/view_create.pbenum.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/view_create.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/view_create.pbjson.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/view_create.pbjson.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/view_create.pbjson.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/view_create.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/view_create.pbserver.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/view_create.pbserver.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/view_create.pbserver.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/view_query.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/view_query.pb.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/view_query.pb.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/view_query.pb.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/view_query.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/view_query.pbenum.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/view_query.pbenum.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/view_query.pbenum.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/view_query.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/view_query.pbjson.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/view_query.pbjson.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/view_query.pbjson.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/view_query.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/view_query.pbserver.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/view_query.pbserver.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/view_query.pbserver.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/view_update.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/view_update.pb.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/view_update.pb.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/view_update.pb.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/view_update.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/view_update.pbenum.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/view_update.pbenum.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/view_update.pbenum.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/view_update.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/view_update.pbjson.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/view_update.pbjson.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/view_update.pbjson.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/view_update.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/view_update.pbserver.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/view_update.pbserver.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/view_update.pbserver.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_create.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_create.pb.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_create.pb.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_create.pb.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_create.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_create.pbenum.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_create.pbenum.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_create.pbenum.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_create.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_create.pbjson.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_create.pbjson.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_create.pbjson.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_create.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_create.pbserver.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_create.pbserver.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_create.pbserver.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_query.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_query.pb.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_query.pb.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_query.pb.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_query.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_query.pbenum.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_query.pbenum.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_query.pbenum.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_query.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_query.pbjson.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_query.pbjson.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_query.pbjson.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_query.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_query.pbserver.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_query.pbserver.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_query.pbserver.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_setting.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_setting.pb.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_setting.pb.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_setting.pb.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_setting.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_setting.pbenum.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_setting.pbenum.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_setting.pbenum.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_setting.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_setting.pbjson.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_setting.pbjson.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_setting.pbjson.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_setting.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_setting.pbserver.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_setting.pbserver.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_setting.pbserver.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_update.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_update.pb.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_update.pb.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_update.pb.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_update.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_update.pbenum.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_update.pbenum.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_update.pbenum.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_update.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_update.pbjson.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_update.pbjson.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_update.pbjson.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_update.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_update.pbserver.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace-infra/workspace_update.pbserver.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-infra/workspace_update.pbserver.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/pubspec.lock b/frontend/app_flowy/packages/flowy_sdk/pubspec.lock index 43137b2f58..895c00a297 100644 --- a/frontend/app_flowy/packages/flowy_sdk/pubspec.lock +++ b/frontend/app_flowy/packages/flowy_sdk/pubspec.lock @@ -463,7 +463,7 @@ packages: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.1" watcher: dependency: transitive description: @@ -486,5 +486,5 @@ packages: source: hosted version: "3.1.0" sdks: - dart: ">=2.12.0 <3.0.0" + dart: ">=2.14.0 <3.0.0" flutter: ">=1.17.0" diff --git a/frontend/app_flowy/pubspec.lock b/frontend/app_flowy/pubspec.lock index 7d1c411e1d..11622827be 100644 --- a/frontend/app_flowy/pubspec.lock +++ b/frontend/app_flowy/pubspec.lock @@ -1126,7 +1126,7 @@ packages: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.1" video_player: dependency: transitive description: diff --git a/frontend/rust-lib/flowy-core/Cargo.toml b/frontend/rust-lib/flowy-core/Cargo.toml index 2df640a9e3..fc242bb3e2 100644 --- a/frontend/rust-lib/flowy-core/Cargo.toml +++ b/frontend/rust-lib/flowy-core/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -flowy-workspace-infra = { path = "../../../shared-lib/flowy-workspace-infra" } +flowy-core-infra = { path = "../../../shared-lib/flowy-core-infra" } flowy-document-infra = { path = "../../../shared-lib/flowy-document-infra" } flowy-derive = { path = "../../../shared-lib/flowy-derive" } lib-ot = { path = "../../../shared-lib/lib-ot" } diff --git a/frontend/rust-lib/flowy-core/src/core/aggregate_tasks/workspace_task.rs b/frontend/rust-lib/flowy-core/src/core/aggregate_tasks/workspace_task.rs index 07f24c1a88..39cffec56e 100644 --- a/frontend/rust-lib/flowy-core/src/core/aggregate_tasks/workspace_task.rs +++ b/frontend/rust-lib/flowy-core/src/core/aggregate_tasks/workspace_task.rs @@ -4,7 +4,7 @@ use crate::{ notify::{send_dart_notification, WorkspaceNotification}, services::workspace::sql::{WorkspaceTable, WorkspaceTableSql}, }; -use flowy_workspace_infra::entities::workspace::WorkspaceIdentifier; +use flowy_core_infra::entities::workspace::WorkspaceIdentifier; use lib_dispatch::prelude::Unit; use std::sync::Arc; diff --git a/frontend/rust-lib/flowy-core/src/core/core_context.rs b/frontend/rust-lib/flowy-core/src/core/core_context.rs index e29ddb0a4c..d5931f19dd 100644 --- a/frontend/rust-lib/flowy-core/src/core/core_context.rs +++ b/frontend/rust-lib/flowy-core/src/core/core_context.rs @@ -6,8 +6,8 @@ use crate::{ services::{server::Server, AppController, TrashController, ViewController, WorkspaceController}, }; use chrono::Utc; +use flowy_core_infra::user_default; use flowy_document_infra::{entities::doc::DocDelta, user_default::initial_read_me}; -use flowy_workspace_infra::user_default; use lazy_static::lazy_static; use lib_infra::entities::network_state::NetworkType; use parking_lot::RwLock; diff --git a/frontend/rust-lib/flowy-core/src/core/event_handler.rs b/frontend/rust-lib/flowy-core/src/core/event_handler.rs index e451ec35f3..9d9a7b7bb4 100644 --- a/frontend/rust-lib/flowy-core/src/core/event_handler.rs +++ b/frontend/rust-lib/flowy-core/src/core/event_handler.rs @@ -3,7 +3,7 @@ use crate::{ errors::WorkspaceError, services::{get_current_workspace, read_local_workspace_apps}, }; -use flowy_workspace_infra::entities::{ +use flowy_core_infra::entities::{ view::View, workspace::{CurrentWorkspaceSetting, QueryWorkspaceRequest, RepeatedWorkspace, WorkspaceIdentifier}, }; diff --git a/frontend/rust-lib/flowy-core/src/errors.rs b/frontend/rust-lib/flowy-core/src/errors.rs index 19e4113898..c0240ad2c5 100644 --- a/frontend/rust-lib/flowy-core/src/errors.rs +++ b/frontend/rust-lib/flowy-core/src/errors.rs @@ -1,9 +1,9 @@ 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; -pub use flowy_workspace_infra::errors::ErrorCode; use lib_dispatch::prelude::{EventResponse, ResponseBuilder}; use std::{convert::TryInto, fmt, fmt::Debug}; diff --git a/frontend/rust-lib/flowy-core/src/lib.rs b/frontend/rust-lib/flowy-core/src/lib.rs index f3d3d51b8c..8de43ec141 100644 --- a/frontend/rust-lib/flowy-core/src/lib.rs +++ b/frontend/rust-lib/flowy-core/src/lib.rs @@ -1,4 +1,4 @@ -pub use flowy_workspace_infra::entities; +pub use flowy_core_infra::entities; pub mod event; pub mod module; @@ -17,7 +17,7 @@ pub mod protobuf; mod util; pub mod prelude { - pub use flowy_workspace_infra::entities::{app::*, trash::*, view::*, workspace::*}; + pub use flowy_core_infra::entities::{app::*, trash::*, view::*, workspace::*}; pub use crate::{core::*, errors::*, module::*}; } diff --git a/frontend/rust-lib/flowy-core/src/services/server/server_api.rs b/frontend/rust-lib/flowy-core/src/services/server/server_api.rs index eab8668db6..2d0efbc892 100644 --- a/frontend/rust-lib/flowy-core/src/services/server/server_api.rs +++ b/frontend/rust-lib/flowy-core/src/services/server/server_api.rs @@ -10,7 +10,7 @@ use crate::{ services::server::WorkspaceServerAPI, }; use backend_service::{configuration::ClientServerConfiguration, middleware::*, workspace_request::*}; -use flowy_workspace_infra::errors::ErrorCode; +use flowy_core_infra::errors::ErrorCode; use lib_infra::future::ResultFuture; pub struct WorkspaceHttpServer { diff --git a/frontend/rust-lib/flowy-core/src/services/view/controller.rs b/frontend/rust-lib/flowy-core/src/services/view/controller.rs index 2e98984dd8..b933a9b93d 100644 --- a/frontend/rust-lib/flowy-core/src/services/view/controller.rs +++ b/frontend/rust-lib/flowy-core/src/services/view/controller.rs @@ -18,8 +18,8 @@ use crate::{ TrashEvent, }, }; +use flowy_core_infra::entities::share::{ExportData, ExportParams}; use flowy_document::module::FlowyDocument; -use flowy_workspace_infra::entities::share::{ExportData, ExportParams}; use lib_infra::kv::KV; const LATEST_VIEW_ID: &str = "latest_view_id"; diff --git a/frontend/rust-lib/flowy-core/src/services/view/event_handler.rs b/frontend/rust-lib/flowy-core/src/services/view/event_handler.rs index 7a1e11e5aa..c917ef2b9a 100644 --- a/frontend/rust-lib/flowy-core/src/services/view/event_handler.rs +++ b/frontend/rust-lib/flowy-core/src/services/view/event_handler.rs @@ -15,8 +15,8 @@ use crate::{ errors::WorkspaceError, services::{TrashController, ViewController}, }; +use flowy_core_infra::entities::share::{ExportData, ExportParams, ExportRequest}; use flowy_document_infra::entities::doc::DocDelta; -use flowy_workspace_infra::entities::share::{ExportData, ExportParams, ExportRequest}; use lib_dispatch::prelude::{data_result, Data, DataResult, Unit}; use std::{convert::TryInto, sync::Arc}; diff --git a/frontend/rust-lib/flowy-core/src/services/workspace/controller.rs b/frontend/rust-lib/flowy-core/src/services/workspace/controller.rs index 789fb6a0a0..2edf7eea57 100644 --- a/frontend/rust-lib/flowy-core/src/services/workspace/controller.rs +++ b/frontend/rust-lib/flowy-core/src/services/workspace/controller.rs @@ -9,8 +9,8 @@ use crate::{ TrashController, }, }; +use flowy_core_infra::entities::{app::RepeatedApp, workspace::*}; use flowy_database::SqliteConnection; -use flowy_workspace_infra::entities::{app::RepeatedApp, workspace::*}; use lib_infra::kv::KV; use std::sync::Arc; diff --git a/frontend/rust-lib/flowy-core/src/services/workspace/event_handler.rs b/frontend/rust-lib/flowy-core/src/services/workspace/event_handler.rs index e52ed5772c..7f04b7f56c 100644 --- a/frontend/rust-lib/flowy-core/src/services/workspace/event_handler.rs +++ b/frontend/rust-lib/flowy-core/src/services/workspace/event_handler.rs @@ -1,6 +1,6 @@ use crate::{errors::WorkspaceError, services::WorkspaceController}; -use flowy_workspace_infra::entities::{app::RepeatedApp, workspace::*}; +use flowy_core_infra::entities::{app::RepeatedApp, workspace::*}; use lib_dispatch::prelude::{data_result, Data, DataResult, Unit}; use std::{convert::TryInto, sync::Arc}; diff --git a/shared-lib/Cargo.lock b/shared-lib/Cargo.lock index eafd1ca8d7..a09a4f3f5f 100644 --- a/shared-lib/Cargo.lock +++ b/shared-lib/Cargo.lock @@ -258,8 +258,8 @@ dependencies = [ "bytes", "config", "derive_more", + "flowy-core-infra", "flowy-user-infra", - "flowy-workspace-infra", "hyper", "lazy_static", "log", @@ -657,6 +657,23 @@ dependencies = [ "syn", ] +[[package]] +name = "flowy-core-infra" +version = "0.1.0" +dependencies = [ + "bytes", + "chrono", + "derive_more", + "flowy-derive", + "flowy-document-infra", + "log", + "protobuf", + "strum", + "strum_macros", + "unicode-segmentation", + "uuid", +] + [[package]] name = "flowy-derive" version = "0.1.0" @@ -710,23 +727,6 @@ dependencies = [ "validator", ] -[[package]] -name = "flowy-workspace-infra" -version = "0.1.0" -dependencies = [ - "bytes", - "chrono", - "derive_more", - "flowy-derive", - "flowy-document-infra", - "log", - "protobuf", - "strum", - "strum_macros", - "unicode-segmentation", - "uuid", -] - [[package]] name = "fnv" version = "1.0.7" diff --git a/shared-lib/Cargo.toml b/shared-lib/Cargo.toml index 80961d62a2..970ce58de4 100644 --- a/shared-lib/Cargo.toml +++ b/shared-lib/Cargo.toml @@ -1,7 +1,7 @@ [workspace] members = [ "flowy-user-infra", - "flowy-workspace-infra", + "flowy-core-infra", "flowy-document-infra", "lib-ot", "lib-ws", diff --git a/shared-lib/backend-service/Cargo.toml b/shared-lib/backend-service/Cargo.toml index 1ff700b542..2f7fae8454 100644 --- a/shared-lib/backend-service/Cargo.toml +++ b/shared-lib/backend-service/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -flowy-workspace-infra = { path = "../flowy-workspace-infra" } +flowy-core-infra = { path = "../flowy-core-infra" } flowy-user-infra = { path = "../flowy-user-infra" } log = "0.4.14" diff --git a/shared-lib/backend-service/src/workspace_request.rs b/shared-lib/backend-service/src/workspace_request.rs index 440c429719..8aa1ad640a 100644 --- a/shared-lib/backend-service/src/workspace_request.rs +++ b/shared-lib/backend-service/src/workspace_request.rs @@ -1,5 +1,5 @@ use crate::{configuration::HEADER_TOKEN, errors::ServerError, request::HttpRequestBuilder}; -use flowy_workspace_infra::entities::prelude::*; +use flowy_core_infra::entities::prelude::*; pub(crate) fn request_builder() -> HttpRequestBuilder { HttpRequestBuilder::new().middleware(crate::middleware::BACKEND_API_MIDDLEWARE.clone()) diff --git a/shared-lib/flowy-workspace-infra/Cargo.toml b/shared-lib/flowy-core-infra/Cargo.toml similarity index 94% rename from shared-lib/flowy-workspace-infra/Cargo.toml rename to shared-lib/flowy-core-infra/Cargo.toml index d8c8459ae1..71ff468c9a 100644 --- a/shared-lib/flowy-workspace-infra/Cargo.toml +++ b/shared-lib/flowy-core-infra/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "flowy-workspace-infra" +name = "flowy-core-infra" version = "0.1.0" edition = "2018" diff --git a/shared-lib/flowy-workspace-infra/Flowy.toml b/shared-lib/flowy-core-infra/Flowy.toml similarity index 100% rename from shared-lib/flowy-workspace-infra/Flowy.toml rename to shared-lib/flowy-core-infra/Flowy.toml diff --git a/shared-lib/flowy-workspace-infra/src/entities/app/app_create.rs b/shared-lib/flowy-core-infra/src/entities/app/app_create.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/entities/app/app_create.rs rename to shared-lib/flowy-core-infra/src/entities/app/app_create.rs diff --git a/shared-lib/flowy-workspace-infra/src/entities/app/app_query.rs b/shared-lib/flowy-core-infra/src/entities/app/app_query.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/entities/app/app_query.rs rename to shared-lib/flowy-core-infra/src/entities/app/app_query.rs diff --git a/shared-lib/flowy-workspace-infra/src/entities/app/app_update.rs b/shared-lib/flowy-core-infra/src/entities/app/app_update.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/entities/app/app_update.rs rename to shared-lib/flowy-core-infra/src/entities/app/app_update.rs diff --git a/shared-lib/flowy-workspace-infra/src/entities/app/mod.rs b/shared-lib/flowy-core-infra/src/entities/app/mod.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/entities/app/mod.rs rename to shared-lib/flowy-core-infra/src/entities/app/mod.rs diff --git a/shared-lib/flowy-workspace-infra/src/entities/mod.rs b/shared-lib/flowy-core-infra/src/entities/mod.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/entities/mod.rs rename to shared-lib/flowy-core-infra/src/entities/mod.rs diff --git a/shared-lib/flowy-workspace-infra/src/entities/share/export.rs b/shared-lib/flowy-core-infra/src/entities/share/export.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/entities/share/export.rs rename to shared-lib/flowy-core-infra/src/entities/share/export.rs diff --git a/shared-lib/flowy-workspace-infra/src/entities/share/mod.rs b/shared-lib/flowy-core-infra/src/entities/share/mod.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/entities/share/mod.rs rename to shared-lib/flowy-core-infra/src/entities/share/mod.rs diff --git a/shared-lib/flowy-workspace-infra/src/entities/trash/mod.rs b/shared-lib/flowy-core-infra/src/entities/trash/mod.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/entities/trash/mod.rs rename to shared-lib/flowy-core-infra/src/entities/trash/mod.rs diff --git a/shared-lib/flowy-workspace-infra/src/entities/trash/trash_create.rs b/shared-lib/flowy-core-infra/src/entities/trash/trash_create.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/entities/trash/trash_create.rs rename to shared-lib/flowy-core-infra/src/entities/trash/trash_create.rs diff --git a/shared-lib/flowy-workspace-infra/src/entities/view/mod.rs b/shared-lib/flowy-core-infra/src/entities/view/mod.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/entities/view/mod.rs rename to shared-lib/flowy-core-infra/src/entities/view/mod.rs diff --git a/shared-lib/flowy-workspace-infra/src/entities/view/view_create.rs b/shared-lib/flowy-core-infra/src/entities/view/view_create.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/entities/view/view_create.rs rename to shared-lib/flowy-core-infra/src/entities/view/view_create.rs diff --git a/shared-lib/flowy-workspace-infra/src/entities/view/view_query.rs b/shared-lib/flowy-core-infra/src/entities/view/view_query.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/entities/view/view_query.rs rename to shared-lib/flowy-core-infra/src/entities/view/view_query.rs diff --git a/shared-lib/flowy-workspace-infra/src/entities/view/view_update.rs b/shared-lib/flowy-core-infra/src/entities/view/view_update.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/entities/view/view_update.rs rename to shared-lib/flowy-core-infra/src/entities/view/view_update.rs diff --git a/shared-lib/flowy-workspace-infra/src/entities/workspace/mod.rs b/shared-lib/flowy-core-infra/src/entities/workspace/mod.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/entities/workspace/mod.rs rename to shared-lib/flowy-core-infra/src/entities/workspace/mod.rs diff --git a/shared-lib/flowy-workspace-infra/src/entities/workspace/workspace_create.rs b/shared-lib/flowy-core-infra/src/entities/workspace/workspace_create.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/entities/workspace/workspace_create.rs rename to shared-lib/flowy-core-infra/src/entities/workspace/workspace_create.rs diff --git a/shared-lib/flowy-workspace-infra/src/entities/workspace/workspace_query.rs b/shared-lib/flowy-core-infra/src/entities/workspace/workspace_query.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/entities/workspace/workspace_query.rs rename to shared-lib/flowy-core-infra/src/entities/workspace/workspace_query.rs diff --git a/shared-lib/flowy-workspace-infra/src/entities/workspace/workspace_setting.rs b/shared-lib/flowy-core-infra/src/entities/workspace/workspace_setting.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/entities/workspace/workspace_setting.rs rename to shared-lib/flowy-core-infra/src/entities/workspace/workspace_setting.rs diff --git a/shared-lib/flowy-workspace-infra/src/entities/workspace/workspace_update.rs b/shared-lib/flowy-core-infra/src/entities/workspace/workspace_update.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/entities/workspace/workspace_update.rs rename to shared-lib/flowy-core-infra/src/entities/workspace/workspace_update.rs diff --git a/shared-lib/flowy-workspace-infra/src/errors.rs b/shared-lib/flowy-core-infra/src/errors.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/errors.rs rename to shared-lib/flowy-core-infra/src/errors.rs diff --git a/shared-lib/flowy-workspace-infra/src/lib.rs b/shared-lib/flowy-core-infra/src/lib.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/lib.rs rename to shared-lib/flowy-core-infra/src/lib.rs diff --git a/shared-lib/flowy-workspace-infra/src/macros.rs b/shared-lib/flowy-core-infra/src/macros.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/macros.rs rename to shared-lib/flowy-core-infra/src/macros.rs diff --git a/shared-lib/flowy-workspace-infra/src/parser/app/app_color_style.rs b/shared-lib/flowy-core-infra/src/parser/app/app_color_style.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/parser/app/app_color_style.rs rename to shared-lib/flowy-core-infra/src/parser/app/app_color_style.rs diff --git a/shared-lib/flowy-workspace-infra/src/parser/app/app_desc.rs b/shared-lib/flowy-core-infra/src/parser/app/app_desc.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/parser/app/app_desc.rs rename to shared-lib/flowy-core-infra/src/parser/app/app_desc.rs diff --git a/shared-lib/flowy-workspace-infra/src/parser/app/app_id.rs b/shared-lib/flowy-core-infra/src/parser/app/app_id.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/parser/app/app_id.rs rename to shared-lib/flowy-core-infra/src/parser/app/app_id.rs diff --git a/shared-lib/flowy-workspace-infra/src/parser/app/app_name.rs b/shared-lib/flowy-core-infra/src/parser/app/app_name.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/parser/app/app_name.rs rename to shared-lib/flowy-core-infra/src/parser/app/app_name.rs diff --git a/shared-lib/flowy-workspace-infra/src/parser/app/mod.rs b/shared-lib/flowy-core-infra/src/parser/app/mod.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/parser/app/mod.rs rename to shared-lib/flowy-core-infra/src/parser/app/mod.rs diff --git a/shared-lib/flowy-workspace-infra/src/parser/mod.rs b/shared-lib/flowy-core-infra/src/parser/mod.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/parser/mod.rs rename to shared-lib/flowy-core-infra/src/parser/mod.rs diff --git a/shared-lib/flowy-workspace-infra/src/parser/trash/mod.rs b/shared-lib/flowy-core-infra/src/parser/trash/mod.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/parser/trash/mod.rs rename to shared-lib/flowy-core-infra/src/parser/trash/mod.rs diff --git a/shared-lib/flowy-workspace-infra/src/parser/trash/trash_id.rs b/shared-lib/flowy-core-infra/src/parser/trash/trash_id.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/parser/trash/trash_id.rs rename to shared-lib/flowy-core-infra/src/parser/trash/trash_id.rs diff --git a/shared-lib/flowy-workspace-infra/src/parser/view/delta_data.rs b/shared-lib/flowy-core-infra/src/parser/view/delta_data.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/parser/view/delta_data.rs rename to shared-lib/flowy-core-infra/src/parser/view/delta_data.rs diff --git a/shared-lib/flowy-workspace-infra/src/parser/view/mod.rs b/shared-lib/flowy-core-infra/src/parser/view/mod.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/parser/view/mod.rs rename to shared-lib/flowy-core-infra/src/parser/view/mod.rs diff --git a/shared-lib/flowy-workspace-infra/src/parser/view/view_desc.rs b/shared-lib/flowy-core-infra/src/parser/view/view_desc.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/parser/view/view_desc.rs rename to shared-lib/flowy-core-infra/src/parser/view/view_desc.rs diff --git a/shared-lib/flowy-workspace-infra/src/parser/view/view_id.rs b/shared-lib/flowy-core-infra/src/parser/view/view_id.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/parser/view/view_id.rs rename to shared-lib/flowy-core-infra/src/parser/view/view_id.rs diff --git a/shared-lib/flowy-workspace-infra/src/parser/view/view_name.rs b/shared-lib/flowy-core-infra/src/parser/view/view_name.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/parser/view/view_name.rs rename to shared-lib/flowy-core-infra/src/parser/view/view_name.rs diff --git a/shared-lib/flowy-workspace-infra/src/parser/view/view_thumbnail.rs b/shared-lib/flowy-core-infra/src/parser/view/view_thumbnail.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/parser/view/view_thumbnail.rs rename to shared-lib/flowy-core-infra/src/parser/view/view_thumbnail.rs diff --git a/shared-lib/flowy-workspace-infra/src/parser/workspace/mod.rs b/shared-lib/flowy-core-infra/src/parser/workspace/mod.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/parser/workspace/mod.rs rename to shared-lib/flowy-core-infra/src/parser/workspace/mod.rs diff --git a/shared-lib/flowy-workspace-infra/src/parser/workspace/workspace_desc.rs b/shared-lib/flowy-core-infra/src/parser/workspace/workspace_desc.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/parser/workspace/workspace_desc.rs rename to shared-lib/flowy-core-infra/src/parser/workspace/workspace_desc.rs diff --git a/shared-lib/flowy-workspace-infra/src/parser/workspace/workspace_id.rs b/shared-lib/flowy-core-infra/src/parser/workspace/workspace_id.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/parser/workspace/workspace_id.rs rename to shared-lib/flowy-core-infra/src/parser/workspace/workspace_id.rs diff --git a/shared-lib/flowy-workspace-infra/src/parser/workspace/workspace_name.rs b/shared-lib/flowy-core-infra/src/parser/workspace/workspace_name.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/parser/workspace/workspace_name.rs rename to shared-lib/flowy-core-infra/src/parser/workspace/workspace_name.rs diff --git a/shared-lib/flowy-workspace-infra/src/protobuf/mod.rs b/shared-lib/flowy-core-infra/src/protobuf/mod.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/protobuf/mod.rs rename to shared-lib/flowy-core-infra/src/protobuf/mod.rs diff --git a/shared-lib/flowy-workspace-infra/src/protobuf/model/app_create.rs b/shared-lib/flowy-core-infra/src/protobuf/model/app_create.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/protobuf/model/app_create.rs rename to shared-lib/flowy-core-infra/src/protobuf/model/app_create.rs diff --git a/shared-lib/flowy-workspace-infra/src/protobuf/model/app_query.rs b/shared-lib/flowy-core-infra/src/protobuf/model/app_query.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/protobuf/model/app_query.rs rename to shared-lib/flowy-core-infra/src/protobuf/model/app_query.rs diff --git a/shared-lib/flowy-workspace-infra/src/protobuf/model/app_update.rs b/shared-lib/flowy-core-infra/src/protobuf/model/app_update.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/protobuf/model/app_update.rs rename to shared-lib/flowy-core-infra/src/protobuf/model/app_update.rs diff --git a/shared-lib/flowy-workspace-infra/src/protobuf/model/errors.rs b/shared-lib/flowy-core-infra/src/protobuf/model/errors.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/protobuf/model/errors.rs rename to shared-lib/flowy-core-infra/src/protobuf/model/errors.rs diff --git a/shared-lib/flowy-workspace-infra/src/protobuf/model/export.rs b/shared-lib/flowy-core-infra/src/protobuf/model/export.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/protobuf/model/export.rs rename to shared-lib/flowy-core-infra/src/protobuf/model/export.rs diff --git a/shared-lib/flowy-workspace-infra/src/protobuf/model/mod.rs b/shared-lib/flowy-core-infra/src/protobuf/model/mod.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/protobuf/model/mod.rs rename to shared-lib/flowy-core-infra/src/protobuf/model/mod.rs diff --git a/shared-lib/flowy-workspace-infra/src/protobuf/model/trash_create.rs b/shared-lib/flowy-core-infra/src/protobuf/model/trash_create.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/protobuf/model/trash_create.rs rename to shared-lib/flowy-core-infra/src/protobuf/model/trash_create.rs diff --git a/shared-lib/flowy-workspace-infra/src/protobuf/model/view_create.rs b/shared-lib/flowy-core-infra/src/protobuf/model/view_create.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/protobuf/model/view_create.rs rename to shared-lib/flowy-core-infra/src/protobuf/model/view_create.rs diff --git a/shared-lib/flowy-workspace-infra/src/protobuf/model/view_query.rs b/shared-lib/flowy-core-infra/src/protobuf/model/view_query.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/protobuf/model/view_query.rs rename to shared-lib/flowy-core-infra/src/protobuf/model/view_query.rs diff --git a/shared-lib/flowy-workspace-infra/src/protobuf/model/view_update.rs b/shared-lib/flowy-core-infra/src/protobuf/model/view_update.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/protobuf/model/view_update.rs rename to shared-lib/flowy-core-infra/src/protobuf/model/view_update.rs diff --git a/shared-lib/flowy-workspace-infra/src/protobuf/model/workspace_create.rs b/shared-lib/flowy-core-infra/src/protobuf/model/workspace_create.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/protobuf/model/workspace_create.rs rename to shared-lib/flowy-core-infra/src/protobuf/model/workspace_create.rs diff --git a/shared-lib/flowy-workspace-infra/src/protobuf/model/workspace_query.rs b/shared-lib/flowy-core-infra/src/protobuf/model/workspace_query.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/protobuf/model/workspace_query.rs rename to shared-lib/flowy-core-infra/src/protobuf/model/workspace_query.rs diff --git a/shared-lib/flowy-workspace-infra/src/protobuf/model/workspace_setting.rs b/shared-lib/flowy-core-infra/src/protobuf/model/workspace_setting.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/protobuf/model/workspace_setting.rs rename to shared-lib/flowy-core-infra/src/protobuf/model/workspace_setting.rs diff --git a/shared-lib/flowy-workspace-infra/src/protobuf/model/workspace_update.rs b/shared-lib/flowy-core-infra/src/protobuf/model/workspace_update.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/protobuf/model/workspace_update.rs rename to shared-lib/flowy-core-infra/src/protobuf/model/workspace_update.rs diff --git a/shared-lib/flowy-workspace-infra/src/protobuf/proto/app_create.proto b/shared-lib/flowy-core-infra/src/protobuf/proto/app_create.proto similarity index 100% rename from shared-lib/flowy-workspace-infra/src/protobuf/proto/app_create.proto rename to shared-lib/flowy-core-infra/src/protobuf/proto/app_create.proto diff --git a/shared-lib/flowy-workspace-infra/src/protobuf/proto/app_query.proto b/shared-lib/flowy-core-infra/src/protobuf/proto/app_query.proto similarity index 100% rename from shared-lib/flowy-workspace-infra/src/protobuf/proto/app_query.proto rename to shared-lib/flowy-core-infra/src/protobuf/proto/app_query.proto diff --git a/shared-lib/flowy-workspace-infra/src/protobuf/proto/app_update.proto b/shared-lib/flowy-core-infra/src/protobuf/proto/app_update.proto similarity index 100% rename from shared-lib/flowy-workspace-infra/src/protobuf/proto/app_update.proto rename to shared-lib/flowy-core-infra/src/protobuf/proto/app_update.proto diff --git a/shared-lib/flowy-workspace-infra/src/protobuf/proto/errors.proto b/shared-lib/flowy-core-infra/src/protobuf/proto/errors.proto similarity index 100% rename from shared-lib/flowy-workspace-infra/src/protobuf/proto/errors.proto rename to shared-lib/flowy-core-infra/src/protobuf/proto/errors.proto diff --git a/shared-lib/flowy-workspace-infra/src/protobuf/proto/export.proto b/shared-lib/flowy-core-infra/src/protobuf/proto/export.proto similarity index 100% rename from shared-lib/flowy-workspace-infra/src/protobuf/proto/export.proto rename to shared-lib/flowy-core-infra/src/protobuf/proto/export.proto diff --git a/shared-lib/flowy-workspace-infra/src/protobuf/proto/trash_create.proto b/shared-lib/flowy-core-infra/src/protobuf/proto/trash_create.proto similarity index 100% rename from shared-lib/flowy-workspace-infra/src/protobuf/proto/trash_create.proto rename to shared-lib/flowy-core-infra/src/protobuf/proto/trash_create.proto diff --git a/shared-lib/flowy-workspace-infra/src/protobuf/proto/view_create.proto b/shared-lib/flowy-core-infra/src/protobuf/proto/view_create.proto similarity index 100% rename from shared-lib/flowy-workspace-infra/src/protobuf/proto/view_create.proto rename to shared-lib/flowy-core-infra/src/protobuf/proto/view_create.proto diff --git a/shared-lib/flowy-workspace-infra/src/protobuf/proto/view_query.proto b/shared-lib/flowy-core-infra/src/protobuf/proto/view_query.proto similarity index 100% rename from shared-lib/flowy-workspace-infra/src/protobuf/proto/view_query.proto rename to shared-lib/flowy-core-infra/src/protobuf/proto/view_query.proto diff --git a/shared-lib/flowy-workspace-infra/src/protobuf/proto/view_update.proto b/shared-lib/flowy-core-infra/src/protobuf/proto/view_update.proto similarity index 100% rename from shared-lib/flowy-workspace-infra/src/protobuf/proto/view_update.proto rename to shared-lib/flowy-core-infra/src/protobuf/proto/view_update.proto diff --git a/shared-lib/flowy-workspace-infra/src/protobuf/proto/workspace_create.proto b/shared-lib/flowy-core-infra/src/protobuf/proto/workspace_create.proto similarity index 100% rename from shared-lib/flowy-workspace-infra/src/protobuf/proto/workspace_create.proto rename to shared-lib/flowy-core-infra/src/protobuf/proto/workspace_create.proto diff --git a/shared-lib/flowy-workspace-infra/src/protobuf/proto/workspace_query.proto b/shared-lib/flowy-core-infra/src/protobuf/proto/workspace_query.proto similarity index 100% rename from shared-lib/flowy-workspace-infra/src/protobuf/proto/workspace_query.proto rename to shared-lib/flowy-core-infra/src/protobuf/proto/workspace_query.proto diff --git a/shared-lib/flowy-workspace-infra/src/protobuf/proto/workspace_setting.proto b/shared-lib/flowy-core-infra/src/protobuf/proto/workspace_setting.proto similarity index 100% rename from shared-lib/flowy-workspace-infra/src/protobuf/proto/workspace_setting.proto rename to shared-lib/flowy-core-infra/src/protobuf/proto/workspace_setting.proto diff --git a/shared-lib/flowy-workspace-infra/src/protobuf/proto/workspace_update.proto b/shared-lib/flowy-core-infra/src/protobuf/proto/workspace_update.proto similarity index 100% rename from shared-lib/flowy-workspace-infra/src/protobuf/proto/workspace_update.proto rename to shared-lib/flowy-core-infra/src/protobuf/proto/workspace_update.proto diff --git a/shared-lib/flowy-workspace-infra/src/user_default.rs b/shared-lib/flowy-core-infra/src/user_default.rs similarity index 100% rename from shared-lib/flowy-workspace-infra/src/user_default.rs rename to shared-lib/flowy-core-infra/src/user_default.rs diff --git a/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs b/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs index f5f90b2b79..0b2e87e489 100644 --- a/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs +++ b/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs @@ -24,6 +24,13 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { | "FFIResponse" | "SubscribeObject" | "UserError" + | "CreateDocParams" + | "Doc" + | "UpdateDocParams" + | "DocDelta" + | "NewDocUser" + | "DocIdentifier" + | "WsDocumentData" | "QueryAppRequest" | "AppIdentifier" | "CreateAppRequest" @@ -57,13 +64,6 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { | "RepeatedView" | "ExportRequest" | "ExportData" - | "CreateDocParams" - | "Doc" - | "UpdateDocParams" - | "DocDelta" - | "NewDocUser" - | "DocIdentifier" - | "WsDocumentData" | "WsError" | "WsMessage" | "Revision" @@ -88,10 +88,10 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { | "FFIStatusCode" | "UserEvent" | "UserNotification" + | "WsDataType" | "TrashType" | "ViewType" | "ExportType" - | "WsDataType" | "WsModule" | "RevType" => TypeCategory::Enum, From d80061461bdeba6376888619bb667d406d10063d Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 11 Dec 2021 13:47:16 +0800 Subject: [PATCH 18/39] add flowy-collaboration crate --- backend/Cargo.lock | 15 +- backend/Cargo.toml | 2 +- backend/src/entities/doc.rs | 2 +- backend/src/services/doc/crud.rs | 2 +- backend/src/services/doc/edit/edit_actor.rs | 2 +- backend/src/services/doc/edit/editor.rs | 10 +- backend/src/services/doc/manager.rs | 2 +- backend/src/services/doc/router.rs | 2 +- backend/src/services/doc/ws_actor.rs | 2 +- backend/src/services/user/user_default.rs | 2 +- backend/src/services/view/view.rs | 2 +- backend/src/web_socket/entities/message.rs | 2 +- backend/tests/api/doc.rs | 2 +- backend/tests/document/edit.rs | 2 +- backend/tests/document/helper.rs | 2 +- backend/tests/util/helper.rs | 2 +- .../user/infrastructure/deps_resolver.dart | 9 +- .../user/presentation/skip_log_in_screen.dart | 1 - .../edit_pannel/edit_pannel_bloc.dart | 4 +- .../workspace/application/menu/menu_bloc.dart | 1 - .../application/menu/menu_user_bloc.dart | 1 - .../app_flowy/lib/workspace/domain/i_app.dart | 2 - .../app_flowy/lib/workspace/domain/i_doc.dart | 2 +- .../domain/page_stack/page_stack.dart | 1 - .../workspace/infrastructure/i_doc_impl.dart | 2 +- .../infrastructure/repos/app_repo.dart | 1 - .../infrastructure/repos/doc_repo.dart | 2 +- .../infrastructure/repos/user_repo.dart | 2 - .../doc/widget/toolbar/header_button.dart | 1 - .../stack_page/trash/trash_page.dart | 1 - .../menu/widget/app/create_button.dart | 1 - .../widgets/menu/widget/app/section/item.dart | 1 - .../widgets/menu/widget/menu_trash.dart | 1 - .../packages/flowy_infra/lib/color.dart | 14 +- .../packages/flowy_infra/lib/theme.dart | 1 - .../lib/src/flowy_overlay/layout.dart | 3 - .../lib/style_widget/button.dart | 1 - .../lib/style_widget/extension.dart | 1 - .../lib/style_widget/progress_indicator.dart | 1 - .../widget/buttons/base_styled_button.dart | 2 - .../lib/widget/clickable_extension.dart | 1 - .../lib/widget/mouse_hover_builder.dart | 1 - .../flowy_sdk/lib/dispatch/dispatch.dart | 2 +- .../doc.pb.dart | 0 .../doc.pbenum.dart | 0 .../doc.pbjson.dart | 0 .../doc.pbserver.dart | 0 .../protobuf.dart | 0 .../ws.pb.dart | 0 .../ws.pbenum.dart | 0 .../ws.pbjson.dart | 0 .../ws.pbserver.dart | 0 frontend/rust-lib/flowy-core/Cargo.toml | 2 +- .../flowy-core/src/core/core_context.rs | 2 +- .../src/services/view/controller.rs | 2 +- .../src/services/view/event_handler.rs | 2 +- frontend/rust-lib/flowy-document/Cargo.toml | 2 +- .../rust-lib/flowy-document/src/errors.rs | 4 +- .../rust-lib/flowy-document/src/module.rs | 2 +- .../src/services/doc/controller.rs | 2 +- .../src/services/doc/edit/editor.rs | 6 +- .../src/services/doc/edit/model.rs | 2 +- .../src/services/doc/edit/queue.rs | 4 +- .../src/services/doc/revision/cache.rs | 2 +- .../src/services/doc/revision/manager.rs | 2 +- .../src/services/doc/revision/sync.rs | 10 +- .../flowy-document/src/services/server/mod.rs | 2 +- .../src/services/server/server_api.rs | 2 +- .../src/services/server/server_api_mock.rs | 2 +- .../src/services/ws/ws_manager.rs | 2 +- .../src/sql_tables/doc/rev_table.rs | 2 +- .../tests/editor/attribute_test.rs | 2 +- .../flowy-document/tests/editor/mod.rs | 2 +- .../flowy-document/tests/editor/op_test.rs | 2 +- .../flowy-document/tests/editor/serde_test.rs | 2 +- .../tests/editor/undo_redo_test.rs | 2 +- frontend/rust-lib/flowy-sdk/Cargo.toml | 2 +- .../src/deps_resolve/document_deps.rs | 2 +- frontend/rust-lib/flowy-test/Cargo.toml | 2 +- frontend/rust-lib/flowy-test/src/editor.rs | 4 +- frontend/rust-lib/flowy-test/src/helper.rs | 2 +- .../src/services/user/ws_manager.rs | 20 +- shared-lib/Cargo.lock | 5 +- shared-lib/Cargo.toml | 2 +- .../Cargo.toml | 5 +- .../Flowy.toml | 0 .../src/READ_ME.json | 0 .../src/core/document}/data.rs | 0 .../src/core/document}/document.rs | 2 +- .../extensions/delete/default_delete.rs | 2 +- .../core/document}/extensions/delete/mod.rs | 0 .../delete/preserve_line_format_merge.rs | 2 +- .../extensions/format/format_at_position.rs | 0 .../core/document}/extensions/format/mod.rs | 10 +- .../extensions/format/resolve_block_format.rs | 12 +- .../format/resolve_inline_format.rs | 10 +- .../src/core/document/extensions}/helper.rs | 0 .../extensions/insert/auto_exit_block.rs | 2 +- .../extensions/insert/auto_format.rs | 2 +- .../extensions/insert/default_insert.rs | 2 +- .../core/document}/extensions/insert/mod.rs | 2 +- .../insert/preserve_block_format.rs | 2 +- .../insert/preserve_inline_format.rs | 2 +- .../insert/reset_format_on_new_line.rs | 2 +- .../src/core/document}/extensions/mod.rs | 2 +- .../src/core/document}/history.rs | 0 .../src/core/document}/mod.rs | 4 +- .../src/core/document}/view.rs | 2 +- .../flowy-collaboration/src/core/mod.rs | 2 + .../flowy-collaboration/src/core/sync/mod.rs | 3 + .../src/core/sync/rev_sync.rs | 208 ++++++++++++++++++ .../src/entities/doc/doc.rs | 0 .../src/entities/doc/mod.rs | 0 .../src/entities/doc/parser/doc_id.rs | 0 .../src/entities/doc/parser/mod.rs | 0 .../src/entities/mod.rs | 0 .../src/entities/ws/mod.rs | 0 .../src/entities/ws/ws.rs | 0 .../src/errors.rs | 0 .../src/lib.rs | 0 .../src/protobuf/mod.rs | 0 .../src/protobuf/model/doc.rs | 0 .../src/protobuf/model/mod.rs | 0 .../src/protobuf/model/ws.rs | 0 .../src/protobuf/proto/doc.proto | 0 .../src/protobuf/proto/ws.proto | 0 .../src/user_default.rs | 0 .../src/util.rs | 0 shared-lib/flowy-core-infra/Cargo.toml | 2 +- .../src/entities/view/view_create.rs | 2 +- .../src/entities/view/view_query.rs | 2 +- .../src/derive_cache/derive_cache.rs | 16 +- 132 files changed, 352 insertions(+), 164 deletions(-) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-document-infra => flowy-collaboration}/doc.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-document-infra => flowy-collaboration}/doc.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-document-infra => flowy-collaboration}/doc.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-document-infra => flowy-collaboration}/doc.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-document-infra => flowy-collaboration}/protobuf.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-document-infra => flowy-collaboration}/ws.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-document-infra => flowy-collaboration}/ws.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-document-infra => flowy-collaboration}/ws.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-document-infra => flowy-collaboration}/ws.pbserver.dart (100%) rename shared-lib/{flowy-document-infra => flowy-collaboration}/Cargo.toml (88%) rename shared-lib/{flowy-document-infra => flowy-collaboration}/Flowy.toml (100%) rename shared-lib/{flowy-document-infra => flowy-collaboration}/src/READ_ME.json (100%) rename shared-lib/{flowy-document-infra/src/core => flowy-collaboration/src/core/document}/data.rs (100%) rename shared-lib/{flowy-document-infra/src/core => flowy-collaboration/src/core/document}/document.rs (99%) rename shared-lib/{flowy-document-infra/src/core => flowy-collaboration/src/core/document}/extensions/delete/default_delete.rs (92%) rename shared-lib/{flowy-document-infra/src/core => flowy-collaboration/src/core/document}/extensions/delete/mod.rs (100%) rename shared-lib/{flowy-document-infra/src/core => flowy-collaboration/src/core/document}/extensions/delete/preserve_line_format_merge.rs (97%) rename shared-lib/{flowy-document-infra/src/core => flowy-collaboration/src/core/document}/extensions/format/format_at_position.rs (100%) rename shared-lib/{flowy-document-infra/src/core => flowy-collaboration/src/core/document}/extensions/format/mod.rs (93%) rename shared-lib/{flowy-document-infra/src/core => flowy-collaboration/src/core/document}/extensions/format/resolve_block_format.rs (91%) rename shared-lib/{flowy-document-infra/src/core => flowy-collaboration/src/core/document}/extensions/format/resolve_inline_format.rs (93%) rename shared-lib/{flowy-document-infra/src/core/extensions/format => flowy-collaboration/src/core/document/extensions}/helper.rs (100%) rename shared-lib/{flowy-document-infra/src/core => flowy-collaboration/src/core/document}/extensions/insert/auto_exit_block.rs (96%) rename shared-lib/{flowy-document-infra/src/core => flowy-collaboration/src/core/document}/extensions/insert/auto_format.rs (97%) rename shared-lib/{flowy-document-infra/src/core => flowy-collaboration/src/core/document}/extensions/insert/default_insert.rs (97%) rename shared-lib/{flowy-document-infra/src/core => flowy-collaboration/src/core/document}/extensions/insert/mod.rs (95%) rename shared-lib/{flowy-document-infra/src/core => flowy-collaboration/src/core/document}/extensions/insert/preserve_block_format.rs (97%) rename shared-lib/{flowy-document-infra/src/core => flowy-collaboration/src/core/document}/extensions/insert/preserve_inline_format.rs (98%) rename shared-lib/{flowy-document-infra/src/core => flowy-collaboration/src/core/document}/extensions/insert/reset_format_on_new_line.rs (95%) rename shared-lib/{flowy-document-infra/src/core => flowy-collaboration/src/core/document}/extensions/mod.rs (98%) rename shared-lib/{flowy-document-infra/src/core => flowy-collaboration/src/core/document}/history.rs (100%) rename shared-lib/{flowy-document-infra/src/core => flowy-collaboration/src/core/document}/mod.rs (51%) rename shared-lib/{flowy-document-infra/src/core => flowy-collaboration/src/core/document}/view.rs (99%) create mode 100644 shared-lib/flowy-collaboration/src/core/mod.rs create mode 100644 shared-lib/flowy-collaboration/src/core/sync/mod.rs create mode 100644 shared-lib/flowy-collaboration/src/core/sync/rev_sync.rs rename shared-lib/{flowy-document-infra => flowy-collaboration}/src/entities/doc/doc.rs (100%) rename shared-lib/{flowy-document-infra => flowy-collaboration}/src/entities/doc/mod.rs (100%) rename shared-lib/{flowy-document-infra => flowy-collaboration}/src/entities/doc/parser/doc_id.rs (100%) rename shared-lib/{flowy-document-infra => flowy-collaboration}/src/entities/doc/parser/mod.rs (100%) rename shared-lib/{flowy-document-infra => flowy-collaboration}/src/entities/mod.rs (100%) rename shared-lib/{flowy-document-infra => flowy-collaboration}/src/entities/ws/mod.rs (100%) rename shared-lib/{flowy-document-infra => flowy-collaboration}/src/entities/ws/ws.rs (100%) rename shared-lib/{flowy-document-infra => flowy-collaboration}/src/errors.rs (100%) rename shared-lib/{flowy-document-infra => flowy-collaboration}/src/lib.rs (100%) rename shared-lib/{flowy-document-infra => flowy-collaboration}/src/protobuf/mod.rs (100%) rename shared-lib/{flowy-document-infra => flowy-collaboration}/src/protobuf/model/doc.rs (100%) rename shared-lib/{flowy-document-infra => flowy-collaboration}/src/protobuf/model/mod.rs (100%) rename shared-lib/{flowy-document-infra => flowy-collaboration}/src/protobuf/model/ws.rs (100%) rename shared-lib/{flowy-document-infra => flowy-collaboration}/src/protobuf/proto/doc.proto (100%) rename shared-lib/{flowy-document-infra => flowy-collaboration}/src/protobuf/proto/ws.proto (100%) rename shared-lib/{flowy-document-infra => flowy-collaboration}/src/user_default.rs (100%) rename shared-lib/{flowy-document-infra => flowy-collaboration}/src/util.rs (100%) diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 32efba1a58..c5504943a5 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -457,7 +457,7 @@ dependencies = [ "derive_more", "flowy-core-infra", "flowy-document", - "flowy-document-infra", + "flowy-ot", "flowy-sdk", "flowy-test", "flowy-user", @@ -1213,7 +1213,7 @@ dependencies = [ "flowy-database", "flowy-derive", "flowy-document", - "flowy-document-infra", + "flowy-ot", "futures", "futures-core", "lazy_static", @@ -1240,7 +1240,7 @@ dependencies = [ "chrono", "derive_more", "flowy-derive", - "flowy-document-infra", + "flowy-ot", "log", "protobuf", "strum", @@ -1286,7 +1286,7 @@ dependencies = [ "diesel_derives", "flowy-database", "flowy-derive", - "flowy-document-infra", + "flowy-ot", "futures", "futures-core", "futures-util", @@ -1310,7 +1310,7 @@ dependencies = [ ] [[package]] -name = "flowy-document-infra" +name = "flowy-ot" version = "0.1.0" dependencies = [ "bytes", @@ -1319,6 +1319,7 @@ dependencies = [ "lib-ot", "log", "md5", + "parking_lot", "protobuf", "serde", "strum", @@ -1338,7 +1339,7 @@ dependencies = [ "flowy-core", "flowy-database", "flowy-document", - "flowy-document-infra", + "flowy-ot", "flowy-user", "futures-core", "lib-dispatch", @@ -1361,7 +1362,7 @@ dependencies = [ "claim", "flowy-core", "flowy-document", - "flowy-document-infra", + "flowy-ot", "flowy-sdk", "flowy-user", "futures-util", diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 9fefaf3941..f6a7d9aa76 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -61,7 +61,7 @@ async-stream = "0.3.2" flowy-user-infra = { path = "../shared-lib/flowy-user-infra" } flowy-core-infra = { path = "../shared-lib/flowy-core-infra" } -flowy-document-infra = { path = "../shared-lib/flowy-document-infra" } +flowy-collaboration = { path = "../shared-lib/flowy-collaboration" } lib-ws = { path = "../shared-lib/lib-ws" } lib-ot = { path = "../shared-lib/lib-ot" } backend-service = { path = "../shared-lib/backend-service", features = ["http_server"] } diff --git a/backend/src/entities/doc.rs b/backend/src/entities/doc.rs index c1c47a8ca4..a6d7b9fd03 100644 --- a/backend/src/entities/doc.rs +++ b/backend/src/entities/doc.rs @@ -1,4 +1,4 @@ -use flowy_document_infra::protobuf::Doc; +use flowy_collaboration::protobuf::Doc; pub(crate) const DOC_TABLE: &str = "doc_table"; diff --git a/backend/src/services/doc/crud.rs b/backend/src/services/doc/crud.rs index a2c5a00864..0d83d5922a 100644 --- a/backend/src/services/doc/crud.rs +++ b/backend/src/services/doc/crud.rs @@ -4,7 +4,7 @@ use crate::{ }; use anyhow::Context; use backend_service::errors::ServerError; -use flowy_document_infra::protobuf::{CreateDocParams, Doc, DocIdentifier, UpdateDocParams}; +use flowy_collaboration::protobuf::{CreateDocParams, Doc, DocIdentifier, UpdateDocParams}; use sqlx::{postgres::PgArguments, PgPool, Postgres}; use uuid::Uuid; diff --git a/backend/src/services/doc/edit/edit_actor.rs b/backend/src/services/doc/edit/edit_actor.rs index f73dfa0237..0bbca02419 100644 --- a/backend/src/services/doc/edit/edit_actor.rs +++ b/backend/src/services/doc/edit/edit_actor.rs @@ -5,7 +5,7 @@ use crate::{ use actix_web::web::Data; use async_stream::stream; use backend_service::errors::{internal_error, Result as DocResult, ServerError}; -use flowy_document_infra::protobuf::Doc; +use flowy_collaboration::protobuf::Doc; use futures::stream::StreamExt; use lib_ot::protobuf::Revision; use sqlx::PgPool; diff --git a/backend/src/services/doc/edit/editor.rs b/backend/src/services/doc/edit/editor.rs index 96b10c710d..f78d265e53 100644 --- a/backend/src/services/doc/edit/editor.rs +++ b/backend/src/services/doc/edit/editor.rs @@ -8,8 +8,8 @@ use crate::{ use actix_web::web::Data; use backend_service::errors::{internal_error, ServerError}; use dashmap::DashMap; -use flowy_document_infra::{ - core::Document, +use flowy_collaboration::{ + core::document::Document, entities::ws::{WsDataType, WsDocumentData}, protobuf::{Doc, UpdateDocParams}, }; @@ -102,8 +102,9 @@ impl ServerDocEditor { let next_rev_id = next(cur_rev_id); if cur_rev_id == revision.base_rev_id || next_rev_id == revision.base_rev_id { // The rev is in the right order, just compose it. - let _ = self.compose_revision(&revision, pg_pool).await?; + let _ = self.compose_revision(&revision).await?; let _ = send_acked_msg(&user.socket, &revision)?; + let _ = self.save_revision(&revision, pg_pool).await?; } else { // The server document is outdated, pull the missing revision from the client. let _ = send_pull_message(&user.socket, &self.doc_id, next_rev_id, revision.rev_id)?; @@ -126,11 +127,10 @@ impl ServerDocEditor { pub fn document_json(&self) -> String { self.document.read().to_json() } - async fn compose_revision(&self, revision: &Revision, pg_pool: Data) -> Result<(), ServerError> { + async fn compose_revision(&self, revision: &Revision) -> Result<(), ServerError> { let delta = RichTextDelta::from_bytes(&revision.delta_data).map_err(internal_error)?; let _ = self.compose_delta(delta)?; let _ = self.rev_id.fetch_update(SeqCst, SeqCst, |_e| Some(revision.rev_id)); - let _ = self.save_revision(&revision, pg_pool).await?; Ok(()) } diff --git a/backend/src/services/doc/manager.rs b/backend/src/services/doc/manager.rs index 4b3159f9f9..4ea6255726 100644 --- a/backend/src/services/doc/manager.rs +++ b/backend/src/services/doc/manager.rs @@ -9,7 +9,7 @@ use crate::{ use actix_web::web::Data; use backend_service::errors::{internal_error, Result as DocResult, ServerError}; use dashmap::DashMap; -use flowy_document_infra::protobuf::{Doc, DocIdentifier}; +use flowy_collaboration::protobuf::{Doc, DocIdentifier}; use lib_ot::protobuf::Revision; use sqlx::PgPool; use std::sync::Arc; diff --git a/backend/src/services/doc/router.rs b/backend/src/services/doc/router.rs index 8446c4336b..74883ae4f6 100644 --- a/backend/src/services/doc/router.rs +++ b/backend/src/services/doc/router.rs @@ -8,7 +8,7 @@ use actix_web::{ }; use anyhow::Context; use backend_service::{errors::ServerError, response::FlowyResponse}; -use flowy_document_infra::protobuf::{CreateDocParams, DocIdentifier, UpdateDocParams}; +use flowy_collaboration::protobuf::{CreateDocParams, DocIdentifier, UpdateDocParams}; use sqlx::PgPool; pub async fn create_handler(payload: Payload, pool: Data) -> Result { diff --git a/backend/src/services/doc/ws_actor.rs b/backend/src/services/doc/ws_actor.rs index b6542588d5..71deaf1d2a 100644 --- a/backend/src/services/doc/ws_actor.rs +++ b/backend/src/services/doc/ws_actor.rs @@ -9,7 +9,7 @@ use actix_rt::task::spawn_blocking; use actix_web::web::Data; use async_stream::stream; use backend_service::errors::{internal_error, Result as DocResult, ServerError}; -use flowy_document_infra::protobuf::{NewDocUser, WsDataType, WsDocumentData}; +use flowy_collaboration::protobuf::{NewDocUser, WsDataType, WsDocumentData}; use futures::stream::StreamExt; use lib_ot::protobuf::Revision; use sqlx::PgPool; diff --git a/backend/src/services/user/user_default.rs b/backend/src/services/user/user_default.rs index a70e493b69..380e77e0af 100644 --- a/backend/src/services/user/user_default.rs +++ b/backend/src/services/user/user_default.rs @@ -9,8 +9,8 @@ use crate::{ use crate::services::view::{create_view_with_args, sql_builder::NewViewSqlBuilder}; use backend_service::errors::ServerError; use chrono::Utc; +use flowy_collaboration::user_default::doc_initial_string; use flowy_core_infra::protobuf::Workspace; -use flowy_document_infra::user_default::doc_initial_string; use std::convert::TryInto; #[allow(dead_code)] diff --git a/backend/src/services/view/view.rs b/backend/src/services/view/view.rs index 4cb7d65b80..05715303d5 100644 --- a/backend/src/services/view/view.rs +++ b/backend/src/services/view/view.rs @@ -10,6 +10,7 @@ use crate::{ }; use backend_service::errors::{invalid_params, ServerError}; use chrono::Utc; +use flowy_collaboration::protobuf::CreateDocParams; use flowy_core_infra::{ parser::{ app::AppId, @@ -17,7 +18,6 @@ use flowy_core_infra::{ }, protobuf::{CreateViewParams, RepeatedView, View}, }; -use flowy_document_infra::protobuf::CreateDocParams; use sqlx::{postgres::PgArguments, Postgres}; use uuid::Uuid; diff --git a/backend/src/web_socket/entities/message.rs b/backend/src/web_socket/entities/message.rs index 0ebc379b8c..9438d9587e 100644 --- a/backend/src/web_socket/entities/message.rs +++ b/backend/src/web_socket/entities/message.rs @@ -1,6 +1,6 @@ use actix::Message; use bytes::Bytes; -use flowy_document_infra::entities::ws::WsDocumentData; +use flowy_collaboration::entities::ws::WsDocumentData; use lib_ws::{WsMessage, WsModule}; use std::convert::TryInto; diff --git a/backend/tests/api/doc.rs b/backend/tests/api/doc.rs index 571d74ac4d..83b5d71285 100644 --- a/backend/tests/api/doc.rs +++ b/backend/tests/api/doc.rs @@ -1,6 +1,6 @@ use crate::util::helper::ViewTest; +use flowy_collaboration::entities::doc::DocIdentifier; use flowy_core_infra::entities::view::ViewIdentifiers; -use flowy_document_infra::entities::doc::DocIdentifier; #[actix_rt::test] async fn doc_read() { diff --git a/backend/tests/document/edit.rs b/backend/tests/document/edit.rs index 30d2be0850..274cf85579 100644 --- a/backend/tests/document/edit.rs +++ b/backend/tests/document/edit.rs @@ -1,5 +1,5 @@ use crate::document::helper::{DocScript, DocumentTest}; -use flowy_document_infra::core::{Document, FlowyDoc}; +use flowy_collaboration::core::document::{Document, FlowyDoc}; use lib_ot::{core::Interval, rich_text::RichTextAttribute}; #[rustfmt::skip] diff --git a/backend/tests/document/helper.rs b/backend/tests/document/helper.rs index b153ea6571..4f3b3dbf3c 100644 --- a/backend/tests/document/helper.rs +++ b/backend/tests/document/helper.rs @@ -11,7 +11,7 @@ use std::sync::Arc; use tokio::time::{sleep, Duration}; // use crate::helper::*; use crate::util::helper::{spawn_server, TestServer}; -use flowy_document_infra::{entities::doc::DocIdentifier, protobuf::UpdateDocParams}; +use flowy_collaboration::{entities::doc::DocIdentifier, protobuf::UpdateDocParams}; use lib_ot::rich_text::{RichTextAttribute, RichTextDelta}; use parking_lot::RwLock; use lib_ot::core::Interval; diff --git a/backend/tests/util/helper.rs b/backend/tests/util/helper.rs index 3fb8dcd617..42438bbb41 100644 --- a/backend/tests/util/helper.rs +++ b/backend/tests/util/helper.rs @@ -9,9 +9,9 @@ use backend_service::{ user_request::*, workspace_request::*, }; +use flowy_collaboration::entities::doc::{Doc, DocIdentifier}; use flowy_core_infra::entities::prelude::*; use flowy_document::services::server::read_doc_request; -use flowy_document_infra::entities::doc::{Doc, DocIdentifier}; use flowy_user_infra::entities::*; use sqlx::{Connection, Executor, PgConnection, PgPool}; use uuid::Uuid; diff --git a/frontend/app_flowy/lib/user/infrastructure/deps_resolver.dart b/frontend/app_flowy/lib/user/infrastructure/deps_resolver.dart index 61397010fa..113f100c7b 100644 --- a/frontend/app_flowy/lib/user/infrastructure/deps_resolver.dart +++ b/frontend/app_flowy/lib/user/infrastructure/deps_resolver.dart @@ -11,7 +11,6 @@ import 'package:app_flowy/workspace/application/home/home_bloc.dart'; import 'package:app_flowy/workspace/application/home/home_listen_bloc.dart'; import 'package:app_flowy/workspace/domain/i_user.dart'; import 'package:app_flowy/workspace/infrastructure/i_user_impl.dart'; -import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile; import 'package:get_it/get_it.dart'; import 'network_monitor.dart'; @@ -34,11 +33,9 @@ class UserDepsResolver { getIt.registerFactory(() => EditPannelBloc()); getIt.registerFactory(() => SplashBloc(getIt())); - getIt.registerFactoryParam( - (user, _) => HomeListenBloc( - getIt(param1: user), - ), - ); + getIt.registerFactoryParam((user, _) => HomeListenBloc( + getIt(param1: user), + )); getIt.registerLazySingleton(() => NetworkMonitor()); } diff --git a/frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart b/frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart index f6fbfd9701..4c6df28b0f 100644 --- a/frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart +++ b/frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart @@ -11,7 +11,6 @@ import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/protobuf.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:url_launcher/url_launcher.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/edit_pannel/edit_pannel_bloc.dart b/frontend/app_flowy/lib/workspace/application/edit_pannel/edit_pannel_bloc.dart index 4b687e8eb8..ca4f6652b4 100644 --- a/frontend/app_flowy/lib/workspace/application/edit_pannel/edit_pannel_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/edit_pannel/edit_pannel_bloc.dart @@ -1,6 +1,5 @@ import 'package:app_flowy/workspace/domain/edit_context.dart'; import 'package:dartz/dartz.dart'; -import 'package:flutter/material.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; // ignore: import_of_legacy_library_into_null_safe import 'package:flutter_bloc/flutter_bloc.dart'; @@ -27,8 +26,7 @@ class EditPannelBloc extends Bloc { @freezed class EditPannelEvent with _$EditPannelEvent { - const factory EditPannelEvent.startEdit(EditPannelContext context) = - _StartEdit; + const factory EditPannelEvent.startEdit(EditPannelContext context) = _StartEdit; const factory EditPannelEvent.endEdit(EditPannelContext context) = _EndEdit; } diff --git a/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart b/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart index bb2c2d013b..84db381db7 100644 --- a/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart @@ -6,7 +6,6 @@ import 'package:dartz/dartz.dart'; import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/app_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; -import 'package:flutter/material.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart b/frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart index 5e1c4a1746..b68700f4d8 100644 --- a/frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart @@ -1,6 +1,5 @@ import 'package:app_flowy/workspace/domain/i_user.dart'; import 'package:flowy_log/flowy_log.dart'; -import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile; import 'package:flowy_sdk/protobuf/flowy-core-infra/workspace_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/app_flowy/lib/workspace/domain/i_app.dart b/frontend/app_flowy/lib/workspace/domain/i_app.dart index 255d1ab78a..3073809dc5 100644 --- a/frontend/app_flowy/lib/workspace/domain/i_app.dart +++ b/frontend/app_flowy/lib/workspace/domain/i_app.dart @@ -1,5 +1,3 @@ -import 'package:flowy_sdk/protobuf/flowy-core-infra/app_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/protobuf.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; diff --git a/frontend/app_flowy/lib/workspace/domain/i_doc.dart b/frontend/app_flowy/lib/workspace/domain/i_doc.dart index 9092302b70..14c99c5118 100644 --- a/frontend/app_flowy/lib/workspace/domain/i_doc.dart +++ b/frontend/app_flowy/lib/workspace/domain/i_doc.dart @@ -1,6 +1,6 @@ import 'dart:async'; import 'package:dartz/dartz.dart'; -import 'package:flowy_sdk/protobuf/flowy-document-infra/doc.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-collaboration/doc.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; abstract class IDoc { diff --git a/frontend/app_flowy/lib/workspace/domain/page_stack/page_stack.dart b/frontend/app_flowy/lib/workspace/domain/page_stack/page_stack.dart index d01b77ba59..8c908d1a9a 100644 --- a/frontend/app_flowy/lib/workspace/domain/page_stack/page_stack.dart +++ b/frontend/app_flowy/lib/workspace/domain/page_stack/page_stack.dart @@ -2,7 +2,6 @@ import 'package:flowy_infra/notifier.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:app_flowy/startup/startup.dart'; -import 'package:app_flowy/workspace/presentation/stack_page/blank/blank_page.dart'; import 'package:app_flowy/workspace/presentation/stack_page/home_stack.dart'; import 'package:app_flowy/workspace/presentation/widgets/prelude.dart'; diff --git a/frontend/app_flowy/lib/workspace/infrastructure/i_doc_impl.dart b/frontend/app_flowy/lib/workspace/infrastructure/i_doc_impl.dart index 141e4c45b4..a1f281bea0 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/i_doc_impl.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/i_doc_impl.dart @@ -4,7 +4,7 @@ import 'dart:typed_data'; import 'package:dartz/dartz.dart'; import 'package:app_flowy/workspace/domain/i_doc.dart'; import 'package:app_flowy/workspace/infrastructure/repos/doc_repo.dart'; -import 'package:flowy_sdk/protobuf/flowy-document-infra/doc.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-collaboration/doc.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; class IDocImpl extends IDoc { diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/app_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/app_repo.dart index 1fe3f2e00b..d5cb40af1c 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/app_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/app_repo.dart @@ -9,7 +9,6 @@ import 'package:flowy_sdk/protobuf/flowy-core-infra/app_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/app_query.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/app_update.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pbenum.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/observable.pb.dart'; import 'package:flowy_sdk/rust_stream.dart'; diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/doc_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/doc_repo.dart index 401d469f79..696143f6fd 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/doc_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/doc_repo.dart @@ -1,6 +1,6 @@ import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; -import 'package:flowy_sdk/protobuf/flowy-document-infra/doc.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-collaboration/doc.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/view_query.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/user_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/user_repo.dart index 3adaa87006..2d5411739a 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/user_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/user_repo.dart @@ -1,8 +1,6 @@ import 'dart:async'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; -import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile; import 'package:flowy_sdk/protobuf/flowy-core-infra/workspace_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/workspace_query.pb.dart'; import 'package:app_flowy/workspace/domain/i_user.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/toolbar/header_button.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/toolbar/header_button.dart index fce8ba6941..dbe3b413f9 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/toolbar/header_button.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/widget/toolbar/header_button.dart @@ -1,5 +1,4 @@ import 'package:flutter_quill/flutter_quill.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter_quill/models/documents/style.dart'; import 'package:flutter/material.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart index bd8c0c03b4..472f548d68 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart @@ -14,7 +14,6 @@ import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:provider/provider.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/create_button.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/create_button.dart index ef75be0232..503980ae86 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/create_button.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/create_button.dart @@ -5,7 +5,6 @@ import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/size.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flutter/material.dart'; -import 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart'; import 'package:flowy_infra_ui/style_widget/extension.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; // ignore: implementation_imports diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart index 11adbed14b..744d4f29f7 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/section/item.dart @@ -11,7 +11,6 @@ import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:provider/provider.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:app_flowy/workspace/domain/image.dart'; import 'package:app_flowy/workspace/presentation/widgets/menu/widget/app/menu_app.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_trash.dart b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_trash.dart index 7f6b094777..73bcbe40b8 100644 --- a/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_trash.dart +++ b/frontend/app_flowy/lib/workspace/presentation/widgets/menu/widget/menu_trash.dart @@ -7,7 +7,6 @@ import 'package:flowy_infra/image.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; import 'package:provider/provider.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; diff --git a/frontend/app_flowy/packages/flowy_infra/lib/color.dart b/frontend/app_flowy/packages/flowy_infra/lib/color.dart index 02af0d687a..68e194aaa7 100644 --- a/frontend/app_flowy/packages/flowy_infra/lib/color.dart +++ b/frontend/app_flowy/packages/flowy_infra/lib/color.dart @@ -1,5 +1,3 @@ -import 'dart:ui'; - import 'package:flutter/cupertino.dart'; class ColorUtils { @@ -8,18 +6,14 @@ class ColorUtils { return hslc.withLightness((hslc.lightness + amt).clamp(0.0, 1.0)).toColor(); } - static Color parseHex(String value) => - Color(int.parse(value.substring(1, 7), radix: 16) + 0xFF000000); + static Color parseHex(String value) => Color(int.parse(value.substring(1, 7), radix: 16) + 0xFF000000); static Color blend(Color dst, Color src, double opacity) { return Color.fromARGB( 255, - (dst.red.toDouble() * (1.0 - opacity) + src.red.toDouble() * opacity) - .toInt(), - (dst.green.toDouble() * (1.0 - opacity) + src.green.toDouble() * opacity) - .toInt(), - (dst.blue.toDouble() * (1.0 - opacity) + src.blue.toDouble() * opacity) - .toInt(), + (dst.red.toDouble() * (1.0 - opacity) + src.red.toDouble() * opacity).toInt(), + (dst.green.toDouble() * (1.0 - opacity) + src.green.toDouble() * opacity).toInt(), + (dst.blue.toDouble() * (1.0 - opacity) + src.blue.toDouble() * opacity).toInt(), ); } } diff --git a/frontend/app_flowy/packages/flowy_infra/lib/theme.dart b/frontend/app_flowy/packages/flowy_infra/lib/theme.dart index 48804c277b..b3b77d07ce 100644 --- a/frontend/app_flowy/packages/flowy_infra/lib/theme.dart +++ b/frontend/app_flowy/packages/flowy_infra/lib/theme.dart @@ -1,5 +1,4 @@ import 'package:flowy_infra/color.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; enum ThemeType { diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/layout.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/layout.dart index 40bcbc3b26..87dd63b715 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/layout.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/layout.dart @@ -1,8 +1,5 @@ import 'dart:math' as math; -import 'dart:ui'; - import 'package:flutter/material.dart'; - import 'flowy_overlay.dart'; class OverlayLayoutDelegate extends SingleChildLayoutDelegate { diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart index 6d72dc3605..6b67081ca2 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/button.dart @@ -3,7 +3,6 @@ import 'package:flowy_infra_ui/style_widget/hover.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; class FlowyButton extends StatelessWidget { final Widget text; diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/extension.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/extension.dart index a51b716031..bd6245563f 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/extension.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/extension.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; export 'package:styled_widget/styled_widget.dart'; extension FlowyStyledWidget on Widget { diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/progress_indicator.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/progress_indicator.dart index 6c6a1cfc2b..8eb2a12047 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/progress_indicator.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/style_widget/progress_indicator.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; import 'package:loading_indicator/loading_indicator.dart'; List _kDefaultRainbowColors = const [ diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/buttons/base_styled_button.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/buttons/base_styled_button.dart index 2253722c83..0c257f3d3a 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/buttons/base_styled_button.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/buttons/base_styled_button.dart @@ -1,9 +1,7 @@ import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/text_style.dart'; import 'package:flowy_infra/theme.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; import 'package:provider/provider.dart'; class BaseStyledButton extends StatefulWidget { diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/clickable_extension.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/clickable_extension.dart index c0231d91e7..267913fe9a 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/clickable_extension.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/clickable_extension.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; extension ClickableExtensions on Widget { Widget clickable(void Function() action, {bool opaque = true}) { diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/mouse_hover_builder.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/mouse_hover_builder.dart index 0d49d878e2..207775a275 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/mouse_hover_builder.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/widget/mouse_hover_builder.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; typedef HoverBuilder = Widget Function(BuildContext context, bool onHover); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart index 088bfb6e4d..328d6a6af4 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart @@ -19,7 +19,7 @@ import 'package:flowy_sdk/ffi.dart' as ffi; import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart'; import 'package:flowy_sdk/protobuf/dart-ffi/protobuf.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/protobuf.dart'; -import 'package:flowy_sdk/protobuf/flowy-document-infra/protobuf.dart'; +import 'package:flowy_sdk/protobuf/flowy-collaboration/protobuf.dart'; // ignore: unused_import import 'package:flowy_sdk/protobuf/lib-infra/protobuf.dart'; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/doc.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/doc.pb.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/doc.pb.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/doc.pb.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/doc.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/doc.pbenum.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/doc.pbenum.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/doc.pbenum.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/doc.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/doc.pbjson.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/doc.pbjson.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/doc.pbjson.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/doc.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/doc.pbserver.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/doc.pbserver.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/doc.pbserver.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/protobuf.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/protobuf.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/protobuf.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/protobuf.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/ws.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pb.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/ws.pb.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pb.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/ws.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbenum.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/ws.pbenum.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbenum.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/ws.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbjson.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/ws.pbjson.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbjson.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/ws.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbserver.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document-infra/ws.pbserver.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbserver.dart diff --git a/frontend/rust-lib/flowy-core/Cargo.toml b/frontend/rust-lib/flowy-core/Cargo.toml index fc242bb3e2..e460874384 100644 --- a/frontend/rust-lib/flowy-core/Cargo.toml +++ b/frontend/rust-lib/flowy-core/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [dependencies] flowy-core-infra = { path = "../../../shared-lib/flowy-core-infra" } -flowy-document-infra = { path = "../../../shared-lib/flowy-document-infra" } +flowy-collaboration = { path = "../../../shared-lib/flowy-collaboration" } flowy-derive = { path = "../../../shared-lib/flowy-derive" } lib-ot = { path = "../../../shared-lib/lib-ot" } lib-sqlite = { path = "../../../shared-lib/lib-sqlite" } diff --git a/frontend/rust-lib/flowy-core/src/core/core_context.rs b/frontend/rust-lib/flowy-core/src/core/core_context.rs index d5931f19dd..983aaed33d 100644 --- a/frontend/rust-lib/flowy-core/src/core/core_context.rs +++ b/frontend/rust-lib/flowy-core/src/core/core_context.rs @@ -6,8 +6,8 @@ use crate::{ services::{server::Server, AppController, TrashController, ViewController, WorkspaceController}, }; use chrono::Utc; +use flowy_collaboration::{entities::doc::DocDelta, user_default::initial_read_me}; use flowy_core_infra::user_default; -use flowy_document_infra::{entities::doc::DocDelta, user_default::initial_read_me}; use lazy_static::lazy_static; use lib_infra::entities::network_state::NetworkType; use parking_lot::RwLock; diff --git a/frontend/rust-lib/flowy-core/src/services/view/controller.rs b/frontend/rust-lib/flowy-core/src/services/view/controller.rs index b933a9b93d..80ca0677cf 100644 --- a/frontend/rust-lib/flowy-core/src/services/view/controller.rs +++ b/frontend/rust-lib/flowy-core/src/services/view/controller.rs @@ -1,5 +1,5 @@ +use flowy_collaboration::entities::doc::{DocDelta, DocIdentifier}; use flowy_database::SqliteConnection; -use flowy_document_infra::entities::doc::{DocDelta, DocIdentifier}; use futures::{FutureExt, StreamExt}; use std::{collections::HashSet, sync::Arc}; diff --git a/frontend/rust-lib/flowy-core/src/services/view/event_handler.rs b/frontend/rust-lib/flowy-core/src/services/view/event_handler.rs index c917ef2b9a..1f5a1e3b80 100644 --- a/frontend/rust-lib/flowy-core/src/services/view/event_handler.rs +++ b/frontend/rust-lib/flowy-core/src/services/view/event_handler.rs @@ -15,8 +15,8 @@ use crate::{ errors::WorkspaceError, services::{TrashController, ViewController}, }; +use flowy_collaboration::entities::doc::DocDelta; use flowy_core_infra::entities::share::{ExportData, ExportParams, ExportRequest}; -use flowy_document_infra::entities::doc::DocDelta; use lib_dispatch::prelude::{data_result, Data, DataResult, Unit}; use std::{convert::TryInto, sync::Arc}; diff --git a/frontend/rust-lib/flowy-document/Cargo.toml b/frontend/rust-lib/flowy-document/Cargo.toml index 8eab79e1b8..ab7e0de92a 100644 --- a/frontend/rust-lib/flowy-document/Cargo.toml +++ b/frontend/rust-lib/flowy-document/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -flowy-document-infra = { path = "../../../shared-lib/flowy-document-infra" } +flowy-collaboration = { path = "../../../shared-lib/flowy-collaboration" } flowy-derive = { path = "../../../shared-lib/flowy-derive" } lib-ot = { path = "../../../shared-lib/lib-ot" } lib-ws = { path = "../../../shared-lib/lib-ws" } diff --git a/frontend/rust-lib/flowy-document/src/errors.rs b/frontend/rust-lib/flowy-document/src/errors.rs index d55f5d430f..0925ff62d1 100644 --- a/frontend/rust-lib/flowy-document/src/errors.rs +++ b/frontend/rust-lib/flowy-document/src/errors.rs @@ -92,8 +92,8 @@ impl std::convert::From for DocError { fn from(error: lib_ot::errors::OTError) -> Self { DocError::internal().context(error) } } -impl std::convert::From for DocError { - fn from(error: flowy_document_infra::errors::DocumentError) -> Self { DocError::internal().context(error) } +impl std::convert::From for DocError { + fn from(error: flowy_collaboration::errors::DocumentError) -> Self { DocError::internal().context(error) } } impl std::convert::From for DocError { diff --git a/frontend/rust-lib/flowy-document/src/module.rs b/frontend/rust-lib/flowy-document/src/module.rs index 582beba1e5..adda90094c 100644 --- a/frontend/rust-lib/flowy-document/src/module.rs +++ b/frontend/rust-lib/flowy-document/src/module.rs @@ -7,8 +7,8 @@ use crate::{ }, }; use backend_service::configuration::ClientServerConfiguration; +use flowy_collaboration::entities::doc::{DocDelta, DocIdentifier}; use flowy_database::ConnectionPool; -use flowy_document_infra::entities::doc::{DocDelta, DocIdentifier}; use std::sync::Arc; pub trait DocumentUser: Send + Sync { diff --git a/frontend/rust-lib/flowy-document/src/services/doc/controller.rs b/frontend/rust-lib/flowy-document/src/services/doc/controller.rs index 9996054fe3..019a30a250 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/controller.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/controller.rs @@ -12,8 +12,8 @@ use crate::{ }; use bytes::Bytes; use dashmap::DashMap; +use flowy_collaboration::entities::doc::{Doc, DocDelta, DocIdentifier}; use flowy_database::ConnectionPool; -use flowy_document_infra::entities::doc::{Doc, DocDelta, DocIdentifier}; use lib_infra::future::ResultFuture; use std::sync::Arc; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs index 58242d778b..4df66253d2 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs @@ -10,12 +10,12 @@ use crate::{ }, }; use bytes::Bytes; -use flowy_database::ConnectionPool; -use flowy_document_infra::{ - core::history::UndoResult, +use flowy_collaboration::{ + core::document::history::UndoResult, entities::{doc::DocDelta, ws::WsDocumentData}, errors::DocumentResult, }; +use flowy_database::ConnectionPool; use lib_infra::retry::{ExponentialBackoff, Retry}; use lib_ot::{ core::Interval, diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/model.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/model.rs index 2916dce85a..f75cc672e2 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/model.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/model.rs @@ -1,5 +1,5 @@ use crate::{errors::DocError, services::ws::DocumentWebSocket}; -use flowy_document_infra::entities::doc::NewDocUser; +use flowy_collaboration::entities::doc::NewDocUser; use futures::future::BoxFuture; use lib_infra::retry::Action; use lib_ot::revision::RevId; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs index ed65d9ccf5..573fbc3111 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs @@ -1,7 +1,7 @@ use async_stream::stream; use bytes::Bytes; -use flowy_document_infra::{ - core::{history::UndoResult, Document}, +use flowy_collaboration::{ + core::document::{history::UndoResult, Document}, errors::DocumentError, }; use futures::stream::StreamExt; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs index 77e8cc649a..2ff4e5b09c 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs @@ -3,8 +3,8 @@ use crate::{ services::doc::revision::RevisionServer, sql_tables::RevTableSql, }; +use flowy_collaboration::entities::doc::Doc; use flowy_database::ConnectionPool; -use flowy_document_infra::entities::doc::Doc; use lib_infra::future::ResultFuture; use lib_ot::{ core::{Operation, OperationTransformable}, diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs index 20d10ef639..d7d74a47c5 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs @@ -5,7 +5,7 @@ use crate::{ ws::DocumentWebSocket, }, }; -use flowy_document_infra::{entities::doc::Doc, util::RevIdCounter}; +use flowy_collaboration::{entities::doc::Doc, util::RevIdCounter}; use lib_infra::future::ResultFuture; use lib_ot::{ core::OperationTransformable, diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs index ecf7a72c89..8859951717 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs @@ -10,12 +10,12 @@ use crate::{ }; use async_stream::stream; use bytes::Bytes; -use flowy_document_infra::entities::ws::{WsDataType, WsDocumentData}; +use flowy_collaboration::entities::ws::{WsDataType, WsDocumentData}; use futures::stream::StreamExt; use lib_ot::revision::{RevId, RevisionRange}; use std::{convert::TryFrom, sync::Arc}; use tokio::{ - sync::{broadcast, mpsc}, + sync::{broadcast, mpsc, mpsc::error::SendError}, task::spawn_blocking, time::{interval, Duration}, }; @@ -175,7 +175,7 @@ impl RevisionUpStream { match self.revisions.next().await? { None => Ok(()), Some(record) => { - tracing::debug!( + tracing::trace!( "[RevisionUpStream]: processes revision: {}:{:?}", record.revision.doc_id, record.revision.rev_id @@ -193,7 +193,9 @@ async fn tick(sender: mpsc::UnboundedSender) { loop { match sender.send(UpStreamMsg::Tick) { Ok(_) => {}, - Err(e) => log::error!("RevisionUploadStream tick error: {}", e), + Err(_e) => { + break; + }, } i.tick().await; } diff --git a/frontend/rust-lib/flowy-document/src/services/server/mod.rs b/frontend/rust-lib/flowy-document/src/services/server/mod.rs index b009d2d3a4..501886ca16 100644 --- a/frontend/rust-lib/flowy-document/src/services/server/mod.rs +++ b/frontend/rust-lib/flowy-document/src/services/server/mod.rs @@ -6,7 +6,7 @@ pub use server_api::*; // TODO: ignore mock files in production use crate::errors::DocError; use backend_service::configuration::ClientServerConfiguration; -use flowy_document_infra::entities::doc::{CreateDocParams, Doc, DocIdentifier, UpdateDocParams}; +use flowy_collaboration::entities::doc::{CreateDocParams, Doc, DocIdentifier, UpdateDocParams}; use lib_infra::future::ResultFuture; pub use server_api_mock::*; use std::sync::Arc; diff --git a/frontend/rust-lib/flowy-document/src/services/server/server_api.rs b/frontend/rust-lib/flowy-document/src/services/server/server_api.rs index ab572135cf..a55f70ba8d 100644 --- a/frontend/rust-lib/flowy-document/src/services/server/server_api.rs +++ b/frontend/rust-lib/flowy-document/src/services/server/server_api.rs @@ -1,6 +1,6 @@ use crate::{errors::DocError, services::server::DocumentServerAPI}; use backend_service::{configuration::*, request::HttpRequestBuilder}; -use flowy_document_infra::entities::doc::{CreateDocParams, Doc, DocIdentifier, UpdateDocParams}; +use flowy_collaboration::entities::doc::{CreateDocParams, Doc, DocIdentifier, UpdateDocParams}; use lib_infra::future::ResultFuture; pub struct DocServer { diff --git a/frontend/rust-lib/flowy-document/src/services/server/server_api_mock.rs b/frontend/rust-lib/flowy-document/src/services/server/server_api_mock.rs index f78d3d4f40..9e087ec0de 100644 --- a/frontend/rust-lib/flowy-document/src/services/server/server_api_mock.rs +++ b/frontend/rust-lib/flowy-document/src/services/server/server_api_mock.rs @@ -1,5 +1,5 @@ use crate::{errors::DocError, services::server::DocumentServerAPI}; -use flowy_document_infra::{ +use flowy_collaboration::{ entities::doc::{CreateDocParams, Doc, DocIdentifier, UpdateDocParams}, user_default::doc_initial_string, }; diff --git a/frontend/rust-lib/flowy-document/src/services/ws/ws_manager.rs b/frontend/rust-lib/flowy-document/src/services/ws/ws_manager.rs index f5678e6934..8a24549f2c 100644 --- a/frontend/rust-lib/flowy-document/src/services/ws/ws_manager.rs +++ b/frontend/rust-lib/flowy-document/src/services/ws/ws_manager.rs @@ -1,7 +1,7 @@ use crate::errors::DocError; use bytes::Bytes; use dashmap::DashMap; -use flowy_document_infra::entities::ws::WsDocumentData; +use flowy_collaboration::entities::ws::WsDocumentData; use lib_ws::WsConnectState; use std::{convert::TryInto, sync::Arc}; diff --git a/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_table.rs b/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_table.rs index 2dcdf9b368..85a592dc79 100644 --- a/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_table.rs +++ b/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_table.rs @@ -1,7 +1,7 @@ use diesel::sql_types::Integer; use flowy_database::schema::rev_table; -use flowy_document_infra::util::md5; +use flowy_collaboration::util::md5; use lib_ot::revision::{RevId, RevState, RevType, Revision}; #[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable, Associations)] diff --git a/frontend/rust-lib/flowy-document/tests/editor/attribute_test.rs b/frontend/rust-lib/flowy-document/tests/editor/attribute_test.rs index d740eee324..e13102093a 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/attribute_test.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/attribute_test.rs @@ -1,6 +1,6 @@ #![cfg_attr(rustfmt, rustfmt::skip)] use crate::editor::{TestBuilder, TestOp::*}; -use flowy_document_infra::core::{FlowyDoc, PlainDoc}; +use flowy_collaboration::core::document::{FlowyDoc, PlainDoc}; use lib_ot::core::{Interval, OperationTransformable, NEW_LINE, WHITESPACE, FlowyStr}; use unicode_segmentation::UnicodeSegmentation; use lib_ot::rich_text::RichTextDelta; diff --git a/frontend/rust-lib/flowy-document/tests/editor/mod.rs b/frontend/rust-lib/flowy-document/tests/editor/mod.rs index 02a947beea..4fe37a1919 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/mod.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/mod.rs @@ -6,7 +6,7 @@ mod serde_test; mod undo_redo_test; use derive_more::Display; -use flowy_document_infra::core::{CustomDocument, Document}; +use flowy_collaboration::core::document::{CustomDocument, Document}; use lib_ot::{ core::*, rich_text::{RichTextAttribute, RichTextAttributes, RichTextDelta}, diff --git a/frontend/rust-lib/flowy-document/tests/editor/op_test.rs b/frontend/rust-lib/flowy-document/tests/editor/op_test.rs index c1b8c4496b..54ee3faccc 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/op_test.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/op_test.rs @@ -1,6 +1,6 @@ #![allow(clippy::all)] use crate::editor::{Rng, TestBuilder, TestOp::*}; -use flowy_document_infra::core::{FlowyDoc, PlainDoc}; +use flowy_collaboration::core::document::{FlowyDoc, PlainDoc}; use lib_ot::{ core::*, rich_text::{AttributeBuilder, RichTextAttribute, RichTextAttributes, RichTextDelta}, diff --git a/frontend/rust-lib/flowy-document/tests/editor/serde_test.rs b/frontend/rust-lib/flowy-document/tests/editor/serde_test.rs index a4a0ff3994..6024dc0dda 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/serde_test.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/serde_test.rs @@ -1,4 +1,4 @@ -use flowy_document_infra::core::{Document, PlainDoc}; +use flowy_collaboration::core::document::{Document, PlainDoc}; use lib_ot::{ core::*, rich_text::{AttributeBuilder, RichTextAttribute, RichTextAttributeValue, RichTextDelta}, diff --git a/frontend/rust-lib/flowy-document/tests/editor/undo_redo_test.rs b/frontend/rust-lib/flowy-document/tests/editor/undo_redo_test.rs index 95def758ab..450c8fd42d 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/undo_redo_test.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/undo_redo_test.rs @@ -1,5 +1,5 @@ use crate::editor::{TestBuilder, TestOp::*}; -use flowy_document_infra::core::{FlowyDoc, PlainDoc, RECORD_THRESHOLD}; +use flowy_collaboration::core::document::{FlowyDoc, PlainDoc, RECORD_THRESHOLD}; use lib_ot::core::{Interval, NEW_LINE, WHITESPACE}; #[test] diff --git a/frontend/rust-lib/flowy-sdk/Cargo.toml b/frontend/rust-lib/flowy-sdk/Cargo.toml index 057e4a7825..12a8df451a 100644 --- a/frontend/rust-lib/flowy-sdk/Cargo.toml +++ b/frontend/rust-lib/flowy-sdk/Cargo.toml @@ -22,7 +22,7 @@ tokio = { version = "1", features = ["rt"] } parking_lot = "0.11" -flowy-document-infra = { path = "../../../shared-lib/flowy-document-infra" } +flowy-collaboration = { path = "../../../shared-lib/flowy-collaboration" } lib-ws = { path = "../../../shared-lib/lib-ws" } backend-service = { path = "../../../shared-lib/backend-service" } diff --git a/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs b/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs index 90bbbe64a0..c1f329aa8c 100644 --- a/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs +++ b/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs @@ -1,11 +1,11 @@ use bytes::Bytes; +use flowy_collaboration::entities::ws::WsDocumentData; use flowy_database::ConnectionPool; use flowy_document::{ errors::{internal_error, DocError}, module::DocumentUser, services::ws::{DocumentWebSocket, WsDocumentManager, WsStateReceiver}, }; -use flowy_document_infra::entities::ws::WsDocumentData; use flowy_user::{ errors::{ErrorCode, UserError}, services::user::UserSession, diff --git a/frontend/rust-lib/flowy-test/Cargo.toml b/frontend/rust-lib/flowy-test/Cargo.toml index fc59336c48..8d2b68cd73 100644 --- a/frontend/rust-lib/flowy-test/Cargo.toml +++ b/frontend/rust-lib/flowy-test/Cargo.toml @@ -13,7 +13,7 @@ flowy-document = { path = "../flowy-document"} lib-dispatch = { path = "../lib-dispatch" } lib-infra = { path = "../lib-infra" } -flowy-document-infra = { path = "../../../shared-lib/flowy-document-infra" } +flowy-collaboration = { path = "../../../shared-lib/flowy-collaboration" } backend-service = { path = "../../../shared-lib/backend-service" } lib-ot = { path = "../../../shared-lib/lib-ot" } diff --git a/frontend/rust-lib/flowy-test/src/editor.rs b/frontend/rust-lib/flowy-test/src/editor.rs index 7953577b89..615272d178 100644 --- a/frontend/rust-lib/flowy-test/src/editor.rs +++ b/frontend/rust-lib/flowy-test/src/editor.rs @@ -1,9 +1,9 @@ use crate::{helper::ViewTest, FlowySDKTest}; -use flowy_document::services::doc::{edit::ClientDocEditor, revision::RevisionIterator}; -use flowy_document_infra::entities::{ +use flowy_collaboration::entities::{ doc::DocIdentifier, ws::{WsDocumentData, WsDocumentDataBuilder}, }; +use flowy_document::services::doc::{edit::ClientDocEditor, revision::RevisionIterator}; use lib_ot::{ core::Interval, revision::{RevState, RevType, Revision, RevisionRange}, diff --git a/frontend/rust-lib/flowy-test/src/helper.rs b/frontend/rust-lib/flowy-test/src/helper.rs index 340bef8ad4..9c0e8628a2 100644 --- a/frontend/rust-lib/flowy-test/src/helper.rs +++ b/frontend/rust-lib/flowy-test/src/helper.rs @@ -1,5 +1,6 @@ use crate::prelude::*; use bytes::Bytes; +use flowy_collaboration::entities::doc::Doc; use flowy_core::{ entities::{ app::*, @@ -10,7 +11,6 @@ use flowy_core::{ errors::{ErrorCode, WorkspaceError}, event::WorkspaceEvent::{CreateWorkspace, OpenWorkspace, *}, }; -use flowy_document_infra::entities::doc::Doc; use flowy_user::{ entities::{SignInRequest, SignUpRequest, UserProfile}, errors::UserError, diff --git a/frontend/rust-lib/flowy-user/src/services/user/ws_manager.rs b/frontend/rust-lib/flowy-user/src/services/user/ws_manager.rs index 3b82e6a96d..07fef218f7 100644 --- a/frontend/rust-lib/flowy-user/src/services/user/ws_manager.rs +++ b/frontend/rust-lib/flowy-user/src/services/user/ws_manager.rs @@ -103,7 +103,7 @@ impl std::default::Default for WsManager { let ws: Arc = if cfg!(feature = "http_server") { Arc::new(Arc::new(WsController::new())) } else { - mock::MockWebSocket::new() + Arc::new(Arc::new(mock::MockWebSocket::new())) }; WsManager { @@ -181,10 +181,13 @@ mod mock { } impl MockWebSocket { - pub fn new() -> Arc { - let ws = Arc::new(MockWebSocket::default()); - let mut ws_receiver = ws.ws_sender.subscribe(); - let cloned_ws = ws.clone(); + pub fn new() -> MockWebSocket { MockWebSocket::default() } + } + + impl FlowyWebSocket for Arc { + fn start_connect(&self, _addr: String) -> ResultFuture<(), UserError> { + let mut ws_receiver = self.ws_sender.subscribe(); + let cloned_ws = self.clone(); tokio::spawn(async move { while let Ok(message) = ws_receiver.recv().await { match cloned_ws.handlers.get(&message.module) { @@ -193,12 +196,9 @@ mod mock { } } }); - ws - } - } - impl FlowyWebSocket for MockWebSocket { - fn start_connect(&self, _addr: String) -> ResultFuture<(), UserError> { ResultFuture::new(async { Ok(()) }) } + ResultFuture::new(async { Ok(()) }) + } fn conn_state_subscribe(&self) -> Receiver { self.state_sender.subscribe() } diff --git a/shared-lib/Cargo.lock b/shared-lib/Cargo.lock index a09a4f3f5f..a02292d8c6 100644 --- a/shared-lib/Cargo.lock +++ b/shared-lib/Cargo.lock @@ -665,7 +665,7 @@ dependencies = [ "chrono", "derive_more", "flowy-derive", - "flowy-document-infra", + "flowy-ot", "log", "protobuf", "strum", @@ -688,7 +688,7 @@ dependencies = [ ] [[package]] -name = "flowy-document-infra" +name = "flowy-ot" version = "0.1.0" dependencies = [ "bytes", @@ -697,6 +697,7 @@ dependencies = [ "lib-ot", "log", "md5", + "parking_lot", "protobuf", "serde", "strum", diff --git a/shared-lib/Cargo.toml b/shared-lib/Cargo.toml index 970ce58de4..d9405a14a2 100644 --- a/shared-lib/Cargo.toml +++ b/shared-lib/Cargo.toml @@ -2,7 +2,7 @@ members = [ "flowy-user-infra", "flowy-core-infra", - "flowy-document-infra", + "flowy-collaboration", "lib-ot", "lib-ws", "lib-sqlite", diff --git a/shared-lib/flowy-document-infra/Cargo.toml b/shared-lib/flowy-collaboration/Cargo.toml similarity index 88% rename from shared-lib/flowy-document-infra/Cargo.toml rename to shared-lib/flowy-collaboration/Cargo.toml index 4e3bca95f7..efd97a2899 100644 --- a/shared-lib/flowy-document-infra/Cargo.toml +++ b/shared-lib/flowy-collaboration/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "flowy-document-infra" +name = "flowy-collaboration" version = "0.1.0" edition = "2018" @@ -18,4 +18,5 @@ tracing = { version = "0.1", features = ["log"] } url = "2.2" strum = "0.21" strum_macros = "0.21" -chrono = "0.4.19" \ No newline at end of file +chrono = "0.4.19" +parking_lot = "0.11" \ No newline at end of file diff --git a/shared-lib/flowy-document-infra/Flowy.toml b/shared-lib/flowy-collaboration/Flowy.toml similarity index 100% rename from shared-lib/flowy-document-infra/Flowy.toml rename to shared-lib/flowy-collaboration/Flowy.toml diff --git a/shared-lib/flowy-document-infra/src/READ_ME.json b/shared-lib/flowy-collaboration/src/READ_ME.json similarity index 100% rename from shared-lib/flowy-document-infra/src/READ_ME.json rename to shared-lib/flowy-collaboration/src/READ_ME.json diff --git a/shared-lib/flowy-document-infra/src/core/data.rs b/shared-lib/flowy-collaboration/src/core/document/data.rs similarity index 100% rename from shared-lib/flowy-document-infra/src/core/data.rs rename to shared-lib/flowy-collaboration/src/core/document/data.rs diff --git a/shared-lib/flowy-document-infra/src/core/document.rs b/shared-lib/flowy-collaboration/src/core/document/document.rs similarity index 99% rename from shared-lib/flowy-document-infra/src/core/document.rs rename to shared-lib/flowy-collaboration/src/core/document/document.rs index 0d17222d0e..baa6d5c453 100644 --- a/shared-lib/flowy-document-infra/src/core/document.rs +++ b/shared-lib/flowy-collaboration/src/core/document/document.rs @@ -1,5 +1,5 @@ use crate::{ - core::{ + core::document::{ history::{History, UndoResult}, view::{View, RECORD_THRESHOLD}, }, diff --git a/shared-lib/flowy-document-infra/src/core/extensions/delete/default_delete.rs b/shared-lib/flowy-collaboration/src/core/document/extensions/delete/default_delete.rs similarity index 92% rename from shared-lib/flowy-document-infra/src/core/extensions/delete/default_delete.rs rename to shared-lib/flowy-collaboration/src/core/document/extensions/delete/default_delete.rs index 32c767cd5d..7a8ae2d46e 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/delete/default_delete.rs +++ b/shared-lib/flowy-collaboration/src/core/document/extensions/delete/default_delete.rs @@ -1,4 +1,4 @@ -use crate::core::extensions::DeleteExt; +use crate::core::document::DeleteExt; use lib_ot::{ core::{DeltaBuilder, Interval}, rich_text::RichTextDelta, diff --git a/shared-lib/flowy-document-infra/src/core/extensions/delete/mod.rs b/shared-lib/flowy-collaboration/src/core/document/extensions/delete/mod.rs similarity index 100% rename from shared-lib/flowy-document-infra/src/core/extensions/delete/mod.rs rename to shared-lib/flowy-collaboration/src/core/document/extensions/delete/mod.rs diff --git a/shared-lib/flowy-document-infra/src/core/extensions/delete/preserve_line_format_merge.rs b/shared-lib/flowy-collaboration/src/core/document/extensions/delete/preserve_line_format_merge.rs similarity index 97% rename from shared-lib/flowy-document-infra/src/core/extensions/delete/preserve_line_format_merge.rs rename to shared-lib/flowy-collaboration/src/core/document/extensions/delete/preserve_line_format_merge.rs index 8b8ed215e8..05333fb04f 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/delete/preserve_line_format_merge.rs +++ b/shared-lib/flowy-collaboration/src/core/document/extensions/delete/preserve_line_format_merge.rs @@ -1,4 +1,4 @@ -use crate::{core::extensions::DeleteExt, util::is_newline}; +use crate::{core::document::DeleteExt, util::is_newline}; use lib_ot::{ core::{Attributes, CharMetric, DeltaBuilder, DeltaIter, Interval, NEW_LINE}, rich_text::{plain_attributes, RichTextDelta}, diff --git a/shared-lib/flowy-document-infra/src/core/extensions/format/format_at_position.rs b/shared-lib/flowy-collaboration/src/core/document/extensions/format/format_at_position.rs similarity index 100% rename from shared-lib/flowy-document-infra/src/core/extensions/format/format_at_position.rs rename to shared-lib/flowy-collaboration/src/core/document/extensions/format/format_at_position.rs diff --git a/shared-lib/flowy-document-infra/src/core/extensions/format/mod.rs b/shared-lib/flowy-collaboration/src/core/document/extensions/format/mod.rs similarity index 93% rename from shared-lib/flowy-document-infra/src/core/extensions/format/mod.rs rename to shared-lib/flowy-collaboration/src/core/document/extensions/format/mod.rs index 962b357776..513320c335 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/format/mod.rs +++ b/shared-lib/flowy-collaboration/src/core/document/extensions/format/mod.rs @@ -1,8 +1,8 @@ -mod format_at_position; -mod helper; -mod resolve_block_format; -mod resolve_inline_format; - pub use format_at_position::*; pub use resolve_block_format::*; pub use resolve_inline_format::*; + +mod format_at_position; +mod resolve_block_format; +mod resolve_inline_format; + diff --git a/shared-lib/flowy-document-infra/src/core/extensions/format/resolve_block_format.rs b/shared-lib/flowy-collaboration/src/core/document/extensions/format/resolve_block_format.rs similarity index 91% rename from shared-lib/flowy-document-infra/src/core/extensions/format/resolve_block_format.rs rename to shared-lib/flowy-collaboration/src/core/document/extensions/format/resolve_block_format.rs index 7854a6fbc5..30c4bbb481 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/format/resolve_block_format.rs +++ b/shared-lib/flowy-collaboration/src/core/document/extensions/format/resolve_block_format.rs @@ -1,12 +1,14 @@ -use crate::{ - core::extensions::{format::helper::line_break, FormatExt}, - util::find_newline, -}; use lib_ot::{ core::{DeltaBuilder, DeltaIter, Interval}, - rich_text::{plain_attributes, AttributeScope, RichTextAttribute, RichTextDelta}, + rich_text::{AttributeScope, plain_attributes, RichTextAttribute, RichTextDelta}, }; +use crate::{ + core::document::FormatExt, + util::find_newline, +}; +use crate::core::document::extensions::helper::line_break; + pub struct ResolveBlockFormat {} impl FormatExt for ResolveBlockFormat { fn ext_name(&self) -> &str { std::any::type_name::() } diff --git a/shared-lib/flowy-document-infra/src/core/extensions/format/resolve_inline_format.rs b/shared-lib/flowy-collaboration/src/core/document/extensions/format/resolve_inline_format.rs similarity index 93% rename from shared-lib/flowy-document-infra/src/core/extensions/format/resolve_inline_format.rs rename to shared-lib/flowy-collaboration/src/core/document/extensions/format/resolve_inline_format.rs index 82ae255559..827b3753d1 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/format/resolve_inline_format.rs +++ b/shared-lib/flowy-collaboration/src/core/document/extensions/format/resolve_inline_format.rs @@ -1,12 +1,14 @@ -use crate::{ - core::extensions::{format::helper::line_break, FormatExt}, - util::find_newline, -}; use lib_ot::{ core::{DeltaBuilder, DeltaIter, Interval}, rich_text::{AttributeScope, RichTextAttribute, RichTextDelta}, }; +use crate::{ + core::document::FormatExt, + util::find_newline, +}; +use crate::core::document::extensions::helper::line_break; + pub struct ResolveInlineFormat {} impl FormatExt for ResolveInlineFormat { fn ext_name(&self) -> &str { std::any::type_name::() } diff --git a/shared-lib/flowy-document-infra/src/core/extensions/format/helper.rs b/shared-lib/flowy-collaboration/src/core/document/extensions/helper.rs similarity index 100% rename from shared-lib/flowy-document-infra/src/core/extensions/format/helper.rs rename to shared-lib/flowy-collaboration/src/core/document/extensions/helper.rs diff --git a/shared-lib/flowy-document-infra/src/core/extensions/insert/auto_exit_block.rs b/shared-lib/flowy-collaboration/src/core/document/extensions/insert/auto_exit_block.rs similarity index 96% rename from shared-lib/flowy-document-infra/src/core/extensions/insert/auto_exit_block.rs rename to shared-lib/flowy-collaboration/src/core/document/extensions/insert/auto_exit_block.rs index 8b9fa77d2a..de6a298106 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/insert/auto_exit_block.rs +++ b/shared-lib/flowy-collaboration/src/core/document/extensions/insert/auto_exit_block.rs @@ -1,4 +1,4 @@ -use crate::{core::extensions::InsertExt, util::is_newline}; +use crate::{core::document::InsertExt, util::is_newline}; use lib_ot::{ core::{is_empty_line_at_index, DeltaBuilder, DeltaIter}, rich_text::{attributes_except_header, RichTextAttributeKey, RichTextDelta}, diff --git a/shared-lib/flowy-document-infra/src/core/extensions/insert/auto_format.rs b/shared-lib/flowy-collaboration/src/core/document/extensions/insert/auto_format.rs similarity index 97% rename from shared-lib/flowy-document-infra/src/core/extensions/insert/auto_format.rs rename to shared-lib/flowy-collaboration/src/core/document/extensions/insert/auto_format.rs index 4887f80ba4..979cbce91b 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/insert/auto_format.rs +++ b/shared-lib/flowy-collaboration/src/core/document/extensions/insert/auto_format.rs @@ -1,4 +1,4 @@ -use crate::{core::extensions::InsertExt, util::is_whitespace}; +use crate::{core::document::InsertExt, util::is_whitespace}; use lib_ot::{ core::{count_utf16_code_units, DeltaBuilder, DeltaIter}, rich_text::{plain_attributes, RichTextAttribute, RichTextAttributes, RichTextDelta}, diff --git a/shared-lib/flowy-document-infra/src/core/extensions/insert/default_insert.rs b/shared-lib/flowy-collaboration/src/core/document/extensions/insert/default_insert.rs similarity index 97% rename from shared-lib/flowy-document-infra/src/core/extensions/insert/default_insert.rs rename to shared-lib/flowy-collaboration/src/core/document/extensions/insert/default_insert.rs index 1d3e897427..c796b6075f 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/insert/default_insert.rs +++ b/shared-lib/flowy-collaboration/src/core/document/extensions/insert/default_insert.rs @@ -1,4 +1,4 @@ -use crate::core::extensions::InsertExt; +use crate::core::document::InsertExt; use lib_ot::{ core::{Attributes, DeltaBuilder, DeltaIter, NEW_LINE}, rich_text::{RichTextAttributeKey, RichTextAttributes, RichTextDelta}, diff --git a/shared-lib/flowy-document-infra/src/core/extensions/insert/mod.rs b/shared-lib/flowy-collaboration/src/core/document/extensions/insert/mod.rs similarity index 95% rename from shared-lib/flowy-document-infra/src/core/extensions/insert/mod.rs rename to shared-lib/flowy-collaboration/src/core/document/extensions/insert/mod.rs index 8e353018d0..9389f0131c 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/insert/mod.rs +++ b/shared-lib/flowy-collaboration/src/core/document/extensions/insert/mod.rs @@ -1,4 +1,4 @@ -use crate::core::extensions::InsertExt; +use crate::core::document::InsertExt; pub use auto_exit_block::*; pub use auto_format::*; pub use default_insert::*; diff --git a/shared-lib/flowy-document-infra/src/core/extensions/insert/preserve_block_format.rs b/shared-lib/flowy-collaboration/src/core/document/extensions/insert/preserve_block_format.rs similarity index 97% rename from shared-lib/flowy-document-infra/src/core/extensions/insert/preserve_block_format.rs rename to shared-lib/flowy-collaboration/src/core/document/extensions/insert/preserve_block_format.rs index 47301f7090..f4a0d3d7e5 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/insert/preserve_block_format.rs +++ b/shared-lib/flowy-collaboration/src/core/document/extensions/insert/preserve_block_format.rs @@ -1,4 +1,4 @@ -use crate::{core::extensions::InsertExt, util::is_newline}; +use crate::{core::document::InsertExt, util::is_newline}; use lib_ot::{ core::{DeltaBuilder, DeltaIter, NEW_LINE}, rich_text::{ diff --git a/shared-lib/flowy-document-infra/src/core/extensions/insert/preserve_inline_format.rs b/shared-lib/flowy-collaboration/src/core/document/extensions/insert/preserve_inline_format.rs similarity index 98% rename from shared-lib/flowy-document-infra/src/core/extensions/insert/preserve_inline_format.rs rename to shared-lib/flowy-collaboration/src/core/document/extensions/insert/preserve_inline_format.rs index d97d913c31..8b263a16b0 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/insert/preserve_inline_format.rs +++ b/shared-lib/flowy-collaboration/src/core/document/extensions/insert/preserve_inline_format.rs @@ -1,5 +1,5 @@ use crate::{ - core::extensions::InsertExt, + core::document::InsertExt, util::{contain_newline, is_newline}, }; use lib_ot::{ diff --git a/shared-lib/flowy-document-infra/src/core/extensions/insert/reset_format_on_new_line.rs b/shared-lib/flowy-collaboration/src/core/document/extensions/insert/reset_format_on_new_line.rs similarity index 95% rename from shared-lib/flowy-document-infra/src/core/extensions/insert/reset_format_on_new_line.rs rename to shared-lib/flowy-collaboration/src/core/document/extensions/insert/reset_format_on_new_line.rs index 4e22c5767c..d2f2b0286e 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/insert/reset_format_on_new_line.rs +++ b/shared-lib/flowy-collaboration/src/core/document/extensions/insert/reset_format_on_new_line.rs @@ -1,4 +1,4 @@ -use crate::{core::extensions::InsertExt, util::is_newline}; +use crate::{core::document::InsertExt, util::is_newline}; use lib_ot::{ core::{CharMetric, DeltaBuilder, DeltaIter, NEW_LINE}, rich_text::{RichTextAttributeKey, RichTextAttributes, RichTextDelta}, diff --git a/shared-lib/flowy-document-infra/src/core/extensions/mod.rs b/shared-lib/flowy-collaboration/src/core/document/extensions/mod.rs similarity index 98% rename from shared-lib/flowy-document-infra/src/core/extensions/mod.rs rename to shared-lib/flowy-collaboration/src/core/document/extensions/mod.rs index 4c67f6b888..82360ebb53 100644 --- a/shared-lib/flowy-document-infra/src/core/extensions/mod.rs +++ b/shared-lib/flowy-collaboration/src/core/document/extensions/mod.rs @@ -1,7 +1,6 @@ pub use delete::*; pub use format::*; pub use insert::*; - use lib_ot::{ core::Interval, rich_text::{RichTextAttribute, RichTextDelta}, @@ -10,6 +9,7 @@ use lib_ot::{ mod delete; mod format; mod insert; +mod helper; pub type InsertExtension = Box; pub type FormatExtension = Box; diff --git a/shared-lib/flowy-document-infra/src/core/history.rs b/shared-lib/flowy-collaboration/src/core/document/history.rs similarity index 100% rename from shared-lib/flowy-document-infra/src/core/history.rs rename to shared-lib/flowy-collaboration/src/core/document/history.rs diff --git a/shared-lib/flowy-document-infra/src/core/mod.rs b/shared-lib/flowy-collaboration/src/core/document/mod.rs similarity index 51% rename from shared-lib/flowy-document-infra/src/core/mod.rs rename to shared-lib/flowy-collaboration/src/core/document/mod.rs index 6acb4e4a27..44fcb264a7 100644 --- a/shared-lib/flowy-document-infra/src/core/mod.rs +++ b/shared-lib/flowy-collaboration/src/core/document/mod.rs @@ -1,3 +1,4 @@ +#![allow(clippy::module_inception)] mod data; mod document; mod extensions; @@ -5,4 +6,5 @@ pub mod history; mod view; pub use document::*; -pub use view::RECORD_THRESHOLD; +pub(crate) use extensions::*; +pub use view::*; diff --git a/shared-lib/flowy-document-infra/src/core/view.rs b/shared-lib/flowy-collaboration/src/core/document/view.rs similarity index 99% rename from shared-lib/flowy-document-infra/src/core/view.rs rename to shared-lib/flowy-collaboration/src/core/document/view.rs index ee752abb6f..56c659c503 100644 --- a/shared-lib/flowy-document-infra/src/core/view.rs +++ b/shared-lib/flowy-collaboration/src/core/document/view.rs @@ -1,4 +1,4 @@ -use crate::core::extensions::*; +use crate::core::document::*; use lib_ot::{ core::{trim, Interval}, errors::{ErrorBuilder, OTError, OTErrorCode}, diff --git a/shared-lib/flowy-collaboration/src/core/mod.rs b/shared-lib/flowy-collaboration/src/core/mod.rs new file mode 100644 index 0000000000..3a39374a3e --- /dev/null +++ b/shared-lib/flowy-collaboration/src/core/mod.rs @@ -0,0 +1,2 @@ +pub mod document; +pub mod sync; diff --git a/shared-lib/flowy-collaboration/src/core/sync/mod.rs b/shared-lib/flowy-collaboration/src/core/sync/mod.rs new file mode 100644 index 0000000000..cf1006c232 --- /dev/null +++ b/shared-lib/flowy-collaboration/src/core/sync/mod.rs @@ -0,0 +1,3 @@ +mod rev_sync; + +pub use rev_sync::*; diff --git a/shared-lib/flowy-collaboration/src/core/sync/rev_sync.rs b/shared-lib/flowy-collaboration/src/core/sync/rev_sync.rs new file mode 100644 index 0000000000..94e98fe924 --- /dev/null +++ b/shared-lib/flowy-collaboration/src/core/sync/rev_sync.rs @@ -0,0 +1,208 @@ +use crate::{ + core::document::Document, + entities::ws::{WsDataType, WsDocumentData}, +}; +use bytes::Bytes; +use lib_ot::{ + core::OperationTransformable, + errors::OTError, + protobuf::RevId, + revision::{RevType, Revision, RevisionRange}, + rich_text::RichTextDelta, +}; +use parking_lot::RwLock; +use protobuf::Message; +use std::{ + cmp::Ordering, + convert::TryInto, + sync::{ + atomic::{AtomicI64, Ordering::SeqCst}, + Arc, + }, + time::Duration, +}; +use tokio::sync::mpsc; + +pub enum SynchronizerCommand { + Pull(WsDocumentData), + Push(WsDocumentData), + Ack(WsDocumentData), + SaveRevision(Revision), +} + +pub type CommandReceiver = Arc; + +pub struct RevisionSynchronizer { + pub doc_id: String, + pub rev_id: AtomicI64, + document: Arc>, + command_receiver: CommandReceiver, +} + +impl RevisionSynchronizer { + pub fn new( + doc_id: &str, + rev_id: i64, + document: Arc>, + command_receiver: CommandReceiver, + ) -> RevisionSynchronizer { + RevisionSynchronizer { + doc_id: doc_id.to_string(), + rev_id: AtomicI64::new(rev_id), + document, + command_receiver, + } + } + + pub fn new_conn(&self, rev_id: i64) { + let cur_rev_id = self.rev_id.load(SeqCst); + match cur_rev_id.cmp(&rev_id) { + Ordering::Less => { + let msg = mk_pull_message(&self.doc_id, next(cur_rev_id), rev_id); + self.send_command(SynchronizerCommand::Pull(msg)); + }, + Ordering::Equal => {}, + Ordering::Greater => { + let doc_delta = self.document.read().delta().clone(); + let revision = self.mk_revision(rev_id, doc_delta); + let data = mk_push_message(&self.doc_id, revision); + self.send_command(SynchronizerCommand::Push(data)); + }, + } + } + + pub fn apply_revision(&self, revision: Revision) -> Result<(), OTError> { + let cur_rev_id = self.rev_id.load(SeqCst); + match cur_rev_id.cmp(&revision.rev_id) { + Ordering::Less => { + let next_rev_id = next(cur_rev_id); + if cur_rev_id == revision.base_rev_id || next_rev_id == revision.base_rev_id { + // The rev is in the right order, just compose it. + let _ = self.compose_revision(&revision)?; + self.send_command(SynchronizerCommand::Ack(mk_acked_message(&revision))); + self.send_command(SynchronizerCommand::SaveRevision(revision)); + } else { + // The server document is outdated, pull the missing revision from the client. + let msg = mk_pull_message(&self.doc_id, next_rev_id, revision.rev_id); + self.send_command(SynchronizerCommand::Pull(msg)); + } + }, + Ordering::Equal => { + // Do nothing + log::warn!("Applied revision rev_id is the same as cur_rev_id"); + }, + Ordering::Greater => { + // The client document is outdated. Transform the client revision delta and then + // send the prime delta to the client. Client should compose the this prime + // delta. + let cli_revision = self.transform_revision(&revision)?; + let data = mk_push_message(&self.doc_id, cli_revision); + self.send_command(SynchronizerCommand::Push(data)); + }, + } + Ok(()) + } + + fn compose_revision(&self, revision: &Revision) -> Result<(), OTError> { + let delta = RichTextDelta::from_bytes(&revision.delta_data)?; + let _ = self.compose_delta(delta)?; + let _ = self.rev_id.fetch_update(SeqCst, SeqCst, |_e| Some(revision.rev_id)); + Ok(()) + } + + #[tracing::instrument(level = "debug", skip(self, revision))] + fn transform_revision(&self, revision: &Revision) -> Result { + let cli_delta = RichTextDelta::from_bytes(&revision.delta_data)?; + let (cli_prime, server_prime) = self.document.read().delta().transform(&cli_delta)?; + + let _ = self.compose_delta(server_prime)?; + let cli_revision = self.mk_revision(revision.rev_id, cli_prime); + Ok(cli_revision) + } + + fn send_command(&self, command: SynchronizerCommand) { (self.command_receiver)(command); } + + #[tracing::instrument( + level = "debug", + skip(self, delta), + fields( + revision_delta = %delta.to_json(), + result, + ) + )] + fn compose_delta(&self, delta: RichTextDelta) -> Result<(), OTError> { + if delta.is_empty() { + log::warn!("Composed delta is empty"); + } + + match self.document.try_write_for(Duration::from_millis(300)) { + None => log::error!("Failed to acquire write lock of document"), + Some(mut write_guard) => { + let _ = write_guard.compose_delta(delta); + tracing::Span::current().record("result", &write_guard.to_json().as_str()); + }, + } + Ok(()) + } + + fn mk_revision(&self, base_rev_id: i64, delta: RichTextDelta) -> Revision { + let delta_data = delta.to_bytes().to_vec(); + let md5 = md5(&delta_data); + Revision { + base_rev_id, + rev_id: self.rev_id.load(SeqCst), + delta_data, + md5, + doc_id: self.doc_id.to_string(), + ty: RevType::Remote, + user_id: "".to_string(), + } + } +} + +fn mk_push_message(doc_id: &str, revision: Revision) -> WsDocumentData { + let bytes: Bytes = revision.try_into().unwrap(); + WsDocumentData { + doc_id: doc_id.to_string(), + ty: WsDataType::PushRev, + data: bytes.to_vec(), + } +} + +fn mk_pull_message(doc_id: &str, from_rev_id: i64, to_rev_id: i64) -> WsDocumentData { + let range = RevisionRange { + doc_id: doc_id.to_string(), + start: from_rev_id, + end: to_rev_id, + }; + + let bytes: Bytes = range.try_into().unwrap(); + WsDocumentData { + doc_id: doc_id.to_string(), + ty: WsDataType::PullRev, + data: bytes.to_vec(), + } +} + +fn mk_acked_message(revision: &Revision) -> WsDocumentData { + // let mut wtr = vec![]; + // let _ = wtr.write_i64::(revision.rev_id); + let mut rev_id = RevId::new(); + rev_id.set_value(revision.rev_id); + let data = rev_id.write_to_bytes().unwrap(); + + WsDocumentData { + doc_id: revision.doc_id.clone(), + ty: WsDataType::Acked, + data, + } +} + +#[inline] +fn next(rev_id: i64) -> i64 { rev_id + 1 } + +#[inline] +fn md5>(data: T) -> String { + let md5 = format!("{:x}", md5::compute(data)); + md5 +} diff --git a/shared-lib/flowy-document-infra/src/entities/doc/doc.rs b/shared-lib/flowy-collaboration/src/entities/doc/doc.rs similarity index 100% rename from shared-lib/flowy-document-infra/src/entities/doc/doc.rs rename to shared-lib/flowy-collaboration/src/entities/doc/doc.rs diff --git a/shared-lib/flowy-document-infra/src/entities/doc/mod.rs b/shared-lib/flowy-collaboration/src/entities/doc/mod.rs similarity index 100% rename from shared-lib/flowy-document-infra/src/entities/doc/mod.rs rename to shared-lib/flowy-collaboration/src/entities/doc/mod.rs diff --git a/shared-lib/flowy-document-infra/src/entities/doc/parser/doc_id.rs b/shared-lib/flowy-collaboration/src/entities/doc/parser/doc_id.rs similarity index 100% rename from shared-lib/flowy-document-infra/src/entities/doc/parser/doc_id.rs rename to shared-lib/flowy-collaboration/src/entities/doc/parser/doc_id.rs diff --git a/shared-lib/flowy-document-infra/src/entities/doc/parser/mod.rs b/shared-lib/flowy-collaboration/src/entities/doc/parser/mod.rs similarity index 100% rename from shared-lib/flowy-document-infra/src/entities/doc/parser/mod.rs rename to shared-lib/flowy-collaboration/src/entities/doc/parser/mod.rs diff --git a/shared-lib/flowy-document-infra/src/entities/mod.rs b/shared-lib/flowy-collaboration/src/entities/mod.rs similarity index 100% rename from shared-lib/flowy-document-infra/src/entities/mod.rs rename to shared-lib/flowy-collaboration/src/entities/mod.rs diff --git a/shared-lib/flowy-document-infra/src/entities/ws/mod.rs b/shared-lib/flowy-collaboration/src/entities/ws/mod.rs similarity index 100% rename from shared-lib/flowy-document-infra/src/entities/ws/mod.rs rename to shared-lib/flowy-collaboration/src/entities/ws/mod.rs diff --git a/shared-lib/flowy-document-infra/src/entities/ws/ws.rs b/shared-lib/flowy-collaboration/src/entities/ws/ws.rs similarity index 100% rename from shared-lib/flowy-document-infra/src/entities/ws/ws.rs rename to shared-lib/flowy-collaboration/src/entities/ws/ws.rs diff --git a/shared-lib/flowy-document-infra/src/errors.rs b/shared-lib/flowy-collaboration/src/errors.rs similarity index 100% rename from shared-lib/flowy-document-infra/src/errors.rs rename to shared-lib/flowy-collaboration/src/errors.rs diff --git a/shared-lib/flowy-document-infra/src/lib.rs b/shared-lib/flowy-collaboration/src/lib.rs similarity index 100% rename from shared-lib/flowy-document-infra/src/lib.rs rename to shared-lib/flowy-collaboration/src/lib.rs diff --git a/shared-lib/flowy-document-infra/src/protobuf/mod.rs b/shared-lib/flowy-collaboration/src/protobuf/mod.rs similarity index 100% rename from shared-lib/flowy-document-infra/src/protobuf/mod.rs rename to shared-lib/flowy-collaboration/src/protobuf/mod.rs diff --git a/shared-lib/flowy-document-infra/src/protobuf/model/doc.rs b/shared-lib/flowy-collaboration/src/protobuf/model/doc.rs similarity index 100% rename from shared-lib/flowy-document-infra/src/protobuf/model/doc.rs rename to shared-lib/flowy-collaboration/src/protobuf/model/doc.rs diff --git a/shared-lib/flowy-document-infra/src/protobuf/model/mod.rs b/shared-lib/flowy-collaboration/src/protobuf/model/mod.rs similarity index 100% rename from shared-lib/flowy-document-infra/src/protobuf/model/mod.rs rename to shared-lib/flowy-collaboration/src/protobuf/model/mod.rs diff --git a/shared-lib/flowy-document-infra/src/protobuf/model/ws.rs b/shared-lib/flowy-collaboration/src/protobuf/model/ws.rs similarity index 100% rename from shared-lib/flowy-document-infra/src/protobuf/model/ws.rs rename to shared-lib/flowy-collaboration/src/protobuf/model/ws.rs diff --git a/shared-lib/flowy-document-infra/src/protobuf/proto/doc.proto b/shared-lib/flowy-collaboration/src/protobuf/proto/doc.proto similarity index 100% rename from shared-lib/flowy-document-infra/src/protobuf/proto/doc.proto rename to shared-lib/flowy-collaboration/src/protobuf/proto/doc.proto diff --git a/shared-lib/flowy-document-infra/src/protobuf/proto/ws.proto b/shared-lib/flowy-collaboration/src/protobuf/proto/ws.proto similarity index 100% rename from shared-lib/flowy-document-infra/src/protobuf/proto/ws.proto rename to shared-lib/flowy-collaboration/src/protobuf/proto/ws.proto diff --git a/shared-lib/flowy-document-infra/src/user_default.rs b/shared-lib/flowy-collaboration/src/user_default.rs similarity index 100% rename from shared-lib/flowy-document-infra/src/user_default.rs rename to shared-lib/flowy-collaboration/src/user_default.rs diff --git a/shared-lib/flowy-document-infra/src/util.rs b/shared-lib/flowy-collaboration/src/util.rs similarity index 100% rename from shared-lib/flowy-document-infra/src/util.rs rename to shared-lib/flowy-collaboration/src/util.rs diff --git a/shared-lib/flowy-core-infra/Cargo.toml b/shared-lib/flowy-core-infra/Cargo.toml index 71ff468c9a..28898dabf7 100644 --- a/shared-lib/flowy-core-infra/Cargo.toml +++ b/shared-lib/flowy-core-infra/Cargo.toml @@ -14,7 +14,7 @@ strum = "0.21" strum_macros = "0.21" derive_more = {version = "0.99", features = ["display"]} log = "0.4.14" -flowy-document-infra = { path = "../flowy-document-infra" } +flowy-collaboration = { path = "../flowy-collaboration" } uuid = { version = "0.8", features = ["serde", "v4"] } chrono = { version = "0.4" } diff --git a/shared-lib/flowy-core-infra/src/entities/view/view_create.rs b/shared-lib/flowy-core-infra/src/entities/view/view_create.rs index b1a78e3545..905daf28a3 100644 --- a/shared-lib/flowy-core-infra/src/entities/view/view_create.rs +++ b/shared-lib/flowy-core-infra/src/entities/view/view_create.rs @@ -7,8 +7,8 @@ use crate::{ view::{ViewName, ViewThumbnail}, }, }; +use flowy_collaboration::user_default::doc_initial_string; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; -use flowy_document_infra::user_default::doc_initial_string; use std::convert::TryInto; #[derive(PartialEq, Debug, ProtoBuf_Enum, Clone)] diff --git a/shared-lib/flowy-core-infra/src/entities/view/view_query.rs b/shared-lib/flowy-core-infra/src/entities/view/view_query.rs index f852ae9a34..e9f6a72534 100644 --- a/shared-lib/flowy-core-infra/src/entities/view/view_query.rs +++ b/shared-lib/flowy-core-infra/src/entities/view/view_query.rs @@ -1,6 +1,6 @@ use crate::{errors::ErrorCode, parser::view::ViewId}; +use flowy_collaboration::entities::doc::DocIdentifier; use flowy_derive::ProtoBuf; -use flowy_document_infra::entities::doc::DocIdentifier; use std::convert::TryInto; #[derive(Default, ProtoBuf)] diff --git a/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs b/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs index 0b2e87e489..f5f90b2b79 100644 --- a/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs +++ b/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs @@ -24,13 +24,6 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { | "FFIResponse" | "SubscribeObject" | "UserError" - | "CreateDocParams" - | "Doc" - | "UpdateDocParams" - | "DocDelta" - | "NewDocUser" - | "DocIdentifier" - | "WsDocumentData" | "QueryAppRequest" | "AppIdentifier" | "CreateAppRequest" @@ -64,6 +57,13 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { | "RepeatedView" | "ExportRequest" | "ExportData" + | "CreateDocParams" + | "Doc" + | "UpdateDocParams" + | "DocDelta" + | "NewDocUser" + | "DocIdentifier" + | "WsDocumentData" | "WsError" | "WsMessage" | "Revision" @@ -88,10 +88,10 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { | "FFIStatusCode" | "UserEvent" | "UserNotification" - | "WsDataType" | "TrashType" | "ViewType" | "ExportType" + | "WsDataType" | "WsModule" | "RevType" => TypeCategory::Enum, From d3bfca10e92707a385706a3ea8f2cbc98b9bf1ee Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 11 Dec 2021 17:48:39 +0800 Subject: [PATCH 19/39] refactor backend editor --- backend/Cargo.lock | 52 ++-- backend/src/services/doc/edit/edit_actor.rs | 123 -------- backend/src/services/doc/edit/editor.rs | 265 ------------------ backend/src/services/doc/edit/mod.rs | 5 - backend/src/services/doc/editor.rs | 149 ++++++++++ backend/src/services/doc/manager.rs | 142 ++++++++-- backend/src/services/doc/mod.rs | 3 +- backend/src/web_socket/biz_handler.rs | 2 +- backend/src/web_socket/router.rs | 18 ++ backend/src/web_socket/ws_client.rs | 2 +- .../src/services/doc/revision/sync.rs | 12 +- .../src/services/user/ws_manager.rs | 2 +- shared-lib/Cargo.lock | 42 +-- .../src/core/sync/rev_sync.rs | 64 ++--- shared-lib/lib-ot/src/errors.rs | 9 + shared-lib/lib-ot/src/revision/model.rs | 6 + 16 files changed, 389 insertions(+), 507 deletions(-) delete mode 100644 backend/src/services/doc/edit/edit_actor.rs delete mode 100644 backend/src/services/doc/edit/editor.rs delete mode 100644 backend/src/services/doc/edit/mod.rs create mode 100644 backend/src/services/doc/editor.rs diff --git a/backend/Cargo.lock b/backend/Cargo.lock index c5504943a5..a9cc97f8c5 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -455,9 +455,9 @@ dependencies = [ "config", "dashmap", "derive_more", + "flowy-collaboration", "flowy-core-infra", "flowy-document", - "flowy-ot", "flowy-sdk", "flowy-test", "flowy-user", @@ -1195,6 +1195,26 @@ dependencies = [ "syn", ] +[[package]] +name = "flowy-collaboration" +version = "0.1.0" +dependencies = [ + "bytes", + "chrono", + "flowy-derive", + "lib-ot", + "log", + "md5", + "parking_lot", + "protobuf", + "serde", + "strum", + "strum_macros", + "tokio", + "tracing", + "url", +] + [[package]] name = "flowy-core" version = "0.1.0" @@ -1209,11 +1229,11 @@ dependencies = [ "derive_more", "diesel", "diesel_derives", + "flowy-collaboration", "flowy-core-infra", "flowy-database", "flowy-derive", "flowy-document", - "flowy-ot", "futures", "futures-core", "lazy_static", @@ -1239,8 +1259,8 @@ dependencies = [ "bytes", "chrono", "derive_more", + "flowy-collaboration", "flowy-derive", - "flowy-ot", "log", "protobuf", "strum", @@ -1284,9 +1304,9 @@ dependencies = [ "derive_more", "diesel", "diesel_derives", + "flowy-collaboration", "flowy-database", "flowy-derive", - "flowy-ot", "futures", "futures-core", "futures-util", @@ -1309,26 +1329,6 @@ dependencies = [ "url", ] -[[package]] -name = "flowy-ot" -version = "0.1.0" -dependencies = [ - "bytes", - "chrono", - "flowy-derive", - "lib-ot", - "log", - "md5", - "parking_lot", - "protobuf", - "serde", - "strum", - "strum_macros", - "tokio", - "tracing", - "url", -] - [[package]] name = "flowy-sdk" version = "0.1.0" @@ -1336,10 +1336,10 @@ dependencies = [ "backend-service", "bytes", "color-eyre", + "flowy-collaboration", "flowy-core", "flowy-database", "flowy-document", - "flowy-ot", "flowy-user", "futures-core", "lib-dispatch", @@ -1360,9 +1360,9 @@ dependencies = [ "bincode", "bytes", "claim", + "flowy-collaboration", "flowy-core", "flowy-document", - "flowy-ot", "flowy-sdk", "flowy-user", "futures-util", diff --git a/backend/src/services/doc/edit/edit_actor.rs b/backend/src/services/doc/edit/edit_actor.rs deleted file mode 100644 index 0bbca02419..0000000000 --- a/backend/src/services/doc/edit/edit_actor.rs +++ /dev/null @@ -1,123 +0,0 @@ -use crate::{ - services::doc::edit::ServerDocEditor, - web_socket::{entities::Socket, WsUser}, -}; -use actix_web::web::Data; -use async_stream::stream; -use backend_service::errors::{internal_error, Result as DocResult, ServerError}; -use flowy_collaboration::protobuf::Doc; -use futures::stream::StreamExt; -use lib_ot::protobuf::Revision; -use sqlx::PgPool; -use std::sync::{atomic::Ordering::SeqCst, Arc}; -use tokio::{ - sync::{mpsc, oneshot}, - task::spawn_blocking, -}; - -#[derive(Clone)] -pub struct EditUser { - user: Arc, - pub(crate) socket: Socket, -} - -impl EditUser { - pub fn id(&self) -> String { self.user.id().to_string() } -} - -#[derive(Debug)] -pub enum EditMsg { - Revision { - user: Arc, - socket: Socket, - revision: Revision, - ret: oneshot::Sender>, - }, - DocumentJson { - ret: oneshot::Sender>, - }, - DocumentRevId { - ret: oneshot::Sender>, - }, - NewDocUser { - user: Arc, - socket: Socket, - rev_id: i64, - ret: oneshot::Sender>, - }, -} - -pub struct EditDocActor { - receiver: Option>, - edit_doc: Arc, - pg_pool: Data, -} - -impl EditDocActor { - pub fn new(receiver: mpsc::Receiver, doc: Doc, pg_pool: Data) -> Result { - let edit_doc = Arc::new(ServerDocEditor::new(doc)?); - Ok(Self { - receiver: Some(receiver), - edit_doc, - pg_pool, - }) - } - - pub async fn run(mut self) { - let mut receiver = self - .receiver - .take() - .expect("DocActor's receiver should only take one time"); - - let stream = stream! { - loop { - match receiver.recv().await { - Some(msg) => yield msg, - None => break, - } - } - }; - stream.for_each(|msg| self.handle_message(msg)).await; - } - - async fn handle_message(&self, msg: EditMsg) { - match msg { - EditMsg::Revision { - user, - socket, - revision, - ret, - } => { - let user = EditUser { - user: user.clone(), - socket: socket.clone(), - }; - let _ = ret.send(self.edit_doc.apply_revision(user, revision, self.pg_pool.clone()).await); - }, - EditMsg::DocumentJson { ret } => { - let edit_context = self.edit_doc.clone(); - let json = spawn_blocking(move || edit_context.document_json()) - .await - .map_err(internal_error); - let _ = ret.send(json); - }, - EditMsg::DocumentRevId { ret } => { - let edit_context = self.edit_doc.clone(); - let _ = ret.send(Ok(edit_context.rev_id.load(SeqCst))); - }, - EditMsg::NewDocUser { - user, - socket, - rev_id, - ret, - } => { - log::debug!("Receive new doc user: {:?}, rev_id: {}", user, rev_id); - let user = EditUser { - user: user.clone(), - socket: socket.clone(), - }; - let _ = ret.send(self.edit_doc.new_doc_user(user, rev_id).await); - }, - } - } -} diff --git a/backend/src/services/doc/edit/editor.rs b/backend/src/services/doc/edit/editor.rs deleted file mode 100644 index f78d265e53..0000000000 --- a/backend/src/services/doc/edit/editor.rs +++ /dev/null @@ -1,265 +0,0 @@ -use crate::{ - services::{ - doc::{edit::edit_actor::EditUser, update_doc}, - util::md5, - }, - web_socket::{entities::Socket, WsMessageAdaptor}, -}; -use actix_web::web::Data; -use backend_service::errors::{internal_error, ServerError}; -use dashmap::DashMap; -use flowy_collaboration::{ - core::document::Document, - entities::ws::{WsDataType, WsDocumentData}, - protobuf::{Doc, UpdateDocParams}, -}; -use lib_ot::{ - core::OperationTransformable, - protobuf::{RevId, RevType, Revision, RevisionRange}, - rich_text::RichTextDelta, -}; -use parking_lot::RwLock; -use protobuf::Message; -use sqlx::PgPool; -use std::{ - cmp::Ordering, - sync::{ - atomic::{AtomicI64, Ordering::SeqCst}, - Arc, - }, - time::Duration, -}; - -pub struct ServerDocEditor { - pub doc_id: String, - pub rev_id: AtomicI64, - document: Arc>, - users: DashMap, -} - -impl ServerDocEditor { - pub fn new(doc: Doc) -> Result { - let delta = RichTextDelta::from_bytes(&doc.data).map_err(internal_error)?; - let document = Arc::new(RwLock::new(Document::from_delta(delta))); - let users = DashMap::new(); - Ok(Self { - doc_id: doc.id.clone(), - rev_id: AtomicI64::new(doc.rev_id), - document, - users, - }) - } - - #[tracing::instrument( - level = "debug", - skip(self, user), - fields( - user_id = %user.id(), - rev_id = %rev_id, - ) - )] - pub async fn new_doc_user(&self, user: EditUser, rev_id: i64) -> Result<(), ServerError> { - self.users.insert(user.id(), user.clone()); - let cur_rev_id = self.rev_id.load(SeqCst); - match cur_rev_id.cmp(&rev_id) { - Ordering::Less => { - user.socket - .do_send(mk_pull_message(&self.doc_id, next(cur_rev_id), rev_id)) - .map_err(internal_error)?; - }, - Ordering::Equal => {}, - Ordering::Greater => { - let doc_delta = self.document.read().delta().clone(); - let cli_revision = self.mk_revision(rev_id, doc_delta); - let ws_cli_revision = mk_push_message(&self.doc_id, cli_revision); - user.socket.do_send(ws_cli_revision).map_err(internal_error)?; - }, - } - - Ok(()) - } - - #[tracing::instrument( - level = "debug", - skip(self, user, pg_pool, revision), - fields( - cur_rev_id = %self.rev_id.load(SeqCst), - base_rev_id = %revision.base_rev_id, - rev_id = %revision.rev_id, - ), - err - )] - pub async fn apply_revision( - &self, - user: EditUser, - revision: Revision, - pg_pool: Data, - ) -> Result<(), ServerError> { - self.users.insert(user.id(), user.clone()); - let cur_rev_id = self.rev_id.load(SeqCst); - match cur_rev_id.cmp(&revision.rev_id) { - Ordering::Less => { - let next_rev_id = next(cur_rev_id); - if cur_rev_id == revision.base_rev_id || next_rev_id == revision.base_rev_id { - // The rev is in the right order, just compose it. - let _ = self.compose_revision(&revision).await?; - let _ = send_acked_msg(&user.socket, &revision)?; - let _ = self.save_revision(&revision, pg_pool).await?; - } else { - // The server document is outdated, pull the missing revision from the client. - let _ = send_pull_message(&user.socket, &self.doc_id, next_rev_id, revision.rev_id)?; - } - }, - Ordering::Equal => { - // Do nothing - log::warn!("Applied revision rev_id is the same as cur_rev_id"); - }, - Ordering::Greater => { - // The client document is outdated. Transform the client revision delta and then - // send the prime delta to the client. Client should compose the this prime - // delta. - let cli_revision = self.transform_revision(&revision)?; - let _ = send_push_message(&user.socket, &self.doc_id, cli_revision)?; - }, - } - Ok(()) - } - - pub fn document_json(&self) -> String { self.document.read().to_json() } - - async fn compose_revision(&self, revision: &Revision) -> Result<(), ServerError> { - let delta = RichTextDelta::from_bytes(&revision.delta_data).map_err(internal_error)?; - let _ = self.compose_delta(delta)?; - let _ = self.rev_id.fetch_update(SeqCst, SeqCst, |_e| Some(revision.rev_id)); - Ok(()) - } - - #[tracing::instrument(level = "debug", skip(self, revision))] - fn transform_revision(&self, revision: &Revision) -> Result { - let cli_delta = RichTextDelta::from_bytes(&revision.delta_data).map_err(internal_error)?; - let (cli_prime, server_prime) = self - .document - .read() - .delta() - .transform(&cli_delta) - .map_err(internal_error)?; - - let _ = self.compose_delta(server_prime)?; - let cli_revision = self.mk_revision(revision.rev_id, cli_prime); - Ok(cli_revision) - } - - fn mk_revision(&self, base_rev_id: i64, delta: RichTextDelta) -> Revision { - let delta_data = delta.to_bytes().to_vec(); - let md5 = md5(&delta_data); - Revision { - base_rev_id, - rev_id: self.rev_id.load(SeqCst), - delta_data, - md5, - doc_id: self.doc_id.to_string(), - ty: RevType::Remote, - ..Default::default() - } - } - - #[tracing::instrument( - level = "debug", - skip(self, delta), - fields( - revision_delta = %delta.to_json(), - result, - ) - )] - fn compose_delta(&self, delta: RichTextDelta) -> Result<(), ServerError> { - if delta.is_empty() { - log::warn!("Composed delta is empty"); - } - - match self.document.try_write_for(Duration::from_millis(300)) { - None => { - log::error!("Failed to acquire write lock of document"); - }, - Some(mut write_guard) => { - let _ = write_guard.compose_delta(delta).map_err(internal_error)?; - tracing::Span::current().record("result", &write_guard.to_json().as_str()); - }, - } - Ok(()) - } - - #[tracing::instrument(level = "debug", skip(self, revision, pg_pool), err)] - async fn save_revision(&self, revision: &Revision, pg_pool: Data) -> Result<(), ServerError> { - // Opti: save with multiple revisions - let mut params = UpdateDocParams::new(); - params.set_doc_id(self.doc_id.clone()); - params.set_data(self.document.read().to_json()); - params.set_rev_id(revision.rev_id); - let _ = update_doc(pg_pool.get_ref(), params).await?; - Ok(()) - } -} - -#[tracing::instrument(level = "debug", skip(socket, doc_id, revision), err)] -fn send_push_message(socket: &Socket, doc_id: &str, revision: Revision) -> Result<(), ServerError> { - let msg = mk_push_message(doc_id, revision); - socket.try_send(msg).map_err(internal_error) -} - -fn mk_push_message(doc_id: &str, revision: Revision) -> WsMessageAdaptor { - let bytes = revision.write_to_bytes().unwrap(); - let data = WsDocumentData { - doc_id: doc_id.to_string(), - ty: WsDataType::PushRev, - data: bytes, - }; - data.into() -} - -#[tracing::instrument(level = "debug", skip(socket, doc_id), err)] -fn send_pull_message(socket: &Socket, doc_id: &str, from_rev_id: i64, to_rev_id: i64) -> Result<(), ServerError> { - let msg = mk_pull_message(doc_id, from_rev_id, to_rev_id); - socket.try_send(msg).map_err(internal_error) -} - -fn mk_pull_message(doc_id: &str, from_rev_id: i64, to_rev_id: i64) -> WsMessageAdaptor { - let range = RevisionRange { - doc_id: doc_id.to_string(), - start: from_rev_id, - end: to_rev_id, - ..Default::default() - }; - - let bytes = range.write_to_bytes().unwrap(); - let data = WsDocumentData { - doc_id: doc_id.to_string(), - ty: WsDataType::PullRev, - data: bytes, - }; - data.into() -} - -#[tracing::instrument(level = "debug", skip(socket, revision), err)] -fn send_acked_msg(socket: &Socket, revision: &Revision) -> Result<(), ServerError> { - let msg = mk_acked_message(revision); - socket.try_send(msg).map_err(internal_error) -} - -fn mk_acked_message(revision: &Revision) -> WsMessageAdaptor { - // let mut wtr = vec![]; - // let _ = wtr.write_i64::(revision.rev_id); - let mut rev_id = RevId::new(); - rev_id.set_value(revision.rev_id); - let data = rev_id.write_to_bytes().unwrap(); - - let data = WsDocumentData { - doc_id: revision.doc_id.clone(), - ty: WsDataType::Acked, - data, - }; - - data.into() -} - -#[inline] -fn next(rev_id: i64) -> i64 { rev_id + 1 } diff --git a/backend/src/services/doc/edit/mod.rs b/backend/src/services/doc/edit/mod.rs deleted file mode 100644 index 9012184ffc..0000000000 --- a/backend/src/services/doc/edit/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub(crate) mod edit_actor; -mod editor; - -pub use edit_actor::*; -pub use editor::*; diff --git a/backend/src/services/doc/editor.rs b/backend/src/services/doc/editor.rs new file mode 100644 index 0000000000..c700e87dd1 --- /dev/null +++ b/backend/src/services/doc/editor.rs @@ -0,0 +1,149 @@ +use crate::{ + services::doc::update_doc, + web_socket::{entities::Socket, WsMessageAdaptor, WsUser}, +}; +use actix_web::web::Data; +use backend_service::errors::{internal_error, ServerError}; +use dashmap::DashMap; +use flowy_collaboration::{ + core::{ + document::Document, + sync::{RevisionSynchronizer, RevisionUser, SyncResponse}, + }, + protobuf::{Doc, UpdateDocParams}, +}; +use lib_ot::{protobuf::Revision, rich_text::RichTextDelta}; +use sqlx::PgPool; +use std::{ + convert::TryInto, + sync::{ + atomic::{AtomicI64, Ordering::SeqCst}, + Arc, + }, +}; + +#[rustfmt::skip] +// ┌──────────────────────┐ ┌────────────┐ +// ┌───▶│ RevisionSynchronizer │────▶│ Document │ +// │ └──────────────────────┘ └────────────┘ +// ┌────────────────┐ │ +// │ServerDocEditor │────┤ ┌───────────┐ +// └────────────────┘ │ ┌───▶│ WsUser │ +// │ │ └───────────┘ +// │ ┌────────┐ ┌───────────┐ │ ┌───────────┐ +// └───▶│ Users │◆──────│ DocUser ├───┼───▶│ Socket │ +// └────────┘ └───────────┘ │ └───────────┘ +// │ ┌───────────┐ +// └───▶│ PgPool │ +// └───────────┘ +pub struct ServerDocEditor { + pub doc_id: String, + pub rev_id: AtomicI64, + synchronizer: Arc, + users: DashMap, +} + +impl ServerDocEditor { + pub fn new(doc: Doc) -> Result { + let delta = RichTextDelta::from_bytes(&doc.data).map_err(internal_error)?; + let users = DashMap::new(); + let synchronizer = Arc::new(RevisionSynchronizer::new( + &doc.id, + doc.rev_id, + Document::from_delta(delta), + )); + + Ok(Self { + doc_id: doc.id.clone(), + rev_id: AtomicI64::new(doc.rev_id), + synchronizer, + users, + }) + } + + #[tracing::instrument( + level = "debug", + skip(self, user), + fields( + user_id = %user.id(), + rev_id = %rev_id, + ) + )] + pub async fn new_doc_user(&self, user: DocUser, rev_id: i64) -> Result<(), ServerError> { + self.users.insert(user.id(), user.clone()); + self.synchronizer.new_conn(user, rev_id); + Ok(()) + } + + #[tracing::instrument( + level = "debug", + skip(self, user, revision), + fields( + cur_rev_id = %self.rev_id.load(SeqCst), + base_rev_id = %revision.base_rev_id, + rev_id = %revision.rev_id, + ), + err + )] + pub async fn apply_revision(&self, user: DocUser, mut revision: Revision) -> Result<(), ServerError> { + self.users.insert(user.id(), user.clone()); + let revision = (&mut revision).try_into().map_err(internal_error)?; + self.synchronizer.apply_revision(user, revision).unwrap(); + Ok(()) + } + + pub fn document_json(&self) -> String { self.synchronizer.doc_json() } +} + +#[derive(Clone)] +pub struct DocUser { + pub user: Arc, + pub(crate) socket: Socket, + pub pg_pool: Data, +} + +impl DocUser { + pub fn id(&self) -> String { self.user.id().to_string() } +} + +impl RevisionUser for DocUser { + fn recv(&self, resp: SyncResponse) { + let result = match resp { + SyncResponse::Pull(data) => { + let msg: WsMessageAdaptor = data.into(); + self.socket.try_send(msg).map_err(internal_error) + }, + SyncResponse::Push(data) => { + let msg: WsMessageAdaptor = data.into(); + self.socket.try_send(msg).map_err(internal_error) + }, + SyncResponse::Ack(data) => { + let msg: WsMessageAdaptor = data.into(); + self.socket.try_send(msg).map_err(internal_error) + }, + SyncResponse::NewRevision { + rev_id, + doc_id, + doc_json, + } => { + let pg_pool = self.pg_pool.clone(); + tokio::task::spawn(async move { + let mut params = UpdateDocParams::new(); + params.set_doc_id(doc_id); + params.set_data(doc_json); + params.set_rev_id(rev_id); + match update_doc(pg_pool.get_ref(), params).await { + Ok(_) => {}, + Err(e) => log::error!("{}", e), + } + }); + Ok(()) + }, + }; + + match result { + Ok(_) => {}, + Err(e) => log::error!("{}", e), + } + } +} diff --git a/backend/src/services/doc/manager.rs b/backend/src/services/doc/manager.rs index 4ea6255726..25b1d96427 100644 --- a/backend/src/services/doc/manager.rs +++ b/backend/src/services/doc/manager.rs @@ -1,18 +1,20 @@ use crate::{ services::doc::{ - edit::edit_actor::{EditDocActor, EditMsg}, + editor::{DocUser, ServerDocEditor}, read_doc, ws_actor::{DocWsActor, DocWsMsg}, }, web_socket::{entities::Socket, WsBizHandler, WsClientData, WsUser}, }; use actix_web::web::Data; +use async_stream::stream; use backend_service::errors::{internal_error, Result as DocResult, ServerError}; use dashmap::DashMap; use flowy_collaboration::protobuf::{Doc, DocIdentifier}; +use futures::stream::StreamExt; use lib_ot::protobuf::Revision; use sqlx::PgPool; -use std::sync::Arc; +use std::sync::{atomic::Ordering::SeqCst, Arc}; use tokio::{ sync::{mpsc, oneshot}, task::spawn_blocking, @@ -43,13 +45,17 @@ impl DocumentCore { } impl WsBizHandler for DocumentCore { - fn receive_data(&self, client_data: WsClientData) { + fn receive(&self, data: WsClientData) { let (ret, rx) = oneshot::channel(); let sender = self.ws_sender.clone(); let pool = self.pg_pool.clone(); actix_rt::spawn(async move { - let msg = DocWsMsg::ClientData { client_data, ret, pool }; + let msg = DocWsMsg::ClientData { + client_data: data, + ret, + pool, + }; match sender.send(msg).await { Ok(_) => {}, Err(e) => log::error!("{}", e), @@ -63,16 +69,9 @@ impl WsBizHandler for DocumentCore { } #[rustfmt::skip] -// EditDocActor -// ┌────────────────────────────────────┐ -// │ ServerDocEditor │ -// │ ┌──────────────────────────────┐ │ -// ┌────────────┐ 1 n ┌───────────────┐ │ │ ┌──────────┐ ┌──────────┐ │ │ -// │ DocManager │─────▶│ OpenDocHandle │──────▶│ │ │ Document │ │ Users │ │ │ -// └────────────┘ └───────────────┘ │ │ └──────────┘ └──────────┘ │ │ -// │ └──────────────────────────────┘ │ -// │ │ -// └────────────────────────────────────┘ +// ┌────────────┐ 1 n ┌───────────────┐ ┌──────────────────┐ ┌────────────────┐ +// │ DocManager │───────▶│ OpenDocHandle │────▶│ DocMessageQueue │───▶│ServerDocEditor │ +// └────────────┘ └───────────────┘ └──────────────────┘ └────────────────┘ pub struct DocManager { open_doc_map: DashMap>, } @@ -109,20 +108,20 @@ impl DocManager { } pub struct OpenDocHandle { - pub sender: mpsc::Sender, + pub sender: mpsc::Sender, } impl OpenDocHandle { pub fn new(doc: Doc, pg_pool: Data) -> Result { let (sender, receiver) = mpsc::channel(100); - let actor = EditDocActor::new(receiver, doc, pg_pool)?; - tokio::task::spawn(actor.run()); + let queue = DocMessageQueue::new(receiver, doc, pg_pool)?; + tokio::task::spawn(queue.run()); Ok(Self { sender }) } pub async fn add_user(&self, user: Arc, rev_id: i64, socket: Socket) -> Result<(), ServerError> { let (ret, rx) = oneshot::channel(); - let msg = EditMsg::NewDocUser { + let msg = DocMessage::NewConnectedUser { user, socket, rev_id, @@ -139,7 +138,7 @@ impl OpenDocHandle { revision: Revision, ) -> Result<(), ServerError> { let (ret, rx) = oneshot::channel(); - let msg = EditMsg::Revision { + let msg = DocMessage::ReceiveRevision { user, socket, revision, @@ -151,19 +150,118 @@ impl OpenDocHandle { pub async fn document_json(&self) -> DocResult { let (ret, rx) = oneshot::channel(); - let msg = EditMsg::DocumentJson { ret }; + let msg = DocMessage::GetDocJson { ret }; self.send(msg, rx).await? } pub async fn rev_id(&self) -> DocResult { let (ret, rx) = oneshot::channel(); - let msg = EditMsg::DocumentRevId { ret }; + let msg = DocMessage::GetDocRevId { ret }; self.send(msg, rx).await? } - pub(crate) async fn send(&self, msg: EditMsg, rx: oneshot::Receiver) -> DocResult { + pub(crate) async fn send(&self, msg: DocMessage, rx: oneshot::Receiver) -> DocResult { let _ = self.sender.send(msg).await.map_err(internal_error)?; let result = rx.await?; Ok(result) } } + +#[derive(Debug)] +pub enum DocMessage { + NewConnectedUser { + user: Arc, + socket: Socket, + rev_id: i64, + ret: oneshot::Sender>, + }, + ReceiveRevision { + user: Arc, + socket: Socket, + revision: Revision, + ret: oneshot::Sender>, + }, + GetDocJson { + ret: oneshot::Sender>, + }, + GetDocRevId { + ret: oneshot::Sender>, + }, +} + +struct DocMessageQueue { + receiver: Option>, + edit_doc: Arc, + pg_pool: Data, +} + +impl DocMessageQueue { + fn new(receiver: mpsc::Receiver, doc: Doc, pg_pool: Data) -> Result { + let edit_doc = Arc::new(ServerDocEditor::new(doc)?); + Ok(Self { + receiver: Some(receiver), + edit_doc, + pg_pool, + }) + } + + async fn run(mut self) { + let mut receiver = self + .receiver + .take() + .expect("DocActor's receiver should only take one time"); + + let stream = stream! { + loop { + match receiver.recv().await { + Some(msg) => yield msg, + None => break, + } + } + }; + stream.for_each(|msg| self.handle_message(msg)).await; + } + + async fn handle_message(&self, msg: DocMessage) { + match msg { + DocMessage::NewConnectedUser { + user, + socket, + rev_id, + ret, + } => { + log::debug!("Receive new doc user: {:?}, rev_id: {}", user, rev_id); + let user = DocUser { + user: user.clone(), + socket: socket.clone(), + pg_pool: self.pg_pool.clone(), + }; + let _ = ret.send(self.edit_doc.new_doc_user(user, rev_id).await); + }, + DocMessage::ReceiveRevision { + user, + socket, + revision, + ret, + } => { + let user = DocUser { + user: user.clone(), + socket: socket.clone(), + pg_pool: self.pg_pool.clone(), + }; + let _ = ret.send(self.edit_doc.apply_revision(user, revision).await); + }, + DocMessage::GetDocJson { ret } => { + let edit_context = self.edit_doc.clone(); + let json = spawn_blocking(move || edit_context.document_json()) + .await + .map_err(internal_error); + let _ = ret.send(json); + }, + DocMessage::GetDocRevId { ret } => { + let rev_id = self.edit_doc.rev_id.load(SeqCst); + let _ = ret.send(Ok(rev_id)); + }, + } + } +} diff --git a/backend/src/services/doc/mod.rs b/backend/src/services/doc/mod.rs index 6e0a2c9694..f37c30a403 100644 --- a/backend/src/services/doc/mod.rs +++ b/backend/src/services/doc/mod.rs @@ -1,9 +1,10 @@ #![allow(clippy::module_inception)] + pub(crate) use crud::*; pub use router::*; pub mod crud; -mod edit; +mod editor; pub mod manager; pub mod router; mod ws_actor; diff --git a/backend/src/web_socket/biz_handler.rs b/backend/src/web_socket/biz_handler.rs index 2b98b60db3..144ee0ac79 100644 --- a/backend/src/web_socket/biz_handler.rs +++ b/backend/src/web_socket/biz_handler.rs @@ -3,7 +3,7 @@ use lib_ws::WsModule; use std::{collections::HashMap, sync::Arc}; pub trait WsBizHandler: Send + Sync { - fn receive_data(&self, client_data: WsClientData); + fn receive(&self, data: WsClientData); } pub type BizHandler = Arc; diff --git a/backend/src/web_socket/router.rs b/backend/src/web_socket/router.rs index d6c5c2c53b..59250685b7 100644 --- a/backend/src/web_socket/router.rs +++ b/backend/src/web_socket/router.rs @@ -12,6 +12,24 @@ use actix_web::{ }; use actix_web_actors::ws; +#[rustfmt::skip] +// WsClient +// ┌─────────────┐ +// │ ┌────────┐ │ +// wss://xxx ─────▶│ │ WsUser │ │───┐ +// │ └────────┘ │ │ +// └─────────────┘ │ +// │ +// │ ┌───────────────┐ ┌─────────────┐ ┌────────────────┐ +// ├───▶│ WsBizHandlers │──▶│WsBizHandler │───▶│ WsClientData │ +// │ └───────────────┘ └─────────────┘ └────────────────┘ +// WsClient │ △ +// ┌─────────────┐ │ │ +// │ ┌────────┐ │ │ │ +// wss://xxx ─────▶│ │ WsUser │ │───┘ ┌───────────────┐ +// │ └────────┘ │ │ DocumentCore │ +// └─────────────┘ └───────────────┘ + #[get("/{token}")] pub async fn establish_ws_connection( request: HttpRequest, diff --git a/backend/src/web_socket/ws_client.rs b/backend/src/web_socket/ws_client.rs index d356f1c405..f2365958fd 100644 --- a/backend/src/web_socket/ws_client.rs +++ b/backend/src/web_socket/ws_client.rs @@ -75,7 +75,7 @@ impl WsClient { socket, data: Bytes::from(message.data), }; - handler.receive_data(client_data); + handler.receive(client_data); }, } } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs index 8859951717..98b2ccace5 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs @@ -15,7 +15,7 @@ use futures::stream::StreamExt; use lib_ot::revision::{RevId, RevisionRange}; use std::{convert::TryFrom, sync::Arc}; use tokio::{ - sync::{broadcast, mpsc, mpsc::error::SendError}, + sync::{broadcast, mpsc}, task::spawn_blocking, time::{interval, Duration}, }; @@ -175,7 +175,7 @@ impl RevisionUpStream { match self.revisions.next().await? { None => Ok(()), Some(record) => { - tracing::trace!( + tracing::debug!( "[RevisionUpStream]: processes revision: {}:{:?}", record.revision.doc_id, record.revision.rev_id @@ -190,13 +190,7 @@ impl RevisionUpStream { async fn tick(sender: mpsc::UnboundedSender) { let mut i = interval(Duration::from_secs(2)); - loop { - match sender.send(UpStreamMsg::Tick) { - Ok(_) => {}, - Err(_e) => { - break; - }, - } + while sender.send(UpStreamMsg::Tick).is_ok() { i.tick().await; } } diff --git a/frontend/rust-lib/flowy-user/src/services/user/ws_manager.rs b/frontend/rust-lib/flowy-user/src/services/user/ws_manager.rs index 07fef218f7..35245c2390 100644 --- a/frontend/rust-lib/flowy-user/src/services/user/ws_manager.rs +++ b/frontend/rust-lib/flowy-user/src/services/user/ws_manager.rs @@ -218,7 +218,7 @@ mod mock { impl FlowyWsSender for broadcast::Sender { fn send(&self, _msg: WsMessage) -> Result<(), UserError> { - // let _ = self.send(msg).unwrap(); + let _ = self.send(msg).unwrap(); Ok(()) } } diff --git a/shared-lib/Cargo.lock b/shared-lib/Cargo.lock index a02292d8c6..327a427a0e 100644 --- a/shared-lib/Cargo.lock +++ b/shared-lib/Cargo.lock @@ -657,6 +657,26 @@ dependencies = [ "syn", ] +[[package]] +name = "flowy-collaboration" +version = "0.1.0" +dependencies = [ + "bytes", + "chrono", + "flowy-derive", + "lib-ot", + "log", + "md5", + "parking_lot", + "protobuf", + "serde", + "strum", + "strum_macros", + "tokio", + "tracing", + "url", +] + [[package]] name = "flowy-core-infra" version = "0.1.0" @@ -664,8 +684,8 @@ dependencies = [ "bytes", "chrono", "derive_more", + "flowy-collaboration", "flowy-derive", - "flowy-ot", "log", "protobuf", "strum", @@ -687,26 +707,6 @@ dependencies = [ "trybuild", ] -[[package]] -name = "flowy-ot" -version = "0.1.0" -dependencies = [ - "bytes", - "chrono", - "flowy-derive", - "lib-ot", - "log", - "md5", - "parking_lot", - "protobuf", - "serde", - "strum", - "strum_macros", - "tokio", - "tracing", - "url", -] - [[package]] name = "flowy-user-infra" version = "0.1.0" diff --git a/shared-lib/flowy-collaboration/src/core/sync/rev_sync.rs b/shared-lib/flowy-collaboration/src/core/sync/rev_sync.rs index 94e98fe924..0bdd9643a6 100644 --- a/shared-lib/flowy-collaboration/src/core/sync/rev_sync.rs +++ b/shared-lib/flowy-collaboration/src/core/sync/rev_sync.rs @@ -21,57 +21,59 @@ use std::{ }, time::Duration, }; -use tokio::sync::mpsc; -pub enum SynchronizerCommand { +pub trait RevisionUser { + fn recv(&self, resp: SyncResponse); +} + +pub enum SyncResponse { Pull(WsDocumentData), Push(WsDocumentData), Ack(WsDocumentData), - SaveRevision(Revision), + NewRevision { + rev_id: i64, + doc_json: String, + doc_id: String, + }, } -pub type CommandReceiver = Arc; - pub struct RevisionSynchronizer { pub doc_id: String, pub rev_id: AtomicI64, document: Arc>, - command_receiver: CommandReceiver, } impl RevisionSynchronizer { - pub fn new( - doc_id: &str, - rev_id: i64, - document: Arc>, - command_receiver: CommandReceiver, - ) -> RevisionSynchronizer { + pub fn new(doc_id: &str, rev_id: i64, document: Document) -> RevisionSynchronizer { + let document = Arc::new(RwLock::new(document)); RevisionSynchronizer { doc_id: doc_id.to_string(), rev_id: AtomicI64::new(rev_id), document, - command_receiver, } } - pub fn new_conn(&self, rev_id: i64) { + pub fn new_conn(&self, user: T, rev_id: i64) { let cur_rev_id = self.rev_id.load(SeqCst); match cur_rev_id.cmp(&rev_id) { Ordering::Less => { let msg = mk_pull_message(&self.doc_id, next(cur_rev_id), rev_id); - self.send_command(SynchronizerCommand::Pull(msg)); + user.recv(SyncResponse::Pull(msg)); }, Ordering::Equal => {}, Ordering::Greater => { let doc_delta = self.document.read().delta().clone(); let revision = self.mk_revision(rev_id, doc_delta); let data = mk_push_message(&self.doc_id, revision); - self.send_command(SynchronizerCommand::Push(data)); + user.recv(SyncResponse::Push(data)); }, } } - pub fn apply_revision(&self, revision: Revision) -> Result<(), OTError> { + pub fn apply_revision(&self, user: T, revision: Revision) -> Result<(), OTError> + where + T: RevisionUser, + { let cur_rev_id = self.rev_id.load(SeqCst); match cur_rev_id.cmp(&revision.rev_id) { Ordering::Less => { @@ -79,12 +81,19 @@ impl RevisionSynchronizer { if cur_rev_id == revision.base_rev_id || next_rev_id == revision.base_rev_id { // The rev is in the right order, just compose it. let _ = self.compose_revision(&revision)?; - self.send_command(SynchronizerCommand::Ack(mk_acked_message(&revision))); - self.send_command(SynchronizerCommand::SaveRevision(revision)); + user.recv(SyncResponse::Ack(mk_acked_message(&revision))); + let rev_id = revision.rev_id; + let doc_id = self.doc_id.clone(); + let doc_json = self.doc_json(); + user.recv(SyncResponse::NewRevision { + rev_id, + doc_id, + doc_json, + }); } else { // The server document is outdated, pull the missing revision from the client. let msg = mk_pull_message(&self.doc_id, next_rev_id, revision.rev_id); - self.send_command(SynchronizerCommand::Pull(msg)); + user.recv(SyncResponse::Pull(msg)); } }, Ordering::Equal => { @@ -97,12 +106,14 @@ impl RevisionSynchronizer { // delta. let cli_revision = self.transform_revision(&revision)?; let data = mk_push_message(&self.doc_id, cli_revision); - self.send_command(SynchronizerCommand::Push(data)); + user.recv(SyncResponse::Push(data)); }, } Ok(()) } + pub fn doc_json(&self) -> String { self.document.read().to_json() } + fn compose_revision(&self, revision: &Revision) -> Result<(), OTError> { let delta = RichTextDelta::from_bytes(&revision.delta_data)?; let _ = self.compose_delta(delta)?; @@ -120,16 +131,6 @@ impl RevisionSynchronizer { Ok(cli_revision) } - fn send_command(&self, command: SynchronizerCommand) { (self.command_receiver)(command); } - - #[tracing::instrument( - level = "debug", - skip(self, delta), - fields( - revision_delta = %delta.to_json(), - result, - ) - )] fn compose_delta(&self, delta: RichTextDelta) -> Result<(), OTError> { if delta.is_empty() { log::warn!("Composed delta is empty"); @@ -139,7 +140,6 @@ impl RevisionSynchronizer { None => log::error!("Failed to acquire write lock of document"), Some(mut write_guard) => { let _ = write_guard.compose_delta(delta); - tracing::Span::current().record("result", &write_guard.to_json().as_str()); }, } Ok(()) diff --git a/shared-lib/lib-ot/src/errors.rs b/shared-lib/lib-ot/src/errors.rs index fde37f2c42..ea0df1b69e 100644 --- a/shared-lib/lib-ot/src/errors.rs +++ b/shared-lib/lib-ot/src/errors.rs @@ -37,6 +37,7 @@ impl OTError { static_ot_error!(duplicate_revision, OTErrorCode::DuplicatedRevision); static_ot_error!(revision_id_conflict, OTErrorCode::RevisionIDConflict); + static_ot_error!(internal, OTErrorCode::Internal); } impl fmt::Display for OTError { @@ -68,6 +69,7 @@ pub enum OTErrorCode { SerdeError, DuplicatedRevision, RevisionIDConflict, + Internal, } pub struct ErrorBuilder { @@ -96,3 +98,10 @@ impl ErrorBuilder { pub fn build(mut self) -> OTError { OTError::new(self.code, &self.msg.take().unwrap_or_else(|| "".to_owned())) } } + +pub fn internal_error(e: T) -> OTError +where + T: std::fmt::Debug, +{ + OTError::internal().context(e) +} diff --git a/shared-lib/lib-ot/src/revision/model.rs b/shared-lib/lib-ot/src/revision/model.rs index 79c9ed7bff..63a56fc314 100644 --- a/shared-lib/lib-ot/src/revision/model.rs +++ b/shared-lib/lib-ot/src/revision/model.rs @@ -30,6 +30,12 @@ impl Revision { pub fn is_empty(&self) -> bool { self.base_rev_id == self.rev_id } pub fn pair_rev_id(&self) -> (i64, i64) { (self.base_rev_id, self.rev_id) } + + // pub fn from_pb(pb: &mut crate::protobuf::Revision) -> Self { + // pb.try_into().unwrap() } + + // pub fn from_pb(mut pb: crate::protobuf::Revision) -> Self { + // Revision::try_from(&mut pb).unwrap() } } impl std::fmt::Debug for Revision { From 90e3ba14f1929fdd26d462cf276003a8efb2f8b3 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 12 Dec 2021 12:41:16 +0800 Subject: [PATCH 20/39] mv server's DocManager to flowy_collaboration crate --- .gitignore | 2 +- backend/Cargo.lock | 4 + backend/src/services/doc/editor.rs | 102 +------ backend/src/services/doc/manager.rs | 224 +-------------- backend/src/services/doc/ws_actor.rs | 60 ++-- backend/tests/document/helper.rs | 17 +- .../rust-lib/flowy-document/src/errors.rs | 4 +- .../src/services/doc/edit/editor.rs | 26 +- .../src/services/doc/edit/queue.rs | 8 +- .../tests/editor/revision_test.rs | 11 + frontend/rust-lib/flowy-test/src/helper.rs | 8 +- frontend/rust-lib/flowy-test/src/lib.rs | 1 + frontend/rust-lib/flowy-user/Cargo.toml | 1 + .../flowy-user/src/services/server/mod.rs | 13 + .../flowy-user/src/services/server/ws_mock.rs | 109 +++++++ .../flowy-user/src/services/user/mod.rs | 2 +- .../src/services/user/ws_manager.rs | 76 +---- shared-lib/Cargo.lock | 24 ++ shared-lib/flowy-collaboration/Cargo.toml | 7 +- .../src/core/document/document.rs | 32 ++- .../flowy-collaboration/src/core/sync/mod.rs | 2 + .../src/core/sync/rev_sync.rs | 11 +- .../src/core/sync/server_editor.rs | 272 ++++++++++++++++++ .../flowy-collaboration/src/entities/ws/ws.rs | 6 +- shared-lib/flowy-collaboration/src/errors.rs | 29 +- 25 files changed, 578 insertions(+), 473 deletions(-) create mode 100644 frontend/rust-lib/flowy-user/src/services/server/ws_mock.rs create mode 100644 shared-lib/flowy-collaboration/src/core/sync/server_editor.rs diff --git a/.gitignore b/.gitignore index 199285461d..0d9faef146 100644 --- a/.gitignore +++ b/.gitignore @@ -13,5 +13,5 @@ Cargo.lock **/target/ **/*.db .idea/ -**/flowy-test/** +**/temp/** .ruby-version diff --git a/backend/Cargo.lock b/backend/Cargo.lock index a9cc97f8c5..ed95e928da 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -1199,9 +1199,12 @@ dependencies = [ name = "flowy-collaboration" version = "0.1.0" dependencies = [ + "async-stream", "bytes", "chrono", + "dashmap", "flowy-derive", + "futures", "lib-ot", "log", "md5", @@ -1388,6 +1391,7 @@ dependencies = [ "derive_more", "diesel", "diesel_derives", + "flowy-collaboration", "flowy-database", "flowy-derive", "flowy-user-infra", diff --git a/backend/src/services/doc/editor.rs b/backend/src/services/doc/editor.rs index c700e87dd1..f797f52e35 100644 --- a/backend/src/services/doc/editor.rs +++ b/backend/src/services/doc/editor.rs @@ -3,110 +3,26 @@ use crate::{ web_socket::{entities::Socket, WsMessageAdaptor, WsUser}, }; use actix_web::web::Data; -use backend_service::errors::{internal_error, ServerError}; -use dashmap::DashMap; +use backend_service::errors::internal_error; + use flowy_collaboration::{ - core::{ - document::Document, - sync::{RevisionSynchronizer, RevisionUser, SyncResponse}, - }, - protobuf::{Doc, UpdateDocParams}, + core::sync::{RevisionUser, SyncResponse}, + protobuf::UpdateDocParams, }; -use lib_ot::{protobuf::Revision, rich_text::RichTextDelta}; + use sqlx::PgPool; -use std::{ - convert::TryInto, - sync::{ - atomic::{AtomicI64, Ordering::SeqCst}, - Arc, - }, -}; +use std::sync::Arc; -#[rustfmt::skip] -// ┌──────────────────────┐ ┌────────────┐ -// ┌───▶│ RevisionSynchronizer │────▶│ Document │ -// │ └──────────────────────┘ └────────────┘ -// ┌────────────────┐ │ -// │ServerDocEditor │────┤ ┌───────────┐ -// └────────────────┘ │ ┌───▶│ WsUser │ -// │ │ └───────────┘ -// │ ┌────────┐ ┌───────────┐ │ ┌───────────┐ -// └───▶│ Users │◆──────│ DocUser ├───┼───▶│ Socket │ -// └────────┘ └───────────┘ │ └───────────┘ -// │ ┌───────────┐ -// └───▶│ PgPool │ -// └───────────┘ -pub struct ServerDocEditor { - pub doc_id: String, - pub rev_id: AtomicI64, - synchronizer: Arc, - users: DashMap, -} - -impl ServerDocEditor { - pub fn new(doc: Doc) -> Result { - let delta = RichTextDelta::from_bytes(&doc.data).map_err(internal_error)?; - let users = DashMap::new(); - let synchronizer = Arc::new(RevisionSynchronizer::new( - &doc.id, - doc.rev_id, - Document::from_delta(delta), - )); - - Ok(Self { - doc_id: doc.id.clone(), - rev_id: AtomicI64::new(doc.rev_id), - synchronizer, - users, - }) - } - - #[tracing::instrument( - level = "debug", - skip(self, user), - fields( - user_id = %user.id(), - rev_id = %rev_id, - ) - )] - pub async fn new_doc_user(&self, user: DocUser, rev_id: i64) -> Result<(), ServerError> { - self.users.insert(user.id(), user.clone()); - self.synchronizer.new_conn(user, rev_id); - Ok(()) - } - - #[tracing::instrument( - level = "debug", - skip(self, user, revision), - fields( - cur_rev_id = %self.rev_id.load(SeqCst), - base_rev_id = %revision.base_rev_id, - rev_id = %revision.rev_id, - ), - err - )] - pub async fn apply_revision(&self, user: DocUser, mut revision: Revision) -> Result<(), ServerError> { - self.users.insert(user.id(), user.clone()); - let revision = (&mut revision).try_into().map_err(internal_error)?; - self.synchronizer.apply_revision(user, revision).unwrap(); - Ok(()) - } - - pub fn document_json(&self) -> String { self.synchronizer.doc_json() } -} - -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct DocUser { pub user: Arc, pub(crate) socket: Socket, pub pg_pool: Data, } -impl DocUser { - pub fn id(&self) -> String { self.user.id().to_string() } -} - impl RevisionUser for DocUser { + fn user_id(&self) -> String { self.user.id().to_string() } + fn recv(&self, resp: SyncResponse) { let result = match resp { SyncResponse::Pull(data) => { diff --git a/backend/src/services/doc/manager.rs b/backend/src/services/doc/manager.rs index 25b1d96427..a8315a3629 100644 --- a/backend/src/services/doc/manager.rs +++ b/backend/src/services/doc/manager.rs @@ -1,29 +1,13 @@ use crate::{ - services::doc::{ - editor::{DocUser, ServerDocEditor}, - read_doc, - ws_actor::{DocWsActor, DocWsMsg}, - }, - web_socket::{entities::Socket, WsBizHandler, WsClientData, WsUser}, + services::doc::ws_actor::{DocWsActor, DocWsMsg}, + web_socket::{WsBizHandler, WsClientData}, }; use actix_web::web::Data; -use async_stream::stream; -use backend_service::errors::{internal_error, Result as DocResult, ServerError}; -use dashmap::DashMap; -use flowy_collaboration::protobuf::{Doc, DocIdentifier}; -use futures::stream::StreamExt; -use lib_ot::protobuf::Revision; +use flowy_collaboration::core::sync::DocManager; use sqlx::PgPool; -use std::sync::{atomic::Ordering::SeqCst, Arc}; -use tokio::{ - sync::{mpsc, oneshot}, - task::spawn_blocking, -}; +use std::sync::Arc; +use tokio::sync::{mpsc, oneshot}; -#[rustfmt::skip] -// ┌──────────────┐ ┌────────────┐ 1 n ┌───────────────┐ -// │ DocumentCore │────▶│ DocManager │─────▶│ OpenDocHandle │ -// └──────────────┘ └────────────┘ └───────────────┘ pub struct DocumentCore { pub manager: Arc, ws_sender: mpsc::Sender, @@ -67,201 +51,3 @@ impl WsBizHandler for DocumentCore { }); } } - -#[rustfmt::skip] -// ┌────────────┐ 1 n ┌───────────────┐ ┌──────────────────┐ ┌────────────────┐ -// │ DocManager │───────▶│ OpenDocHandle │────▶│ DocMessageQueue │───▶│ServerDocEditor │ -// └────────────┘ └───────────────┘ └──────────────────┘ └────────────────┘ -pub struct DocManager { - open_doc_map: DashMap>, -} - -impl std::default::Default for DocManager { - fn default() -> Self { - Self { - open_doc_map: DashMap::new(), - } - } -} - -impl DocManager { - pub fn new() -> Self { DocManager::default() } - - pub async fn get(&self, doc_id: &str, pg_pool: Data) -> Result>, ServerError> { - match self.open_doc_map.get(doc_id) { - None => { - let params = DocIdentifier { - doc_id: doc_id.to_string(), - ..Default::default() - }; - let doc = read_doc(pg_pool.get_ref(), params).await?; - let handle = spawn_blocking(|| OpenDocHandle::new(doc, pg_pool)) - .await - .map_err(internal_error)?; - let handle = Arc::new(handle?); - self.open_doc_map.insert(doc_id.to_string(), handle.clone()); - Ok(Some(handle)) - }, - Some(ctx) => Ok(Some(ctx.clone())), - } - } -} - -pub struct OpenDocHandle { - pub sender: mpsc::Sender, -} - -impl OpenDocHandle { - pub fn new(doc: Doc, pg_pool: Data) -> Result { - let (sender, receiver) = mpsc::channel(100); - let queue = DocMessageQueue::new(receiver, doc, pg_pool)?; - tokio::task::spawn(queue.run()); - Ok(Self { sender }) - } - - pub async fn add_user(&self, user: Arc, rev_id: i64, socket: Socket) -> Result<(), ServerError> { - let (ret, rx) = oneshot::channel(); - let msg = DocMessage::NewConnectedUser { - user, - socket, - rev_id, - ret, - }; - let _ = self.send(msg, rx).await?; - Ok(()) - } - - pub async fn apply_revision( - &self, - user: Arc, - socket: Socket, - revision: Revision, - ) -> Result<(), ServerError> { - let (ret, rx) = oneshot::channel(); - let msg = DocMessage::ReceiveRevision { - user, - socket, - revision, - ret, - }; - let _ = self.send(msg, rx).await?; - Ok(()) - } - - pub async fn document_json(&self) -> DocResult { - let (ret, rx) = oneshot::channel(); - let msg = DocMessage::GetDocJson { ret }; - self.send(msg, rx).await? - } - - pub async fn rev_id(&self) -> DocResult { - let (ret, rx) = oneshot::channel(); - let msg = DocMessage::GetDocRevId { ret }; - self.send(msg, rx).await? - } - - pub(crate) async fn send(&self, msg: DocMessage, rx: oneshot::Receiver) -> DocResult { - let _ = self.sender.send(msg).await.map_err(internal_error)?; - let result = rx.await?; - Ok(result) - } -} - -#[derive(Debug)] -pub enum DocMessage { - NewConnectedUser { - user: Arc, - socket: Socket, - rev_id: i64, - ret: oneshot::Sender>, - }, - ReceiveRevision { - user: Arc, - socket: Socket, - revision: Revision, - ret: oneshot::Sender>, - }, - GetDocJson { - ret: oneshot::Sender>, - }, - GetDocRevId { - ret: oneshot::Sender>, - }, -} - -struct DocMessageQueue { - receiver: Option>, - edit_doc: Arc, - pg_pool: Data, -} - -impl DocMessageQueue { - fn new(receiver: mpsc::Receiver, doc: Doc, pg_pool: Data) -> Result { - let edit_doc = Arc::new(ServerDocEditor::new(doc)?); - Ok(Self { - receiver: Some(receiver), - edit_doc, - pg_pool, - }) - } - - async fn run(mut self) { - let mut receiver = self - .receiver - .take() - .expect("DocActor's receiver should only take one time"); - - let stream = stream! { - loop { - match receiver.recv().await { - Some(msg) => yield msg, - None => break, - } - } - }; - stream.for_each(|msg| self.handle_message(msg)).await; - } - - async fn handle_message(&self, msg: DocMessage) { - match msg { - DocMessage::NewConnectedUser { - user, - socket, - rev_id, - ret, - } => { - log::debug!("Receive new doc user: {:?}, rev_id: {}", user, rev_id); - let user = DocUser { - user: user.clone(), - socket: socket.clone(), - pg_pool: self.pg_pool.clone(), - }; - let _ = ret.send(self.edit_doc.new_doc_user(user, rev_id).await); - }, - DocMessage::ReceiveRevision { - user, - socket, - revision, - ret, - } => { - let user = DocUser { - user: user.clone(), - socket: socket.clone(), - pg_pool: self.pg_pool.clone(), - }; - let _ = ret.send(self.edit_doc.apply_revision(user, revision).await); - }, - DocMessage::GetDocJson { ret } => { - let edit_context = self.edit_doc.clone(); - let json = spawn_blocking(move || edit_context.document_json()) - .await - .map_err(internal_error); - let _ = ret.send(json); - }, - DocMessage::GetDocRevId { ret } => { - let rev_id = self.edit_doc.rev_id.load(SeqCst); - let _ = ret.send(Ok(rev_id)); - }, - } - } -} diff --git a/backend/src/services/doc/ws_actor.rs b/backend/src/services/doc/ws_actor.rs index 71deaf1d2a..4fc1fa2789 100644 --- a/backend/src/services/doc/ws_actor.rs +++ b/backend/src/services/doc/ws_actor.rs @@ -1,6 +1,6 @@ use crate::{ services::{ - doc::manager::{DocManager, OpenDocHandle}, + doc::{editor::DocUser, read_doc}, util::{md5, parse_from_bytes}, }, web_socket::{entities::Socket, WsClientData, WsUser}, @@ -9,11 +9,14 @@ use actix_rt::task::spawn_blocking; use actix_web::web::Data; use async_stream::stream; use backend_service::errors::{internal_error, Result as DocResult, ServerError}; -use flowy_collaboration::protobuf::{NewDocUser, WsDataType, WsDocumentData}; +use flowy_collaboration::{ + core::sync::{DocManager, OpenDocHandle}, + protobuf::{DocIdentifier, NewDocUser, WsDataType, WsDocumentData}, +}; use futures::stream::StreamExt; use lib_ot::protobuf::Revision; use sqlx::PgPool; -use std::sync::Arc; +use std::{convert::TryInto, sync::Arc}; use tokio::sync::{mpsc, oneshot}; pub enum DocWsMsg { @@ -88,7 +91,7 @@ impl DocWsActor { user: Arc, socket: Socket, data: Vec, - pool: Data, + pg_pool: Data, ) -> DocResult<()> { let doc_user = spawn_blocking(move || { let user: NewDocUser = parse_from_bytes(&data)?; @@ -96,8 +99,9 @@ impl DocWsActor { }) .await .map_err(internal_error)??; - if let Some(handle) = self.find_doc_handle(&doc_user.doc_id, pool).await { - handle.add_user(user, doc_user.rev_id, socket).await?; + if let Some(handle) = self.get_doc_handle(&doc_user.doc_id, pg_pool.clone()).await { + let user = Arc::new(DocUser { user, socket, pg_pool }); + handle.add_user(user, doc_user.rev_id).await.map_err(internal_error)?; } Ok(()) } @@ -107,31 +111,47 @@ impl DocWsActor { user: Arc, socket: Socket, data: Vec, - pool: Data, + pg_pool: Data, ) -> DocResult<()> { - let revision = spawn_blocking(move || { + let mut revision = spawn_blocking(move || { let revision: Revision = parse_from_bytes(&data)?; let _ = verify_md5(&revision)?; DocResult::Ok(revision) }) .await .map_err(internal_error)??; - if let Some(handle) = self.find_doc_handle(&revision.doc_id, pool).await { - handle.apply_revision(user, socket, revision).await?; + if let Some(handle) = self.get_doc_handle(&revision.doc_id, pg_pool.clone()).await { + let user = Arc::new(DocUser { user, socket, pg_pool }); + let revision = (&mut revision).try_into().map_err(internal_error).unwrap(); + handle.apply_revision(user, revision).await.map_err(internal_error)?; } Ok(()) } - async fn find_doc_handle(&self, doc_id: &str, pool: Data) -> Option> { - match self.doc_manager.get(doc_id, pool).await { - Ok(Some(edit_doc)) => Some(edit_doc), - Ok(None) => { - log::error!("Document with id: {} not exist", doc_id); - None - }, - Err(e) => { - log::error!("Get doc handle failed: {:?}", e); - None + async fn get_doc_handle(&self, doc_id: &str, pg_pool: Data) -> Option> { + match self.doc_manager.get(doc_id) { + Some(edit_doc) => Some(edit_doc), + None => { + let params = DocIdentifier { + doc_id: doc_id.to_string(), + ..Default::default() + }; + + let f = || async { + let mut pb_doc = read_doc(pg_pool.get_ref(), params).await?; + let doc = (&mut pb_doc).try_into().map_err(internal_error)?; + self.doc_manager.cache(doc).await.map_err(internal_error)?; + let handler = self.doc_manager.get(doc_id); + Ok::>, ServerError>(handler) + }; + + match f().await { + Ok(handler) => handler, + Err(e) => { + log::error!("{}", e); + None + }, + } }, } } diff --git a/backend/tests/document/helper.rs b/backend/tests/document/helper.rs index 4f3b3dbf3c..66b85d6d52 100644 --- a/backend/tests/document/helper.rs +++ b/backend/tests/document/helper.rs @@ -1,7 +1,7 @@ #![allow(clippy::all)] #![cfg_attr(rustfmt, rustfmt::skip)] use actix_web::web::Data; -use backend::services::doc::{crud::update_doc, manager::DocManager}; +use backend::services::doc::{crud::update_doc}; use flowy_document::services::doc::edit::ClientDocEditor as ClientEditDocContext; use flowy_test::{helper::ViewTest, FlowySDKTest}; use flowy_user::services::user::UserSession; @@ -15,6 +15,7 @@ use flowy_collaboration::{entities::doc::DocIdentifier, protobuf::UpdateDocParam use lib_ot::rich_text::{RichTextAttribute, RichTextDelta}; use parking_lot::RwLock; use lib_ot::core::Interval; +use flowy_collaboration::core::sync::DocManager; pub struct DocumentTest { server: TestServer, @@ -121,14 +122,14 @@ async fn run_scripts(context: Arc>, scripts: Vec { + DocScript::AssertServer(_s, _rev_id) => { sleep(Duration::from_millis(100)).await; - let pg_pool = context.read().server_pg_pool.clone(); - let doc_manager = context.read().server_doc_manager.clone(); - let edit_doc = doc_manager.get(&doc_id, pg_pool).await.unwrap().unwrap(); - let json = edit_doc.document_json().await.unwrap(); - assert_eq(s, &json); - assert_eq!(edit_doc.rev_id().await.unwrap(), rev_id); + // let pg_pool = context.read().server_pg_pool.clone(); + // let doc_manager = context.read().server_doc_manager.clone(); + // let edit_doc = doc_manager.get(&doc_id).unwrap(); + // let json = edit_doc.document_json().await.unwrap(); + // assert_eq(s, &json); + // assert_eq!(edit_doc.rev_id().await.unwrap(), rev_id); }, DocScript::ServerSaveDocument(json, rev_id) => { let pg_pool = context.read().server_pg_pool.clone(); diff --git a/frontend/rust-lib/flowy-document/src/errors.rs b/frontend/rust-lib/flowy-document/src/errors.rs index 0925ff62d1..526799dcb5 100644 --- a/frontend/rust-lib/flowy-document/src/errors.rs +++ b/frontend/rust-lib/flowy-document/src/errors.rs @@ -92,8 +92,8 @@ impl std::convert::From for DocError { fn from(error: lib_ot::errors::OTError) -> Self { DocError::internal().context(error) } } -impl std::convert::From for DocError { - fn from(error: flowy_collaboration::errors::DocumentError) -> Self { DocError::internal().context(error) } +impl std::convert::From for DocError { + fn from(error: flowy_collaboration::errors::CollaborateError) -> Self { DocError::internal().context(error) } } impl std::convert::From for DocError { diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs index 4df66253d2..3246d8fcc9 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs @@ -13,7 +13,7 @@ use bytes::Bytes; use flowy_collaboration::{ core::document::history::UndoResult, entities::{doc::DocDelta, ws::WsDocumentData}, - errors::DocumentResult, + errors::CollaborateResult, }; use flowy_database::ConnectionPool; use lib_infra::retry::{ExponentialBackoff, Retry}; @@ -70,7 +70,7 @@ impl ClientDocEditor { } pub async fn insert(&self, index: usize, data: T) -> Result<(), DocError> { - let (ret, rx) = oneshot::channel::>(); + let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::Insert { index, data: data.to_string(), @@ -83,7 +83,7 @@ impl ClientDocEditor { } pub async fn delete(&self, interval: Interval) -> Result<(), DocError> { - let (ret, rx) = oneshot::channel::>(); + let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::Delete { interval, ret }; let _ = self.edit_cmd_tx.send(msg); let delta = rx.await.map_err(internal_error)??; @@ -92,7 +92,7 @@ impl ClientDocEditor { } pub async fn format(&self, interval: Interval, attribute: RichTextAttribute) -> Result<(), DocError> { - let (ret, rx) = oneshot::channel::>(); + let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::Format { interval, attribute, @@ -105,7 +105,7 @@ impl ClientDocEditor { } pub async fn replace(&self, interval: Interval, data: T) -> Result<(), DocError> { - let (ret, rx) = oneshot::channel::>(); + let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::Replace { interval, data: data.to_string(), @@ -132,7 +132,7 @@ impl ClientDocEditor { } pub async fn undo(&self) -> Result { - let (ret, rx) = oneshot::channel::>(); + let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::Undo { ret }; let _ = self.edit_cmd_tx.send(msg); let r = rx.await.map_err(internal_error)??; @@ -140,7 +140,7 @@ impl ClientDocEditor { } pub async fn redo(&self) -> Result { - let (ret, rx) = oneshot::channel::>(); + let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::Redo { ret }; let _ = self.edit_cmd_tx.send(msg); let r = rx.await.map_err(internal_error)??; @@ -148,7 +148,7 @@ impl ClientDocEditor { } pub async fn delta(&self) -> DocResult { - let (ret, rx) = oneshot::channel::>(); + let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::ReadDoc { ret }; let _ = self.edit_cmd_tx.send(msg); let data = rx.await.map_err(internal_error)??; @@ -172,7 +172,7 @@ impl ClientDocEditor { #[tracing::instrument(level = "debug", skip(self, data), err)] pub(crate) async fn composing_local_delta(&self, data: Bytes) -> Result<(), DocError> { let delta = RichTextDelta::from_bytes(&data)?; - let (ret, rx) = oneshot::channel::>(); + let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::ComposeDelta { delta: delta.clone(), ret, @@ -209,7 +209,7 @@ impl ClientDocEditor { #[tracing::instrument(level = "debug", skip(self))] pub(crate) async fn handle_push_rev(&self, bytes: Bytes) -> DocResult<()> { // Transform the revision - let (ret, rx) = oneshot::channel::>(); + let (ret, rx) = oneshot::channel::>(); let _ = self.edit_cmd_tx.send(EditCommand::ProcessRemoteRevision { bytes, ret }); let TransformDeltas { client_prime, @@ -223,7 +223,7 @@ impl ClientDocEditor { } // compose delta - let (ret, rx) = oneshot::channel::>(); + let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::ComposeDelta { delta: client_prime.clone(), ret, @@ -326,7 +326,7 @@ fn start_sync( #[cfg(feature = "flowy_unit_test")] impl ClientDocEditor { pub async fn doc_json(&self) -> DocResult { - let (ret, rx) = oneshot::channel::>(); + let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::ReadDoc { ret }; let _ = self.edit_cmd_tx.send(msg); let s = rx.await.map_err(internal_error)??; @@ -334,7 +334,7 @@ impl ClientDocEditor { } pub async fn doc_delta(&self) -> DocResult { - let (ret, rx) = oneshot::channel::>(); + let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::ReadDocDelta { ret }; let _ = self.edit_cmd_tx.send(msg); let delta = rx.await.map_err(internal_error)??; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs index 573fbc3111..df240e8543 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs @@ -2,7 +2,7 @@ use async_stream::stream; use bytes::Bytes; use flowy_collaboration::{ core::document::{history::UndoResult, Document}, - errors::DocumentError, + errors::CollaborateError, }; use futures::stream::StreamExt; use lib_ot::{ @@ -63,7 +63,7 @@ impl EditCommandQueue { server_prime, server_rev_id: rev_id, }; - Ok::(transform_delta) + Ok::(transform_delta) }; let _ = ret.send(f().await); }, @@ -113,7 +113,7 @@ impl EditCommandQueue { } #[tracing::instrument(level = "debug", skip(self, delta), fields(compose_result), err)] - async fn composed_delta(&self, delta: RichTextDelta) -> Result<(), DocumentError> { + async fn composed_delta(&self, delta: RichTextDelta) -> Result<(), CollaborateError> { // tracing::debug!("{:?} thread handle_message", thread::current(),); let mut document = self.document.write().await; tracing::Span::current().record( @@ -128,7 +128,7 @@ impl EditCommandQueue { } } -pub(crate) type Ret = oneshot::Sender>; +pub(crate) type Ret = oneshot::Sender>; #[allow(dead_code)] pub(crate) enum EditCommand { ComposeDelta { diff --git a/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs b/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs index 81c23b3f86..aa30549459 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs @@ -50,3 +50,14 @@ async fn doc_push_test() { ]; EditorTest::new().await.run_scripts(scripts).await; } + +#[tokio::test] +async fn doc_sync_test() { + let scripts = vec![ + InsertText("1", 0), + InsertText("2", 1), + InsertText("3", 2), + AssertJson(r#"[{"insert":"123\n"}]"#), + ]; + EditorTest::new().await.run_scripts(scripts).await; +} diff --git a/frontend/rust-lib/flowy-test/src/helper.rs b/frontend/rust-lib/flowy-test/src/helper.rs index 9c0e8628a2..cfec412418 100644 --- a/frontend/rust-lib/flowy-test/src/helper.rs +++ b/frontend/rust-lib/flowy-test/src/helper.rs @@ -14,7 +14,7 @@ use flowy_core::{ use flowy_user::{ entities::{SignInRequest, SignUpRequest, UserProfile}, errors::UserError, - event::UserEvent::{SignIn, SignOut, SignUp}, + event::UserEvent::{InitUser, SignIn, SignOut, SignUp}, }; use lib_dispatch::prelude::{EventDispatcher, ModuleRequest, ToBytes}; use lib_infra::{kv::KV, uuid}; @@ -282,7 +282,6 @@ pub fn root_dir() -> String { let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| "./".to_owned()); let mut path_buf = fs::canonicalize(&PathBuf::from(&manifest_dir)).unwrap(); path_buf.pop(); // rust-lib - path_buf.push("flowy-test"); path_buf.push("temp"); path_buf.push("flowy"); @@ -384,6 +383,11 @@ pub async fn async_sign_up(dispatch: Arc) -> SignUpContext { SignUpContext { user_profile, password } } +pub async fn init_user_setting(dispatch: Arc) { + let request = ModuleRequest::new(InitUser); + let _ = EventDispatcher::async_send(dispatch.clone(), request).await; +} + #[allow(dead_code)] fn sign_in(dispatch: Arc) -> UserProfile { let payload = SignInRequest { diff --git a/frontend/rust-lib/flowy-test/src/lib.rs b/frontend/rust-lib/flowy-test/src/lib.rs index 492d5d3b1d..5fda18cff1 100644 --- a/frontend/rust-lib/flowy-test/src/lib.rs +++ b/frontend/rust-lib/flowy-test/src/lib.rs @@ -43,6 +43,7 @@ impl FlowySDKTest { pub async fn init_user(&self) -> UserProfile { let context = async_sign_up(self.0.dispatcher()).await; + init_user_setting(self.0.dispatcher()).await; context.user_profile } } diff --git a/frontend/rust-lib/flowy-user/Cargo.toml b/frontend/rust-lib/flowy-user/Cargo.toml index 4a907f98b1..ed99e4fb72 100644 --- a/frontend/rust-lib/flowy-user/Cargo.toml +++ b/frontend/rust-lib/flowy-user/Cargo.toml @@ -8,6 +8,7 @@ edition = "2018" [dependencies] flowy-user-infra = { path = "../../../shared-lib/flowy-user-infra" } backend-service = { path = "../../../shared-lib/backend-service" } +flowy-collaboration = { path = "../../../shared-lib/flowy-collaboration" } flowy-derive = { path = "../../../shared-lib/flowy-derive" } lib-ws = { path = "../../../shared-lib/lib-ws" } lib-sqlite = { path = "../../../shared-lib/lib-sqlite" } diff --git a/frontend/rust-lib/flowy-user/src/services/server/mod.rs b/frontend/rust-lib/flowy-user/src/services/server/mod.rs index 81d61938af..503399d16d 100644 --- a/frontend/rust-lib/flowy-user/src/services/server/mod.rs +++ b/frontend/rust-lib/flowy-user/src/services/server/mod.rs @@ -1,5 +1,9 @@ mod server_api; mod server_api_mock; + +// #[cfg(feature = "http_server")] +pub(crate) mod ws_mock; + pub use server_api::*; pub use server_api_mock::*; @@ -8,6 +12,7 @@ pub(crate) type Server = Arc; use crate::{ entities::{SignInParams, SignInResponse, SignUpParams, SignUpResponse, UpdateUserParams, UserProfile}, errors::UserError, + services::user::ws_manager::FlowyWebSocket, }; use backend_service::configuration::ClientServerConfiguration; use lib_infra::future::ResultFuture; @@ -28,3 +33,11 @@ pub(crate) fn construct_user_server(config: &ClientServerConfiguration) -> Arc Arc { + if cfg!(debug_assertions) { + Arc::new(Arc::new(ws_mock::MockWebSocket::default())) + } else { + Arc::new(Arc::new(ws_mock::LocalWebSocket::default())) + } +} diff --git a/frontend/rust-lib/flowy-user/src/services/server/ws_mock.rs b/frontend/rust-lib/flowy-user/src/services/server/ws_mock.rs new file mode 100644 index 0000000000..705c999bc3 --- /dev/null +++ b/frontend/rust-lib/flowy-user/src/services/server/ws_mock.rs @@ -0,0 +1,109 @@ +use crate::{ + errors::UserError, + services::user::ws_manager::{FlowyWebSocket, FlowyWsSender}, +}; +use bytes::Bytes; +use dashmap::DashMap; +use flowy_collaboration::entities::ws::{WsDataType, WsDocumentData}; +use lib_infra::future::ResultFuture; +use lib_ws::{WsConnectState, WsMessage, WsMessageHandler, WsModule}; +use std::{convert::TryFrom, sync::Arc}; +use tokio::sync::{broadcast, broadcast::Receiver}; + +pub struct MockWebSocket { + handlers: DashMap>, + state_sender: broadcast::Sender, + ws_sender: broadcast::Sender, +} + +impl std::default::Default for MockWebSocket { + fn default() -> Self { + let (state_sender, _) = broadcast::channel(16); + let (ws_sender, _) = broadcast::channel(16); + MockWebSocket { + handlers: DashMap::new(), + state_sender, + ws_sender, + } + } +} + +impl MockWebSocket { + pub fn new() -> MockWebSocket { MockWebSocket::default() } +} + +impl FlowyWebSocket for Arc { + fn start_connect(&self, _addr: String) -> ResultFuture<(), UserError> { + let mut ws_receiver = self.ws_sender.subscribe(); + let cloned_ws = self.clone(); + tokio::spawn(async move { + while let Ok(message) = ws_receiver.recv().await { + let ws_data = WsDocumentData::try_from(Bytes::from(message.data.clone())).unwrap(); + match ws_data.ty { + WsDataType::Acked => {}, + WsDataType::PushRev => {}, + WsDataType::PullRev => {}, + WsDataType::Conflict => {}, + WsDataType::NewDocUser => {}, + } + + match cloned_ws.handlers.get(&message.module) { + None => log::error!("Can't find any handler for message: {:?}", message), + Some(handler) => handler.receive_message(message.clone()), + } + } + }); + + ResultFuture::new(async { Ok(()) }) + } + + fn conn_state_subscribe(&self) -> Receiver { self.state_sender.subscribe() } + + fn reconnect(&self, _count: usize) -> ResultFuture<(), UserError> { ResultFuture::new(async { Ok(()) }) } + + fn add_handler(&self, handler: Arc) -> Result<(), UserError> { + let source = handler.source(); + if self.handlers.contains_key(&source) { + log::error!("WsSource's {:?} is already registered", source); + } + self.handlers.insert(source, handler); + Ok(()) + } + + fn ws_sender(&self) -> Result, UserError> { Ok(Arc::new(self.ws_sender.clone())) } +} + +impl FlowyWsSender for broadcast::Sender { + fn send(&self, msg: WsMessage) -> Result<(), UserError> { + let _ = self.send(msg).unwrap(); + Ok(()) + } +} + +pub(crate) struct LocalWebSocket { + state_sender: broadcast::Sender, + ws_sender: broadcast::Sender, +} + +impl std::default::Default for LocalWebSocket { + fn default() -> Self { + let (state_sender, _) = broadcast::channel(16); + let (ws_sender, _) = broadcast::channel(16); + LocalWebSocket { + state_sender, + ws_sender, + } + } +} + +impl FlowyWebSocket for Arc { + fn start_connect(&self, _addr: String) -> ResultFuture<(), UserError> { ResultFuture::new(async { Ok(()) }) } + + fn conn_state_subscribe(&self) -> Receiver { self.state_sender.subscribe() } + + fn reconnect(&self, _count: usize) -> ResultFuture<(), UserError> { ResultFuture::new(async { Ok(()) }) } + + fn add_handler(&self, _handler: Arc) -> Result<(), UserError> { Ok(()) } + + fn ws_sender(&self) -> Result, UserError> { Ok(Arc::new(self.ws_sender.clone())) } +} diff --git a/frontend/rust-lib/flowy-user/src/services/user/mod.rs b/frontend/rust-lib/flowy-user/src/services/user/mod.rs index a3fc88a637..c8737d7a30 100644 --- a/frontend/rust-lib/flowy-user/src/services/user/mod.rs +++ b/frontend/rust-lib/flowy-user/src/services/user/mod.rs @@ -3,4 +3,4 @@ pub use user_session::*; pub mod database; mod notifier; mod user_session; -mod ws_manager; +pub mod ws_manager; diff --git a/frontend/rust-lib/flowy-user/src/services/user/ws_manager.rs b/frontend/rust-lib/flowy-user/src/services/user/ws_manager.rs index 35245c2390..412843e9d0 100644 --- a/frontend/rust-lib/flowy-user/src/services/user/ws_manager.rs +++ b/frontend/rust-lib/flowy-user/src/services/user/ws_manager.rs @@ -103,7 +103,7 @@ impl std::default::Default for WsManager { let ws: Arc = if cfg!(feature = "http_server") { Arc::new(Arc::new(WsController::new())) } else { - Arc::new(Arc::new(mock::MockWebSocket::new())) + crate::services::server::local_web_socket() }; WsManager { @@ -149,77 +149,3 @@ impl FlowyWsSender for WsSender { Ok(()) } } - -// #[cfg(not(feature = "http_server"))] -mod mock { - use crate::{ - errors::UserError, - services::user::ws_manager::{FlowyWebSocket, FlowyWsSender}, - }; - use dashmap::DashMap; - use lib_infra::future::ResultFuture; - use lib_ws::{WsConnectState, WsMessage, WsMessageHandler, WsModule}; - use std::sync::Arc; - use tokio::sync::{broadcast, broadcast::Receiver}; - - pub struct MockWebSocket { - handlers: DashMap>, - state_sender: broadcast::Sender, - ws_sender: broadcast::Sender, - } - - impl std::default::Default for MockWebSocket { - fn default() -> Self { - let (state_sender, _) = broadcast::channel(16); - let (ws_sender, _) = broadcast::channel(16); - MockWebSocket { - handlers: DashMap::new(), - state_sender, - ws_sender, - } - } - } - - impl MockWebSocket { - pub fn new() -> MockWebSocket { MockWebSocket::default() } - } - - impl FlowyWebSocket for Arc { - fn start_connect(&self, _addr: String) -> ResultFuture<(), UserError> { - let mut ws_receiver = self.ws_sender.subscribe(); - let cloned_ws = self.clone(); - tokio::spawn(async move { - while let Ok(message) = ws_receiver.recv().await { - match cloned_ws.handlers.get(&message.module) { - None => log::error!("Can't find any handler for message: {:?}", message), - Some(handler) => handler.receive_message(message.clone()), - } - } - }); - - ResultFuture::new(async { Ok(()) }) - } - - fn conn_state_subscribe(&self) -> Receiver { self.state_sender.subscribe() } - - fn reconnect(&self, _count: usize) -> ResultFuture<(), UserError> { ResultFuture::new(async { Ok(()) }) } - - fn add_handler(&self, handler: Arc) -> Result<(), UserError> { - let source = handler.source(); - if self.handlers.contains_key(&source) { - log::error!("WsSource's {:?} is already registered", source); - } - self.handlers.insert(source, handler); - Ok(()) - } - - fn ws_sender(&self) -> Result, UserError> { Ok(Arc::new(self.ws_sender.clone())) } - } - - impl FlowyWsSender for broadcast::Sender { - fn send(&self, _msg: WsMessage) -> Result<(), UserError> { - let _ = self.send(msg).unwrap(); - Ok(()) - } - } -} diff --git a/shared-lib/Cargo.lock b/shared-lib/Cargo.lock index 327a427a0e..e3a7e34a49 100644 --- a/shared-lib/Cargo.lock +++ b/shared-lib/Cargo.lock @@ -232,6 +232,27 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" +[[package]] +name = "async-stream" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "171374e7e3b2504e0e5236e3b59260560f9fe94bfe9ac39ba5e4e929c5590625" +dependencies = [ + "async-stream-impl", + "futures-core", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "648ed8c8d2ce5409ccd57453d9d1b214b342a0d69376a6feda1fd6cae3299308" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "atty" version = "0.2.14" @@ -661,9 +682,12 @@ dependencies = [ name = "flowy-collaboration" version = "0.1.0" dependencies = [ + "async-stream", "bytes", "chrono", + "dashmap", "flowy-derive", + "futures", "lib-ot", "log", "md5", diff --git a/shared-lib/flowy-collaboration/Cargo.toml b/shared-lib/flowy-collaboration/Cargo.toml index efd97a2899..35d539f883 100644 --- a/shared-lib/flowy-collaboration/Cargo.toml +++ b/shared-lib/flowy-collaboration/Cargo.toml @@ -12,11 +12,14 @@ protobuf = {version = "2.18.0"} bytes = "1.0" log = "0.4.14" md5 = "0.7.0" -tokio = {version = "1", features = ["sync"]} +tokio = { version = "1", features = ["full"] } serde = { version = "1.0", features = ["derive"] } tracing = { version = "0.1", features = ["log"] } url = "2.2" strum = "0.21" strum_macros = "0.21" chrono = "0.4.19" -parking_lot = "0.11" \ No newline at end of file +parking_lot = "0.11" +dashmap = "4.0" +futures = "0.3.15" +async-stream = "0.3.2" \ No newline at end of file diff --git a/shared-lib/flowy-collaboration/src/core/document/document.rs b/shared-lib/flowy-collaboration/src/core/document/document.rs index baa6d5c453..7d58eb128a 100644 --- a/shared-lib/flowy-collaboration/src/core/document/document.rs +++ b/shared-lib/flowy-collaboration/src/core/document/document.rs @@ -3,7 +3,7 @@ use crate::{ history::{History, UndoResult}, view::{View, RECORD_THRESHOLD}, }, - errors::DocumentError, + errors::CollaborateError, user_default::doc_initial_delta, }; use lib_ot::{ @@ -47,7 +47,7 @@ impl Document { } } - pub fn from_json(json: &str) -> Result { + pub fn from_json(json: &str) -> Result { let delta = RichTextDelta::from_json(json)?; Ok(Self::from_delta(delta)) } @@ -73,7 +73,7 @@ impl Document { } } - pub fn compose_delta(&mut self, mut delta: RichTextDelta) -> Result<(), DocumentError> { + pub fn compose_delta(&mut self, mut delta: RichTextDelta) -> Result<(), CollaborateError> { trim(&mut delta); tracing::trace!("{} compose {}", &self.delta.to_json(), delta.to_json()); let mut composed_delta = self.delta.compose(&delta)?; @@ -103,7 +103,7 @@ impl Document { Ok(()) } - pub fn insert(&mut self, index: usize, data: T) -> Result { + pub fn insert(&mut self, index: usize, data: T) -> Result { let interval = Interval::new(index, index); let _ = validate_interval(&self.delta, &interval)?; @@ -114,7 +114,7 @@ impl Document { Ok(delta) } - pub fn delete(&mut self, interval: Interval) -> Result { + pub fn delete(&mut self, interval: Interval) -> Result { let _ = validate_interval(&self.delta, &interval)?; debug_assert_eq!(interval.is_empty(), false); let delete = self.view.delete(&self.delta, interval)?; @@ -125,7 +125,11 @@ impl Document { Ok(delete) } - pub fn format(&mut self, interval: Interval, attribute: RichTextAttribute) -> Result { + pub fn format( + &mut self, + interval: Interval, + attribute: RichTextAttribute, + ) -> Result { let _ = validate_interval(&self.delta, &interval)?; tracing::trace!("format with {} at {}", attribute, interval); let format_delta = self.view.format(&self.delta, attribute, interval).unwrap(); @@ -135,7 +139,7 @@ impl Document { Ok(format_delta) } - pub fn replace(&mut self, interval: Interval, data: T) -> Result { + pub fn replace(&mut self, interval: Interval, data: T) -> Result { let _ = validate_interval(&self.delta, &interval)?; let mut delta = RichTextDelta::default(); let text = data.to_string(); @@ -157,9 +161,9 @@ impl Document { pub fn can_redo(&self) -> bool { self.history.can_redo() } - pub fn undo(&mut self) -> Result { + pub fn undo(&mut self) -> Result { match self.history.undo() { - None => Err(DocumentError::undo().context("Undo stack is empty")), + None => Err(CollaborateError::undo().context("Undo stack is empty")), Some(undo_delta) => { let (new_delta, inverted_delta) = self.invert(&undo_delta)?; let result = UndoResult::success(new_delta.target_len as usize); @@ -171,9 +175,9 @@ impl Document { } } - pub fn redo(&mut self) -> Result { + pub fn redo(&mut self) -> Result { match self.history.redo() { - None => Err(DocumentError::redo()), + None => Err(CollaborateError::redo()), Some(redo_delta) => { let (new_delta, inverted_delta) = self.invert(&redo_delta)?; let result = UndoResult::success(new_delta.target_len as usize); @@ -187,7 +191,7 @@ impl Document { } impl Document { - fn invert(&self, delta: &RichTextDelta) -> Result<(RichTextDelta, RichTextDelta), DocumentError> { + fn invert(&self, delta: &RichTextDelta) -> Result<(RichTextDelta, RichTextDelta), CollaborateError> { // c = a.compose(b) // d = b.invert(a) // a = c.compose(d) @@ -198,10 +202,10 @@ impl Document { } } -fn validate_interval(delta: &RichTextDelta, interval: &Interval) -> Result<(), DocumentError> { +fn validate_interval(delta: &RichTextDelta, interval: &Interval) -> Result<(), CollaborateError> { if delta.target_len < interval.end { log::error!("{:?} out of bounds. should 0..{}", interval, delta.target_len); - return Err(DocumentError::out_of_bound()); + return Err(CollaborateError::out_of_bound()); } Ok(()) } diff --git a/shared-lib/flowy-collaboration/src/core/sync/mod.rs b/shared-lib/flowy-collaboration/src/core/sync/mod.rs index cf1006c232..df599d3adc 100644 --- a/shared-lib/flowy-collaboration/src/core/sync/mod.rs +++ b/shared-lib/flowy-collaboration/src/core/sync/mod.rs @@ -1,3 +1,5 @@ mod rev_sync; +mod server_editor; pub use rev_sync::*; +pub use server_editor::*; diff --git a/shared-lib/flowy-collaboration/src/core/sync/rev_sync.rs b/shared-lib/flowy-collaboration/src/core/sync/rev_sync.rs index 0bdd9643a6..e193364250 100644 --- a/shared-lib/flowy-collaboration/src/core/sync/rev_sync.rs +++ b/shared-lib/flowy-collaboration/src/core/sync/rev_sync.rs @@ -15,6 +15,7 @@ use protobuf::Message; use std::{ cmp::Ordering, convert::TryInto, + fmt::Debug, sync::{ atomic::{AtomicI64, Ordering::SeqCst}, Arc, @@ -22,7 +23,8 @@ use std::{ time::Duration, }; -pub trait RevisionUser { +pub trait RevisionUser: Send + Sync + Debug { + fn user_id(&self) -> String; fn recv(&self, resp: SyncResponse); } @@ -53,7 +55,7 @@ impl RevisionSynchronizer { } } - pub fn new_conn(&self, user: T, rev_id: i64) { + pub fn new_conn(&self, user: Arc, rev_id: i64) { let cur_rev_id = self.rev_id.load(SeqCst); match cur_rev_id.cmp(&rev_id) { Ordering::Less => { @@ -70,10 +72,7 @@ impl RevisionSynchronizer { } } - pub fn apply_revision(&self, user: T, revision: Revision) -> Result<(), OTError> - where - T: RevisionUser, - { + pub fn apply_revision(&self, user: Arc, revision: Revision) -> Result<(), OTError> { let cur_rev_id = self.rev_id.load(SeqCst); match cur_rev_id.cmp(&revision.rev_id) { Ordering::Less => { diff --git a/shared-lib/flowy-collaboration/src/core/sync/server_editor.rs b/shared-lib/flowy-collaboration/src/core/sync/server_editor.rs new file mode 100644 index 0000000000..ac5699b57c --- /dev/null +++ b/shared-lib/flowy-collaboration/src/core/sync/server_editor.rs @@ -0,0 +1,272 @@ +use crate::{ + core::{ + document::Document, + sync::{RevisionSynchronizer, RevisionUser}, + }, + entities::doc::Doc, + errors::{internal_error, CollaborateError, CollaborateResult}, +}; +use async_stream::stream; +use dashmap::DashMap; +use futures::stream::StreamExt; +use lib_ot::{errors::OTError, revision::Revision, rich_text::RichTextDelta}; +use std::sync::{ + atomic::{AtomicI64, Ordering::SeqCst}, + Arc, +}; +use tokio::{ + sync::{mpsc, oneshot}, + task::spawn_blocking, +}; + +#[rustfmt::skip] +// ┌────────────┐ +// │ DocManager │ +// └────────────┘ +// │ 1 +// │ +// ▼ n +// ┌───────────────┐ +// │ OpenDocHandle │ +// └───────────────┘ +// │ +// ▼ +// ┌──────────────────┐ +// │ DocCommandQueue │ +// └──────────────────┘ ┌──────────────────────┐ ┌────────────┐ +// │ ┌────▶│ RevisionSynchronizer │────▶│ Document │ +// ▼ │ └──────────────────────┘ └────────────┘ +// ┌────────────────┐ │ +// │ServerDocEditor │─────┤ +// └────────────────┘ │ +// │ +// │ ┌────────┐ ┌────────────┐ +// └────▶│ Users │◆──────│RevisionUser│ +// └────────┘ └────────────┘ +pub struct DocManager { + open_doc_map: DashMap>, +} + +impl std::default::Default for DocManager { + fn default() -> Self { + Self { + open_doc_map: DashMap::new(), + } + } +} +impl DocManager { + pub fn new() -> Self { DocManager::default() } + + pub fn get(&self, doc_id: &str) -> Option> { + self.open_doc_map.get(doc_id).map(|ctx| ctx.clone()) + } + + pub async fn cache(&self, doc: Doc) -> Result<(), CollaborateError> { + let doc_id = doc.id.clone(); + let handle = spawn_blocking(|| OpenDocHandle::new(doc)) + .await + .map_err(internal_error)?; + let handle = Arc::new(handle?); + self.open_doc_map.insert(doc_id, handle); + Ok(()) + } +} + +pub struct OpenDocHandle { + sender: mpsc::Sender, +} + +impl OpenDocHandle { + pub fn new(doc: Doc) -> Result { + let (sender, receiver) = mpsc::channel(100); + let queue = DocCommandQueue::new(receiver, doc)?; + tokio::task::spawn(queue.run()); + Ok(Self { sender }) + } + + pub async fn add_user(&self, user: Arc, rev_id: i64) -> Result<(), CollaborateError> { + let (ret, rx) = oneshot::channel(); + let msg = DocCommand::NewConnectedUser { user, rev_id, ret }; + let _ = self.send(msg, rx).await?; + Ok(()) + } + + pub async fn apply_revision( + &self, + user: Arc, + revision: Revision, + ) -> Result<(), CollaborateError> { + let (ret, rx) = oneshot::channel(); + let msg = DocCommand::ReceiveRevision { user, revision, ret }; + let _ = self.send(msg, rx).await?; + Ok(()) + } + + pub async fn document_json(&self) -> CollaborateResult { + let (ret, rx) = oneshot::channel(); + let msg = DocCommand::GetDocJson { ret }; + self.send(msg, rx).await? + } + + pub async fn rev_id(&self) -> CollaborateResult { + let (ret, rx) = oneshot::channel(); + let msg = DocCommand::GetDocRevId { ret }; + self.send(msg, rx).await? + } + + async fn send(&self, msg: DocCommand, rx: oneshot::Receiver) -> CollaborateResult { + let _ = self.sender.send(msg).await.map_err(internal_error)?; + let result = rx.await.map_err(internal_error)?; + Ok(result) + } +} + +#[derive(Debug)] +enum DocCommand { + NewConnectedUser { + user: Arc, + rev_id: i64, + ret: oneshot::Sender>, + }, + ReceiveRevision { + user: Arc, + revision: Revision, + ret: oneshot::Sender>, + }, + GetDocJson { + ret: oneshot::Sender>, + }, + GetDocRevId { + ret: oneshot::Sender>, + }, +} + +struct DocCommandQueue { + receiver: Option>, + edit_doc: Arc, +} + +impl DocCommandQueue { + fn new(receiver: mpsc::Receiver, doc: Doc) -> Result { + let edit_doc = Arc::new(ServerDocEditor::new(doc).map_err(internal_error)?); + Ok(Self { + receiver: Some(receiver), + edit_doc, + }) + } + + async fn run(mut self) { + let mut receiver = self + .receiver + .take() + .expect("DocActor's receiver should only take one time"); + + let stream = stream! { + loop { + match receiver.recv().await { + Some(msg) => yield msg, + None => break, + } + } + }; + stream.for_each(|msg| self.handle_message(msg)).await; + } + + async fn handle_message(&self, msg: DocCommand) { + match msg { + DocCommand::NewConnectedUser { user, rev_id, ret } => { + log::debug!("Receive new doc user: {:?}, rev_id: {}", user, rev_id); + let _ = ret.send(self.edit_doc.new_doc_user(user, rev_id).await.map_err(internal_error)); + }, + DocCommand::ReceiveRevision { user, revision, ret } => { + // let revision = (&mut revision).try_into().map_err(internal_error).unwrap(); + let _ = ret.send( + self.edit_doc + .apply_revision(user, revision) + .await + .map_err(internal_error), + ); + }, + DocCommand::GetDocJson { ret } => { + let edit_context = self.edit_doc.clone(); + let json = spawn_blocking(move || edit_context.document_json()) + .await + .map_err(internal_error); + let _ = ret.send(json); + }, + DocCommand::GetDocRevId { ret } => { + let rev_id = self.edit_doc.rev_id.load(SeqCst); + let _ = ret.send(Ok(rev_id)); + }, + } + } +} + +#[rustfmt::skip] +// ┌──────────────────────┐ ┌────────────┐ +// ┌───▶│ RevisionSynchronizer │────▶│ Document │ +// │ └──────────────────────┘ └────────────┘ +// ┌────────────────┐ │ +// ───▶│ServerDocEditor │────┤ +// └────────────────┘ │ +// │ +// │ ┌────────┐ ┌────────────┐ +// └───▶│ Users │◆──────│RevisionUser│ +// └────────┘ └────────────┘ +pub struct ServerDocEditor { + pub doc_id: String, + pub rev_id: AtomicI64, + synchronizer: Arc, + users: DashMap>, +} + +impl ServerDocEditor { + pub fn new(doc: Doc) -> Result { + let delta = RichTextDelta::from_bytes(&doc.data)?; + let users = DashMap::new(); + let synchronizer = Arc::new(RevisionSynchronizer::new( + &doc.id, + doc.rev_id, + Document::from_delta(delta), + )); + + Ok(Self { + doc_id: doc.id.clone(), + rev_id: AtomicI64::new(doc.rev_id), + synchronizer, + users, + }) + } + + #[tracing::instrument( + level = "debug", + skip(self, user), + fields( + user_id = %user.user_id(), + rev_id = %rev_id, + ) + )] + pub async fn new_doc_user(&self, user: Arc, rev_id: i64) -> Result<(), OTError> { + self.users.insert(user.user_id(), user.clone()); + self.synchronizer.new_conn(user, rev_id); + Ok(()) + } + + #[tracing::instrument( + level = "debug", + skip(self, user, revision), + fields( + cur_rev_id = %self.rev_id.load(SeqCst), + base_rev_id = %revision.base_rev_id, + rev_id = %revision.rev_id, + ), + err + )] + pub async fn apply_revision(&self, user: Arc, revision: Revision) -> Result<(), OTError> { + self.users.insert(user.user_id(), user.clone()); + self.synchronizer.apply_revision(user, revision).unwrap(); + Ok(()) + } + + pub fn document_json(&self) -> String { self.synchronizer.doc_json() } +} diff --git a/shared-lib/flowy-collaboration/src/entities/ws/ws.rs b/shared-lib/flowy-collaboration/src/entities/ws/ws.rs index 6b3555ce16..f31ffd2bc2 100644 --- a/shared-lib/flowy-collaboration/src/entities/ws/ws.rs +++ b/shared-lib/flowy-collaboration/src/entities/ws/ws.rs @@ -1,4 +1,4 @@ -use crate::{entities::doc::NewDocUser, errors::DocumentError}; +use crate::{entities::doc::NewDocUser, errors::CollaborateError}; use bytes::Bytes; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use lib_ot::revision::{RevId, Revision, RevisionRange}; @@ -17,9 +17,9 @@ pub enum WsDataType { } impl WsDataType { - pub fn data(&self, bytes: Bytes) -> Result + pub fn data(&self, bytes: Bytes) -> Result where - T: TryFrom, + T: TryFrom, { T::try_from(bytes) } diff --git a/shared-lib/flowy-collaboration/src/errors.rs b/shared-lib/flowy-collaboration/src/errors.rs index 0a82f1741e..d438444db4 100644 --- a/shared-lib/flowy-collaboration/src/errors.rs +++ b/shared-lib/flowy-collaboration/src/errors.rs @@ -4,8 +4,8 @@ use strum_macros::Display; macro_rules! static_doc_error { ($name:ident, $status:expr) => { #[allow(non_snake_case, missing_docs)] - pub fn $name() -> DocumentError { - DocumentError { + pub fn $name() -> CollaborateError { + CollaborateError { code: $status, msg: format!("{}", $status), } @@ -13,15 +13,15 @@ macro_rules! static_doc_error { }; } -pub type DocumentResult = std::result::Result; +pub type CollaborateResult = std::result::Result; #[derive(Debug, Clone)] -pub struct DocumentError { +pub struct CollaborateError { pub code: ErrorCode, pub msg: String, } -impl DocumentError { +impl CollaborateError { fn new(code: ErrorCode, msg: &str) -> Self { Self { code, @@ -40,7 +40,7 @@ impl DocumentError { static_doc_error!(out_of_bound, ErrorCode::OutOfBound); } -impl fmt::Display for DocumentError { +impl fmt::Display for CollaborateError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}: {}", &self.code, &self.msg) } } @@ -54,10 +54,19 @@ pub enum ErrorCode { InternalError = 1000, } -impl std::convert::From for DocumentError { - fn from(error: lib_ot::errors::OTError) -> Self { DocumentError::new(ErrorCode::InternalError, "").context(error) } +impl std::convert::From for CollaborateError { + fn from(error: lib_ot::errors::OTError) -> Self { + CollaborateError::new(ErrorCode::InternalError, "").context(error) + } } -impl std::convert::From for DocumentError { - fn from(e: protobuf::ProtobufError) -> Self { DocumentError::internal().context(e) } +impl std::convert::From for CollaborateError { + fn from(e: protobuf::ProtobufError) -> Self { CollaborateError::internal().context(e) } +} + +pub fn internal_error(e: T) -> CollaborateError +where + T: std::fmt::Debug, +{ + CollaborateError::internal().context(e) } From 0231ad3adf6fea1f8c5a8dddc136d630ca866336 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 12 Dec 2021 16:02:58 +0800 Subject: [PATCH 21/39] add doc persistence trait --- backend/src/services/doc/editor.rs | 4 +-- backend/src/services/doc/manager.rs | 20 +++++++++-- backend/src/services/doc/ws_actor.rs | 12 +++---- backend/tests/document/helper.rs | 4 +-- frontend/rust-lib/lib-infra/Cargo.toml | 3 +- .../flowy-collaboration/src/core/sync/mod.rs | 4 +-- .../src/core/sync/server_editor.rs | 36 ++++++++++--------- .../sync/{rev_sync.rs => synchronizer.rs} | 0 8 files changed, 50 insertions(+), 33 deletions(-) rename shared-lib/flowy-collaboration/src/core/sync/{rev_sync.rs => synchronizer.rs} (100%) diff --git a/backend/src/services/doc/editor.rs b/backend/src/services/doc/editor.rs index f797f52e35..33aac0be76 100644 --- a/backend/src/services/doc/editor.rs +++ b/backend/src/services/doc/editor.rs @@ -14,13 +14,13 @@ use sqlx::PgPool; use std::sync::Arc; #[derive(Clone, Debug)] -pub struct DocUser { +pub struct ServerDocUser { pub user: Arc, pub(crate) socket: Socket, pub pg_pool: Data, } -impl RevisionUser for DocUser { +impl RevisionUser for ServerDocUser { fn user_id(&self) -> String { self.user.id().to_string() } fn recv(&self, resp: SyncResponse) { diff --git a/backend/src/services/doc/manager.rs b/backend/src/services/doc/manager.rs index a8315a3629..749099b6a2 100644 --- a/backend/src/services/doc/manager.rs +++ b/backend/src/services/doc/manager.rs @@ -3,20 +3,25 @@ use crate::{ web_socket::{WsBizHandler, WsClientData}, }; use actix_web::web::Data; -use flowy_collaboration::core::sync::DocManager; +use flowy_collaboration::{ + core::sync::{ServerDocManager, ServerDocPersistence}, + entities::doc::Doc, + errors::CollaborateResult, +}; +use lib_ot::rich_text::RichTextDelta; use sqlx::PgPool; use std::sync::Arc; use tokio::sync::{mpsc, oneshot}; pub struct DocumentCore { - pub manager: Arc, + pub manager: Arc, ws_sender: mpsc::Sender, pg_pool: Data, } impl DocumentCore { pub fn new(pg_pool: Data) -> Self { - let manager = Arc::new(DocManager::new()); + let manager = Arc::new(ServerDocManager::new(Arc::new(DocPersistenceImpl()))); let (ws_sender, rx) = mpsc::channel(100); let actor = DocWsActor::new(rx, manager.clone()); tokio::task::spawn(actor.run()); @@ -51,3 +56,12 @@ impl WsBizHandler for DocumentCore { }); } } + +struct DocPersistenceImpl(); +impl ServerDocPersistence for DocPersistenceImpl { + fn create_doc(&self, doc_id: &str, delta: RichTextDelta) -> CollaborateResult<()> { unimplemented!() } + + fn update_doc(&self, doc_id: &str, delta: RichTextDelta) -> CollaborateResult<()> { unimplemented!() } + + fn read_doc(&self, doc_id: &str) -> CollaborateResult { unimplemented!() } +} diff --git a/backend/src/services/doc/ws_actor.rs b/backend/src/services/doc/ws_actor.rs index 4fc1fa2789..0e851b5f8e 100644 --- a/backend/src/services/doc/ws_actor.rs +++ b/backend/src/services/doc/ws_actor.rs @@ -1,6 +1,6 @@ use crate::{ services::{ - doc::{editor::DocUser, read_doc}, + doc::{editor::ServerDocUser, read_doc}, util::{md5, parse_from_bytes}, }, web_socket::{entities::Socket, WsClientData, WsUser}, @@ -10,7 +10,7 @@ use actix_web::web::Data; use async_stream::stream; use backend_service::errors::{internal_error, Result as DocResult, ServerError}; use flowy_collaboration::{ - core::sync::{DocManager, OpenDocHandle}, + core::sync::{OpenDocHandle, ServerDocManager}, protobuf::{DocIdentifier, NewDocUser, WsDataType, WsDocumentData}, }; use futures::stream::StreamExt; @@ -29,11 +29,11 @@ pub enum DocWsMsg { pub struct DocWsActor { receiver: Option>, - doc_manager: Arc, + doc_manager: Arc, } impl DocWsActor { - pub fn new(receiver: mpsc::Receiver, manager: Arc) -> Self { + pub fn new(receiver: mpsc::Receiver, manager: Arc) -> Self { Self { receiver: Some(receiver), doc_manager: manager, @@ -100,7 +100,7 @@ impl DocWsActor { .await .map_err(internal_error)??; if let Some(handle) = self.get_doc_handle(&doc_user.doc_id, pg_pool.clone()).await { - let user = Arc::new(DocUser { user, socket, pg_pool }); + let user = Arc::new(ServerDocUser { user, socket, pg_pool }); handle.add_user(user, doc_user.rev_id).await.map_err(internal_error)?; } Ok(()) @@ -121,7 +121,7 @@ impl DocWsActor { .await .map_err(internal_error)??; if let Some(handle) = self.get_doc_handle(&revision.doc_id, pg_pool.clone()).await { - let user = Arc::new(DocUser { user, socket, pg_pool }); + let user = Arc::new(ServerDocUser { user, socket, pg_pool }); let revision = (&mut revision).try_into().map_err(internal_error).unwrap(); handle.apply_revision(user, revision).await.map_err(internal_error)?; } diff --git a/backend/tests/document/helper.rs b/backend/tests/document/helper.rs index 66b85d6d52..182bd32448 100644 --- a/backend/tests/document/helper.rs +++ b/backend/tests/document/helper.rs @@ -15,7 +15,7 @@ use flowy_collaboration::{entities::doc::DocIdentifier, protobuf::UpdateDocParam use lib_ot::rich_text::{RichTextAttribute, RichTextDelta}; use parking_lot::RwLock; use lib_ot::core::Interval; -use flowy_collaboration::core::sync::DocManager; +use flowy_collaboration::core::sync::ServerDocManager; pub struct DocumentTest { server: TestServer, @@ -53,7 +53,7 @@ struct ScriptContext { client_edit_context: Option>, client_sdk: FlowySDKTest, client_user_session: Arc, - server_doc_manager: Arc, + server_doc_manager: Arc, server_pg_pool: Data, doc_id: String, } diff --git a/frontend/rust-lib/lib-infra/Cargo.toml b/frontend/rust-lib/lib-infra/Cargo.toml index c9a9c8808a..ce43059378 100644 --- a/frontend/rust-lib/lib-infra/Cargo.toml +++ b/frontend/rust-lib/lib-infra/Cargo.toml @@ -20,4 +20,5 @@ bytes = { version = "1.0" } pin-project = "1.0" futures-core = { version = "0.3", default-features = false } tokio = { version = "1.0", features = ["time", "rt"] } -rand = "0.8.3" \ No newline at end of file +rand = "0.8.3" + diff --git a/shared-lib/flowy-collaboration/src/core/sync/mod.rs b/shared-lib/flowy-collaboration/src/core/sync/mod.rs index df599d3adc..69dd8a5114 100644 --- a/shared-lib/flowy-collaboration/src/core/sync/mod.rs +++ b/shared-lib/flowy-collaboration/src/core/sync/mod.rs @@ -1,5 +1,5 @@ -mod rev_sync; mod server_editor; +mod synchronizer; -pub use rev_sync::*; pub use server_editor::*; +pub use synchronizer::*; diff --git a/shared-lib/flowy-collaboration/src/core/sync/server_editor.rs b/shared-lib/flowy-collaboration/src/core/sync/server_editor.rs index ac5699b57c..16b18c58ac 100644 --- a/shared-lib/flowy-collaboration/src/core/sync/server_editor.rs +++ b/shared-lib/flowy-collaboration/src/core/sync/server_editor.rs @@ -19,12 +19,17 @@ use tokio::{ task::spawn_blocking, }; +pub trait ServerDocPersistence: Send + Sync { + fn create_doc(&self, doc_id: &str, delta: RichTextDelta) -> CollaborateResult<()>; + fn update_doc(&self, doc_id: &str, delta: RichTextDelta) -> CollaborateResult<()>; + fn read_doc(&self, doc_id: &str) -> CollaborateResult; +} + #[rustfmt::skip] -// ┌────────────┐ -// │ DocManager │ -// └────────────┘ +// ┌─────────────────┐ +// │ServerDocManager │ +// └─────────────────┘ // │ 1 -// │ // ▼ n // ┌───────────────┐ // │ OpenDocHandle │ @@ -33,29 +38,26 @@ use tokio::{ // ▼ // ┌──────────────────┐ // │ DocCommandQueue │ -// └──────────────────┘ ┌──────────────────────┐ ┌────────────┐ -// │ ┌────▶│ RevisionSynchronizer │────▶│ Document │ -// ▼ │ └──────────────────────┘ └────────────┘ -// ┌────────────────┐ │ +// └──────────────────┘ +// │ ┌──────────────────────┐ ┌────────────┐ +// ▼ ┌────▶│ RevisionSynchronizer │────▶│ Document │ +// ┌────────────────┐ │ └──────────────────────┘ └────────────┘ // │ServerDocEditor │─────┤ -// └────────────────┘ │ -// │ -// │ ┌────────┐ ┌────────────┐ +// └────────────────┘ │ ┌────────┐ ┌────────────┐ // └────▶│ Users │◆──────│RevisionUser│ // └────────┘ └────────────┘ -pub struct DocManager { +pub struct ServerDocManager { open_doc_map: DashMap>, + persistence: Arc, } -impl std::default::Default for DocManager { - fn default() -> Self { +impl ServerDocManager { + pub fn new(persistence: Arc) -> Self { Self { open_doc_map: DashMap::new(), + persistence, } } -} -impl DocManager { - pub fn new() -> Self { DocManager::default() } pub fn get(&self, doc_id: &str) -> Option> { self.open_doc_map.get(doc_id).map(|ctx| ctx.clone()) diff --git a/shared-lib/flowy-collaboration/src/core/sync/rev_sync.rs b/shared-lib/flowy-collaboration/src/core/sync/synchronizer.rs similarity index 100% rename from shared-lib/flowy-collaboration/src/core/sync/rev_sync.rs rename to shared-lib/flowy-collaboration/src/core/sync/synchronizer.rs From dfa9c04f5a2b07f0c9f44b564e547ad099f4951f Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 12 Dec 2021 21:18:23 +0800 Subject: [PATCH 22/39] mv kv to flowy-database --- backend/Cargo.lock | 7 +-- .../src/services/view/controller.rs | 2 +- .../src/services/workspace/controller.rs | 3 +- frontend/rust-lib/flowy-database/Cargo.toml | 4 +- .../src/kv/kv.rs | 12 +---- .../src/kv/mod.rs | 0 .../src/kv/schema.rs | 0 frontend/rust-lib/flowy-database/src/lib.rs | 21 ++++---- frontend/rust-lib/flowy-sdk/src/lib.rs | 2 +- frontend/rust-lib/flowy-test/src/helper.rs | 51 +++---------------- .../src/services/user/user_session.rs | 43 ++++++++-------- frontend/rust-lib/lib-infra/Cargo.toml | 5 -- frontend/rust-lib/lib-infra/src/lib.rs | 7 --- shared-lib/Cargo.lock | 5 -- 14 files changed, 48 insertions(+), 114 deletions(-) rename frontend/rust-lib/{lib-infra => flowy-database}/src/kv/kv.rs (95%) rename frontend/rust-lib/{lib-infra => flowy-database}/src/kv/mod.rs (100%) rename frontend/rust-lib/{lib-infra => flowy-database}/src/kv/schema.rs (100%) diff --git a/backend/Cargo.lock b/backend/Cargo.lock index ed95e928da..3062c72aa4 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -1279,7 +1279,9 @@ dependencies = [ "diesel", "diesel_derives", "diesel_migrations", + "lazy_static", "lib-sqlite", + "log", ] [[package]] @@ -1942,13 +1944,8 @@ version = "0.1.0" dependencies = [ "bytes", "chrono", - "diesel", - "diesel_derives", - "diesel_migrations", "flowy-derive", "futures-core", - "lazy_static", - "lib-sqlite", "log", "pin-project 1.0.8", "protobuf", diff --git a/frontend/rust-lib/flowy-core/src/services/view/controller.rs b/frontend/rust-lib/flowy-core/src/services/view/controller.rs index 80ca0677cf..d6ff221383 100644 --- a/frontend/rust-lib/flowy-core/src/services/view/controller.rs +++ b/frontend/rust-lib/flowy-core/src/services/view/controller.rs @@ -19,8 +19,8 @@ use crate::{ }, }; use flowy_core_infra::entities::share::{ExportData, ExportParams}; +use flowy_database::kv::KV; use flowy_document::module::FlowyDocument; -use lib_infra::kv::KV; const LATEST_VIEW_ID: &str = "latest_view_id"; diff --git a/frontend/rust-lib/flowy-core/src/services/workspace/controller.rs b/frontend/rust-lib/flowy-core/src/services/workspace/controller.rs index 2edf7eea57..aebda93def 100644 --- a/frontend/rust-lib/flowy-core/src/services/workspace/controller.rs +++ b/frontend/rust-lib/flowy-core/src/services/workspace/controller.rs @@ -10,8 +10,7 @@ use crate::{ }, }; use flowy_core_infra::entities::{app::RepeatedApp, workspace::*}; -use flowy_database::SqliteConnection; -use lib_infra::kv::KV; +use flowy_database::{kv::KV, SqliteConnection}; use std::sync::Arc; pub struct WorkspaceController { diff --git a/frontend/rust-lib/flowy-database/Cargo.toml b/frontend/rust-lib/flowy-database/Cargo.toml index 35f68c1480..c2e3f64fd4 100644 --- a/frontend/rust-lib/flowy-database/Cargo.toml +++ b/frontend/rust-lib/flowy-database/Cargo.toml @@ -9,4 +9,6 @@ edition = "2018" diesel = {version = "1.4.8", features = ["sqlite"]} diesel_derives = {version = "1.4.1", features = ["sqlite"]} diesel_migrations = {version = "1.4.0", features = ["sqlite"]} -lib-sqlite = { path = "../../../shared-lib/lib-sqlite" } \ No newline at end of file +lib-sqlite = { path = "../../../shared-lib/lib-sqlite" } +log = "0.4" +lazy_static = "1.4.0" \ No newline at end of file diff --git a/frontend/rust-lib/lib-infra/src/kv/kv.rs b/frontend/rust-lib/flowy-database/src/kv/kv.rs similarity index 95% rename from frontend/rust-lib/lib-infra/src/kv/kv.rs rename to frontend/rust-lib/flowy-database/src/kv/kv.rs index c9303e7520..7dcb5b86c4 100644 --- a/frontend/rust-lib/lib-infra/src/kv/kv.rs +++ b/frontend/rust-lib/flowy-database/src/kv/kv.rs @@ -1,7 +1,6 @@ use crate::kv::schema::{kv_table, kv_table::dsl, KV_SQL}; use ::diesel::{query_dsl::*, ExpressionMethods}; use diesel::{Connection, SqliteConnection}; -use flowy_derive::ProtoBuf; use lazy_static::lazy_static; use lib_sqlite::{DBConnection, Database, PoolConfig}; use std::{collections::HashMap, path::Path, sync::RwLock}; @@ -178,23 +177,14 @@ fn get_connection() -> Result { } } -#[derive(Clone, Debug, ProtoBuf, Default, Queryable, Identifiable, Insertable, AsChangeset)] +#[derive(Clone, Debug, Default, Queryable, Identifiable, Insertable, AsChangeset)] #[table_name = "kv_table"] #[primary_key(key)] pub struct KeyValue { - #[pb(index = 1)] pub key: String, - - #[pb(index = 2, one_of)] pub str_value: Option, - - #[pb(index = 3, one_of)] pub int_value: Option, - - #[pb(index = 4, one_of)] pub float_value: Option, - - #[pb(index = 5, one_of)] pub bool_value: Option, } diff --git a/frontend/rust-lib/lib-infra/src/kv/mod.rs b/frontend/rust-lib/flowy-database/src/kv/mod.rs similarity index 100% rename from frontend/rust-lib/lib-infra/src/kv/mod.rs rename to frontend/rust-lib/flowy-database/src/kv/mod.rs diff --git a/frontend/rust-lib/lib-infra/src/kv/schema.rs b/frontend/rust-lib/flowy-database/src/kv/schema.rs similarity index 100% rename from frontend/rust-lib/lib-infra/src/kv/schema.rs rename to frontend/rust-lib/flowy-database/src/kv/schema.rs diff --git a/frontend/rust-lib/flowy-database/src/lib.rs b/frontend/rust-lib/flowy-database/src/lib.rs index 4d50552f55..bfdec920d4 100644 --- a/frontend/rust-lib/flowy-database/src/lib.rs +++ b/frontend/rust-lib/flowy-database/src/lib.rs @@ -1,3 +1,12 @@ +pub use diesel::*; +pub use diesel_derives::*; +use diesel_migrations::*; +use std::{fmt::Debug, io, path::Path}; +pub mod kv; + +use lib_sqlite::PoolConfig; +pub use lib_sqlite::{ConnectionPool, DBConnection, Database}; + pub mod schema; #[macro_use] @@ -5,25 +14,17 @@ pub mod macros; #[macro_use] extern crate diesel; -pub use diesel::*; - #[macro_use] extern crate diesel_derives; -pub use diesel_derives::*; - #[macro_use] extern crate diesel_migrations; -pub use lib_sqlite::{ConnectionPool, DBConnection, Database}; pub type Error = diesel::result::Error; -use diesel_migrations::*; -use lib_sqlite::PoolConfig; -use std::{fmt::Debug, io, path::Path}; - pub mod prelude { - pub use super::UserDatabaseConnection; pub use diesel::{query_dsl::*, BelongingToDsl, ExpressionMethods, RunQueryDsl}; + + pub use super::UserDatabaseConnection; } embed_migrations!("../flowy-database/migrations/"); diff --git a/frontend/rust-lib/flowy-sdk/src/lib.rs b/frontend/rust-lib/flowy-sdk/src/lib.rs index 2f2322d478..0e3a19bad2 100644 --- a/frontend/rust-lib/flowy-sdk/src/lib.rs +++ b/frontend/rust-lib/flowy-sdk/src/lib.rs @@ -148,7 +148,7 @@ async fn _listen_network_status(mut subscribe: broadcast::Receiver, } fn init_kv(root: &str) { - match lib_infra::kv::KV::init(root) { + match flowy_database::kv::KV::init(root) { Ok(_) => {}, Err(e) => tracing::error!("Init kv store failedL: {}", e), } diff --git a/frontend/rust-lib/flowy-test/src/helper.rs b/frontend/rust-lib/flowy-test/src/helper.rs index cfec412418..a533e8473f 100644 --- a/frontend/rust-lib/flowy-test/src/helper.rs +++ b/frontend/rust-lib/flowy-test/src/helper.rs @@ -1,5 +1,5 @@ -use crate::prelude::*; -use bytes::Bytes; +use std::{fs, path::PathBuf, sync::Arc}; + use flowy_collaboration::entities::doc::Doc; use flowy_core::{ entities::{ @@ -8,7 +8,7 @@ use flowy_core::{ view::*, workspace::{CreateWorkspaceRequest, QueryWorkspaceRequest, Workspace, *}, }, - errors::{ErrorCode, WorkspaceError}, + errors::ErrorCode, event::WorkspaceEvent::{CreateWorkspace, OpenWorkspace, *}, }; use flowy_user::{ @@ -17,8 +17,9 @@ use flowy_user::{ event::UserEvent::{InitUser, SignIn, SignOut, SignUp}, }; use lib_dispatch::prelude::{EventDispatcher, ModuleRequest, ToBytes}; -use lib_infra::{kv::KV, uuid}; -use std::{fs, path::PathBuf, sync::Arc}; +use lib_infra::uuid; + +use crate::prelude::*; pub struct WorkspaceTest { pub sdk: FlowySDKTest, @@ -298,46 +299,6 @@ pub fn login_email() -> String { "annie2@appflowy.io".to_string() } pub fn login_password() -> String { "HelloWorld!123".to_string() } -const DEFAULT_WORKSPACE_NAME: &str = "My workspace"; -const DEFAULT_WORKSPACE_DESC: &str = "This is your first workspace"; -const DEFAULT_WORKSPACE: &str = "Default_Workspace"; - -#[allow(dead_code)] -pub(crate) fn create_default_workspace_if_need(dispatch: Arc, user_id: &str) -> Result<(), UserError> { - let key = format!("{}{}", user_id, DEFAULT_WORKSPACE); - if KV::get_bool(&key).unwrap_or(false) { - return Err(UserError::internal()); - } - KV::set_bool(&key, true); - - let payload: Bytes = CreateWorkspaceRequest { - name: DEFAULT_WORKSPACE_NAME.to_string(), - desc: DEFAULT_WORKSPACE_DESC.to_string(), - } - .into_bytes() - .unwrap(); - - let request = ModuleRequest::new(CreateWorkspace).payload(payload); - let result = EventDispatcher::sync_send(dispatch.clone(), request) - .parse::() - .map_err(|e| UserError::internal().context(e))?; - - let workspace = result.map_err(|e| UserError::internal().context(e))?; - let query: Bytes = QueryWorkspaceRequest { - workspace_id: Some(workspace.id), - } - .into_bytes() - .unwrap(); - - let request = ModuleRequest::new(OpenWorkspace).payload(query); - let _result = EventDispatcher::sync_send(dispatch, request) - .parse::() - .unwrap() - .unwrap(); - - Ok(()) -} - pub struct SignUpContext { pub user_profile: UserProfile, pub password: String, diff --git a/frontend/rust-lib/flowy-user/src/services/user/user_session.rs b/frontend/rust-lib/flowy-user/src/services/user/user_session.rs index 010e462801..e0c99b65e6 100644 --- a/frontend/rust-lib/flowy-user/src/services/user/user_session.rs +++ b/frontend/rust-lib/flowy-user/src/services/user/user_session.rs @@ -1,22 +1,12 @@ -use crate::{ - entities::{SignInParams, SignUpParams, UpdateUserParams, UserProfile}, - errors::{ErrorCode, UserError}, - services::user::database::UserDB, - sql_tables::{UserTable, UserTableChangeset}, -}; +use std::sync::Arc; + +use parking_lot::RwLock; +use serde::{Deserialize, Serialize}; +use tokio::sync::{broadcast, mpsc}; -use crate::{ - notify::*, - services::{ - server::{construct_user_server, Server}, - user::{ - notifier::UserNotifier, - ws_manager::{FlowyWsSender, WsManager}, - }, - }, -}; use backend_service::configuration::ClientServerConfiguration; use flowy_database::{ + kv::KV, query_dsl::*, schema::{user_table, user_table::dsl}, DBConnection, @@ -24,13 +14,24 @@ use flowy_database::{ UserDatabaseConnection, }; use flowy_user_infra::entities::{SignInResponse, SignUpResponse}; -use lib_infra::{entities::network_state::NetworkState, kv::KV}; +use lib_infra::entities::network_state::NetworkState; use lib_sqlite::ConnectionPool; use lib_ws::{WsConnectState, WsMessageHandler}; -use parking_lot::RwLock; -use serde::{Deserialize, Serialize}; -use std::sync::Arc; -use tokio::sync::{broadcast, mpsc}; + +use crate::{ + entities::{SignInParams, SignUpParams, UpdateUserParams, UserProfile}, + errors::{ErrorCode, UserError}, + notify::*, + services::{ + server::{construct_user_server, Server}, + user::{ + database::UserDB, + notifier::UserNotifier, + ws_manager::{FlowyWsSender, WsManager}, + }, + }, + sql_tables::{UserTable, UserTableChangeset}, +}; pub struct UserSessionConfig { root_dir: String, diff --git a/frontend/rust-lib/lib-infra/Cargo.toml b/frontend/rust-lib/lib-infra/Cargo.toml index ce43059378..57a7a2dee3 100644 --- a/frontend/rust-lib/lib-infra/Cargo.toml +++ b/frontend/rust-lib/lib-infra/Cargo.toml @@ -7,12 +7,7 @@ edition = "2018" [dependencies] uuid = { version = "0.8", features = ["serde", "v4"] } -diesel = {version = "1.4.8", features = ["sqlite"]} -diesel_derives = {version = "1.4.1", features = ["sqlite"]} -diesel_migrations = {version = "1.4.0", features = ["sqlite"]} flowy-derive = { path = "../../../shared-lib/flowy-derive" } -lib-sqlite = { path = "../../../shared-lib/lib-sqlite" } -lazy_static = "1.4.0" protobuf = {version = "2.18.0"} log = "0.4.14" chrono = "0.4.19" diff --git a/frontend/rust-lib/lib-infra/src/lib.rs b/frontend/rust-lib/lib-infra/src/lib.rs index a934281b0e..681f4aa7f2 100644 --- a/frontend/rust-lib/lib-infra/src/lib.rs +++ b/frontend/rust-lib/lib-infra/src/lib.rs @@ -1,12 +1,5 @@ -#[macro_use] -extern crate diesel; - -#[macro_use] -extern crate diesel_derives; - pub mod entities; pub mod future; -pub mod kv; mod protobuf; pub mod retry; diff --git a/shared-lib/Cargo.lock b/shared-lib/Cargo.lock index e3a7e34a49..34d88e6bf5 100644 --- a/shared-lib/Cargo.lock +++ b/shared-lib/Cargo.lock @@ -1132,13 +1132,8 @@ version = "0.1.0" dependencies = [ "bytes", "chrono", - "diesel", - "diesel_derives", - "diesel_migrations", "flowy-derive", "futures-core", - "lazy_static", - "lib-sqlite", "log", "pin-project", "protobuf", From df432d11c38c367c7d48b7cf58d98e46f4f953cc Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 12 Dec 2021 21:48:52 +0800 Subject: [PATCH 23/39] add flowy-net crate --- backend/Cargo.lock | 10 + .../flowy_sdk/lib/dispatch/dispatch.dart | 2 +- .../network_state.pb.dart | 0 .../network_state.pbenum.dart | 0 .../network_state.pbjson.dart | 0 .../network_state.pbserver.dart | 0 .../lib/protobuf/flowy-net/protobuf.dart | 2 + .../lib/protobuf/lib-infra/kv.pb.dart | 167 ------ .../lib/protobuf/lib-infra/kv.pbenum.dart | 7 - .../lib/protobuf/lib-infra/kv.pbjson.dart | 30 -- .../lib/protobuf/lib-infra/kv.pbserver.dart | 9 - .../lib/protobuf/lib-infra/protobuf.dart | 2 - frontend/rust-lib/Cargo.toml | 1 + frontend/rust-lib/flowy-core/Cargo.toml | 1 + .../flowy-core/src/core/core_context.rs | 2 +- frontend/rust-lib/flowy-net/Cargo.toml | 10 + frontend/rust-lib/flowy-net/Flowy.toml | 2 + .../rust-lib/flowy-net/src/entities/mod.rs | 2 + .../src/entities/network_state.rs | 0 frontend/rust-lib/flowy-net/src/lib.rs | 2 + .../src/protobuf/mod.rs | 0 .../src/protobuf/model/mod.rs | 3 - .../src/protobuf/model/network_state.rs | 30 +- .../src/protobuf/proto/network_state.proto | 1 - frontend/rust-lib/flowy-user/Cargo.toml | 1 + .../flowy-user/src/handlers/user_handler.rs | 2 +- .../flowy-user/src/services/user/notifier.rs | 2 +- .../src/services/user/user_session.rs | 2 +- .../src/services/user/ws_manager.rs | 3 +- frontend/rust-lib/lib-infra/Flowy.toml | 2 - .../rust-lib/lib-infra/src/entities/mod.rs | 1 - frontend/rust-lib/lib-infra/src/lib.rs | 2 - .../lib-infra/src/protobuf/model/kv.rs | 478 ------------------ .../lib-infra/src/protobuf/proto/kv.proto | 9 - frontend/scripts/flowy-tool/src/util/file.rs | 2 +- .../src/derive_cache/derive_cache.rs | 9 +- 36 files changed, 58 insertions(+), 738 deletions(-) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{lib-infra => flowy-net}/network_state.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{lib-infra => flowy-net}/network_state.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{lib-infra => flowy-net}/network_state.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{lib-infra => flowy-net}/network_state.pbserver.dart (100%) create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/protobuf.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-infra/kv.pb.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-infra/kv.pbenum.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-infra/kv.pbjson.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-infra/kv.pbserver.dart create mode 100644 frontend/rust-lib/flowy-net/Cargo.toml create mode 100644 frontend/rust-lib/flowy-net/Flowy.toml create mode 100644 frontend/rust-lib/flowy-net/src/entities/mod.rs rename frontend/rust-lib/{lib-infra => flowy-net}/src/entities/network_state.rs (100%) create mode 100644 frontend/rust-lib/flowy-net/src/lib.rs rename frontend/rust-lib/{lib-infra => flowy-net}/src/protobuf/mod.rs (100%) rename frontend/rust-lib/{lib-infra => flowy-net}/src/protobuf/model/mod.rs (82%) rename frontend/rust-lib/{lib-infra => flowy-net}/src/protobuf/model/network_state.rs (89%) rename frontend/rust-lib/{lib-infra => flowy-net}/src/protobuf/proto/network_state.proto (99%) delete mode 100644 frontend/rust-lib/lib-infra/Flowy.toml delete mode 100644 frontend/rust-lib/lib-infra/src/entities/mod.rs delete mode 100644 frontend/rust-lib/lib-infra/src/protobuf/model/kv.rs delete mode 100644 frontend/rust-lib/lib-infra/src/protobuf/proto/kv.proto diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 3062c72aa4..d800cbc4c5 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -1237,6 +1237,7 @@ dependencies = [ "flowy-database", "flowy-derive", "flowy-document", + "flowy-net", "futures", "futures-core", "lazy_static", @@ -1334,6 +1335,14 @@ dependencies = [ "url", ] +[[package]] +name = "flowy-net" +version = "0.1.0" +dependencies = [ + "flowy-derive", + "protobuf", +] + [[package]] name = "flowy-sdk" version = "0.1.0" @@ -1396,6 +1405,7 @@ dependencies = [ "flowy-collaboration", "flowy-database", "flowy-derive", + "flowy-net", "flowy-user-infra", "futures-core", "lazy_static", diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart index 328d6a6af4..cdfdad7631 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart @@ -3,11 +3,11 @@ import 'package:dartz/dartz.dart'; import 'package:flowy_log/flowy_log.dart'; // ignore: unnecessary_import import 'package:flowy_sdk/protobuf/dart-ffi/ffi_response.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-net/network_state.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user/event.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/event.pb.dart'; -import 'package:flowy_sdk/protobuf/lib-infra/network_state.pb.dart'; import 'package:isolates/isolates.dart'; import 'package:isolates/ports.dart'; import 'package:ffi/ffi.dart'; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-infra/network_state.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/network_state.pb.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-infra/network_state.pb.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/network_state.pb.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-infra/network_state.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/network_state.pbenum.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-infra/network_state.pbenum.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/network_state.pbenum.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-infra/network_state.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/network_state.pbjson.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-infra/network_state.pbjson.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/network_state.pbjson.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-infra/network_state.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/network_state.pbserver.dart similarity index 100% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-infra/network_state.pbserver.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/network_state.pbserver.dart diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/protobuf.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/protobuf.dart new file mode 100644 index 0000000000..53a97620cf --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/protobuf.dart @@ -0,0 +1,2 @@ +// Auto-generated, do not edit +export './network_state.pb.dart'; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-infra/kv.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-infra/kv.pb.dart deleted file mode 100644 index 971c06cd0a..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-infra/kv.pb.dart +++ /dev/null @@ -1,167 +0,0 @@ -/// -// Generated code. Do not modify. -// source: kv.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields - -import 'dart:core' as $core; - -import 'package:fixnum/fixnum.dart' as $fixnum; -import 'package:protobuf/protobuf.dart' as $pb; - -enum KeyValue_OneOfStrValue { - strValue, - notSet -} - -enum KeyValue_OneOfIntValue { - intValue, - notSet -} - -enum KeyValue_OneOfFloatValue { - floatValue, - notSet -} - -enum KeyValue_OneOfBoolValue { - boolValue, - notSet -} - -class KeyValue extends $pb.GeneratedMessage { - static const $core.Map<$core.int, KeyValue_OneOfStrValue> _KeyValue_OneOfStrValueByTag = { - 2 : KeyValue_OneOfStrValue.strValue, - 0 : KeyValue_OneOfStrValue.notSet - }; - static const $core.Map<$core.int, KeyValue_OneOfIntValue> _KeyValue_OneOfIntValueByTag = { - 3 : KeyValue_OneOfIntValue.intValue, - 0 : KeyValue_OneOfIntValue.notSet - }; - static const $core.Map<$core.int, KeyValue_OneOfFloatValue> _KeyValue_OneOfFloatValueByTag = { - 4 : KeyValue_OneOfFloatValue.floatValue, - 0 : KeyValue_OneOfFloatValue.notSet - }; - static const $core.Map<$core.int, KeyValue_OneOfBoolValue> _KeyValue_OneOfBoolValueByTag = { - 5 : KeyValue_OneOfBoolValue.boolValue, - 0 : KeyValue_OneOfBoolValue.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'KeyValue', createEmptyInstance: create) - ..oo(0, [2]) - ..oo(1, [3]) - ..oo(2, [4]) - ..oo(3, [5]) - ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'key') - ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'strValue') - ..aInt64(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'intValue') - ..a<$core.double>(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'floatValue', $pb.PbFieldType.OD) - ..aOB(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'boolValue') - ..hasRequiredFields = false - ; - - KeyValue._() : super(); - factory KeyValue({ - $core.String? key, - $core.String? strValue, - $fixnum.Int64? intValue, - $core.double? floatValue, - $core.bool? boolValue, - }) { - final _result = create(); - if (key != null) { - _result.key = key; - } - if (strValue != null) { - _result.strValue = strValue; - } - if (intValue != null) { - _result.intValue = intValue; - } - if (floatValue != null) { - _result.floatValue = floatValue; - } - if (boolValue != null) { - _result.boolValue = boolValue; - } - return _result; - } - factory KeyValue.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory KeyValue.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' - 'Will be removed in next major version') - KeyValue clone() => KeyValue()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - KeyValue copyWith(void Function(KeyValue) updates) => super.copyWith((message) => updates(message as KeyValue)) as KeyValue; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static KeyValue create() => KeyValue._(); - KeyValue createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static KeyValue getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static KeyValue? _defaultInstance; - - KeyValue_OneOfStrValue whichOneOfStrValue() => _KeyValue_OneOfStrValueByTag[$_whichOneof(0)]!; - void clearOneOfStrValue() => clearField($_whichOneof(0)); - - KeyValue_OneOfIntValue whichOneOfIntValue() => _KeyValue_OneOfIntValueByTag[$_whichOneof(1)]!; - void clearOneOfIntValue() => clearField($_whichOneof(1)); - - KeyValue_OneOfFloatValue whichOneOfFloatValue() => _KeyValue_OneOfFloatValueByTag[$_whichOneof(2)]!; - void clearOneOfFloatValue() => clearField($_whichOneof(2)); - - KeyValue_OneOfBoolValue whichOneOfBoolValue() => _KeyValue_OneOfBoolValueByTag[$_whichOneof(3)]!; - void clearOneOfBoolValue() => clearField($_whichOneof(3)); - - @$pb.TagNumber(1) - $core.String get key => $_getSZ(0); - @$pb.TagNumber(1) - set key($core.String v) { $_setString(0, v); } - @$pb.TagNumber(1) - $core.bool hasKey() => $_has(0); - @$pb.TagNumber(1) - void clearKey() => clearField(1); - - @$pb.TagNumber(2) - $core.String get strValue => $_getSZ(1); - @$pb.TagNumber(2) - set strValue($core.String v) { $_setString(1, v); } - @$pb.TagNumber(2) - $core.bool hasStrValue() => $_has(1); - @$pb.TagNumber(2) - void clearStrValue() => clearField(2); - - @$pb.TagNumber(3) - $fixnum.Int64 get intValue => $_getI64(2); - @$pb.TagNumber(3) - set intValue($fixnum.Int64 v) { $_setInt64(2, v); } - @$pb.TagNumber(3) - $core.bool hasIntValue() => $_has(2); - @$pb.TagNumber(3) - void clearIntValue() => clearField(3); - - @$pb.TagNumber(4) - $core.double get floatValue => $_getN(3); - @$pb.TagNumber(4) - set floatValue($core.double v) { $_setDouble(3, v); } - @$pb.TagNumber(4) - $core.bool hasFloatValue() => $_has(3); - @$pb.TagNumber(4) - void clearFloatValue() => clearField(4); - - @$pb.TagNumber(5) - $core.bool get boolValue => $_getBF(4); - @$pb.TagNumber(5) - set boolValue($core.bool v) { $_setBool(4, v); } - @$pb.TagNumber(5) - $core.bool hasBoolValue() => $_has(4); - @$pb.TagNumber(5) - void clearBoolValue() => clearField(5); -} - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-infra/kv.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-infra/kv.pbenum.dart deleted file mode 100644 index 79c2244e07..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-infra/kv.pbenum.dart +++ /dev/null @@ -1,7 +0,0 @@ -/// -// Generated code. Do not modify. -// source: kv.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-infra/kv.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-infra/kv.pbjson.dart deleted file mode 100644 index 45152125bb..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-infra/kv.pbjson.dart +++ /dev/null @@ -1,30 +0,0 @@ -/// -// Generated code. Do not modify. -// source: kv.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package - -import 'dart:core' as $core; -import 'dart:convert' as $convert; -import 'dart:typed_data' as $typed_data; -@$core.Deprecated('Use keyValueDescriptor instead') -const KeyValue$json = const { - '1': 'KeyValue', - '2': const [ - const {'1': 'key', '3': 1, '4': 1, '5': 9, '10': 'key'}, - const {'1': 'str_value', '3': 2, '4': 1, '5': 9, '9': 0, '10': 'strValue'}, - const {'1': 'int_value', '3': 3, '4': 1, '5': 3, '9': 1, '10': 'intValue'}, - const {'1': 'float_value', '3': 4, '4': 1, '5': 1, '9': 2, '10': 'floatValue'}, - const {'1': 'bool_value', '3': 5, '4': 1, '5': 8, '9': 3, '10': 'boolValue'}, - ], - '8': const [ - const {'1': 'one_of_str_value'}, - const {'1': 'one_of_int_value'}, - const {'1': 'one_of_float_value'}, - const {'1': 'one_of_bool_value'}, - ], -}; - -/// Descriptor for `KeyValue`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List keyValueDescriptor = $convert.base64Decode('CghLZXlWYWx1ZRIQCgNrZXkYASABKAlSA2tleRIdCglzdHJfdmFsdWUYAiABKAlIAFIIc3RyVmFsdWUSHQoJaW50X3ZhbHVlGAMgASgDSAFSCGludFZhbHVlEiEKC2Zsb2F0X3ZhbHVlGAQgASgBSAJSCmZsb2F0VmFsdWUSHwoKYm9vbF92YWx1ZRgFIAEoCEgDUglib29sVmFsdWVCEgoQb25lX29mX3N0cl92YWx1ZUISChBvbmVfb2ZfaW50X3ZhbHVlQhQKEm9uZV9vZl9mbG9hdF92YWx1ZUITChFvbmVfb2ZfYm9vbF92YWx1ZQ=='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-infra/kv.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-infra/kv.pbserver.dart deleted file mode 100644 index 0daeedf5a6..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-infra/kv.pbserver.dart +++ /dev/null @@ -1,9 +0,0 @@ -/// -// Generated code. Do not modify. -// source: kv.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package - -export 'kv.pb.dart'; - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-infra/protobuf.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-infra/protobuf.dart index 2cc2dfd9ee..58506e3e5f 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-infra/protobuf.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-infra/protobuf.dart @@ -1,3 +1 @@ // Auto-generated, do not edit -export './kv.pb.dart'; -export './network_state.pb.dart'; diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index 592c6e1d6c..2800206223 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -3,6 +3,7 @@ members = [ "lib-dispatch", "lib-log", "lib-infra", + "flowy-net", "flowy-sdk", "dart-ffi", "flowy-user", diff --git a/frontend/rust-lib/flowy-core/Cargo.toml b/frontend/rust-lib/flowy-core/Cargo.toml index e460874384..33a4e280a0 100644 --- a/frontend/rust-lib/flowy-core/Cargo.toml +++ b/frontend/rust-lib/flowy-core/Cargo.toml @@ -16,6 +16,7 @@ backend-service = { path = "../../../shared-lib/backend-service" } flowy-document = { path = "../flowy-document" } flowy-database = { path = "../flowy-database" } +flowy-net = { path = "../flowy-net" } dart-notify = { path = "../dart-notify" } lib-dispatch = { path = "../lib-dispatch" } lib-infra = { path = "../lib-infra" } diff --git a/frontend/rust-lib/flowy-core/src/core/core_context.rs b/frontend/rust-lib/flowy-core/src/core/core_context.rs index 983aaed33d..7f5236b011 100644 --- a/frontend/rust-lib/flowy-core/src/core/core_context.rs +++ b/frontend/rust-lib/flowy-core/src/core/core_context.rs @@ -8,8 +8,8 @@ use crate::{ use chrono::Utc; use flowy_collaboration::{entities::doc::DocDelta, user_default::initial_read_me}; use flowy_core_infra::user_default; +use flowy_net::entities::NetworkType; use lazy_static::lazy_static; -use lib_infra::entities::network_state::NetworkType; use parking_lot::RwLock; use std::{collections::HashMap, sync::Arc}; lazy_static! { diff --git a/frontend/rust-lib/flowy-net/Cargo.toml b/frontend/rust-lib/flowy-net/Cargo.toml new file mode 100644 index 0000000000..f86272efd5 --- /dev/null +++ b/frontend/rust-lib/flowy-net/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "flowy-net" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +flowy-derive = { path = "../../../shared-lib/flowy-derive" } +protobuf = {version = "2.18.0"} \ No newline at end of file diff --git a/frontend/rust-lib/flowy-net/Flowy.toml b/frontend/rust-lib/flowy-net/Flowy.toml new file mode 100644 index 0000000000..9744b45163 --- /dev/null +++ b/frontend/rust-lib/flowy-net/Flowy.toml @@ -0,0 +1,2 @@ +proto_crates = ["src/entities"] +event_files = [] \ No newline at end of file diff --git a/frontend/rust-lib/flowy-net/src/entities/mod.rs b/frontend/rust-lib/flowy-net/src/entities/mod.rs new file mode 100644 index 0000000000..10dad6191c --- /dev/null +++ b/frontend/rust-lib/flowy-net/src/entities/mod.rs @@ -0,0 +1,2 @@ +mod network_state; +pub use network_state::*; diff --git a/frontend/rust-lib/lib-infra/src/entities/network_state.rs b/frontend/rust-lib/flowy-net/src/entities/network_state.rs similarity index 100% rename from frontend/rust-lib/lib-infra/src/entities/network_state.rs rename to frontend/rust-lib/flowy-net/src/entities/network_state.rs diff --git a/frontend/rust-lib/flowy-net/src/lib.rs b/frontend/rust-lib/flowy-net/src/lib.rs new file mode 100644 index 0000000000..85976edd74 --- /dev/null +++ b/frontend/rust-lib/flowy-net/src/lib.rs @@ -0,0 +1,2 @@ +pub mod entities; +pub mod protobuf; diff --git a/frontend/rust-lib/lib-infra/src/protobuf/mod.rs b/frontend/rust-lib/flowy-net/src/protobuf/mod.rs similarity index 100% rename from frontend/rust-lib/lib-infra/src/protobuf/mod.rs rename to frontend/rust-lib/flowy-net/src/protobuf/mod.rs diff --git a/frontend/rust-lib/lib-infra/src/protobuf/model/mod.rs b/frontend/rust-lib/flowy-net/src/protobuf/model/mod.rs similarity index 82% rename from frontend/rust-lib/lib-infra/src/protobuf/model/mod.rs rename to frontend/rust-lib/flowy-net/src/protobuf/model/mod.rs index 535c9c70f6..0873fb624e 100644 --- a/frontend/rust-lib/lib-infra/src/protobuf/model/mod.rs +++ b/frontend/rust-lib/flowy-net/src/protobuf/model/mod.rs @@ -1,8 +1,5 @@ #![cfg_attr(rustfmt, rustfmt::skip)] // Auto-generated, do not edit -mod kv; -pub use kv::*; - mod network_state; pub use network_state::*; diff --git a/frontend/rust-lib/lib-infra/src/protobuf/model/network_state.rs b/frontend/rust-lib/flowy-net/src/protobuf/model/network_state.rs similarity index 89% rename from frontend/rust-lib/lib-infra/src/protobuf/model/network_state.rs rename to frontend/rust-lib/flowy-net/src/protobuf/model/network_state.rs index b74f295a86..82286beead 100644 --- a/frontend/rust-lib/lib-infra/src/protobuf/model/network_state.rs +++ b/frontend/rust-lib/flowy-net/src/protobuf/model/network_state.rs @@ -231,21 +231,21 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \n\x13network_state.proto\",\n\x0cNetworkState\x12\x1c\n\x02ty\x18\x01\ \x20\x01(\x0e2\x0c.NetworkTypeR\x02ty*G\n\x0bNetworkType\x12\x16\n\x12Un\ knownNetworkType\x10\0\x12\x08\n\x04Wifi\x10\x01\x12\x08\n\x04Cell\x10\ - \x02\x12\x0c\n\x08Ethernet\x10\x03J\x9d\x02\n\x06\x12\x04\0\0\n\x01\n\ - \x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x04\x01\n\n\ - \n\x03\x04\0\x01\x12\x03\x02\x08\x14\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\x0f\n\x0c\n\x05\x04\ - \0\x02\0\x01\x12\x03\x03\x10\x12\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\ - \x15\x16\n\n\n\x02\x05\0\x12\x04\x05\0\n\x01\n\n\n\x03\x05\0\x01\x12\x03\ - \x05\x05\x10\n\x0b\n\x04\x05\0\x02\0\x12\x03\x06\x04\x1b\n\x0c\n\x05\x05\ - \0\x02\0\x01\x12\x03\x06\x04\x16\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x06\ - \x19\x1a\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x07\x04\r\n\x0c\n\x05\x05\0\ - \x02\x01\x01\x12\x03\x07\x04\x08\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\ - \x07\x0b\x0c\n\x0b\n\x04\x05\0\x02\x02\x12\x03\x08\x04\r\n\x0c\n\x05\x05\ - \0\x02\x02\x01\x12\x03\x08\x04\x08\n\x0c\n\x05\x05\0\x02\x02\x02\x12\x03\ - \x08\x0b\x0c\n\x0b\n\x04\x05\0\x02\x03\x12\x03\t\x04\x11\n\x0c\n\x05\x05\ - \0\x02\x03\x01\x12\x03\t\x04\x0c\n\x0c\n\x05\x05\0\x02\x03\x02\x12\x03\t\ - \x0f\x10b\x06proto3\ + \x02\x12\x0c\n\x08Ethernet\x10\x03J\x9d\x02\n\x06\x12\x04\0\0\t\x01\n\ + \x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x01\0\x03\x01\n\n\ + \n\x03\x04\0\x01\x12\x03\x01\x08\x14\n\x0b\n\x04\x04\0\x02\0\x12\x03\x02\ + \x04\x17\n\x0c\n\x05\x04\0\x02\0\x06\x12\x03\x02\x04\x0f\n\x0c\n\x05\x04\ + \0\x02\0\x01\x12\x03\x02\x10\x12\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x02\ + \x15\x16\n\n\n\x02\x05\0\x12\x04\x04\0\t\x01\n\n\n\x03\x05\0\x01\x12\x03\ + \x04\x05\x10\n\x0b\n\x04\x05\0\x02\0\x12\x03\x05\x04\x1b\n\x0c\n\x05\x05\ + \0\x02\0\x01\x12\x03\x05\x04\x16\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x05\ + \x19\x1a\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x06\x04\r\n\x0c\n\x05\x05\0\ + \x02\x01\x01\x12\x03\x06\x04\x08\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\ + \x06\x0b\x0c\n\x0b\n\x04\x05\0\x02\x02\x12\x03\x07\x04\r\n\x0c\n\x05\x05\ + \0\x02\x02\x01\x12\x03\x07\x04\x08\n\x0c\n\x05\x05\0\x02\x02\x02\x12\x03\ + \x07\x0b\x0c\n\x0b\n\x04\x05\0\x02\x03\x12\x03\x08\x04\x11\n\x0c\n\x05\ + \x05\0\x02\x03\x01\x12\x03\x08\x04\x0c\n\x0c\n\x05\x05\0\x02\x03\x02\x12\ + \x03\x08\x0f\x10b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/frontend/rust-lib/lib-infra/src/protobuf/proto/network_state.proto b/frontend/rust-lib/flowy-net/src/protobuf/proto/network_state.proto similarity index 99% rename from frontend/rust-lib/lib-infra/src/protobuf/proto/network_state.proto rename to frontend/rust-lib/flowy-net/src/protobuf/proto/network_state.proto index 06a4aa5f3c..390def7011 100644 --- a/frontend/rust-lib/lib-infra/src/protobuf/proto/network_state.proto +++ b/frontend/rust-lib/flowy-net/src/protobuf/proto/network_state.proto @@ -1,5 +1,4 @@ syntax = "proto3"; - message NetworkState { NetworkType ty = 1; } diff --git a/frontend/rust-lib/flowy-user/Cargo.toml b/frontend/rust-lib/flowy-user/Cargo.toml index ed99e4fb72..5c2b70f1a7 100644 --- a/frontend/rust-lib/flowy-user/Cargo.toml +++ b/frontend/rust-lib/flowy-user/Cargo.toml @@ -15,6 +15,7 @@ lib-sqlite = { path = "../../../shared-lib/lib-sqlite" } derive_more = {version = "0.99", features = ["display"]} flowy-database = { path = "../flowy-database" } +flowy-net = { path = "../flowy-net" } dart-notify = { path = "../dart-notify" } lib-dispatch = { path = "../lib-dispatch" } lib-infra = { path = "../lib-infra" } diff --git a/frontend/rust-lib/flowy-user/src/handlers/user_handler.rs b/frontend/rust-lib/flowy-user/src/handlers/user_handler.rs index c82fe44d1b..531b79b696 100644 --- a/frontend/rust-lib/flowy-user/src/handlers/user_handler.rs +++ b/frontend/rust-lib/flowy-user/src/handlers/user_handler.rs @@ -1,6 +1,6 @@ use crate::{entities::*, errors::UserError, services::user::UserSession}; +use flowy_net::entities::NetworkState; use lib_dispatch::prelude::*; -use lib_infra::entities::network_state::NetworkState; use std::{convert::TryInto, sync::Arc}; #[tracing::instrument(skip(session))] diff --git a/frontend/rust-lib/flowy-user/src/services/user/notifier.rs b/frontend/rust-lib/flowy-user/src/services/user/notifier.rs index 1b181165c9..c25f2d3dbe 100644 --- a/frontend/rust-lib/flowy-user/src/services/user/notifier.rs +++ b/frontend/rust-lib/flowy-user/src/services/user/notifier.rs @@ -1,5 +1,5 @@ use crate::entities::{UserProfile, UserStatus}; -use lib_infra::entities::network_state::NetworkType; +use flowy_net::entities::NetworkType; use tokio::sync::{broadcast, mpsc}; pub struct UserNotifier { diff --git a/frontend/rust-lib/flowy-user/src/services/user/user_session.rs b/frontend/rust-lib/flowy-user/src/services/user/user_session.rs index e0c99b65e6..dd49e239b9 100644 --- a/frontend/rust-lib/flowy-user/src/services/user/user_session.rs +++ b/frontend/rust-lib/flowy-user/src/services/user/user_session.rs @@ -14,7 +14,6 @@ use flowy_database::{ UserDatabaseConnection, }; use flowy_user_infra::entities::{SignInResponse, SignUpResponse}; -use lib_infra::entities::network_state::NetworkState; use lib_sqlite::ConnectionPool; use lib_ws::{WsConnectState, WsMessageHandler}; @@ -32,6 +31,7 @@ use crate::{ }, sql_tables::{UserTable, UserTableChangeset}, }; +use flowy_net::entities::NetworkState; pub struct UserSessionConfig { root_dir: String, diff --git a/frontend/rust-lib/flowy-user/src/services/user/ws_manager.rs b/frontend/rust-lib/flowy-user/src/services/user/ws_manager.rs index 412843e9d0..c73cd94ee9 100644 --- a/frontend/rust-lib/flowy-user/src/services/user/ws_manager.rs +++ b/frontend/rust-lib/flowy-user/src/services/user/ws_manager.rs @@ -1,6 +1,7 @@ use crate::errors::UserError; -use lib_infra::{entities::network_state::NetworkType, future::ResultFuture}; +use flowy_net::entities::NetworkType; +use lib_infra::future::ResultFuture; use lib_ws::{WsConnectState, WsController, WsMessage, WsMessageHandler, WsSender}; use parking_lot::RwLock; use std::sync::Arc; diff --git a/frontend/rust-lib/lib-infra/Flowy.toml b/frontend/rust-lib/lib-infra/Flowy.toml deleted file mode 100644 index f018887748..0000000000 --- a/frontend/rust-lib/lib-infra/Flowy.toml +++ /dev/null @@ -1,2 +0,0 @@ -proto_crates = ["src/kv", "src/entities"] -event_files = [] \ No newline at end of file diff --git a/frontend/rust-lib/lib-infra/src/entities/mod.rs b/frontend/rust-lib/lib-infra/src/entities/mod.rs deleted file mode 100644 index 52d57f3d0b..0000000000 --- a/frontend/rust-lib/lib-infra/src/entities/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod network_state; diff --git a/frontend/rust-lib/lib-infra/src/lib.rs b/frontend/rust-lib/lib-infra/src/lib.rs index 681f4aa7f2..4e67d61c44 100644 --- a/frontend/rust-lib/lib-infra/src/lib.rs +++ b/frontend/rust-lib/lib-infra/src/lib.rs @@ -1,6 +1,4 @@ -pub mod entities; pub mod future; -mod protobuf; pub mod retry; #[allow(dead_code)] diff --git a/frontend/rust-lib/lib-infra/src/protobuf/model/kv.rs b/frontend/rust-lib/lib-infra/src/protobuf/model/kv.rs deleted file mode 100644 index a28d4c9373..0000000000 --- a/frontend/rust-lib/lib-infra/src/protobuf/model/kv.rs +++ /dev/null @@ -1,478 +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 `kv.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 KeyValue { - // message fields - pub key: ::std::string::String, - // message oneof groups - pub one_of_str_value: ::std::option::Option, - pub one_of_int_value: ::std::option::Option, - pub one_of_float_value: ::std::option::Option, - pub one_of_bool_value: ::std::option::Option, - // special fields - pub unknown_fields: ::protobuf::UnknownFields, - pub cached_size: ::protobuf::CachedSize, -} - -impl<'a> ::std::default::Default for &'a KeyValue { - fn default() -> &'a KeyValue { - ::default_instance() - } -} - -#[derive(Clone,PartialEq,Debug)] -pub enum KeyValue_oneof_one_of_str_value { - str_value(::std::string::String), -} - -#[derive(Clone,PartialEq,Debug)] -pub enum KeyValue_oneof_one_of_int_value { - int_value(i64), -} - -#[derive(Clone,PartialEq,Debug)] -pub enum KeyValue_oneof_one_of_float_value { - float_value(f64), -} - -#[derive(Clone,PartialEq,Debug)] -pub enum KeyValue_oneof_one_of_bool_value { - bool_value(bool), -} - -impl KeyValue { - pub fn new() -> KeyValue { - ::std::default::Default::default() - } - - // string key = 1; - - - pub fn get_key(&self) -> &str { - &self.key - } - pub fn clear_key(&mut self) { - self.key.clear(); - } - - // Param is passed by value, moved - pub fn set_key(&mut self, v: ::std::string::String) { - self.key = v; - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_key(&mut self) -> &mut ::std::string::String { - &mut self.key - } - - // Take field - pub fn take_key(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.key, ::std::string::String::new()) - } - - // string str_value = 2; - - - pub fn get_str_value(&self) -> &str { - match self.one_of_str_value { - ::std::option::Option::Some(KeyValue_oneof_one_of_str_value::str_value(ref v)) => v, - _ => "", - } - } - pub fn clear_str_value(&mut self) { - self.one_of_str_value = ::std::option::Option::None; - } - - pub fn has_str_value(&self) -> bool { - match self.one_of_str_value { - ::std::option::Option::Some(KeyValue_oneof_one_of_str_value::str_value(..)) => true, - _ => false, - } - } - - // Param is passed by value, moved - pub fn set_str_value(&mut self, v: ::std::string::String) { - self.one_of_str_value = ::std::option::Option::Some(KeyValue_oneof_one_of_str_value::str_value(v)) - } - - // Mutable pointer to the field. - pub fn mut_str_value(&mut self) -> &mut ::std::string::String { - if let ::std::option::Option::Some(KeyValue_oneof_one_of_str_value::str_value(_)) = self.one_of_str_value { - } else { - self.one_of_str_value = ::std::option::Option::Some(KeyValue_oneof_one_of_str_value::str_value(::std::string::String::new())); - } - match self.one_of_str_value { - ::std::option::Option::Some(KeyValue_oneof_one_of_str_value::str_value(ref mut v)) => v, - _ => panic!(), - } - } - - // Take field - pub fn take_str_value(&mut self) -> ::std::string::String { - if self.has_str_value() { - match self.one_of_str_value.take() { - ::std::option::Option::Some(KeyValue_oneof_one_of_str_value::str_value(v)) => v, - _ => panic!(), - } - } else { - ::std::string::String::new() - } - } - - // int64 int_value = 3; - - - pub fn get_int_value(&self) -> i64 { - match self.one_of_int_value { - ::std::option::Option::Some(KeyValue_oneof_one_of_int_value::int_value(v)) => v, - _ => 0, - } - } - pub fn clear_int_value(&mut self) { - self.one_of_int_value = ::std::option::Option::None; - } - - pub fn has_int_value(&self) -> bool { - match self.one_of_int_value { - ::std::option::Option::Some(KeyValue_oneof_one_of_int_value::int_value(..)) => true, - _ => false, - } - } - - // Param is passed by value, moved - pub fn set_int_value(&mut self, v: i64) { - self.one_of_int_value = ::std::option::Option::Some(KeyValue_oneof_one_of_int_value::int_value(v)) - } - - // double float_value = 4; - - - pub fn get_float_value(&self) -> f64 { - match self.one_of_float_value { - ::std::option::Option::Some(KeyValue_oneof_one_of_float_value::float_value(v)) => v, - _ => 0., - } - } - pub fn clear_float_value(&mut self) { - self.one_of_float_value = ::std::option::Option::None; - } - - pub fn has_float_value(&self) -> bool { - match self.one_of_float_value { - ::std::option::Option::Some(KeyValue_oneof_one_of_float_value::float_value(..)) => true, - _ => false, - } - } - - // Param is passed by value, moved - pub fn set_float_value(&mut self, v: f64) { - self.one_of_float_value = ::std::option::Option::Some(KeyValue_oneof_one_of_float_value::float_value(v)) - } - - // bool bool_value = 5; - - - pub fn get_bool_value(&self) -> bool { - match self.one_of_bool_value { - ::std::option::Option::Some(KeyValue_oneof_one_of_bool_value::bool_value(v)) => v, - _ => false, - } - } - pub fn clear_bool_value(&mut self) { - self.one_of_bool_value = ::std::option::Option::None; - } - - pub fn has_bool_value(&self) -> bool { - match self.one_of_bool_value { - ::std::option::Option::Some(KeyValue_oneof_one_of_bool_value::bool_value(..)) => true, - _ => false, - } - } - - // Param is passed by value, moved - pub fn set_bool_value(&mut self, v: bool) { - self.one_of_bool_value = ::std::option::Option::Some(KeyValue_oneof_one_of_bool_value::bool_value(v)) - } -} - -impl ::protobuf::Message for KeyValue { - 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_singular_proto3_string_into(wire_type, is, &mut self.key)?; - }, - 2 => { - if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { - return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); - } - self.one_of_str_value = ::std::option::Option::Some(KeyValue_oneof_one_of_str_value::str_value(is.read_string()?)); - }, - 3 => { - if wire_type != ::protobuf::wire_format::WireTypeVarint { - return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); - } - self.one_of_int_value = ::std::option::Option::Some(KeyValue_oneof_one_of_int_value::int_value(is.read_int64()?)); - }, - 4 => { - if wire_type != ::protobuf::wire_format::WireTypeFixed64 { - return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); - } - self.one_of_float_value = ::std::option::Option::Some(KeyValue_oneof_one_of_float_value::float_value(is.read_double()?)); - }, - 5 => { - if wire_type != ::protobuf::wire_format::WireTypeVarint { - return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); - } - self.one_of_bool_value = ::std::option::Option::Some(KeyValue_oneof_one_of_bool_value::bool_value(is.read_bool()?)); - }, - _ => { - ::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.key.is_empty() { - my_size += ::protobuf::rt::string_size(1, &self.key); - } - if let ::std::option::Option::Some(ref v) = self.one_of_str_value { - match v { - &KeyValue_oneof_one_of_str_value::str_value(ref v) => { - my_size += ::protobuf::rt::string_size(2, &v); - }, - }; - } - if let ::std::option::Option::Some(ref v) = self.one_of_int_value { - match v { - &KeyValue_oneof_one_of_int_value::int_value(v) => { - my_size += ::protobuf::rt::value_size(3, v, ::protobuf::wire_format::WireTypeVarint); - }, - }; - } - if let ::std::option::Option::Some(ref v) = self.one_of_float_value { - match v { - &KeyValue_oneof_one_of_float_value::float_value(v) => { - my_size += 9; - }, - }; - } - if let ::std::option::Option::Some(ref v) = self.one_of_bool_value { - match v { - &KeyValue_oneof_one_of_bool_value::bool_value(v) => { - my_size += 2; - }, - }; - } - 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.key.is_empty() { - os.write_string(1, &self.key)?; - } - if let ::std::option::Option::Some(ref v) = self.one_of_str_value { - match v { - &KeyValue_oneof_one_of_str_value::str_value(ref v) => { - os.write_string(2, v)?; - }, - }; - } - if let ::std::option::Option::Some(ref v) = self.one_of_int_value { - match v { - &KeyValue_oneof_one_of_int_value::int_value(v) => { - os.write_int64(3, v)?; - }, - }; - } - if let ::std::option::Option::Some(ref v) = self.one_of_float_value { - match v { - &KeyValue_oneof_one_of_float_value::float_value(v) => { - os.write_double(4, v)?; - }, - }; - } - if let ::std::option::Option::Some(ref v) = self.one_of_bool_value { - match v { - &KeyValue_oneof_one_of_bool_value::bool_value(v) => { - os.write_bool(5, v)?; - }, - }; - } - 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) -> ::std::boxed::Box { - self - } - - fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { - Self::descriptor_static() - } - - fn new() -> KeyValue { - KeyValue::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::ProtobufTypeString>( - "key", - |m: &KeyValue| { &m.key }, - |m: &mut KeyValue| { &mut m.key }, - )); - fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>( - "str_value", - KeyValue::has_str_value, - KeyValue::get_str_value, - )); - fields.push(::protobuf::reflect::accessor::make_singular_i64_accessor::<_>( - "int_value", - KeyValue::has_int_value, - KeyValue::get_int_value, - )); - fields.push(::protobuf::reflect::accessor::make_singular_f64_accessor::<_>( - "float_value", - KeyValue::has_float_value, - KeyValue::get_float_value, - )); - fields.push(::protobuf::reflect::accessor::make_singular_bool_accessor::<_>( - "bool_value", - KeyValue::has_bool_value, - KeyValue::get_bool_value, - )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "KeyValue", - fields, - file_descriptor_proto() - ) - }) - } - - fn default_instance() -> &'static KeyValue { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(KeyValue::new) - } -} - -impl ::protobuf::Clear for KeyValue { - fn clear(&mut self) { - self.key.clear(); - self.one_of_str_value = ::std::option::Option::None; - self.one_of_int_value = ::std::option::Option::None; - self.one_of_float_value = ::std::option::Option::None; - self.one_of_bool_value = ::std::option::Option::None; - self.unknown_fields.clear(); - } -} - -impl ::std::fmt::Debug for KeyValue { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - ::protobuf::text_format::fmt(self, f) - } -} - -impl ::protobuf::reflect::ProtobufValue for KeyValue { - fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { - ::protobuf::reflect::ReflectValueRef::Message(self) - } -} - -static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x08kv.proto\"\xf1\x01\n\x08KeyValue\x12\x10\n\x03key\x18\x01\x20\x01(\ - \tR\x03key\x12\x1d\n\tstr_value\x18\x02\x20\x01(\tH\0R\x08strValue\x12\ - \x1d\n\tint_value\x18\x03\x20\x01(\x03H\x01R\x08intValue\x12!\n\x0bfloat\ - _value\x18\x04\x20\x01(\x01H\x02R\nfloatValue\x12\x1f\n\nbool_value\x18\ - \x05\x20\x01(\x08H\x03R\tboolValueB\x12\n\x10one_of_str_valueB\x12\n\x10\ - one_of_int_valueB\x14\n\x12one_of_float_valueB\x13\n\x11one_of_bool_valu\ - eJ\xa9\x03\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\x08\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\x13\n\x0c\n\x05\x04\0\x02\0\ - \x05\x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\x0b\x0e\n\ - \x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x11\x12\n\x0b\n\x04\x04\0\x08\0\ - \x12\x03\x04\x044\n\x0c\n\x05\x04\0\x08\0\x01\x12\x03\x04\n\x1a\n\x0b\n\ - \x04\x04\0\x02\x01\x12\x03\x04\x1d2\n\x0c\n\x05\x04\0\x02\x01\x05\x12\ - \x03\x04\x1d#\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04$-\n\x0c\n\x05\ - \x04\0\x02\x01\x03\x12\x03\x0401\n\x0b\n\x04\x04\0\x08\x01\x12\x03\x05\ - \x043\n\x0c\n\x05\x04\0\x08\x01\x01\x12\x03\x05\n\x1a\n\x0b\n\x04\x04\0\ - \x02\x02\x12\x03\x05\x1d1\n\x0c\n\x05\x04\0\x02\x02\x05\x12\x03\x05\x1d\ - \"\n\x0c\n\x05\x04\0\x02\x02\x01\x12\x03\x05#,\n\x0c\n\x05\x04\0\x02\x02\ - \x03\x12\x03\x05/0\n\x0b\n\x04\x04\0\x08\x02\x12\x03\x06\x048\n\x0c\n\ - \x05\x04\0\x08\x02\x01\x12\x03\x06\n\x1c\n\x0b\n\x04\x04\0\x02\x03\x12\ - \x03\x06\x1f6\n\x0c\n\x05\x04\0\x02\x03\x05\x12\x03\x06\x1f%\n\x0c\n\x05\ - \x04\0\x02\x03\x01\x12\x03\x06&1\n\x0c\n\x05\x04\0\x02\x03\x03\x12\x03\ - \x0645\n\x0b\n\x04\x04\0\x08\x03\x12\x03\x07\x044\n\x0c\n\x05\x04\0\x08\ - \x03\x01\x12\x03\x07\n\x1b\n\x0b\n\x04\x04\0\x02\x04\x12\x03\x07\x1e2\n\ - \x0c\n\x05\x04\0\x02\x04\x05\x12\x03\x07\x1e\"\n\x0c\n\x05\x04\0\x02\x04\ - \x01\x12\x03\x07#-\n\x0c\n\x05\x04\0\x02\x04\x03\x12\x03\x0701b\x06proto\ - 3\ -"; - -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() - }) -} diff --git a/frontend/rust-lib/lib-infra/src/protobuf/proto/kv.proto b/frontend/rust-lib/lib-infra/src/protobuf/proto/kv.proto deleted file mode 100644 index 0644b43adc..0000000000 --- a/frontend/rust-lib/lib-infra/src/protobuf/proto/kv.proto +++ /dev/null @@ -1,9 +0,0 @@ -syntax = "proto3"; - -message KeyValue { - string key = 1; - oneof one_of_str_value { string str_value = 2; }; - oneof one_of_int_value { int64 int_value = 3; }; - oneof one_of_float_value { double float_value = 4; }; - oneof one_of_bool_value { bool bool_value = 5; }; -} diff --git a/frontend/scripts/flowy-tool/src/util/file.rs b/frontend/scripts/flowy-tool/src/util/file.rs index 95197393e0..8a9f93f8a2 100644 --- a/frontend/scripts/flowy-tool/src/util/file.rs +++ b/frontend/scripts/flowy-tool/src/util/file.rs @@ -10,7 +10,7 @@ use tera::Tera; use walkdir::WalkDir; pub fn read_file(path: &str) -> Option { - let mut file = File::open(path).expect("Unable to open file"); + let mut file = File::open(path).expect(&format!("Unable to open file at {}", path)); let mut content = String::new(); match file.read_to_string(&mut content) { Ok(_) => Some(content), diff --git a/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs b/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs index f5f90b2b79..885b9475dd 100644 --- a/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs +++ b/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs @@ -16,13 +16,12 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { "HashMap" => TypeCategory::Map, "u8" => TypeCategory::Bytes, "String" => TypeCategory::Str, - "KeyValue" - | "NetworkState" - | "WorkspaceError" + "WorkspaceError" | "DocError" | "FFIRequest" | "FFIResponse" | "SubscribeObject" + | "NetworkState" | "UserError" | "QueryAppRequest" | "AppIdentifier" @@ -80,12 +79,12 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { | "UpdateUserRequest" | "UpdateUserParams" => TypeCategory::Protobuf, - "NetworkType" - | "WorkspaceEvent" + "WorkspaceEvent" | "WorkspaceNotification" | "ErrorCode" | "DocObservable" | "FFIStatusCode" + | "NetworkType" | "UserEvent" | "UserNotification" | "TrashType" From 31086ad4df1326aaf7854accc13baf8c41518ba7 Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 13 Dec 2021 13:55:44 +0800 Subject: [PATCH 24/39] add mock server --- backend/Cargo.lock | 8 +- backend/Cargo.toml | 1 + backend/src/services/doc/manager.rs | 50 ++++++++-- backend/src/services/doc/ws_actor.rs | 35 ++----- backend/src/services/user/user_default.rs | 4 +- frontend/rust-lib/Cargo.toml | 1 - frontend/rust-lib/flowy-core/Cargo.toml | 5 +- .../flowy-core/src/core/core_context.rs | 18 ++-- .../flowy-core/src/services/server/mod.rs | 32 +++--- .../src/services/server/server_api.rs | 62 ++++++------ .../src/services/server/server_api_mock.rs | 62 ++++++------ frontend/rust-lib/flowy-document/Cargo.toml | 4 +- .../src/services/doc/controller.rs | 6 +- .../src/services/doc/revision/cache.rs | 8 +- .../src/services/doc/revision/manager.rs | 4 +- .../flowy-document/src/services/server/mod.rs | 8 +- .../src/services/server/server_api.rs | 14 +-- .../src/services/server/server_api_mock.rs | 21 ++-- frontend/rust-lib/flowy-net/Cargo.toml | 3 +- frontend/rust-lib/flowy-sdk/Cargo.toml | 5 +- frontend/rust-lib/flowy-sdk/src/lib.rs | 2 +- frontend/rust-lib/flowy-test/Cargo.toml | 2 +- frontend/rust-lib/flowy-user/Cargo.toml | 11 ++- .../flowy-user/src/services/server/mod.rs | 31 +++--- .../src/services/server/server_api.rs | 22 ++--- .../src/services/server/server_api_mock.rs | 20 ++-- .../src/services/server/ws_local.rs | 43 ++++++++ .../flowy-user/src/services/server/ws_mock.rs | 98 +++++++++++-------- .../src/services/user/ws_manager.rs | 14 +-- frontend/scripts/flowy-tool/src/util/file.rs | 2 +- shared-lib/Cargo.lock | 4 +- shared-lib/Cargo.toml | 1 + shared-lib/backend-service/Cargo.toml | 1 + shared-lib/flowy-collaboration/Cargo.toml | 1 + .../src/core/document/default/READ_ME.json | 1 + .../document/default/mod.rs} | 8 +- .../src/core/document/document.rs | 22 +++-- .../src/core/document/mod.rs | 12 ++- .../src/core/sync/server_editor.rs | 23 +++-- shared-lib/flowy-collaboration/src/lib.rs | 1 - .../src/entities/view/view_create.rs | 4 +- .../lib-infra/Cargo.toml | 2 - .../lib-infra/src/future.rs | 37 ++++++- .../lib-infra/src/lib.rs | 0 .../lib-infra/src/retry/future.rs | 0 .../lib-infra/src/retry/mod.rs | 0 .../src/retry/strategy/exponential_backoff.rs | 0 .../src/retry/strategy/fixed_interval.rs | 0 .../lib-infra/src/retry/strategy/jitter.rs | 0 .../lib-infra/src/retry/strategy/mod.rs | 0 shared-lib/lib-ws/Cargo.toml | 2 +- 51 files changed, 423 insertions(+), 292 deletions(-) create mode 100644 frontend/rust-lib/flowy-user/src/services/server/ws_local.rs create mode 100644 shared-lib/flowy-collaboration/src/core/document/default/READ_ME.json rename shared-lib/flowy-collaboration/src/{user_default.rs => core/document/default/mod.rs} (54%) rename {frontend/rust-lib => shared-lib}/lib-infra/Cargo.toml (82%) rename {frontend/rust-lib => shared-lib}/lib-infra/src/future.rs (61%) rename {frontend/rust-lib => shared-lib}/lib-infra/src/lib.rs (100%) rename {frontend/rust-lib => shared-lib}/lib-infra/src/retry/future.rs (100%) rename {frontend/rust-lib => shared-lib}/lib-infra/src/retry/mod.rs (100%) rename {frontend/rust-lib => shared-lib}/lib-infra/src/retry/strategy/exponential_backoff.rs (100%) rename {frontend/rust-lib => shared-lib}/lib-infra/src/retry/strategy/fixed_interval.rs (100%) rename {frontend/rust-lib => shared-lib}/lib-infra/src/retry/strategy/jitter.rs (100%) rename {frontend/rust-lib => shared-lib}/lib-infra/src/retry/strategy/mod.rs (100%) diff --git a/backend/Cargo.lock b/backend/Cargo.lock index d800cbc4c5..95141607db 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -467,6 +467,7 @@ dependencies = [ "futures-util", "jsonwebtoken", "lazy_static", + "lib-infra", "lib-ot", "lib-ws", "linkify", @@ -505,6 +506,7 @@ dependencies = [ "bytes", "config", "derive_more", + "flowy-collaboration", "flowy-core-infra", "flowy-user-infra", "hyper", @@ -1205,6 +1207,7 @@ dependencies = [ "dashmap", "flowy-derive", "futures", + "lib-infra", "lib-ot", "log", "md5", @@ -1339,6 +1342,7 @@ dependencies = [ name = "flowy-net" version = "0.1.0" dependencies = [ + "bytes", "flowy-derive", "protobuf", ] @@ -1354,6 +1358,7 @@ dependencies = [ "flowy-core", "flowy-database", "flowy-document", + "flowy-net", "flowy-user", "futures-core", "lib-dispatch", @@ -1402,7 +1407,6 @@ dependencies = [ "derive_more", "diesel", "diesel_derives", - "flowy-collaboration", "flowy-database", "flowy-derive", "flowy-net", @@ -1954,11 +1958,9 @@ version = "0.1.0" dependencies = [ "bytes", "chrono", - "flowy-derive", "futures-core", "log", "pin-project 1.0.8", - "protobuf", "rand", "tokio", "uuid", diff --git a/backend/Cargo.toml b/backend/Cargo.toml index f6a7d9aa76..dc601fce18 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -64,6 +64,7 @@ flowy-core-infra = { path = "../shared-lib/flowy-core-infra" } flowy-collaboration = { path = "../shared-lib/flowy-collaboration" } lib-ws = { path = "../shared-lib/lib-ws" } lib-ot = { path = "../shared-lib/lib-ot" } +lib-infra = { path = "../shared-lib/lib-infra" } backend-service = { path = "../shared-lib/backend-service", features = ["http_server"] } ormx = { version = "0.7", features = ["postgres"]} diff --git a/backend/src/services/doc/manager.rs b/backend/src/services/doc/manager.rs index 749099b6a2..06c0c59a34 100644 --- a/backend/src/services/doc/manager.rs +++ b/backend/src/services/doc/manager.rs @@ -1,16 +1,23 @@ use crate::{ - services::doc::ws_actor::{DocWsActor, DocWsMsg}, + services::doc::{ + read_doc, + update_doc, + ws_actor::{DocWsActor, DocWsMsg}, + }, web_socket::{WsBizHandler, WsClientData}, }; use actix_web::web::Data; + use flowy_collaboration::{ core::sync::{ServerDocManager, ServerDocPersistence}, entities::doc::Doc, - errors::CollaborateResult, + errors::CollaborateError, + protobuf::{DocIdentifier, UpdateDocParams}, }; +use lib_infra::future::FutureResultSend; use lib_ot::rich_text::RichTextDelta; use sqlx::PgPool; -use std::sync::Arc; +use std::{convert::TryInto, sync::Arc}; use tokio::sync::{mpsc, oneshot}; pub struct DocumentCore { @@ -21,7 +28,7 @@ pub struct DocumentCore { impl DocumentCore { pub fn new(pg_pool: Data) -> Self { - let manager = Arc::new(ServerDocManager::new(Arc::new(DocPersistenceImpl()))); + let manager = Arc::new(ServerDocManager::new(Arc::new(DocPersistenceImpl(pg_pool.clone())))); let (ws_sender, rx) = mpsc::channel(100); let actor = DocWsActor::new(rx, manager.clone()); tokio::task::spawn(actor.run()); @@ -57,11 +64,38 @@ impl WsBizHandler for DocumentCore { } } -struct DocPersistenceImpl(); +struct DocPersistenceImpl(Data); impl ServerDocPersistence for DocPersistenceImpl { - fn create_doc(&self, doc_id: &str, delta: RichTextDelta) -> CollaborateResult<()> { unimplemented!() } + fn update_doc(&self, doc_id: &str, rev_id: i64, delta: RichTextDelta) -> FutureResultSend<(), CollaborateError> { + let pg_pool = self.0.clone(); + let mut params = UpdateDocParams::new(); + let doc_json = delta.to_json(); + params.set_doc_id(doc_id.to_string()); + params.set_data(doc_json); + params.set_rev_id(rev_id); - fn update_doc(&self, doc_id: &str, delta: RichTextDelta) -> CollaborateResult<()> { unimplemented!() } + FutureResultSend::new(async move { + let _ = update_doc(pg_pool.get_ref(), params) + .await + .map_err(|e| CollaborateError::internal().context(e))?; + Ok(()) + }) + } - fn read_doc(&self, doc_id: &str) -> CollaborateResult { unimplemented!() } + fn read_doc(&self, doc_id: &str) -> FutureResultSend { + let params = DocIdentifier { + doc_id: doc_id.to_string(), + ..Default::default() + }; + let pg_pool = self.0.clone(); + FutureResultSend::new(async move { + let mut pb_doc = read_doc(pg_pool.get_ref(), params) + .await + .map_err(|e| CollaborateError::internal().context(e))?; + let doc = (&mut pb_doc) + .try_into() + .map_err(|e| CollaborateError::internal().context(e))?; + Ok(doc) + }) + } } diff --git a/backend/src/services/doc/ws_actor.rs b/backend/src/services/doc/ws_actor.rs index 0e851b5f8e..e93d59a1fc 100644 --- a/backend/src/services/doc/ws_actor.rs +++ b/backend/src/services/doc/ws_actor.rs @@ -1,6 +1,6 @@ use crate::{ services::{ - doc::{editor::ServerDocUser, read_doc}, + doc::editor::ServerDocUser, util::{md5, parse_from_bytes}, }, web_socket::{entities::Socket, WsClientData, WsUser}, @@ -11,7 +11,7 @@ use async_stream::stream; use backend_service::errors::{internal_error, Result as DocResult, ServerError}; use flowy_collaboration::{ core::sync::{OpenDocHandle, ServerDocManager}, - protobuf::{DocIdentifier, NewDocUser, WsDataType, WsDocumentData}, + protobuf::{NewDocUser, WsDataType, WsDocumentData}, }; use futures::stream::StreamExt; use lib_ot::protobuf::Revision; @@ -128,30 +128,13 @@ impl DocWsActor { Ok(()) } - async fn get_doc_handle(&self, doc_id: &str, pg_pool: Data) -> Option> { - match self.doc_manager.get(doc_id) { - Some(edit_doc) => Some(edit_doc), - None => { - let params = DocIdentifier { - doc_id: doc_id.to_string(), - ..Default::default() - }; - - let f = || async { - let mut pb_doc = read_doc(pg_pool.get_ref(), params).await?; - let doc = (&mut pb_doc).try_into().map_err(internal_error)?; - self.doc_manager.cache(doc).await.map_err(internal_error)?; - let handler = self.doc_manager.get(doc_id); - Ok::>, ServerError>(handler) - }; - - match f().await { - Ok(handler) => handler, - Err(e) => { - log::error!("{}", e); - None - }, - } + async fn get_doc_handle(&self, doc_id: &str, _pg_pool: Data) -> Option> { + match self.doc_manager.get(doc_id).await { + Ok(Some(edit_doc)) => Some(edit_doc), + Ok(None) => None, + Err(e) => { + log::error!("{}", e); + None }, } } diff --git a/backend/src/services/user/user_default.rs b/backend/src/services/user/user_default.rs index 380e77e0af..477cc600fb 100644 --- a/backend/src/services/user/user_default.rs +++ b/backend/src/services/user/user_default.rs @@ -9,7 +9,7 @@ use crate::{ use crate::services::view::{create_view_with_args, sql_builder::NewViewSqlBuilder}; use backend_service::errors::ServerError; use chrono::Utc; -use flowy_collaboration::user_default::doc_initial_string; +use flowy_collaboration::core::document::default::initial_string; use flowy_core_infra::protobuf::Workspace; use std::convert::TryInto; @@ -42,7 +42,7 @@ pub async fn create_default_workspace( for view in views.take_items() { let (sql, args, view) = NewViewSqlBuilder::from_view(view)?.build()?; - let _ = create_view_with_args(transaction, sql, args, view, doc_initial_string()).await?; + let _ = create_view_with_args(transaction, sql, args, view, initial_string()).await?; } } Ok(workspace) diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index 2800206223..ebbed5a541 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -2,7 +2,6 @@ members = [ "lib-dispatch", "lib-log", - "lib-infra", "flowy-net", "flowy-sdk", "dart-ffi", diff --git a/frontend/rust-lib/flowy-core/Cargo.toml b/frontend/rust-lib/flowy-core/Cargo.toml index 33a4e280a0..6a464bd687 100644 --- a/frontend/rust-lib/flowy-core/Cargo.toml +++ b/frontend/rust-lib/flowy-core/Cargo.toml @@ -12,14 +12,13 @@ flowy-derive = { path = "../../../shared-lib/flowy-derive" } lib-ot = { path = "../../../shared-lib/lib-ot" } lib-sqlite = { path = "../../../shared-lib/lib-sqlite" } backend-service = { path = "../../../shared-lib/backend-service" } - +lib-infra = { path = "../../../shared-lib/lib-infra" } flowy-document = { path = "../flowy-document" } flowy-database = { path = "../flowy-database" } flowy-net = { path = "../flowy-net" } dart-notify = { path = "../dart-notify" } lib-dispatch = { path = "../lib-dispatch" } -lib-infra = { path = "../lib-infra" } parking_lot = "0.11" @@ -41,7 +40,7 @@ derive_more = {version = "0.99", features = ["display"]} bincode = { version = "1.3"} tracing = { version = "0.1", features = ["log"] } bytes = { version = "1.0" } -crossbeam = "0.8.1" +crossbeam = "0.8" crossbeam-utils = "0.8" chrono = "0.4" diff --git a/frontend/rust-lib/flowy-core/src/core/core_context.rs b/frontend/rust-lib/flowy-core/src/core/core_context.rs index 7f5236b011..0f94565e39 100644 --- a/frontend/rust-lib/flowy-core/src/core/core_context.rs +++ b/frontend/rust-lib/flowy-core/src/core/core_context.rs @@ -1,3 +1,13 @@ +use std::{collections::HashMap, sync::Arc}; + +use chrono::Utc; +use lazy_static::lazy_static; +use parking_lot::RwLock; + +use flowy_collaboration::{core::document::default::initial_read_me, entities::doc::DocDelta}; +use flowy_core_infra::user_default; +use flowy_net::entities::NetworkType; + use crate::{ entities::workspace::RepeatedWorkspace, errors::{WorkspaceError, WorkspaceResult}, @@ -5,13 +15,7 @@ use crate::{ notify::{send_dart_notification, WorkspaceNotification}, services::{server::Server, AppController, TrashController, ViewController, WorkspaceController}, }; -use chrono::Utc; -use flowy_collaboration::{entities::doc::DocDelta, user_default::initial_read_me}; -use flowy_core_infra::user_default; -use flowy_net::entities::NetworkType; -use lazy_static::lazy_static; -use parking_lot::RwLock; -use std::{collections::HashMap, sync::Arc}; + lazy_static! { static ref INIT_WORKSPACE: RwLock> = RwLock::new(HashMap::new()); } diff --git a/frontend/rust-lib/flowy-core/src/services/server/mod.rs b/frontend/rust-lib/flowy-core/src/services/server/mod.rs index 08e231b80d..940ba5d6d3 100644 --- a/frontend/rust-lib/flowy-core/src/services/server/mod.rs +++ b/frontend/rust-lib/flowy-core/src/services/server/mod.rs @@ -15,7 +15,7 @@ use crate::{ errors::WorkspaceError, }; use backend_service::configuration::ClientServerConfiguration; -use lib_infra::future::ResultFuture; +use lib_infra::future::FutureResult; use std::sync::Arc; pub(crate) type Server = Arc; @@ -24,42 +24,42 @@ pub trait WorkspaceServerAPI { fn init(&self); // Workspace - fn create_workspace(&self, token: &str, params: CreateWorkspaceParams) -> ResultFuture; + fn create_workspace(&self, token: &str, params: CreateWorkspaceParams) -> FutureResult; fn read_workspace( &self, token: &str, params: WorkspaceIdentifier, - ) -> ResultFuture; + ) -> FutureResult; - fn update_workspace(&self, token: &str, params: UpdateWorkspaceParams) -> ResultFuture<(), WorkspaceError>; + fn update_workspace(&self, token: &str, params: UpdateWorkspaceParams) -> FutureResult<(), WorkspaceError>; - fn delete_workspace(&self, token: &str, params: WorkspaceIdentifier) -> ResultFuture<(), WorkspaceError>; + fn delete_workspace(&self, token: &str, params: WorkspaceIdentifier) -> FutureResult<(), WorkspaceError>; // View - fn create_view(&self, token: &str, params: CreateViewParams) -> ResultFuture; + fn create_view(&self, token: &str, params: CreateViewParams) -> FutureResult; - fn read_view(&self, token: &str, params: ViewIdentifier) -> ResultFuture, WorkspaceError>; + fn read_view(&self, token: &str, params: ViewIdentifier) -> FutureResult, WorkspaceError>; - fn delete_view(&self, token: &str, params: ViewIdentifiers) -> ResultFuture<(), WorkspaceError>; + fn delete_view(&self, token: &str, params: ViewIdentifiers) -> FutureResult<(), WorkspaceError>; - fn update_view(&self, token: &str, params: UpdateViewParams) -> ResultFuture<(), WorkspaceError>; + fn update_view(&self, token: &str, params: UpdateViewParams) -> FutureResult<(), WorkspaceError>; // App - fn create_app(&self, token: &str, params: CreateAppParams) -> ResultFuture; + fn create_app(&self, token: &str, params: CreateAppParams) -> FutureResult; - fn read_app(&self, token: &str, params: AppIdentifier) -> ResultFuture, WorkspaceError>; + fn read_app(&self, token: &str, params: AppIdentifier) -> FutureResult, WorkspaceError>; - fn update_app(&self, token: &str, params: UpdateAppParams) -> ResultFuture<(), WorkspaceError>; + fn update_app(&self, token: &str, params: UpdateAppParams) -> FutureResult<(), WorkspaceError>; - fn delete_app(&self, token: &str, params: AppIdentifier) -> ResultFuture<(), WorkspaceError>; + fn delete_app(&self, token: &str, params: AppIdentifier) -> FutureResult<(), WorkspaceError>; // Trash - fn create_trash(&self, token: &str, params: TrashIdentifiers) -> ResultFuture<(), WorkspaceError>; + fn create_trash(&self, token: &str, params: TrashIdentifiers) -> FutureResult<(), WorkspaceError>; - fn delete_trash(&self, token: &str, params: TrashIdentifiers) -> ResultFuture<(), WorkspaceError>; + fn delete_trash(&self, token: &str, params: TrashIdentifiers) -> FutureResult<(), WorkspaceError>; - fn read_trash(&self, token: &str) -> ResultFuture; + fn read_trash(&self, token: &str) -> FutureResult; } pub(crate) fn construct_workspace_server( diff --git a/frontend/rust-lib/flowy-core/src/services/server/server_api.rs b/frontend/rust-lib/flowy-core/src/services/server/server_api.rs index 2d0efbc892..68fadd59af 100644 --- a/frontend/rust-lib/flowy-core/src/services/server/server_api.rs +++ b/frontend/rust-lib/flowy-core/src/services/server/server_api.rs @@ -11,7 +11,7 @@ use crate::{ }; use backend_service::{configuration::ClientServerConfiguration, middleware::*, workspace_request::*}; use flowy_core_infra::errors::ErrorCode; -use lib_infra::future::ResultFuture; +use lib_infra::future::FutureResult; pub struct WorkspaceHttpServer { config: ClientServerConfiguration, @@ -34,10 +34,10 @@ impl WorkspaceServerAPI for WorkspaceHttpServer { }); } - fn create_workspace(&self, token: &str, params: CreateWorkspaceParams) -> ResultFuture { + fn create_workspace(&self, token: &str, params: CreateWorkspaceParams) -> FutureResult { let token = token.to_owned(); let url = self.config.workspace_url(); - ResultFuture::new(async move { + FutureResult::new(async move { let workspace = create_workspace_request(&token, params, &url).await?; Ok(workspace) }) @@ -47,127 +47,127 @@ impl WorkspaceServerAPI for WorkspaceHttpServer { &self, token: &str, params: WorkspaceIdentifier, - ) -> ResultFuture { + ) -> FutureResult { let token = token.to_owned(); let url = self.config.workspace_url(); - ResultFuture::new(async move { + FutureResult::new(async move { let repeated_workspace = read_workspaces_request(&token, params, &url).await?; Ok(repeated_workspace) }) } - fn update_workspace(&self, token: &str, params: UpdateWorkspaceParams) -> ResultFuture<(), WorkspaceError> { + fn update_workspace(&self, token: &str, params: UpdateWorkspaceParams) -> FutureResult<(), WorkspaceError> { let token = token.to_owned(); let url = self.config.workspace_url(); - ResultFuture::new(async move { + FutureResult::new(async move { let _ = update_workspace_request(&token, params, &url).await?; Ok(()) }) } - fn delete_workspace(&self, token: &str, params: WorkspaceIdentifier) -> ResultFuture<(), WorkspaceError> { + fn delete_workspace(&self, token: &str, params: WorkspaceIdentifier) -> FutureResult<(), WorkspaceError> { let token = token.to_owned(); let url = self.config.workspace_url(); - ResultFuture::new(async move { + FutureResult::new(async move { let _ = delete_workspace_request(&token, params, &url).await?; Ok(()) }) } - fn create_view(&self, token: &str, params: CreateViewParams) -> ResultFuture { + fn create_view(&self, token: &str, params: CreateViewParams) -> FutureResult { let token = token.to_owned(); let url = self.config.view_url(); - ResultFuture::new(async move { + FutureResult::new(async move { let view = create_view_request(&token, params, &url).await?; Ok(view) }) } - fn read_view(&self, token: &str, params: ViewIdentifier) -> ResultFuture, WorkspaceError> { + fn read_view(&self, token: &str, params: ViewIdentifier) -> FutureResult, WorkspaceError> { let token = token.to_owned(); let url = self.config.view_url(); - ResultFuture::new(async move { + FutureResult::new(async move { let view = read_view_request(&token, params, &url).await?; Ok(view) }) } - fn delete_view(&self, token: &str, params: ViewIdentifiers) -> ResultFuture<(), WorkspaceError> { + fn delete_view(&self, token: &str, params: ViewIdentifiers) -> FutureResult<(), WorkspaceError> { let token = token.to_owned(); let url = self.config.view_url(); - ResultFuture::new(async move { + FutureResult::new(async move { let _ = delete_view_request(&token, params, &url).await?; Ok(()) }) } - fn update_view(&self, token: &str, params: UpdateViewParams) -> ResultFuture<(), WorkspaceError> { + fn update_view(&self, token: &str, params: UpdateViewParams) -> FutureResult<(), WorkspaceError> { let token = token.to_owned(); let url = self.config.view_url(); - ResultFuture::new(async move { + FutureResult::new(async move { let _ = update_view_request(&token, params, &url).await?; Ok(()) }) } - fn create_app(&self, token: &str, params: CreateAppParams) -> ResultFuture { + fn create_app(&self, token: &str, params: CreateAppParams) -> FutureResult { let token = token.to_owned(); let url = self.config.app_url(); - ResultFuture::new(async move { + FutureResult::new(async move { let app = create_app_request(&token, params, &url).await?; Ok(app) }) } - fn read_app(&self, token: &str, params: AppIdentifier) -> ResultFuture, WorkspaceError> { + fn read_app(&self, token: &str, params: AppIdentifier) -> FutureResult, WorkspaceError> { let token = token.to_owned(); let url = self.config.app_url(); - ResultFuture::new(async move { + FutureResult::new(async move { let app = read_app_request(&token, params, &url).await?; Ok(app) }) } - fn update_app(&self, token: &str, params: UpdateAppParams) -> ResultFuture<(), WorkspaceError> { + fn update_app(&self, token: &str, params: UpdateAppParams) -> FutureResult<(), WorkspaceError> { let token = token.to_owned(); let url = self.config.app_url(); - ResultFuture::new(async move { + FutureResult::new(async move { let _ = update_app_request(&token, params, &url).await?; Ok(()) }) } - fn delete_app(&self, token: &str, params: AppIdentifier) -> ResultFuture<(), WorkspaceError> { + fn delete_app(&self, token: &str, params: AppIdentifier) -> FutureResult<(), WorkspaceError> { let token = token.to_owned(); let url = self.config.app_url(); - ResultFuture::new(async move { + FutureResult::new(async move { let _ = delete_app_request(&token, params, &url).await?; Ok(()) }) } - fn create_trash(&self, token: &str, params: TrashIdentifiers) -> ResultFuture<(), WorkspaceError> { + fn create_trash(&self, token: &str, params: TrashIdentifiers) -> FutureResult<(), WorkspaceError> { let token = token.to_owned(); let url = self.config.trash_url(); - ResultFuture::new(async move { + FutureResult::new(async move { let _ = create_trash_request(&token, params, &url).await?; Ok(()) }) } - fn delete_trash(&self, token: &str, params: TrashIdentifiers) -> ResultFuture<(), WorkspaceError> { + fn delete_trash(&self, token: &str, params: TrashIdentifiers) -> FutureResult<(), WorkspaceError> { let token = token.to_owned(); let url = self.config.trash_url(); - ResultFuture::new(async move { + FutureResult::new(async move { let _ = delete_trash_request(&token, params, &url).await?; Ok(()) }) } - fn read_trash(&self, token: &str) -> ResultFuture { + fn read_trash(&self, token: &str) -> FutureResult { let token = token.to_owned(); let url = self.config.trash_url(); - ResultFuture::new(async move { + FutureResult::new(async move { let repeated_trash = read_trash_request(&token, &url).await?; Ok(repeated_trash) }) diff --git a/frontend/rust-lib/flowy-core/src/services/server/server_api_mock.rs b/frontend/rust-lib/flowy-core/src/services/server/server_api_mock.rs index 7a3093472f..336d0d9c53 100644 --- a/frontend/rust-lib/flowy-core/src/services/server/server_api_mock.rs +++ b/frontend/rust-lib/flowy-core/src/services/server/server_api_mock.rs @@ -8,14 +8,14 @@ use crate::{ errors::WorkspaceError, services::server::WorkspaceServerAPI, }; -use lib_infra::{future::ResultFuture, timestamp, uuid}; +use lib_infra::{future::FutureResult, timestamp, uuid}; pub struct WorkspaceServerMock {} impl WorkspaceServerAPI for WorkspaceServerMock { fn init(&self) {} - fn create_workspace(&self, _token: &str, params: CreateWorkspaceParams) -> ResultFuture { + fn create_workspace(&self, _token: &str, params: CreateWorkspaceParams) -> FutureResult { let time = timestamp(); let workspace = Workspace { id: uuid(), @@ -26,29 +26,29 @@ impl WorkspaceServerAPI for WorkspaceServerMock { create_time: time, }; - ResultFuture::new(async { Ok(workspace) }) + FutureResult::new(async { Ok(workspace) }) } fn read_workspace( &self, _token: &str, _params: WorkspaceIdentifier, - ) -> ResultFuture { - ResultFuture::new(async { + ) -> FutureResult { + FutureResult::new(async { let repeated_workspace = RepeatedWorkspace { items: vec![] }; Ok(repeated_workspace) }) } - fn update_workspace(&self, _token: &str, _params: UpdateWorkspaceParams) -> ResultFuture<(), WorkspaceError> { - ResultFuture::new(async { Ok(()) }) + fn update_workspace(&self, _token: &str, _params: UpdateWorkspaceParams) -> FutureResult<(), WorkspaceError> { + FutureResult::new(async { Ok(()) }) } - fn delete_workspace(&self, _token: &str, _params: WorkspaceIdentifier) -> ResultFuture<(), WorkspaceError> { - ResultFuture::new(async { Ok(()) }) + fn delete_workspace(&self, _token: &str, _params: WorkspaceIdentifier) -> FutureResult<(), WorkspaceError> { + FutureResult::new(async { Ok(()) }) } - fn create_view(&self, _token: &str, params: CreateViewParams) -> ResultFuture { + fn create_view(&self, _token: &str, params: CreateViewParams) -> FutureResult { let time = timestamp(); let view = View { id: uuid(), @@ -61,22 +61,22 @@ impl WorkspaceServerAPI for WorkspaceServerMock { modified_time: time, create_time: time, }; - ResultFuture::new(async { Ok(view) }) + FutureResult::new(async { Ok(view) }) } - fn read_view(&self, _token: &str, _params: ViewIdentifier) -> ResultFuture, WorkspaceError> { - ResultFuture::new(async { Ok(None) }) + fn read_view(&self, _token: &str, _params: ViewIdentifier) -> FutureResult, WorkspaceError> { + FutureResult::new(async { Ok(None) }) } - fn delete_view(&self, _token: &str, _params: ViewIdentifiers) -> ResultFuture<(), WorkspaceError> { - ResultFuture::new(async { Ok(()) }) + fn delete_view(&self, _token: &str, _params: ViewIdentifiers) -> FutureResult<(), WorkspaceError> { + FutureResult::new(async { Ok(()) }) } - fn update_view(&self, _token: &str, _params: UpdateViewParams) -> ResultFuture<(), WorkspaceError> { - ResultFuture::new(async { Ok(()) }) + fn update_view(&self, _token: &str, _params: UpdateViewParams) -> FutureResult<(), WorkspaceError> { + FutureResult::new(async { Ok(()) }) } - fn create_app(&self, _token: &str, params: CreateAppParams) -> ResultFuture { + fn create_app(&self, _token: &str, params: CreateAppParams) -> FutureResult { let time = timestamp(); let app = App { id: uuid(), @@ -88,31 +88,31 @@ impl WorkspaceServerAPI for WorkspaceServerMock { modified_time: time, create_time: time, }; - ResultFuture::new(async { Ok(app) }) + FutureResult::new(async { Ok(app) }) } - fn read_app(&self, _token: &str, _params: AppIdentifier) -> ResultFuture, WorkspaceError> { - ResultFuture::new(async { Ok(None) }) + fn read_app(&self, _token: &str, _params: AppIdentifier) -> FutureResult, WorkspaceError> { + FutureResult::new(async { Ok(None) }) } - fn update_app(&self, _token: &str, _params: UpdateAppParams) -> ResultFuture<(), WorkspaceError> { - ResultFuture::new(async { Ok(()) }) + fn update_app(&self, _token: &str, _params: UpdateAppParams) -> FutureResult<(), WorkspaceError> { + FutureResult::new(async { Ok(()) }) } - fn delete_app(&self, _token: &str, _params: AppIdentifier) -> ResultFuture<(), WorkspaceError> { - ResultFuture::new(async { Ok(()) }) + fn delete_app(&self, _token: &str, _params: AppIdentifier) -> FutureResult<(), WorkspaceError> { + FutureResult::new(async { Ok(()) }) } - fn create_trash(&self, _token: &str, _params: TrashIdentifiers) -> ResultFuture<(), WorkspaceError> { - ResultFuture::new(async { Ok(()) }) + fn create_trash(&self, _token: &str, _params: TrashIdentifiers) -> FutureResult<(), WorkspaceError> { + FutureResult::new(async { Ok(()) }) } - fn delete_trash(&self, _token: &str, _params: TrashIdentifiers) -> ResultFuture<(), WorkspaceError> { - ResultFuture::new(async { Ok(()) }) + fn delete_trash(&self, _token: &str, _params: TrashIdentifiers) -> FutureResult<(), WorkspaceError> { + FutureResult::new(async { Ok(()) }) } - fn read_trash(&self, _token: &str) -> ResultFuture { - ResultFuture::new(async { + fn read_trash(&self, _token: &str) -> FutureResult { + FutureResult::new(async { let repeated_trash = RepeatedTrash { items: vec![] }; Ok(repeated_trash) }) diff --git a/frontend/rust-lib/flowy-document/Cargo.toml b/frontend/rust-lib/flowy-document/Cargo.toml index ab7e0de92a..aeb078946c 100644 --- a/frontend/rust-lib/flowy-document/Cargo.toml +++ b/frontend/rust-lib/flowy-document/Cargo.toml @@ -12,10 +12,10 @@ flowy-derive = { path = "../../../shared-lib/flowy-derive" } 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" } -lib-infra = { path = "../lib-infra" } flowy-database = { path = "../flowy-database" } dart-notify = { path = "../dart-notify" } @@ -52,7 +52,7 @@ color-eyre = { version = "0.5", default-features = false } criterion = "0.3" rand = "0.7.3" env_logger = "0.8.2" - +flowy-user = { path = "../flowy-user", features = ["ws_mock"] } [features] http_server = [] diff --git a/frontend/rust-lib/flowy-document/src/services/doc/controller.rs b/frontend/rust-lib/flowy-document/src/services/doc/controller.rs index 019a30a250..82b999a4ff 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/controller.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/controller.rs @@ -14,7 +14,7 @@ use bytes::Bytes; use dashmap::DashMap; use flowy_collaboration::entities::doc::{Doc, DocDelta, DocIdentifier}; use flowy_database::ConnectionPool; -use lib_infra::future::ResultFuture; +use lib_infra::future::FutureResult; use std::sync::Arc; pub(crate) struct DocController { @@ -128,14 +128,14 @@ struct RevisionServerImpl { impl RevisionServer for RevisionServerImpl { #[tracing::instrument(level = "debug", skip(self))] - fn fetch_document(&self, doc_id: &str) -> ResultFuture { + fn fetch_document(&self, doc_id: &str) -> FutureResult { let params = DocIdentifier { doc_id: doc_id.to_string(), }; let server = self.server.clone(); let token = self.token.clone(); - ResultFuture::new(async move { + FutureResult::new(async move { match server.read_doc(&token, params).await? { None => Err(DocError::doc_not_found().context("Remote doesn't have this document")), Some(doc) => Ok(doc), diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs index 2ff4e5b09c..8ded5792c9 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs @@ -5,7 +5,7 @@ use crate::{ }; use flowy_collaboration::entities::doc::Doc; use flowy_database::ConnectionPool; -use lib_infra::future::ResultFuture; +use lib_infra::future::FutureResult; use lib_ot::{ core::{Operation, OperationTransformable}, revision::{RevState, RevType, Revision, RevisionDiskCache, RevisionMemoryCache, RevisionRange, RevisionRecord}, @@ -18,7 +18,7 @@ use tokio::{ }; pub trait RevisionIterator: Send + Sync { - fn next(&self) -> ResultFuture, DocError>; + fn next(&self) -> FutureResult, DocError>; } type DocRevisionDeskCache = dyn RevisionDiskCache; @@ -136,11 +136,11 @@ impl RevisionCache { } impl RevisionIterator for RevisionCache { - fn next(&self) -> ResultFuture, DocError> { + fn next(&self) -> FutureResult, DocError> { let memory_cache = self.memory_cache.clone(); let disk_cache = self.dish_cache.clone(); let doc_id = self.doc_id.clone(); - ResultFuture::new(async move { + FutureResult::new(async move { match memory_cache.front_revision().await { None => { // diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs index d7d74a47c5..af9a2c599c 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs @@ -6,7 +6,7 @@ use crate::{ }, }; use flowy_collaboration::{entities::doc::Doc, util::RevIdCounter}; -use lib_infra::future::ResultFuture; +use lib_infra::future::FutureResult; use lib_ot::{ core::OperationTransformable, revision::{RevId, RevType, Revision, RevisionRange}, @@ -15,7 +15,7 @@ use lib_ot::{ use std::sync::Arc; pub trait RevisionServer: Send + Sync { - fn fetch_document(&self, doc_id: &str) -> ResultFuture; + fn fetch_document(&self, doc_id: &str) -> FutureResult; } pub struct RevisionManager { diff --git a/frontend/rust-lib/flowy-document/src/services/server/mod.rs b/frontend/rust-lib/flowy-document/src/services/server/mod.rs index 501886ca16..864eed78ac 100644 --- a/frontend/rust-lib/flowy-document/src/services/server/mod.rs +++ b/frontend/rust-lib/flowy-document/src/services/server/mod.rs @@ -7,17 +7,17 @@ pub use server_api::*; use crate::errors::DocError; use backend_service::configuration::ClientServerConfiguration; use flowy_collaboration::entities::doc::{CreateDocParams, Doc, DocIdentifier, UpdateDocParams}; -use lib_infra::future::ResultFuture; +use lib_infra::future::FutureResult; pub use server_api_mock::*; use std::sync::Arc; pub(crate) type Server = Arc; pub trait DocumentServerAPI { - fn create_doc(&self, token: &str, params: CreateDocParams) -> ResultFuture<(), DocError>; + fn create_doc(&self, token: &str, params: CreateDocParams) -> FutureResult<(), DocError>; - fn read_doc(&self, token: &str, params: DocIdentifier) -> ResultFuture, DocError>; + fn read_doc(&self, token: &str, params: DocIdentifier) -> FutureResult, DocError>; - fn update_doc(&self, token: &str, params: UpdateDocParams) -> ResultFuture<(), DocError>; + fn update_doc(&self, token: &str, params: UpdateDocParams) -> FutureResult<(), DocError>; } pub(crate) fn construct_doc_server( diff --git a/frontend/rust-lib/flowy-document/src/services/server/server_api.rs b/frontend/rust-lib/flowy-document/src/services/server/server_api.rs index a55f70ba8d..c5a56aaa5c 100644 --- a/frontend/rust-lib/flowy-document/src/services/server/server_api.rs +++ b/frontend/rust-lib/flowy-document/src/services/server/server_api.rs @@ -1,7 +1,7 @@ use crate::{errors::DocError, services::server::DocumentServerAPI}; use backend_service::{configuration::*, request::HttpRequestBuilder}; use flowy_collaboration::entities::doc::{CreateDocParams, Doc, DocIdentifier, UpdateDocParams}; -use lib_infra::future::ResultFuture; +use lib_infra::future::FutureResult; pub struct DocServer { config: ClientServerConfiguration, @@ -12,22 +12,22 @@ impl DocServer { } impl DocumentServerAPI for DocServer { - fn create_doc(&self, token: &str, params: CreateDocParams) -> ResultFuture<(), DocError> { + fn create_doc(&self, token: &str, params: CreateDocParams) -> FutureResult<(), DocError> { let token = token.to_owned(); let url = self.config.doc_url(); - ResultFuture::new(async move { create_doc_request(&token, params, &url).await }) + FutureResult::new(async move { create_doc_request(&token, params, &url).await }) } - fn read_doc(&self, token: &str, params: DocIdentifier) -> ResultFuture, DocError> { + fn read_doc(&self, token: &str, params: DocIdentifier) -> FutureResult, DocError> { let token = token.to_owned(); let url = self.config.doc_url(); - ResultFuture::new(async move { read_doc_request(&token, params, &url).await }) + FutureResult::new(async move { read_doc_request(&token, params, &url).await }) } - fn update_doc(&self, token: &str, params: UpdateDocParams) -> ResultFuture<(), DocError> { + fn update_doc(&self, token: &str, params: UpdateDocParams) -> FutureResult<(), DocError> { let token = token.to_owned(); let url = self.config.doc_url(); - ResultFuture::new(async move { update_doc_request(&token, params, &url).await }) + FutureResult::new(async move { update_doc_request(&token, params, &url).await }) } } diff --git a/frontend/rust-lib/flowy-document/src/services/server/server_api_mock.rs b/frontend/rust-lib/flowy-document/src/services/server/server_api_mock.rs index 9e087ec0de..faf728f195 100644 --- a/frontend/rust-lib/flowy-document/src/services/server/server_api_mock.rs +++ b/frontend/rust-lib/flowy-document/src/services/server/server_api_mock.rs @@ -1,28 +1,29 @@ -use crate::{errors::DocError, services::server::DocumentServerAPI}; use flowy_collaboration::{ + core::document::default::initial_string, entities::doc::{CreateDocParams, Doc, DocIdentifier, UpdateDocParams}, - user_default::doc_initial_string, }; -use lib_infra::future::ResultFuture; +use lib_infra::future::FutureResult; + +use crate::{errors::DocError, services::server::DocumentServerAPI}; pub struct DocServerMock {} impl DocumentServerAPI for DocServerMock { - fn create_doc(&self, _token: &str, _params: CreateDocParams) -> ResultFuture<(), DocError> { - ResultFuture::new(async { Ok(()) }) + fn create_doc(&self, _token: &str, _params: CreateDocParams) -> FutureResult<(), DocError> { + FutureResult::new(async { Ok(()) }) } - fn read_doc(&self, _token: &str, params: DocIdentifier) -> ResultFuture, DocError> { + fn read_doc(&self, _token: &str, params: DocIdentifier) -> FutureResult, DocError> { let doc = Doc { id: params.doc_id, - data: doc_initial_string(), + data: initial_string(), rev_id: 0, base_rev_id: 0, }; - ResultFuture::new(async { Ok(Some(doc)) }) + FutureResult::new(async { Ok(Some(doc)) }) } - fn update_doc(&self, _token: &str, _params: UpdateDocParams) -> ResultFuture<(), DocError> { - ResultFuture::new(async { Ok(()) }) + fn update_doc(&self, _token: &str, _params: UpdateDocParams) -> FutureResult<(), DocError> { + FutureResult::new(async { Ok(()) }) } } diff --git a/frontend/rust-lib/flowy-net/Cargo.toml b/frontend/rust-lib/flowy-net/Cargo.toml index f86272efd5..df98fa11a2 100644 --- a/frontend/rust-lib/flowy-net/Cargo.toml +++ b/frontend/rust-lib/flowy-net/Cargo.toml @@ -7,4 +7,5 @@ edition = "2018" [dependencies] flowy-derive = { path = "../../../shared-lib/flowy-derive" } -protobuf = {version = "2.18.0"} \ No newline at end of file +protobuf = {version = "2.18.0"} +bytes = { version = "1.0" } \ No newline at end of file diff --git a/frontend/rust-lib/flowy-sdk/Cargo.toml b/frontend/rust-lib/flowy-sdk/Cargo.toml index 12a8df451a..d1dcd821f4 100644 --- a/frontend/rust-lib/flowy-sdk/Cargo.toml +++ b/frontend/rust-lib/flowy-sdk/Cargo.toml @@ -9,10 +9,11 @@ edition = "2018" lib-dispatch = { path = "../lib-dispatch" } lib-log = { path = "../lib-log" } flowy-user = { path = "../flowy-user" } +flowy-net = { path = "../flowy-net" } flowy-core = { path = "../flowy-core", default-features = false } flowy-database = { path = "../flowy-database" } flowy-document = { path = "../flowy-document" } -lib-infra = { path = "../lib-infra" } + tracing = { version = "0.1" } log = "0.4.14" futures-core = { version = "0.3", default-features = false } @@ -25,7 +26,7 @@ parking_lot = "0.11" flowy-collaboration = { path = "../../../shared-lib/flowy-collaboration" } lib-ws = { path = "../../../shared-lib/lib-ws" } backend-service = { path = "../../../shared-lib/backend-service" } - +lib-infra = { path = "../../../shared-lib/lib-infra" } [dev-dependencies] serde = { version = "1.0", features = ["derive"] } diff --git a/frontend/rust-lib/flowy-sdk/src/lib.rs b/frontend/rust-lib/flowy-sdk/src/lib.rs index 0e3a19bad2..d03c3911b7 100644 --- a/frontend/rust-lib/flowy-sdk/src/lib.rs +++ b/frontend/rust-lib/flowy-sdk/src/lib.rs @@ -5,12 +5,12 @@ use crate::deps_resolve::WorkspaceDepsResolver; use backend_service::configuration::ClientServerConfiguration; use flowy_core::{errors::WorkspaceError, module::init_core, prelude::CoreContext}; use flowy_document::module::FlowyDocument; +use flowy_net::entities::NetworkType; use flowy_user::{ prelude::UserStatus, services::user::{UserSession, UserSessionConfig}, }; use lib_dispatch::prelude::*; -use lib_infra::entities::network_state::NetworkType; use module::mk_modules; pub use module::*; use std::sync::{ diff --git a/frontend/rust-lib/flowy-test/Cargo.toml b/frontend/rust-lib/flowy-test/Cargo.toml index 8d2b68cd73..f9f9a681da 100644 --- a/frontend/rust-lib/flowy-test/Cargo.toml +++ b/frontend/rust-lib/flowy-test/Cargo.toml @@ -11,11 +11,11 @@ flowy-user = { path = "../flowy-user"} flowy-core = { path = "../flowy-core", default-features = false} flowy-document = { path = "../flowy-document"} lib-dispatch = { path = "../lib-dispatch" } -lib-infra = { path = "../lib-infra" } flowy-collaboration = { path = "../../../shared-lib/flowy-collaboration" } backend-service = { path = "../../../shared-lib/backend-service" } lib-ot = { path = "../../../shared-lib/lib-ot" } +lib-infra = { path = "../../../shared-lib/lib-infra" } serde = { version = "1.0", features = ["derive"] } serde_json = {version = "1.0"} diff --git a/frontend/rust-lib/flowy-user/Cargo.toml b/frontend/rust-lib/flowy-user/Cargo.toml index 5c2b70f1a7..13aed3c9f9 100644 --- a/frontend/rust-lib/flowy-user/Cargo.toml +++ b/frontend/rust-lib/flowy-user/Cargo.toml @@ -8,17 +8,21 @@ edition = "2018" [dependencies] flowy-user-infra = { path = "../../../shared-lib/flowy-user-infra" } backend-service = { path = "../../../shared-lib/backend-service" } -flowy-collaboration = { path = "../../../shared-lib/flowy-collaboration" } flowy-derive = { path = "../../../shared-lib/flowy-derive" } lib-ws = { path = "../../../shared-lib/lib-ws" } lib-sqlite = { path = "../../../shared-lib/lib-sqlite" } +lib-infra = { path = "../../../shared-lib/lib-infra" } + + +flowy-collaboration = { path = "../../../shared-lib/flowy-collaboration", optional = true} +lib-ot = { path = "../../../shared-lib/lib-ot", optional = true } derive_more = {version = "0.99", features = ["display"]} flowy-database = { path = "../flowy-database" } flowy-net = { path = "../flowy-net" } dart-notify = { path = "../dart-notify" } lib-dispatch = { path = "../lib-dispatch" } -lib-infra = { path = "../lib-infra" } + tracing = { version = "0.1", features = ["log"] } bytes = "1.0" @@ -47,4 +51,5 @@ futures = "0.3.15" serial_test = "0.5.1" [features] -http_server = [] \ No newline at end of file +http_server = [] +ws_mock = ["flowy-collaboration", "lib-ot"] \ No newline at end of file diff --git a/frontend/rust-lib/flowy-user/src/services/server/mod.rs b/frontend/rust-lib/flowy-user/src/services/server/mod.rs index 503399d16d..9bb2a9b889 100644 --- a/frontend/rust-lib/flowy-user/src/services/server/mod.rs +++ b/frontend/rust-lib/flowy-user/src/services/server/mod.rs @@ -1,8 +1,6 @@ mod server_api; mod server_api_mock; - -// #[cfg(feature = "http_server")] -pub(crate) mod ws_mock; +mod ws_local; pub use server_api::*; pub use server_api_mock::*; @@ -15,14 +13,14 @@ use crate::{ services::user::ws_manager::FlowyWebSocket, }; use backend_service::configuration::ClientServerConfiguration; -use lib_infra::future::ResultFuture; +use lib_infra::future::FutureResult; pub trait UserServerAPI { - fn sign_up(&self, params: SignUpParams) -> ResultFuture; - fn sign_in(&self, params: SignInParams) -> ResultFuture; - fn sign_out(&self, token: &str) -> ResultFuture<(), UserError>; - fn update_user(&self, token: &str, params: UpdateUserParams) -> ResultFuture<(), UserError>; - fn get_user(&self, token: &str) -> ResultFuture; + fn sign_up(&self, params: SignUpParams) -> FutureResult; + fn sign_in(&self, params: SignInParams) -> FutureResult; + 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; fn ws_addr(&self) -> String; } @@ -34,10 +32,11 @@ pub(crate) fn construct_user_server(config: &ClientServerConfiguration) -> Arc Arc { - if cfg!(debug_assertions) { - Arc::new(Arc::new(ws_mock::MockWebSocket::default())) - } else { - Arc::new(Arc::new(ws_mock::LocalWebSocket::default())) - } -} +#[cfg(feature = "ws_mock")] +mod ws_mock; + +#[cfg(not(feature = "ws_mock"))] +pub(crate) fn local_web_socket() -> Arc { Arc::new(Arc::new(ws_local::LocalWebSocket::default())) } + +#[cfg(feature = "ws_mock")] +pub(crate) fn local_web_socket() -> Arc { Arc::new(Arc::new(ws_mock::MockWebSocket::default())) } diff --git a/frontend/rust-lib/flowy-user/src/services/server/server_api.rs b/frontend/rust-lib/flowy-user/src/services/server/server_api.rs index 096836a509..72d54a7319 100644 --- a/frontend/rust-lib/flowy-user/src/services/server/server_api.rs +++ b/frontend/rust-lib/flowy-user/src/services/server/server_api.rs @@ -4,7 +4,7 @@ use crate::{ services::server::UserServerAPI, }; use backend_service::{configuration::*, user_request::*}; -use lib_infra::future::ResultFuture; +use lib_infra::future::FutureResult; pub struct UserHttpServer { config: ClientServerConfiguration, @@ -14,44 +14,44 @@ impl UserHttpServer { } impl UserServerAPI for UserHttpServer { - fn sign_up(&self, params: SignUpParams) -> ResultFuture { + fn sign_up(&self, params: SignUpParams) -> FutureResult { let url = self.config.sign_up_url(); - ResultFuture::new(async move { + FutureResult::new(async move { let resp = user_sign_up_request(params, &url).await?; Ok(resp) }) } - fn sign_in(&self, params: SignInParams) -> ResultFuture { + fn sign_in(&self, params: SignInParams) -> FutureResult { let url = self.config.sign_in_url(); - ResultFuture::new(async move { + FutureResult::new(async move { let resp = user_sign_in_request(params, &url).await?; Ok(resp) }) } - fn sign_out(&self, token: &str) -> ResultFuture<(), UserError> { + fn sign_out(&self, token: &str) -> FutureResult<(), UserError> { let token = token.to_owned(); let url = self.config.sign_out_url(); - ResultFuture::new(async move { + FutureResult::new(async move { let _ = user_sign_out_request(&token, &url).await; Ok(()) }) } - fn update_user(&self, token: &str, params: UpdateUserParams) -> ResultFuture<(), UserError> { + fn update_user(&self, token: &str, params: UpdateUserParams) -> FutureResult<(), UserError> { let token = token.to_owned(); let url = self.config.user_profile_url(); - ResultFuture::new(async move { + FutureResult::new(async move { let _ = update_user_profile_request(&token, params, &url).await?; Ok(()) }) } - fn get_user(&self, token: &str) -> ResultFuture { + fn get_user(&self, token: &str) -> FutureResult { let token = token.to_owned(); let url = self.config.user_profile_url(); - ResultFuture::new(async move { + FutureResult::new(async move { let profile = get_user_profile_request(&token, &url).await?; Ok(profile) }) diff --git a/frontend/rust-lib/flowy-user/src/services/server/server_api_mock.rs b/frontend/rust-lib/flowy-user/src/services/server/server_api_mock.rs index 53f18f366a..435020e856 100644 --- a/frontend/rust-lib/flowy-user/src/services/server/server_api_mock.rs +++ b/frontend/rust-lib/flowy-user/src/services/server/server_api_mock.rs @@ -4,16 +4,16 @@ use crate::{ }; use crate::services::server::UserServerAPI; -use lib_infra::{future::ResultFuture, uuid}; +use lib_infra::{future::FutureResult, uuid}; pub struct UserServerMock {} impl UserServerMock {} impl UserServerAPI for UserServerMock { - fn sign_up(&self, params: SignUpParams) -> ResultFuture { + fn sign_up(&self, params: SignUpParams) -> FutureResult { let uid = uuid(); - ResultFuture::new(async move { + FutureResult::new(async move { Ok(SignUpResponse { user_id: uid.clone(), name: params.name, @@ -23,9 +23,9 @@ impl UserServerAPI for UserServerMock { }) } - fn sign_in(&self, params: SignInParams) -> ResultFuture { + fn sign_in(&self, params: SignInParams) -> FutureResult { let user_id = uuid(); - ResultFuture::new(async { + FutureResult::new(async { Ok(SignInResponse { user_id: user_id.clone(), name: params.name, @@ -35,14 +35,14 @@ impl UserServerAPI for UserServerMock { }) } - fn sign_out(&self, _token: &str) -> ResultFuture<(), UserError> { ResultFuture::new(async { Ok(()) }) } + fn sign_out(&self, _token: &str) -> FutureResult<(), UserError> { FutureResult::new(async { Ok(()) }) } - fn update_user(&self, _token: &str, _params: UpdateUserParams) -> ResultFuture<(), UserError> { - ResultFuture::new(async { Ok(()) }) + fn update_user(&self, _token: &str, _params: UpdateUserParams) -> FutureResult<(), UserError> { + FutureResult::new(async { Ok(()) }) } - fn get_user(&self, _token: &str) -> ResultFuture { - ResultFuture::new(async { Ok(UserProfile::default()) }) + fn get_user(&self, _token: &str) -> FutureResult { + FutureResult::new(async { Ok(UserProfile::default()) }) } fn ws_addr(&self) -> String { "ws://localhost:8000/ws/".to_owned() } diff --git a/frontend/rust-lib/flowy-user/src/services/server/ws_local.rs b/frontend/rust-lib/flowy-user/src/services/server/ws_local.rs new file mode 100644 index 0000000000..418685a390 --- /dev/null +++ b/frontend/rust-lib/flowy-user/src/services/server/ws_local.rs @@ -0,0 +1,43 @@ +use crate::{ + errors::UserError, + services::user::ws_manager::{FlowyWebSocket, FlowyWsSender}, +}; +use lib_infra::future::FutureResult; +use lib_ws::{WsConnectState, WsMessage, WsMessageHandler}; +use std::sync::Arc; +use tokio::sync::{broadcast, broadcast::Receiver}; + +pub(crate) struct LocalWebSocket { + state_sender: broadcast::Sender, + ws_sender: broadcast::Sender, +} + +impl std::default::Default for LocalWebSocket { + fn default() -> Self { + let (state_sender, _) = broadcast::channel(16); + let (ws_sender, _) = broadcast::channel(16); + LocalWebSocket { + state_sender, + ws_sender, + } + } +} + +impl FlowyWebSocket for Arc { + fn start_connect(&self, _addr: String) -> FutureResult<(), UserError> { FutureResult::new(async { Ok(()) }) } + + fn conn_state_subscribe(&self) -> Receiver { self.state_sender.subscribe() } + + fn reconnect(&self, _count: usize) -> FutureResult<(), UserError> { FutureResult::new(async { Ok(()) }) } + + fn add_handler(&self, _handler: Arc) -> Result<(), UserError> { Ok(()) } + + fn ws_sender(&self) -> Result, UserError> { Ok(Arc::new(self.ws_sender.clone())) } +} + +impl FlowyWsSender for broadcast::Sender { + fn send(&self, msg: WsMessage) -> Result<(), UserError> { + let _ = self.send(msg); + Ok(()) + } +} diff --git a/frontend/rust-lib/flowy-user/src/services/server/ws_mock.rs b/frontend/rust-lib/flowy-user/src/services/server/ws_mock.rs index 705c999bc3..4828781d29 100644 --- a/frontend/rust-lib/flowy-user/src/services/server/ws_mock.rs +++ b/frontend/rust-lib/flowy-user/src/services/server/ws_mock.rs @@ -4,9 +4,19 @@ use crate::{ }; use bytes::Bytes; use dashmap::DashMap; -use flowy_collaboration::entities::ws::{WsDataType, WsDocumentData}; -use lib_infra::future::ResultFuture; +use flowy_collaboration::{ + core::sync::{ServerDocManager, ServerDocPersistence}, + entities::{ + doc::{Doc, NewDocUser}, + ws::{WsDataType, WsDocumentData}, + }, + errors::CollaborateError, +}; +use lazy_static::lazy_static; +use lib_infra::future::{FutureResult, FutureResultSend}; +use lib_ot::{revision::Revision, rich_text::RichTextDelta}; use lib_ws::{WsConnectState, WsMessage, WsMessageHandler, WsModule}; +use parking_lot::RwLock; use std::{convert::TryFrom, sync::Arc}; use tokio::sync::{broadcast, broadcast::Receiver}; @@ -33,33 +43,28 @@ impl MockWebSocket { } impl FlowyWebSocket for Arc { - fn start_connect(&self, _addr: String) -> ResultFuture<(), UserError> { + fn start_connect(&self, _addr: String) -> FutureResult<(), UserError> { let mut ws_receiver = self.ws_sender.subscribe(); let cloned_ws = self.clone(); tokio::spawn(async move { while let Ok(message) = ws_receiver.recv().await { let ws_data = WsDocumentData::try_from(Bytes::from(message.data.clone())).unwrap(); - match ws_data.ty { - WsDataType::Acked => {}, - WsDataType::PushRev => {}, - WsDataType::PullRev => {}, - WsDataType::Conflict => {}, - WsDataType::NewDocUser => {}, - } - - match cloned_ws.handlers.get(&message.module) { - None => log::error!("Can't find any handler for message: {:?}", message), - Some(handler) => handler.receive_message(message.clone()), + match DOC_SERVER.handle_ws_data(ws_data).await { + None => {}, + Some(new_ws_message) => match cloned_ws.handlers.get(&new_ws_message.module) { + None => log::error!("Can't find any handler for message: {:?}", new_ws_message), + Some(handler) => handler.receive_message(new_ws_message.clone()), + }, } } }); - ResultFuture::new(async { Ok(()) }) + FutureResult::new(async { Ok(()) }) } fn conn_state_subscribe(&self) -> Receiver { self.state_sender.subscribe() } - fn reconnect(&self, _count: usize) -> ResultFuture<(), UserError> { ResultFuture::new(async { Ok(()) }) } + fn reconnect(&self, _count: usize) -> FutureResult<(), UserError> { FutureResult::new(async { Ok(()) }) } fn add_handler(&self, handler: Arc) -> Result<(), UserError> { let source = handler.source(); @@ -73,37 +78,48 @@ impl FlowyWebSocket for Arc { fn ws_sender(&self) -> Result, UserError> { Ok(Arc::new(self.ws_sender.clone())) } } -impl FlowyWsSender for broadcast::Sender { - fn send(&self, msg: WsMessage) -> Result<(), UserError> { - let _ = self.send(msg).unwrap(); - Ok(()) - } +lazy_static! { + static ref DOC_SERVER: Arc = Arc::new(MockDocServer::default()); } -pub(crate) struct LocalWebSocket { - state_sender: broadcast::Sender, - ws_sender: broadcast::Sender, +struct MockDocServer { + pub manager: Arc, } -impl std::default::Default for LocalWebSocket { +impl std::default::Default for MockDocServer { fn default() -> Self { - let (state_sender, _) = broadcast::channel(16); - let (ws_sender, _) = broadcast::channel(16); - LocalWebSocket { - state_sender, - ws_sender, - } + let manager = Arc::new(ServerDocManager::new(Arc::new(MockDocServerPersistence {}))); + MockDocServer { manager } } } -impl FlowyWebSocket for Arc { - fn start_connect(&self, _addr: String) -> ResultFuture<(), UserError> { ResultFuture::new(async { Ok(()) }) } - - fn conn_state_subscribe(&self) -> Receiver { self.state_sender.subscribe() } - - fn reconnect(&self, _count: usize) -> ResultFuture<(), UserError> { ResultFuture::new(async { Ok(()) }) } - - fn add_handler(&self, _handler: Arc) -> Result<(), UserError> { Ok(()) } - - fn ws_sender(&self) -> Result, UserError> { Ok(Arc::new(self.ws_sender.clone())) } +impl MockDocServer { + async fn handle_ws_data(&self, ws_data: WsDocumentData) -> Option { + let bytes = Bytes::from(ws_data.data); + match ws_data.ty { + WsDataType::Acked => {}, + WsDataType::PushRev => { + let revision = Revision::try_from(bytes).unwrap(); + log::info!("{:?}", revision); + }, + WsDataType::PullRev => {}, + WsDataType::Conflict => {}, + WsDataType::NewDocUser => { + let new_doc_user = NewDocUser::try_from(bytes).unwrap(); + log::info!("{:?}", new_doc_user); + // NewDocUser + }, + } + None + } +} + +struct MockDocServerPersistence {} + +impl ServerDocPersistence for MockDocServerPersistence { + fn update_doc(&self, doc_id: &str, rev_id: i64, delta: RichTextDelta) -> FutureResultSend<(), CollaborateError> { + unimplemented!() + } + + fn read_doc(&self, doc_id: &str) -> FutureResultSend { unimplemented!() } } diff --git a/frontend/rust-lib/flowy-user/src/services/user/ws_manager.rs b/frontend/rust-lib/flowy-user/src/services/user/ws_manager.rs index c73cd94ee9..b29d0cf36d 100644 --- a/frontend/rust-lib/flowy-user/src/services/user/ws_manager.rs +++ b/frontend/rust-lib/flowy-user/src/services/user/ws_manager.rs @@ -1,16 +1,16 @@ use crate::errors::UserError; use flowy_net::entities::NetworkType; -use lib_infra::future::ResultFuture; +use lib_infra::future::FutureResult; use lib_ws::{WsConnectState, WsController, WsMessage, WsMessageHandler, WsSender}; use parking_lot::RwLock; use std::sync::Arc; use tokio::sync::{broadcast, broadcast::Receiver}; pub trait FlowyWebSocket: Send + Sync { - fn start_connect(&self, addr: String) -> ResultFuture<(), UserError>; + fn start_connect(&self, addr: String) -> FutureResult<(), UserError>; fn conn_state_subscribe(&self) -> broadcast::Receiver; - fn reconnect(&self, count: usize) -> ResultFuture<(), UserError>; + fn reconnect(&self, count: usize) -> FutureResult<(), UserError>; fn add_handler(&self, handler: Arc) -> Result<(), UserError>; fn ws_sender(&self) -> Result, UserError>; } @@ -115,9 +115,9 @@ impl std::default::Default for WsManager { } impl FlowyWebSocket for Arc { - fn start_connect(&self, addr: String) -> ResultFuture<(), UserError> { + fn start_connect(&self, addr: String) -> FutureResult<(), UserError> { let cloned_ws = self.clone(); - ResultFuture::new(async move { + FutureResult::new(async move { let _ = cloned_ws.start(addr).await?; Ok(()) }) @@ -125,9 +125,9 @@ impl FlowyWebSocket for Arc { fn conn_state_subscribe(&self) -> Receiver { self.state_subscribe() } - fn reconnect(&self, count: usize) -> ResultFuture<(), UserError> { + fn reconnect(&self, count: usize) -> FutureResult<(), UserError> { let cloned_ws = self.clone(); - ResultFuture::new(async move { + FutureResult::new(async move { let _ = cloned_ws.retry(count).await?; Ok(()) }) diff --git a/frontend/scripts/flowy-tool/src/util/file.rs b/frontend/scripts/flowy-tool/src/util/file.rs index 8a9f93f8a2..13fad7d4ce 100644 --- a/frontend/scripts/flowy-tool/src/util/file.rs +++ b/frontend/scripts/flowy-tool/src/util/file.rs @@ -10,7 +10,7 @@ use tera::Tera; use walkdir::WalkDir; pub fn read_file(path: &str) -> Option { - let mut file = File::open(path).expect(&format!("Unable to open file at {}", path)); + let mut file = File::open(path).unwrap_or_else(|_| panic!("Unable to open file at {}", path)); let mut content = String::new(); match file.read_to_string(&mut content) { Ok(_) => Some(content), diff --git a/shared-lib/Cargo.lock b/shared-lib/Cargo.lock index 34d88e6bf5..9c0c172f00 100644 --- a/shared-lib/Cargo.lock +++ b/shared-lib/Cargo.lock @@ -279,6 +279,7 @@ dependencies = [ "bytes", "config", "derive_more", + "flowy-collaboration", "flowy-core-infra", "flowy-user-infra", "hyper", @@ -688,6 +689,7 @@ dependencies = [ "dashmap", "flowy-derive", "futures", + "lib-infra", "lib-ot", "log", "md5", @@ -1132,11 +1134,9 @@ version = "0.1.0" dependencies = [ "bytes", "chrono", - "flowy-derive", "futures-core", "log", "pin-project", - "protobuf", "rand 0.8.4", "tokio", "uuid", diff --git a/shared-lib/Cargo.toml b/shared-lib/Cargo.toml index d9405a14a2..d48aa6532e 100644 --- a/shared-lib/Cargo.toml +++ b/shared-lib/Cargo.toml @@ -6,6 +6,7 @@ members = [ "lib-ot", "lib-ws", "lib-sqlite", + "lib-infra", "backend-service", "flowy-derive", "flowy-ast", diff --git a/shared-lib/backend-service/Cargo.toml b/shared-lib/backend-service/Cargo.toml index 2f7fae8454..4ac7621646 100644 --- a/shared-lib/backend-service/Cargo.toml +++ b/shared-lib/backend-service/Cargo.toml @@ -8,6 +8,7 @@ edition = "2018" [dependencies] flowy-core-infra = { path = "../flowy-core-infra" } flowy-user-infra = { path = "../flowy-user-infra" } +flowy-collaboration = { path = "../flowy-collaboration" } log = "0.4.14" lazy_static = "1.4.0" diff --git a/shared-lib/flowy-collaboration/Cargo.toml b/shared-lib/flowy-collaboration/Cargo.toml index 35d539f883..9962b7c031 100644 --- a/shared-lib/flowy-collaboration/Cargo.toml +++ b/shared-lib/flowy-collaboration/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" [dependencies] lib-ot = { path = "../lib-ot" } +lib-infra = { path = "../lib-infra" } flowy-derive = { path = "../flowy-derive" } protobuf = {version = "2.18.0"} bytes = "1.0" diff --git a/shared-lib/flowy-collaboration/src/core/document/default/READ_ME.json b/shared-lib/flowy-collaboration/src/core/document/default/READ_ME.json new file mode 100644 index 0000000000..bb53eff10e --- /dev/null +++ b/shared-lib/flowy-collaboration/src/core/document/default/READ_ME.json @@ -0,0 +1 @@ +[{"insert":"\n👋 Welcome to AppFlowy!"},{"insert":"\n","attributes":{"header":1}},{"insert":"\nHere are the basics"},{"insert":"\n","attributes":{"header":2}},{"insert":"Click anywhere and just start typing"},{"insert":"\n","attributes":{"list":"unchecked"}},{"insert":"Highlight","attributes":{"background":"#fff2cd"}},{"insert":" any text, and use the menu at the bottom to "},{"insert":"style","attributes":{"italic":true}},{"insert":" "},{"insert":"your","attributes":{"bold":true}},{"insert":" "},{"insert":"writing","attributes":{"underline":true}},{"insert":" "},{"insert":"however","attributes":{"code":true}},{"insert":" "},{"insert":"you","attributes":{"strike":true}},{"insert":" "},{"insert":"like","attributes":{"background":"#e8e0ff"}},{"insert":"\n","attributes":{"list":"unchecked"}},{"insert":"Click "},{"insert":"+ New Page","attributes":{"background":"#defff1","bold":true}},{"insert":" button at the bottom of your sidebar to add a new page"},{"insert":"\n","attributes":{"list":"unchecked"}},{"insert":"Click the "},{"insert":"'","attributes":{"background":"#defff1"}},{"insert":"+'","attributes":{"background":"#defff1","bold":true}},{"insert":" next to any page title in the sidebar to quickly add a new subpage"},{"insert":"\n","attributes":{"list":"unchecked"}},{"insert":"\nHave a question? "},{"insert":"\n","attributes":{"header":2}},{"insert":"Click the "},{"insert":"'?'","attributes":{"background":"#defff1","bold":true}},{"insert":" at the bottom right for help and support.\n\nLike AppFlowy? Follow us:"},{"insert":"\n","attributes":{"header":2}},{"insert":"GitHub: https://github.com/AppFlowy-IO/appflowy"},{"insert":"\n","attributes":{"blockquote":true}},{"insert":"Twitter: https://twitter.com/appflowy"},{"insert":"\n","attributes":{"blockquote":true}},{"insert":"Newsletter: https://www.appflowy.io/blog"},{"insert":"\n","attributes":{"blockquote":true}}] \ No newline at end of file diff --git a/shared-lib/flowy-collaboration/src/user_default.rs b/shared-lib/flowy-collaboration/src/core/document/default/mod.rs similarity index 54% rename from shared-lib/flowy-collaboration/src/user_default.rs rename to shared-lib/flowy-collaboration/src/core/document/default/mod.rs index 961d3a377a..9a0f1e8216 100644 --- a/shared-lib/flowy-collaboration/src/user_default.rs +++ b/shared-lib/flowy-collaboration/src/core/document/default/mod.rs @@ -1,20 +1,20 @@ use lib_ot::{core::DeltaBuilder, rich_text::RichTextDelta}; #[inline] -pub fn doc_initial_delta() -> RichTextDelta { DeltaBuilder::new().insert("\n").build() } +pub fn initial_delta() -> RichTextDelta { DeltaBuilder::new().insert("\n").build() } #[inline] -pub fn doc_initial_string() -> String { doc_initial_delta().to_json() } +pub fn initial_string() -> String { initial_delta().to_json() } #[inline] pub fn initial_read_me() -> RichTextDelta { - let json = include_str!("READ_ME.json"); + let json = include_str!("./READ_ME.json"); RichTextDelta::from_json(json).unwrap() } #[cfg(test)] mod tests { - use crate::user_default::initial_read_me; + use crate::core::document::default::initial_read_me; #[test] fn load_read_me() { diff --git a/shared-lib/flowy-collaboration/src/core/document/document.rs b/shared-lib/flowy-collaboration/src/core/document/document.rs index 7d58eb128a..861f9bed24 100644 --- a/shared-lib/flowy-collaboration/src/core/document/document.rs +++ b/shared-lib/flowy-collaboration/src/core/document/document.rs @@ -1,16 +1,18 @@ -use crate::{ - core::document::{ - history::{History, UndoResult}, - view::{View, RECORD_THRESHOLD}, - }, - errors::CollaborateError, - user_default::doc_initial_delta, -}; +use tokio::sync::mpsc; + use lib_ot::{ core::*, rich_text::{RichTextAttribute, RichTextDelta}, }; -use tokio::sync::mpsc; + +use crate::{ + core::document::{ + default::initial_delta, + history::{History, UndoResult}, + view::{View, RECORD_THRESHOLD}, + }, + errors::CollaborateError, +}; pub trait CustomDocument { fn init_delta() -> RichTextDelta; @@ -23,7 +25,7 @@ impl CustomDocument for PlainDoc { pub struct FlowyDoc(); impl CustomDocument for FlowyDoc { - fn init_delta() -> RichTextDelta { doc_initial_delta() } + fn init_delta() -> RichTextDelta { initial_delta() } } pub struct Document { diff --git a/shared-lib/flowy-collaboration/src/core/document/mod.rs b/shared-lib/flowy-collaboration/src/core/document/mod.rs index 44fcb264a7..fa0537c832 100644 --- a/shared-lib/flowy-collaboration/src/core/document/mod.rs +++ b/shared-lib/flowy-collaboration/src/core/document/mod.rs @@ -1,10 +1,12 @@ #![allow(clippy::module_inception)] -mod data; -mod document; -mod extensions; -pub mod history; -mod view; pub use document::*; pub(crate) use extensions::*; pub use view::*; + +mod data; +pub mod default; +mod document; +mod extensions; +pub mod history; +mod view; diff --git a/shared-lib/flowy-collaboration/src/core/sync/server_editor.rs b/shared-lib/flowy-collaboration/src/core/sync/server_editor.rs index 16b18c58ac..cd346913c1 100644 --- a/shared-lib/flowy-collaboration/src/core/sync/server_editor.rs +++ b/shared-lib/flowy-collaboration/src/core/sync/server_editor.rs @@ -9,6 +9,7 @@ use crate::{ use async_stream::stream; use dashmap::DashMap; use futures::stream::StreamExt; +use lib_infra::future::FutureResultSend; use lib_ot::{errors::OTError, revision::Revision, rich_text::RichTextDelta}; use std::sync::{ atomic::{AtomicI64, Ordering::SeqCst}, @@ -20,9 +21,8 @@ use tokio::{ }; pub trait ServerDocPersistence: Send + Sync { - fn create_doc(&self, doc_id: &str, delta: RichTextDelta) -> CollaborateResult<()>; - fn update_doc(&self, doc_id: &str, delta: RichTextDelta) -> CollaborateResult<()>; - fn read_doc(&self, doc_id: &str) -> CollaborateResult; + fn update_doc(&self, doc_id: &str, rev_id: i64, delta: RichTextDelta) -> FutureResultSend<(), CollaborateError>; + fn read_doc(&self, doc_id: &str) -> FutureResultSend; } #[rustfmt::skip] @@ -59,18 +59,25 @@ impl ServerDocManager { } } - pub fn get(&self, doc_id: &str) -> Option> { - self.open_doc_map.get(doc_id).map(|ctx| ctx.clone()) + pub async fn get(&self, doc_id: &str) -> Result>, CollaborateError> { + match self.open_doc_map.get(doc_id).map(|ctx| ctx.clone()) { + Some(edit_doc) => Ok(Some(edit_doc)), + None => { + let doc = self.persistence.read_doc(doc_id).await?; + let handler = self.cache(doc).await.map_err(internal_error)?; + Ok(Some(handler)) + }, + } } - pub async fn cache(&self, doc: Doc) -> Result<(), CollaborateError> { + async fn cache(&self, doc: Doc) -> Result, CollaborateError> { let doc_id = doc.id.clone(); let handle = spawn_blocking(|| OpenDocHandle::new(doc)) .await .map_err(internal_error)?; let handle = Arc::new(handle?); - self.open_doc_map.insert(doc_id, handle); - Ok(()) + self.open_doc_map.insert(doc_id, handle.clone()); + Ok(handle) } } diff --git a/shared-lib/flowy-collaboration/src/lib.rs b/shared-lib/flowy-collaboration/src/lib.rs index bc082bbaa5..60ee3988b0 100644 --- a/shared-lib/flowy-collaboration/src/lib.rs +++ b/shared-lib/flowy-collaboration/src/lib.rs @@ -2,5 +2,4 @@ pub mod core; pub mod entities; pub mod errors; pub mod protobuf; -pub mod user_default; pub mod util; diff --git a/shared-lib/flowy-core-infra/src/entities/view/view_create.rs b/shared-lib/flowy-core-infra/src/entities/view/view_create.rs index 905daf28a3..cffad1cbbd 100644 --- a/shared-lib/flowy-core-infra/src/entities/view/view_create.rs +++ b/shared-lib/flowy-core-infra/src/entities/view/view_create.rs @@ -7,7 +7,7 @@ use crate::{ view::{ViewName, ViewThumbnail}, }, }; -use flowy_collaboration::user_default::doc_initial_string; +use flowy_collaboration::core::document::default::initial_string; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use std::convert::TryInto; @@ -81,7 +81,7 @@ impl CreateViewParams { desc, thumbnail, view_type, - data: doc_initial_string(), + data: initial_string(), } } } diff --git a/frontend/rust-lib/lib-infra/Cargo.toml b/shared-lib/lib-infra/Cargo.toml similarity index 82% rename from frontend/rust-lib/lib-infra/Cargo.toml rename to shared-lib/lib-infra/Cargo.toml index 57a7a2dee3..705d70f18e 100644 --- a/frontend/rust-lib/lib-infra/Cargo.toml +++ b/shared-lib/lib-infra/Cargo.toml @@ -7,8 +7,6 @@ edition = "2018" [dependencies] uuid = { version = "0.8", features = ["serde", "v4"] } -flowy-derive = { path = "../../../shared-lib/flowy-derive" } -protobuf = {version = "2.18.0"} log = "0.4.14" chrono = "0.4.19" bytes = { version = "1.0" } diff --git a/frontend/rust-lib/lib-infra/src/future.rs b/shared-lib/lib-infra/src/future.rs similarity index 61% rename from frontend/rust-lib/lib-infra/src/future.rs rename to shared-lib/lib-infra/src/future.rs index 341e7c6845..24ed7f9f31 100644 --- a/frontend/rust-lib/lib-infra/src/future.rs +++ b/shared-lib/lib-infra/src/future.rs @@ -33,12 +33,12 @@ where } #[pin_project] -pub struct ResultFuture { +pub struct FutureResult { #[pin] pub fut: Pin> + Sync + Send>>, } -impl ResultFuture { +impl FutureResult { pub fn new(f: F) -> Self where F: Future> + Send + Sync + 'static, @@ -49,7 +49,7 @@ impl ResultFuture { } } -impl Future for ResultFuture +impl Future for FutureResult where T: Send + Sync, E: Debug, @@ -62,3 +62,34 @@ where Poll::Ready(result) } } + +#[pin_project] +pub struct FutureResultSend { + #[pin] + pub fut: Pin> + Send>>, +} + +impl FutureResultSend { + pub fn new(f: F) -> Self + where + F: Future> + Send + 'static, + { + Self { + fut: Box::pin(async { f.await }), + } + } +} + +impl Future for FutureResultSend +where + T: Send, + E: Debug, +{ + type Output = Result; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let this = self.as_mut().project(); + let result = ready!(this.fut.poll(cx)); + Poll::Ready(result) + } +} diff --git a/frontend/rust-lib/lib-infra/src/lib.rs b/shared-lib/lib-infra/src/lib.rs similarity index 100% rename from frontend/rust-lib/lib-infra/src/lib.rs rename to shared-lib/lib-infra/src/lib.rs diff --git a/frontend/rust-lib/lib-infra/src/retry/future.rs b/shared-lib/lib-infra/src/retry/future.rs similarity index 100% rename from frontend/rust-lib/lib-infra/src/retry/future.rs rename to shared-lib/lib-infra/src/retry/future.rs diff --git a/frontend/rust-lib/lib-infra/src/retry/mod.rs b/shared-lib/lib-infra/src/retry/mod.rs similarity index 100% rename from frontend/rust-lib/lib-infra/src/retry/mod.rs rename to shared-lib/lib-infra/src/retry/mod.rs diff --git a/frontend/rust-lib/lib-infra/src/retry/strategy/exponential_backoff.rs b/shared-lib/lib-infra/src/retry/strategy/exponential_backoff.rs similarity index 100% rename from frontend/rust-lib/lib-infra/src/retry/strategy/exponential_backoff.rs rename to shared-lib/lib-infra/src/retry/strategy/exponential_backoff.rs diff --git a/frontend/rust-lib/lib-infra/src/retry/strategy/fixed_interval.rs b/shared-lib/lib-infra/src/retry/strategy/fixed_interval.rs similarity index 100% rename from frontend/rust-lib/lib-infra/src/retry/strategy/fixed_interval.rs rename to shared-lib/lib-infra/src/retry/strategy/fixed_interval.rs diff --git a/frontend/rust-lib/lib-infra/src/retry/strategy/jitter.rs b/shared-lib/lib-infra/src/retry/strategy/jitter.rs similarity index 100% rename from frontend/rust-lib/lib-infra/src/retry/strategy/jitter.rs rename to shared-lib/lib-infra/src/retry/strategy/jitter.rs diff --git a/frontend/rust-lib/lib-infra/src/retry/strategy/mod.rs b/shared-lib/lib-infra/src/retry/strategy/mod.rs similarity index 100% rename from frontend/rust-lib/lib-infra/src/retry/strategy/mod.rs rename to shared-lib/lib-infra/src/retry/strategy/mod.rs diff --git a/shared-lib/lib-ws/Cargo.toml b/shared-lib/lib-ws/Cargo.toml index 55de5a1af8..1deef5e0a7 100644 --- a/shared-lib/lib-ws/Cargo.toml +++ b/shared-lib/lib-ws/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" [dependencies] flowy-derive = { path = "../flowy-derive" } backend-service = { path = "../backend-service" } -lib-infra = { path = "../../frontend/rust-lib/lib-infra" } +lib-infra = { path = "../lib-infra" } tokio-tungstenite = "0.15" futures-util = "0.3.17" From 5b7e6690f8f7116a21f5c4194616cb5ea97c8e13 Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 13 Dec 2021 22:46:35 +0800 Subject: [PATCH 25/39] test sync --- backend/src/services/doc/crud.rs | 18 ++- backend/src/services/doc/manager.rs | 39 ++++- backend/src/services/doc/router.rs | 16 +- backend/src/services/doc/ws_actor.rs | 56 ++----- backend/src/services/view/view.rs | 4 +- .../flowy-collaboration/ws.pbenum.dart | 2 - .../flowy-collaboration/ws.pbjson.dart | 3 +- .../src/services/doc/controller.rs | 2 +- .../src/services/doc/edit/editor.rs | 14 +- .../src/services/doc/edit/model.rs | 26 ++-- .../doc/revision/{ => cache}/cache.rs | 95 ++++++++---- .../src/services/doc/revision/cache/disk.rs | 12 ++ .../src/services/doc/revision/cache/memory.rs | 126 +++++++++++++++ .../src/services/doc/revision/cache/mod.rs | 8 + .../src/services/doc/revision/cache/model.rs | 15 ++ .../src/services/doc/revision/manager.rs | 9 +- .../src/services/doc/revision/sync.rs | 14 +- .../src/sql_tables/doc/rev_sql.rs | 21 +-- .../src/sql_tables/doc/rev_table.rs | 12 +- .../tests/editor/revision_test.rs | 5 +- .../src/protobuf/model/network_state.rs | 30 ++-- .../src/protobuf/proto/network_state.proto | 1 + frontend/rust-lib/flowy-test/src/editor.rs | 2 +- .../flowy-user/src/services/server/ws_mock.rs | 144 +++++++++++++++--- .../src/core/sync/server_editor.rs | 62 ++++---- .../src/core/sync/synchronizer.rs | 28 +--- .../src/entities/doc/doc.rs | 25 ++- .../flowy-collaboration/src/entities/ws/ws.rs | 23 +-- shared-lib/flowy-collaboration/src/errors.rs | 16 +- .../src/protobuf/model/ws.rs | 48 +++--- .../src/protobuf/proto/ws.proto | 1 - shared-lib/lib-ot/src/revision/cache.rs | 140 ----------------- shared-lib/lib-ot/src/revision/mod.rs | 2 - shared-lib/lib-ot/src/revision/model.rs | 8 + 34 files changed, 595 insertions(+), 432 deletions(-) rename frontend/rust-lib/flowy-document/src/services/doc/revision/{ => cache}/cache.rs (72%) create mode 100644 frontend/rust-lib/flowy-document/src/services/doc/revision/cache/disk.rs create mode 100644 frontend/rust-lib/flowy-document/src/services/doc/revision/cache/memory.rs create mode 100644 frontend/rust-lib/flowy-document/src/services/doc/revision/cache/mod.rs create mode 100644 frontend/rust-lib/flowy-document/src/services/doc/revision/cache/model.rs delete mode 100644 shared-lib/lib-ot/src/revision/cache.rs diff --git a/backend/src/services/doc/crud.rs b/backend/src/services/doc/crud.rs index 0d83d5922a..264cf6103a 100644 --- a/backend/src/services/doc/crud.rs +++ b/backend/src/services/doc/crud.rs @@ -9,7 +9,7 @@ use sqlx::{postgres::PgArguments, PgPool, Postgres}; use uuid::Uuid; #[tracing::instrument(level = "debug", skip(transaction), err)] -pub(crate) async fn create_doc( +pub(crate) async fn create_doc_with_transaction( transaction: &mut DBTransaction<'_>, params: CreateDocParams, ) -> Result<(), ServerError> { @@ -23,6 +23,22 @@ pub(crate) async fn create_doc( Ok(()) } +pub(crate) async fn create_doc(pool: &PgPool, params: CreateDocParams) -> Result<(), ServerError> { + let mut transaction = pool + .begin() + .await + .context("Failed to acquire a Postgres connection to create doc")?; + + let _ = create_doc_with_transaction(&mut transaction, params).await?; + + transaction + .commit() + .await + .context("Failed to commit SQL transaction to create doc.")?; + + Ok(()) +} + #[tracing::instrument(level = "debug", skip(pool), err)] pub(crate) async fn read_doc(pool: &PgPool, params: DocIdentifier) -> Result { let doc_id = Uuid::parse_str(¶ms.doc_id)?; diff --git a/backend/src/services/doc/manager.rs b/backend/src/services/doc/manager.rs index 06c0c59a34..6ac68a5e0f 100644 --- a/backend/src/services/doc/manager.rs +++ b/backend/src/services/doc/manager.rs @@ -8,14 +8,16 @@ use crate::{ }; use actix_web::web::Data; +use crate::services::doc::create_doc; +use backend_service::errors::ServerError; use flowy_collaboration::{ core::sync::{ServerDocManager, ServerDocPersistence}, entities::doc::Doc, errors::CollaborateError, - protobuf::{DocIdentifier, UpdateDocParams}, + protobuf::{CreateDocParams, DocIdentifier, UpdateDocParams}, }; use lib_infra::future::FutureResultSend; -use lib_ot::rich_text::RichTextDelta; +use lib_ot::{revision::Revision, rich_text::RichTextDelta}; use sqlx::PgPool; use std::{convert::TryInto, sync::Arc}; use tokio::sync::{mpsc, oneshot}; @@ -77,7 +79,7 @@ impl ServerDocPersistence for DocPersistenceImpl { FutureResultSend::new(async move { let _ = update_doc(pg_pool.get_ref(), params) .await - .map_err(|e| CollaborateError::internal().context(e))?; + .map_err(server_error_to_collaborate_error)?; Ok(()) }) } @@ -91,11 +93,40 @@ impl ServerDocPersistence for DocPersistenceImpl { FutureResultSend::new(async move { let mut pb_doc = read_doc(pg_pool.get_ref(), params) .await - .map_err(|e| CollaborateError::internal().context(e))?; + .map_err(server_error_to_collaborate_error)?; let doc = (&mut pb_doc) .try_into() .map_err(|e| CollaborateError::internal().context(e))?; Ok(doc) }) } + + fn create_doc(&self, revision: Revision) -> FutureResultSend { + let pg_pool = self.0.clone(); + FutureResultSend::new(async move { + let delta = RichTextDelta::from_bytes(&revision.delta_data)?; + let doc_json = delta.to_json(); + + let params = CreateDocParams { + id: revision.doc_id.clone(), + data: doc_json.clone(), + unknown_fields: Default::default(), + cached_size: Default::default(), + }; + + let _ = create_doc(pg_pool.get_ref(), params) + .await + .map_err(server_error_to_collaborate_error)?; + let doc: Doc = revision.try_into()?; + Ok(doc) + }) + } +} + +fn server_error_to_collaborate_error(error: ServerError) -> CollaborateError { + if error.is_record_not_found() { + CollaborateError::record_not_found() + } else { + CollaborateError::internal().context(error) + } } diff --git a/backend/src/services/doc/router.rs b/backend/src/services/doc/router.rs index 74883ae4f6..c541db6f69 100644 --- a/backend/src/services/doc/router.rs +++ b/backend/src/services/doc/router.rs @@ -6,26 +6,14 @@ use actix_web::{ web::{Data, Payload}, HttpResponse, }; -use anyhow::Context; + use backend_service::{errors::ServerError, response::FlowyResponse}; use flowy_collaboration::protobuf::{CreateDocParams, DocIdentifier, UpdateDocParams}; use sqlx::PgPool; pub async fn create_handler(payload: Payload, pool: Data) -> Result { let params: CreateDocParams = parse_from_payload(payload).await?; - - let mut transaction = pool - .begin() - .await - .context("Failed to acquire a Postgres connection to create doc")?; - - let _ = create_doc(&mut transaction, params).await?; - - transaction - .commit() - .await - .context("Failed to commit SQL transaction to create doc.")?; - + let _ = create_doc(&pool, params).await?; Ok(FlowyResponse::success().into()) } diff --git a/backend/src/services/doc/ws_actor.rs b/backend/src/services/doc/ws_actor.rs index e93d59a1fc..85b196dfb7 100644 --- a/backend/src/services/doc/ws_actor.rs +++ b/backend/src/services/doc/ws_actor.rs @@ -10,8 +10,8 @@ use actix_web::web::Data; use async_stream::stream; use backend_service::errors::{internal_error, Result as DocResult, ServerError}; use flowy_collaboration::{ - core::sync::{OpenDocHandle, ServerDocManager}, - protobuf::{NewDocUser, WsDataType, WsDocumentData}, + core::sync::ServerDocManager, + protobuf::{WsDataType, WsDocumentData}, }; use futures::stream::StreamExt; use lib_ot::protobuf::Revision; @@ -80,32 +80,11 @@ impl DocWsActor { match document_data.ty { WsDataType::Acked => Ok(()), WsDataType::PushRev => self.apply_pushed_rev(user, socket, data, pool).await, - WsDataType::NewDocUser => self.add_doc_user(user, socket, data, pool).await, WsDataType::PullRev => Ok(()), WsDataType::Conflict => Ok(()), } } - async fn add_doc_user( - &self, - user: Arc, - socket: Socket, - data: Vec, - pg_pool: Data, - ) -> DocResult<()> { - let doc_user = spawn_blocking(move || { - let user: NewDocUser = parse_from_bytes(&data)?; - DocResult::Ok(user) - }) - .await - .map_err(internal_error)??; - if let Some(handle) = self.get_doc_handle(&doc_user.doc_id, pg_pool.clone()).await { - let user = Arc::new(ServerDocUser { user, socket, pg_pool }); - handle.add_user(user, doc_user.rev_id).await.map_err(internal_error)?; - } - Ok(()) - } - async fn apply_pushed_rev( &self, user: Arc, @@ -113,30 +92,27 @@ impl DocWsActor { data: Vec, pg_pool: Data, ) -> DocResult<()> { - let mut revision = spawn_blocking(move || { + let mut revision_pb = spawn_blocking(move || { let revision: Revision = parse_from_bytes(&data)?; let _ = verify_md5(&revision)?; DocResult::Ok(revision) }) .await .map_err(internal_error)??; - if let Some(handle) = self.get_doc_handle(&revision.doc_id, pg_pool.clone()).await { - let user = Arc::new(ServerDocUser { user, socket, pg_pool }); - let revision = (&mut revision).try_into().map_err(internal_error).unwrap(); - handle.apply_revision(user, revision).await.map_err(internal_error)?; - } - Ok(()) - } + let revision: lib_ot::revision::Revision = (&mut revision_pb).try_into().map_err(internal_error)?; + // Create the doc if it doesn't exist + let handler = match self.doc_manager.get(&revision.doc_id).await { + None => self + .doc_manager + .create_doc(revision.clone()) + .await + .map_err(internal_error)?, + Some(handler) => handler, + }; - async fn get_doc_handle(&self, doc_id: &str, _pg_pool: Data) -> Option> { - match self.doc_manager.get(doc_id).await { - Ok(Some(edit_doc)) => Some(edit_doc), - Ok(None) => None, - Err(e) => { - log::error!("{}", e); - None - }, - } + let user = Arc::new(ServerDocUser { user, socket, pg_pool }); + handler.apply_revision(user, revision).await.map_err(internal_error)?; + Ok(()) } } diff --git a/backend/src/services/view/view.rs b/backend/src/services/view/view.rs index 05715303d5..5dd1055d0e 100644 --- a/backend/src/services/view/view.rs +++ b/backend/src/services/view/view.rs @@ -1,7 +1,7 @@ use crate::{ entities::workspace::{ViewTable, VIEW_TABLE}, services::{ - doc::{create_doc, delete_doc}, + doc::{create_doc_with_transaction, delete_doc}, trash::read_trash_ids, user::LoggedUser, view::sql_builder::*, @@ -94,7 +94,7 @@ pub(crate) async fn create_view_with_args( let mut create_doc_params = CreateDocParams::new(); create_doc_params.set_data(view_data); create_doc_params.set_id(view.id.clone()); - let _ = create_doc(transaction, create_doc_params).await?; + let _ = create_doc_with_transaction(transaction, create_doc_params).await?; Ok(view) } diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbenum.dart index 8cedbb2f2e..31f54d22ea 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbenum.dart @@ -14,14 +14,12 @@ class WsDataType extends $pb.ProtobufEnum { static const WsDataType PushRev = WsDataType._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PushRev'); static const WsDataType PullRev = WsDataType._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PullRev'); static const WsDataType Conflict = WsDataType._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Conflict'); - static const WsDataType NewDocUser = WsDataType._(4, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'NewDocUser'); static const $core.List values = [ Acked, PushRev, PullRev, Conflict, - NewDocUser, ]; static final $core.Map<$core.int, WsDataType> _byValue = $pb.ProtobufEnum.initByValue(values); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbjson.dart index 8f57171e33..50bc4f4d5b 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbjson.dart @@ -16,12 +16,11 @@ const WsDataType$json = const { const {'1': 'PushRev', '2': 1}, const {'1': 'PullRev', '2': 2}, const {'1': 'Conflict', '2': 3}, - const {'1': 'NewDocUser', '2': 4}, ], }; /// Descriptor for `WsDataType`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List wsDataTypeDescriptor = $convert.base64Decode('CgpXc0RhdGFUeXBlEgkKBUFja2VkEAASCwoHUHVzaFJldhABEgsKB1B1bGxSZXYQAhIMCghDb25mbGljdBADEg4KCk5ld0RvY1VzZXIQBA=='); +final $typed_data.Uint8List wsDataTypeDescriptor = $convert.base64Decode('CgpXc0RhdGFUeXBlEgkKBUFja2VkEAASCwoHUHVzaFJldhABEgsKB1B1bGxSZXYQAhIMCghDb25mbGljdBAD'); @$core.Deprecated('Use wsDocumentDataDescriptor instead') const WsDocumentData$json = const { '1': 'WsDocumentData', diff --git a/frontend/rust-lib/flowy-document/src/services/doc/controller.rs b/frontend/rust-lib/flowy-document/src/services/doc/controller.rs index 82b999a4ff..cab76400b4 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/controller.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/controller.rs @@ -55,7 +55,7 @@ impl DocController { } pub(crate) fn close(&self, doc_id: &str) -> Result<(), DocError> { - log::debug!("Close doc {}", doc_id); + tracing::debug!("Close doc {}", doc_id); self.open_cache.remove(doc_id); self.ws_manager.remove_handler(doc_id); Ok(()) diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs index 3246d8fcc9..f60a7d5e86 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs @@ -63,7 +63,7 @@ impl ClientDocEditor { stop_sync_tx, }); - edit_doc.notify_open_doc(); + // edit_doc.notify_open_doc(); start_sync(edit_doc.clone(), ws_msg_rx, cloned_stop_sync_tx); Ok(edit_doc) @@ -165,7 +165,7 @@ impl ClientDocEditor { let delta_data = delta_data.to_vec(); let user_id = self.user.user_id()?; let revision = Revision::new(base_rev_id, rev_id, delta_data, &self.doc_id, RevType::Local, user_id); - let _ = self.rev_manager.add_revision(&revision).await?; + let _ = self.rev_manager.add_local_revision(&revision).await?; Ok(rev_id.into()) } @@ -246,7 +246,7 @@ impl ClientDocEditor { RevType::Remote, user_id, ); - let _ = self.rev_manager.add_revision(&revision).await?; + let _ = self.rev_manager.add_remote_revision(&revision).await?; // send the server_prime delta let user_id = self.user.user_id()?; @@ -264,10 +264,8 @@ impl ClientDocEditor { pub async fn handle_ws_message(&self, doc_data: WsDocumentData) -> DocResult<()> { match self.ws_msg_tx.send(doc_data) { - Ok(_) => { - tracing::debug!("Propagate ws message data success") - }, - Err(e) => tracing::error!("Propagate ws message data failed. {}", e), + Ok(_) => {}, + Err(e) => tracing::error!("❌Propagate ws message failed. {}", e), } Ok(()) } @@ -286,7 +284,7 @@ impl WsDocumentHandler for EditDocWsHandler { let edit_doc = self.0.clone(); tokio::spawn(async move { if let Err(e) = edit_doc.handle_ws_message(doc_data).await { - log::error!("{:?}", e); + tracing::error!("❌{:?}", e); } }); } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/model.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/model.rs index f75cc672e2..c2454c267e 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/model.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/model.rs @@ -1,10 +1,13 @@ +#![allow(clippy::all)] +#![cfg_attr(rustfmt, rustfmt::skip)] use crate::{errors::DocError, services::ws::DocumentWebSocket}; -use flowy_collaboration::entities::doc::NewDocUser; + use futures::future::BoxFuture; use lib_infra::retry::Action; use lib_ot::revision::RevId; use std::{future, sync::Arc}; +#[allow(dead_code)] pub(crate) struct OpenDocAction { user_id: String, rev_id: RevId, @@ -29,15 +32,16 @@ impl Action for OpenDocAction { type Error = DocError; fn run(&mut self) -> Self::Future { - let new_doc_user = NewDocUser { - user_id: self.user_id.clone(), - rev_id: self.rev_id.clone().into(), - doc_id: self.doc_id.clone(), - }; - - match self.ws.send(new_doc_user.into()) { - Ok(_) => Box::pin(future::ready(Ok::<(), DocError>(()))), - Err(e) => Box::pin(future::ready(Err::<(), DocError>(e))), - } + // let new_doc_user = NewDocUser { + // user_id: self.user_id.clone(), + // rev_id: self.rev_id.clone().into(), + // doc_id: self.doc_id.clone(), + // }; + // + // match self.ws.send(new_doc_user.into()) { + // Ok(_) => Box::pin(future::ready(Ok::<(), DocError>(()))), + // Err(e) => Box::pin(future::ready(Err::<(), DocError>(e))), + // } + Box::pin(future::ready(Ok::<(), DocError>(()))) } } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs similarity index 72% rename from frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs rename to frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs index 8ded5792c9..8d85696203 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs @@ -1,6 +1,10 @@ use crate::{ errors::{internal_error, DocError, DocResult}, - services::doc::revision::RevisionServer, + services::doc::revision::{ + cache::{disk::RevisionDiskCache, memory::RevisionMemoryCache}, + RevisionRecord, + RevisionServer, + }, sql_tables::RevTableSql, }; use flowy_collaboration::entities::doc::Doc; @@ -8,7 +12,7 @@ use flowy_database::ConnectionPool; use lib_infra::future::FutureResult; use lib_ot::{ core::{Operation, OperationTransformable}, - revision::{RevState, RevType, Revision, RevisionDiskCache, RevisionMemoryCache, RevisionRange, RevisionRecord}, + revision::{RevState, RevType, Revision, RevisionRange}, rich_text::RichTextDelta, }; use std::{sync::Arc, time::Duration}; @@ -53,11 +57,29 @@ impl RevisionCache { } #[tracing::instrument(level = "debug", skip(self, revision))] - pub async fn add_revision(&self, revision: Revision) -> DocResult<()> { + pub async fn add_local_revision(&self, revision: Revision) -> DocResult<()> { if self.memory_cache.contains(&revision.rev_id) { return Err(DocError::duplicate_rev().context(format!("Duplicate revision id: {}", revision.rev_id))); } - self.memory_cache.add_revision(revision.clone()).await?; + let record = RevisionRecord { + revision, + state: RevState::Local, + }; + self.memory_cache.add_revision(record).await?; + self.save_revisions().await; + Ok(()) + } + + #[tracing::instrument(level = "debug", skip(self, revision))] + pub async fn add_remote_revision(&self, revision: Revision) -> DocResult<()> { + if self.memory_cache.contains(&revision.rev_id) { + return Err(DocError::duplicate_rev().context(format!("Duplicate revision id: {}", revision.rev_id))); + } + let record = RevisionRecord { + revision, + state: RevState::Local, + }; + self.memory_cache.add_revision(record).await?; self.save_revisions().await; Ok(()) } @@ -68,8 +90,17 @@ impl RevisionCache { self.save_revisions().await; } - pub async fn query_revision(&self, rev_id: i64) -> Option { - self.memory_cache.query_revision(&rev_id).await + pub async fn query_revision(&self, doc_id: &str, rev_id: i64) -> Option { + match self.memory_cache.query_revision(&rev_id).await { + None => match self.dish_cache.read_revision(doc_id, rev_id) { + Ok(revision) => revision, + Err(e) => { + log::error!("query_revision error: {:?}", e); + None + }, + }, + Some(record) => Some(record), + } } async fn save_revisions(&self) { @@ -102,9 +133,15 @@ impl RevisionCache { } else { let doc_id = self.doc_id.clone(); let disk_cache = self.dish_cache.clone(); - spawn_blocking(move || disk_cache.revisions_in_range(&doc_id, &range)) + let records = spawn_blocking(move || disk_cache.revisions_in_range(&doc_id, &range)) .await - .map_err(internal_error)? + .map_err(internal_error)??; + + let revisions = records + .into_iter() + .map(|record| record.revision) + .collect::>(); + Ok(revisions) } } @@ -126,11 +163,8 @@ impl RevisionCache { RevType::Remote, self.user_id.clone(), ); - let record = RevisionRecord { - revision, - state: RevState::Acked, - }; - let _ = self.dish_cache.create_revisions(vec![record])?; + + self.add_remote_revision(revision).await?; Ok(doc) } } @@ -141,14 +175,14 @@ impl RevisionIterator for RevisionCache { let disk_cache = self.dish_cache.clone(); let doc_id = self.doc_id.clone(); FutureResult::new(async move { - match memory_cache.front_revision().await { + match memory_cache.front_local_revision().await { None => { // - match memory_cache.front_rev_id().await { + match memory_cache.front_local_rev_id().await { None => Ok(None), Some(rev_id) => match disk_cache.read_revision(&doc_id, rev_id)? { None => Ok(None), - Some(revision) => Ok(Some(RevisionRecord::new(revision))), + Some(record) => Ok(Some(record)), }, } }, @@ -166,25 +200,25 @@ async fn load_from_disk( let doc_id = doc_id.to_owned(); let (tx, mut rx) = mpsc::channel(2); let doc = spawn_blocking(move || { - let revisions = disk_cache.read_revisions(&doc_id)?; - if revisions.is_empty() { + 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")); } - let (base_rev_id, rev_id) = revisions.last().unwrap().pair_rev_id(); + let (base_rev_id, rev_id) = records.last().unwrap().revision.pair_rev_id(); let mut delta = RichTextDelta::new(); - for (_, revision) in revisions.into_iter().enumerate() { + for (_, record) in records.into_iter().enumerate() { // Opti: revision's clone may cause memory issues - match RichTextDelta::from_bytes(revision.clone().delta_data) { + match RichTextDelta::from_bytes(record.revision.clone().delta_data) { Ok(local_delta) => { delta = delta.compose(&local_delta)?; - match tx.blocking_send(revision) { + match tx.blocking_send(record) { Ok(_) => {}, - Err(e) => log::error!("Load document from disk error: {}", e), + Err(e) => tracing::error!("❌Load document from disk error: {}", e), } }, Err(e) => { - log::error!("Deserialize delta from revision failed: {}", e); + tracing::error!("Deserialize delta from revision failed: {}", e); }, } } @@ -200,13 +234,12 @@ async fn load_from_disk( .await .map_err(internal_error)?; - while let Some(revision) = rx.recv().await { - match memory_cache.add_revision(revision).await { + while let Some(record) = rx.recv().await { + match memory_cache.add_revision(record).await { Ok(_) => {}, Err(e) => log::error!("{:?}", e), } } - doc } @@ -217,7 +250,7 @@ fn correct_delta_if_need(delta: &mut RichTextDelta) { let data = delta.ops.last().as_ref().unwrap().get_data(); if !data.ends_with('\n') { - log::error!("The op must end with newline. Correcting it by inserting newline op"); + log::error!("❌The op must end with newline. Correcting it by inserting newline op"); delta.ops.push(Operation::Insert("\n".into())); } } @@ -238,19 +271,19 @@ impl RevisionDiskCache for Persistence { }) } - fn revisions_in_range(&self, doc_id: &str, range: &RevisionRange) -> Result, Self::Error> { + fn revisions_in_range(&self, doc_id: &str, range: &RevisionRange) -> Result, Self::Error> { let conn = &*self.pool.get().map_err(internal_error).unwrap(); let revisions = RevTableSql::read_rev_tables_with_range(&self.user_id, doc_id, range.clone(), conn)?; Ok(revisions) } - fn read_revision(&self, doc_id: &str, rev_id: i64) -> Result, Self::Error> { + fn read_revision(&self, doc_id: &str, rev_id: i64) -> Result, Self::Error> { let conn = self.pool.get().map_err(internal_error)?; let some = RevTableSql::read_rev_table(&self.user_id, doc_id, &rev_id, &*conn)?; Ok(some) } - fn read_revisions(&self, doc_id: &str) -> Result, Self::Error> { + fn read_revisions(&self, doc_id: &str) -> Result, Self::Error> { let conn = self.pool.get().map_err(internal_error)?; let some = RevTableSql::read_rev_tables(&self.user_id, doc_id, &*conn)?; Ok(some) diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/disk.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/disk.rs new file mode 100644 index 0000000000..a72a6ede8b --- /dev/null +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/disk.rs @@ -0,0 +1,12 @@ +use crate::services::doc::revision::RevisionRecord; + +use lib_ot::revision::RevisionRange; +use std::fmt::Debug; + +pub trait RevisionDiskCache: Sync + Send { + type Error: Debug; + fn create_revisions(&self, revisions: Vec) -> Result<(), Self::Error>; + fn revisions_in_range(&self, doc_id: &str, range: &RevisionRange) -> Result, Self::Error>; + fn read_revision(&self, doc_id: &str, rev_id: i64) -> Result, Self::Error>; + fn read_revisions(&self, doc_id: &str) -> Result, Self::Error>; +} diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/memory.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/memory.rs new file mode 100644 index 0000000000..ca590e57cd --- /dev/null +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/memory.rs @@ -0,0 +1,126 @@ +use crate::services::doc::revision::RevisionRecord; +use dashmap::DashMap; +use lib_ot::{ + errors::OTError, + revision::{RevState, Revision, RevisionRange}, +}; +use std::{collections::VecDeque, sync::Arc}; +use tokio::sync::RwLock; + +pub struct RevisionMemoryCache { + revs_map: Arc>, + local_revs: Arc>>, +} + +impl std::default::Default for RevisionMemoryCache { + fn default() -> Self { + let local_revs = Arc::new(RwLock::new(VecDeque::new())); + RevisionMemoryCache { + revs_map: Arc::new(DashMap::new()), + local_revs, + } + } +} + +impl RevisionMemoryCache { + pub fn new() -> Self { RevisionMemoryCache::default() } + + pub async fn add_revision(&self, record: RevisionRecord) -> Result<(), OTError> { + // The last revision's rev_id must be greater than the new one. + if let Some(rev_id) = self.local_revs.read().await.back() { + if *rev_id >= record.revision.rev_id { + return Err(OTError::revision_id_conflict() + .context(format!("The new revision's id must be greater than {}", rev_id))); + } + } + + match record.state { + RevState::Local => { + tracing::debug!("{}:add revision {}", record.revision.doc_id, record.revision.rev_id); + self.local_revs.write().await.push_back(record.revision.rev_id); + }, + RevState::Acked => {}, + } + + self.revs_map.insert(record.revision.rev_id, record); + Ok(()) + } + + pub fn remove_revisions(&self, ids: Vec) { self.revs_map.retain(|k, _| !ids.contains(k)); } + + pub async fn ack_revision(&self, rev_id: &i64) { + if let Some(pop_rev_id) = self.front_local_rev_id().await { + if &pop_rev_id != rev_id { + return; + } + } + + match self.local_revs.write().await.pop_front() { + None => tracing::error!("❌The local_revs should not be empty"), + Some(pop_rev_id) => { + if &pop_rev_id != rev_id { + tracing::error!("The front rev_id:{} not equal to ack rev_id: {}", pop_rev_id, rev_id); + assert_eq!(&pop_rev_id, rev_id); + } else { + tracing::debug!("pop revision {}", pop_rev_id); + } + }, + } + } + + pub async fn revisions_in_range(&self, range: &RevisionRange) -> Result, OTError> { + let revs = range + .iter() + .flat_map(|rev_id| match self.revs_map.get(&rev_id) { + None => None, + Some(record) => Some(record.revision.clone()), + }) + .collect::>(); + + if revs.len() == range.len() as usize { + Ok(revs) + } else { + Ok(vec![]) + } + } + + pub fn contains(&self, rev_id: &i64) -> bool { self.revs_map.contains_key(rev_id) } + + pub fn is_empty(&self) -> bool { self.revs_map.is_empty() } + + pub fn revisions(&self) -> (Vec, Vec) { + let mut records: Vec = vec![]; + let mut ids: Vec = vec![]; + + self.revs_map.iter().for_each(|kv| { + records.push(kv.value().clone()); + ids.push(*kv.key()); + }); + (ids, records) + } + + pub async fn query_revision(&self, rev_id: &i64) -> Option { + self.revs_map.get(&rev_id).map(|r| r.value().clone()) + } + + pub async fn front_local_revision(&self) -> Option<(i64, RevisionRecord)> { + match self.local_revs.read().await.front() { + None => None, + Some(rev_id) => match self.revs_map.get(rev_id).map(|r| (*r.key(), r.value().clone())) { + None => None, + Some(val) => { + tracing::debug!("{}:try send revision {}", val.1.revision.doc_id, val.1.revision.rev_id); + Some(val) + }, + }, + } + } + + pub async fn front_local_rev_id(&self) -> Option { self.local_revs.read().await.front().copied() } +} + +#[cfg(feature = "flowy_unit_test")] +impl RevisionMemoryCache { + pub fn revs_map(&self) -> Arc> { self.revs_map.clone() } + pub fn pending_revs(&self) -> Arc>> { self.local_revs.clone() } +} diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/mod.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/mod.rs new file mode 100644 index 0000000000..2886d90fe0 --- /dev/null +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/mod.rs @@ -0,0 +1,8 @@ +#![allow(clippy::module_inception)] +mod cache; +mod disk; +mod memory; +mod model; + +pub use cache::*; +pub use model::*; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/model.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/model.rs new file mode 100644 index 0000000000..f19b351fd9 --- /dev/null +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/model.rs @@ -0,0 +1,15 @@ +use lib_ot::revision::{RevState, Revision}; +use tokio::sync::broadcast; + +pub type RevIdReceiver = broadcast::Receiver; +pub type RevIdSender = broadcast::Sender; + +#[derive(Clone)] +pub struct RevisionRecord { + pub revision: Revision, + pub state: RevState, +} + +impl RevisionRecord { + pub fn ack(&mut self) { self.state = RevState::Acked; } +} diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs index af9a2c599c..434badcfd8 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs @@ -44,8 +44,13 @@ impl RevisionManager { Ok(doc.delta()?) } - pub async fn add_revision(&self, revision: &Revision) -> Result<(), DocError> { - let _ = self.cache.add_revision(revision.clone()).await?; + pub async fn add_remote_revision(&self, revision: &Revision) -> Result<(), DocError> { + let _ = self.cache.add_remote_revision(revision.clone()).await?; + Ok(()) + } + + pub async fn add_local_revision(&self, revision: &Revision) -> Result<(), DocError> { + let _ = self.cache.add_local_revision(revision.clone()).await?; Ok(()) } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs index 98b2ccace5..9fccdd2512 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs @@ -54,8 +54,13 @@ impl RevisionDownStream { tokio::select! { result = receiver.recv() => { match result { - Some(msg) => yield msg, - None => {}, + Some(msg) => { + yield msg + }, + None => { + tracing::debug!("[RevisionDownStream:{}] loop exit", doc_id); + break; + }, } }, _ = stop_rx.recv() => { @@ -82,7 +87,7 @@ impl RevisionDownStream { .await .map_err(internal_error)?; - log::debug!("[RevisionDownStream]: receives new message: {:?}", ty); + tracing::debug!("[RevisionDownStream]: receives new message: {:?}", ty); match ty { WsDataType::PushRev => { let _ = self.editor.handle_push_rev(bytes).await?; @@ -97,7 +102,6 @@ impl RevisionDownStream { let _ = self.rev_manager.ack_revision(rev_id).await?; }, WsDataType::Conflict => {}, - WsDataType::NewDocUser => {}, } Ok(()) @@ -145,7 +149,7 @@ impl RevisionUpStream { result = rx.recv() => { match result { Some(msg) => yield msg, - None => {}, + None => break, } }, _ = stop_rx.recv() => { diff --git a/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_sql.rs b/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_sql.rs index 28cd06895c..61077c26fd 100644 --- a/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_sql.rs +++ b/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_sql.rs @@ -1,10 +1,11 @@ use crate::{ errors::DocError, - sql_tables::{doc::RevTable, mk_revision_from_table, RevChangeset, RevTableState, RevTableType}, + services::doc::revision::RevisionRecord, + sql_tables::{doc::RevTable, mk_revision_record_from_table, RevChangeset, RevTableState, RevTableType}, }; use diesel::update; use flowy_database::{insert_or_ignore_into, prelude::*, schema::rev_table::dsl, SqliteConnection}; -use lib_ot::revision::{Revision, RevisionRange, RevisionRecord}; +use lib_ot::revision::RevisionRange; pub struct RevTableSql {} @@ -45,7 +46,7 @@ impl RevTableSql { user_id: &str, doc_id: &str, conn: &SqliteConnection, - ) -> Result, DocError> { + ) -> Result, DocError> { let filter = dsl::rev_table .filter(dsl::doc_id.eq(doc_id)) .order(dsl::rev_id.asc()) @@ -53,8 +54,8 @@ impl RevTableSql { let rev_tables = filter.load::(conn)?; let revisions = rev_tables .into_iter() - .map(|table| mk_revision_from_table(user_id, table)) - .collect::>(); + .map(|table| mk_revision_record_from_table(user_id, table)) + .collect::>(); Ok(revisions) } @@ -63,7 +64,7 @@ impl RevTableSql { doc_id: &str, revision_id: &i64, conn: &SqliteConnection, - ) -> Result, DocError> { + ) -> Result, DocError> { let filter = dsl::rev_table .filter(dsl::doc_id.eq(doc_id)) .filter(dsl::rev_id.eq(revision_id)); @@ -72,7 +73,7 @@ impl RevTableSql { if Err(diesel::NotFound) == result { Ok(None) } else { - Ok(Some(mk_revision_from_table(user_id, result?))) + Ok(Some(mk_revision_record_from_table(user_id, result?))) } } @@ -81,7 +82,7 @@ impl RevTableSql { doc_id: &str, range: RevisionRange, conn: &SqliteConnection, - ) -> Result, DocError> { + ) -> Result, DocError> { let rev_tables = dsl::rev_table .filter(dsl::rev_id.ge(range.start)) .filter(dsl::rev_id.le(range.end)) @@ -91,8 +92,8 @@ impl RevTableSql { let revisions = rev_tables .into_iter() - .map(|table| mk_revision_from_table(user_id, table)) - .collect::>(); + .map(|table| mk_revision_record_from_table(user_id, table)) + .collect::>(); Ok(revisions) } diff --git a/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_table.rs b/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_table.rs index 85a592dc79..2db34d293a 100644 --- a/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_table.rs +++ b/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_table.rs @@ -1,7 +1,7 @@ +use crate::services::doc::revision::RevisionRecord; use diesel::sql_types::Integer; -use flowy_database::schema::rev_table; - use flowy_collaboration::util::md5; +use flowy_database::schema::rev_table; use lib_ot::revision::{RevId, RevState, RevType, Revision}; #[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable, Associations)] @@ -64,9 +64,9 @@ impl std::convert::From for RevTableState { } } -pub(crate) fn mk_revision_from_table(user_id: &str, table: RevTable) -> Revision { +pub(crate) fn mk_revision_record_from_table(user_id: &str, table: RevTable) -> RevisionRecord { let md5 = md5(&table.data); - Revision { + let revision = Revision { base_rev_id: table.base_rev_id, rev_id: table.rev_id, delta_data: table.data, @@ -74,6 +74,10 @@ pub(crate) fn mk_revision_from_table(user_id: &str, table: RevTable) -> Revision doc_id: table.doc_id, ty: table.ty.into(), user_id: user_id.to_owned(), + }; + RevisionRecord { + revision, + state: table.state.into(), } } diff --git a/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs b/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs index aa30549459..aa2f425b4b 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs @@ -1,5 +1,5 @@ use flowy_test::editor::{EditorScript::*, *}; -use lib_ot::{revision::RevState, rich_text::RichTextDeltaBuilder}; +use lib_ot::revision::RevState; #[tokio::test] async fn doc_rev_state_test1() { @@ -40,12 +40,11 @@ async fn doc_rev_state_test2() { #[tokio::test] async fn doc_push_test() { - let delta = RichTextDeltaBuilder::new().insert("abc\n").build(); + // let delta = RichTextDeltaBuilder::new().insert("abc\n").build(); let scripts = vec![ InsertText("1", 0), InsertText("2", 1), InsertText("3", 2), - SimulatePushRevisionMessageWithDelta(delta), AssertJson(r#"[{"insert":"123\nabc\n"}]"#), ]; EditorTest::new().await.run_scripts(scripts).await; diff --git a/frontend/rust-lib/flowy-net/src/protobuf/model/network_state.rs b/frontend/rust-lib/flowy-net/src/protobuf/model/network_state.rs index 82286beead..b74f295a86 100644 --- a/frontend/rust-lib/flowy-net/src/protobuf/model/network_state.rs +++ b/frontend/rust-lib/flowy-net/src/protobuf/model/network_state.rs @@ -231,21 +231,21 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \n\x13network_state.proto\",\n\x0cNetworkState\x12\x1c\n\x02ty\x18\x01\ \x20\x01(\x0e2\x0c.NetworkTypeR\x02ty*G\n\x0bNetworkType\x12\x16\n\x12Un\ knownNetworkType\x10\0\x12\x08\n\x04Wifi\x10\x01\x12\x08\n\x04Cell\x10\ - \x02\x12\x0c\n\x08Ethernet\x10\x03J\x9d\x02\n\x06\x12\x04\0\0\t\x01\n\ - \x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x01\0\x03\x01\n\n\ - \n\x03\x04\0\x01\x12\x03\x01\x08\x14\n\x0b\n\x04\x04\0\x02\0\x12\x03\x02\ - \x04\x17\n\x0c\n\x05\x04\0\x02\0\x06\x12\x03\x02\x04\x0f\n\x0c\n\x05\x04\ - \0\x02\0\x01\x12\x03\x02\x10\x12\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x02\ - \x15\x16\n\n\n\x02\x05\0\x12\x04\x04\0\t\x01\n\n\n\x03\x05\0\x01\x12\x03\ - \x04\x05\x10\n\x0b\n\x04\x05\0\x02\0\x12\x03\x05\x04\x1b\n\x0c\n\x05\x05\ - \0\x02\0\x01\x12\x03\x05\x04\x16\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x05\ - \x19\x1a\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x06\x04\r\n\x0c\n\x05\x05\0\ - \x02\x01\x01\x12\x03\x06\x04\x08\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\ - \x06\x0b\x0c\n\x0b\n\x04\x05\0\x02\x02\x12\x03\x07\x04\r\n\x0c\n\x05\x05\ - \0\x02\x02\x01\x12\x03\x07\x04\x08\n\x0c\n\x05\x05\0\x02\x02\x02\x12\x03\ - \x07\x0b\x0c\n\x0b\n\x04\x05\0\x02\x03\x12\x03\x08\x04\x11\n\x0c\n\x05\ - \x05\0\x02\x03\x01\x12\x03\x08\x04\x0c\n\x0c\n\x05\x05\0\x02\x03\x02\x12\ - \x03\x08\x0f\x10b\x06proto3\ + \x02\x12\x0c\n\x08Ethernet\x10\x03J\x9d\x02\n\x06\x12\x04\0\0\n\x01\n\ + \x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x04\x01\n\n\ + \n\x03\x04\0\x01\x12\x03\x02\x08\x14\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\x0f\n\x0c\n\x05\x04\ + \0\x02\0\x01\x12\x03\x03\x10\x12\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\ + \x15\x16\n\n\n\x02\x05\0\x12\x04\x05\0\n\x01\n\n\n\x03\x05\0\x01\x12\x03\ + \x05\x05\x10\n\x0b\n\x04\x05\0\x02\0\x12\x03\x06\x04\x1b\n\x0c\n\x05\x05\ + \0\x02\0\x01\x12\x03\x06\x04\x16\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x06\ + \x19\x1a\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x07\x04\r\n\x0c\n\x05\x05\0\ + \x02\x01\x01\x12\x03\x07\x04\x08\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\ + \x07\x0b\x0c\n\x0b\n\x04\x05\0\x02\x02\x12\x03\x08\x04\r\n\x0c\n\x05\x05\ + \0\x02\x02\x01\x12\x03\x08\x04\x08\n\x0c\n\x05\x05\0\x02\x02\x02\x12\x03\ + \x08\x0b\x0c\n\x0b\n\x04\x05\0\x02\x03\x12\x03\t\x04\x11\n\x0c\n\x05\x05\ + \0\x02\x03\x01\x12\x03\t\x04\x0c\n\x0c\n\x05\x05\0\x02\x03\x02\x12\x03\t\ + \x0f\x10b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/frontend/rust-lib/flowy-net/src/protobuf/proto/network_state.proto b/frontend/rust-lib/flowy-net/src/protobuf/proto/network_state.proto index 390def7011..06a4aa5f3c 100644 --- a/frontend/rust-lib/flowy-net/src/protobuf/proto/network_state.proto +++ b/frontend/rust-lib/flowy-net/src/protobuf/proto/network_state.proto @@ -1,4 +1,5 @@ syntax = "proto3"; + message NetworkState { NetworkType ty = 1; } diff --git a/frontend/rust-lib/flowy-test/src/editor.rs b/frontend/rust-lib/flowy-test/src/editor.rs index 615272d178..c326cb5ce9 100644 --- a/frontend/rust-lib/flowy-test/src/editor.rs +++ b/frontend/rust-lib/flowy-test/src/editor.rs @@ -76,7 +76,7 @@ impl EditorTest { self.editor.redo().await.unwrap(); }, EditorScript::AssertRevisionState(rev_id, state) => { - let record = cache.query_revision(rev_id).await.unwrap(); + let record = cache.query_revision(&doc_id, rev_id).await.unwrap(); assert_eq!(record.state, state); }, EditorScript::AssertCurrentRevId(rev_id) => { diff --git a/frontend/rust-lib/flowy-user/src/services/server/ws_mock.rs b/frontend/rust-lib/flowy-user/src/services/server/ws_mock.rs index 4828781d29..dffb8bb710 100644 --- a/frontend/rust-lib/flowy-user/src/services/server/ws_mock.rs +++ b/frontend/rust-lib/flowy-user/src/services/server/ws_mock.rs @@ -7,7 +7,7 @@ use dashmap::DashMap; use flowy_collaboration::{ core::sync::{ServerDocManager, ServerDocPersistence}, entities::{ - doc::{Doc, NewDocUser}, + doc::Doc, ws::{WsDataType, WsDocumentData}, }, errors::CollaborateError, @@ -16,9 +16,13 @@ use lazy_static::lazy_static; use lib_infra::future::{FutureResult, FutureResultSend}; use lib_ot::{revision::Revision, rich_text::RichTextDelta}; use lib_ws::{WsConnectState, WsMessage, WsMessageHandler, WsModule}; -use parking_lot::RwLock; -use std::{convert::TryFrom, sync::Arc}; -use tokio::sync::{broadcast, broadcast::Receiver}; + +use flowy_collaboration::core::sync::{RevisionUser, SyncResponse}; +use std::{ + convert::{TryFrom, TryInto}, + sync::Arc, +}; +use tokio::sync::{broadcast, broadcast::Receiver, mpsc}; pub struct MockWebSocket { handlers: DashMap>, @@ -49,12 +53,11 @@ impl FlowyWebSocket for Arc { tokio::spawn(async move { while let Ok(message) = ws_receiver.recv().await { let ws_data = WsDocumentData::try_from(Bytes::from(message.data.clone())).unwrap(); - match DOC_SERVER.handle_ws_data(ws_data).await { - None => {}, - Some(new_ws_message) => match cloned_ws.handlers.get(&new_ws_message.module) { - None => log::error!("Can't find any handler for message: {:?}", new_ws_message), - Some(handler) => handler.receive_message(new_ws_message.clone()), - }, + let mut rx = DOC_SERVER.handle_ws_data(ws_data).await; + let new_ws_message = rx.recv().await.unwrap(); + match cloned_ws.handlers.get(&new_ws_message.module) { + None => log::error!("Can't find any handler for message: {:?}", new_ws_message), + Some(handler) => handler.receive_message(new_ws_message.clone()), } } }); @@ -88,38 +91,131 @@ struct MockDocServer { impl std::default::Default for MockDocServer { fn default() -> Self { - let manager = Arc::new(ServerDocManager::new(Arc::new(MockDocServerPersistence {}))); + let persistence = Arc::new(MockDocServerPersistence::default()); + let manager = Arc::new(ServerDocManager::new(persistence)); MockDocServer { manager } } } impl MockDocServer { - async fn handle_ws_data(&self, ws_data: WsDocumentData) -> Option { + async fn handle_ws_data(&self, ws_data: WsDocumentData) -> mpsc::Receiver { let bytes = Bytes::from(ws_data.data); match ws_data.ty { - WsDataType::Acked => {}, + WsDataType::Acked => { + unimplemented!() + }, WsDataType::PushRev => { let revision = Revision::try_from(bytes).unwrap(); - log::info!("{:?}", revision); + let handler = match self.manager.get(&revision.doc_id).await { + None => self.manager.create_doc(revision.clone()).await.unwrap(), + Some(handler) => handler, + }; + + let (tx, rx) = mpsc::channel(1); + let user = MockDocUser { + user_id: revision.user_id.clone(), + tx, + }; + handler.apply_revision(Arc::new(user), revision).await.unwrap(); + rx }, - WsDataType::PullRev => {}, - WsDataType::Conflict => {}, - WsDataType::NewDocUser => { - let new_doc_user = NewDocUser::try_from(bytes).unwrap(); - log::info!("{:?}", new_doc_user); - // NewDocUser + WsDataType::PullRev => { + unimplemented!() + }, + WsDataType::Conflict => { + unimplemented!() }, } - None } } -struct MockDocServerPersistence {} +struct MockDocServerPersistence { + inner: Arc>, +} + +impl std::default::Default for MockDocServerPersistence { + fn default() -> Self { + MockDocServerPersistence { + inner: Arc::new(DashMap::new()), + } + } +} impl ServerDocPersistence for MockDocServerPersistence { - fn update_doc(&self, doc_id: &str, rev_id: i64, delta: RichTextDelta) -> FutureResultSend<(), CollaborateError> { + fn update_doc(&self, _doc_id: &str, _rev_id: i64, _delta: RichTextDelta) -> FutureResultSend<(), CollaborateError> { unimplemented!() } - fn read_doc(&self, doc_id: &str) -> FutureResultSend { unimplemented!() } + fn read_doc(&self, doc_id: &str) -> FutureResultSend { + let inner = self.inner.clone(); + let doc_id = doc_id.to_owned(); + FutureResultSend::new(async move { + match inner.get(&doc_id) { + None => { + // + Err(CollaborateError::record_not_found()) + }, + Some(val) => { + // + Ok(val.value().clone()) + }, + } + }) + } + + fn create_doc(&self, revision: Revision) -> FutureResultSend { + FutureResultSend::new(async move { + let doc: Doc = revision.try_into().unwrap(); + Ok(doc) + }) + } +} + +#[derive(Debug)] +struct MockDocUser { + user_id: String, + tx: mpsc::Sender, +} + +impl RevisionUser for MockDocUser { + fn user_id(&self) -> String { self.user_id.clone() } + + fn recv(&self, resp: SyncResponse) { + let sender = self.tx.clone(); + tokio::spawn(async move { + match resp { + SyncResponse::Pull(data) => { + let bytes: Bytes = data.try_into().unwrap(); + let msg = WsMessage { + module: WsModule::Doc, + data: bytes.to_vec(), + }; + sender.send(msg).await.unwrap(); + }, + SyncResponse::Push(data) => { + let bytes: Bytes = data.try_into().unwrap(); + let msg = WsMessage { + module: WsModule::Doc, + data: bytes.to_vec(), + }; + sender.send(msg).await.unwrap(); + }, + SyncResponse::Ack(data) => { + let bytes: Bytes = data.try_into().unwrap(); + let msg = WsMessage { + module: WsModule::Doc, + data: bytes.to_vec(), + }; + sender.send(msg).await.unwrap(); + }, + SyncResponse::NewRevision { + rev_id: _, + doc_id: _, + doc_json: _, + } => { + // unimplemented!() + }, + } + }); + } } diff --git a/shared-lib/flowy-collaboration/src/core/sync/server_editor.rs b/shared-lib/flowy-collaboration/src/core/sync/server_editor.rs index cd346913c1..a15f3201cf 100644 --- a/shared-lib/flowy-collaboration/src/core/sync/server_editor.rs +++ b/shared-lib/flowy-collaboration/src/core/sync/server_editor.rs @@ -23,6 +23,7 @@ use tokio::{ pub trait ServerDocPersistence: Send + Sync { fn update_doc(&self, doc_id: &str, rev_id: i64, delta: RichTextDelta) -> FutureResultSend<(), CollaborateError>; fn read_doc(&self, doc_id: &str) -> FutureResultSend; + fn create_doc(&self, revision: Revision) -> FutureResultSend; } #[rustfmt::skip] @@ -59,17 +60,38 @@ impl ServerDocManager { } } - pub async fn get(&self, doc_id: &str) -> Result>, CollaborateError> { + pub async fn get(&self, doc_id: &str) -> Option> { match self.open_doc_map.get(doc_id).map(|ctx| ctx.clone()) { - Some(edit_doc) => Ok(Some(edit_doc)), + Some(edit_doc) => Some(edit_doc), None => { - let doc = self.persistence.read_doc(doc_id).await?; - let handler = self.cache(doc).await.map_err(internal_error)?; - Ok(Some(handler)) + let f = || async { + let doc = self.persistence.read_doc(doc_id).await?; + let handler = self.cache(doc).await.map_err(internal_error)?; + Ok::, CollaborateError>(handler) + }; + match f().await { + Ok(handler) => Some(handler), + Err(e) => { + log::error!("{}", e); + None + }, + } }, } } + pub async fn create_doc(&self, revision: Revision) -> Result, CollaborateError> { + if !revision.is_initial() { + return Err( + CollaborateError::revision_conflict().context("Revision's rev_id should be 0 when creating the doc") + ); + } + + let doc = self.persistence.create_doc(revision).await?; + let handler = self.cache(doc).await?; + Ok(handler) + } + async fn cache(&self, doc: Doc) -> Result, CollaborateError> { let doc_id = doc.id.clone(); let handle = spawn_blocking(|| OpenDocHandle::new(doc)) @@ -93,13 +115,6 @@ impl OpenDocHandle { Ok(Self { sender }) } - pub async fn add_user(&self, user: Arc, rev_id: i64) -> Result<(), CollaborateError> { - let (ret, rx) = oneshot::channel(); - let msg = DocCommand::NewConnectedUser { user, rev_id, ret }; - let _ = self.send(msg, rx).await?; - Ok(()) - } - pub async fn apply_revision( &self, user: Arc, @@ -132,11 +147,6 @@ impl OpenDocHandle { #[derive(Debug)] enum DocCommand { - NewConnectedUser { - user: Arc, - rev_id: i64, - ret: oneshot::Sender>, - }, ReceiveRevision { user: Arc, revision: Revision, @@ -183,10 +193,6 @@ impl DocCommandQueue { async fn handle_message(&self, msg: DocCommand) { match msg { - DocCommand::NewConnectedUser { user, rev_id, ret } => { - log::debug!("Receive new doc user: {:?}, rev_id: {}", user, rev_id); - let _ = ret.send(self.edit_doc.new_doc_user(user, rev_id).await.map_err(internal_error)); - }, DocCommand::ReceiveRevision { user, revision, ret } => { // let revision = (&mut revision).try_into().map_err(internal_error).unwrap(); let _ = ret.send( @@ -247,20 +253,6 @@ impl ServerDocEditor { }) } - #[tracing::instrument( - level = "debug", - skip(self, user), - fields( - user_id = %user.user_id(), - rev_id = %rev_id, - ) - )] - pub async fn new_doc_user(&self, user: Arc, rev_id: i64) -> Result<(), OTError> { - self.users.insert(user.user_id(), user.clone()); - self.synchronizer.new_conn(user, rev_id); - Ok(()) - } - #[tracing::instrument( level = "debug", skip(self, user, revision), diff --git a/shared-lib/flowy-collaboration/src/core/sync/synchronizer.rs b/shared-lib/flowy-collaboration/src/core/sync/synchronizer.rs index e193364250..2d62071407 100644 --- a/shared-lib/flowy-collaboration/src/core/sync/synchronizer.rs +++ b/shared-lib/flowy-collaboration/src/core/sync/synchronizer.rs @@ -55,29 +55,12 @@ impl RevisionSynchronizer { } } - pub fn new_conn(&self, user: Arc, rev_id: i64) { - let cur_rev_id = self.rev_id.load(SeqCst); - match cur_rev_id.cmp(&rev_id) { - Ordering::Less => { - let msg = mk_pull_message(&self.doc_id, next(cur_rev_id), rev_id); - user.recv(SyncResponse::Pull(msg)); - }, - Ordering::Equal => {}, - Ordering::Greater => { - let doc_delta = self.document.read().delta().clone(); - let revision = self.mk_revision(rev_id, doc_delta); - let data = mk_push_message(&self.doc_id, revision); - user.recv(SyncResponse::Push(data)); - }, - } - } - pub fn apply_revision(&self, user: Arc, revision: Revision) -> Result<(), OTError> { - let cur_rev_id = self.rev_id.load(SeqCst); - match cur_rev_id.cmp(&revision.rev_id) { + let server_base_rev_id = self.rev_id.load(SeqCst); + match server_base_rev_id.cmp(&revision.rev_id) { Ordering::Less => { - let next_rev_id = next(cur_rev_id); - if cur_rev_id == revision.base_rev_id || next_rev_id == revision.base_rev_id { + let server_rev_id = next(server_base_rev_id); + if server_base_rev_id == revision.base_rev_id || server_rev_id == revision.rev_id { // The rev is in the right order, just compose it. let _ = self.compose_revision(&revision)?; user.recv(SyncResponse::Ack(mk_acked_message(&revision))); @@ -91,13 +74,14 @@ impl RevisionSynchronizer { }); } else { // The server document is outdated, pull the missing revision from the client. - let msg = mk_pull_message(&self.doc_id, next_rev_id, revision.rev_id); + let msg = mk_pull_message(&self.doc_id, server_rev_id, revision.rev_id); user.recv(SyncResponse::Pull(msg)); } }, Ordering::Equal => { // Do nothing log::warn!("Applied revision rev_id is the same as cur_rev_id"); + user.recv(SyncResponse::Ack(mk_acked_message(&revision))); }, Ordering::Greater => { // The client document is outdated. Transform the client revision delta and then diff --git a/shared-lib/flowy-collaboration/src/entities/doc/doc.rs b/shared-lib/flowy-collaboration/src/entities/doc/doc.rs index 151bef5b57..7e740f101b 100644 --- a/shared-lib/flowy-collaboration/src/entities/doc/doc.rs +++ b/shared-lib/flowy-collaboration/src/entities/doc/doc.rs @@ -1,5 +1,6 @@ +use crate::errors::CollaborateError; use flowy_derive::ProtoBuf; -use lib_ot::{errors::OTError, rich_text::RichTextDelta}; +use lib_ot::{errors::OTError, revision::Revision, rich_text::RichTextDelta}; #[derive(ProtoBuf, Default, Debug, Clone)] pub struct CreateDocParams { @@ -41,6 +42,28 @@ impl Doc { } } +impl std::convert::TryFrom for Doc { + type Error = CollaborateError; + + fn try_from(revision: Revision) -> Result { + if !revision.is_initial() { + return Err( + CollaborateError::revision_conflict().context("Revision's rev_id should be 0 when creating the doc") + ); + } + + let delta = RichTextDelta::from_bytes(&revision.delta_data)?; + let doc_json = delta.to_json(); + + Ok(Doc { + id: revision.doc_id, + data: doc_json, + rev_id: revision.rev_id, + base_rev_id: revision.base_rev_id, + }) + } +} + #[derive(ProtoBuf, Default, Debug, Clone)] pub struct UpdateDocParams { #[pb(index = 1)] diff --git a/shared-lib/flowy-collaboration/src/entities/ws/ws.rs b/shared-lib/flowy-collaboration/src/entities/ws/ws.rs index f31ffd2bc2..3e41268aef 100644 --- a/shared-lib/flowy-collaboration/src/entities/ws/ws.rs +++ b/shared-lib/flowy-collaboration/src/entities/ws/ws.rs @@ -1,4 +1,4 @@ -use crate::{entities::doc::NewDocUser, errors::CollaborateError}; +use crate::errors::CollaborateError; use bytes::Bytes; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use lib_ot::revision::{RevId, Revision, RevisionRange}; @@ -7,13 +7,12 @@ use std::convert::{TryFrom, TryInto}; #[derive(Debug, Clone, ProtoBuf_Enum, Eq, PartialEq, Hash)] pub enum WsDataType { // The frontend receives the Acked means the backend has accepted the revision - Acked = 0, + Acked = 0, // The frontend receives the PushRev event means the backend is pushing the new revision to frontend - PushRev = 1, + PushRev = 1, // The fronted receives the PullRev event means the backend try to pull the revision from frontend - PullRev = 2, - Conflict = 3, - NewDocUser = 4, + PullRev = 2, + Conflict = 3, } impl WsDataType { @@ -53,18 +52,6 @@ impl std::convert::From for WsDocumentData { } } -impl std::convert::From for WsDocumentData { - fn from(user: NewDocUser) -> Self { - let doc_id = user.doc_id.clone(); - let bytes: Bytes = user.try_into().unwrap(); - Self { - doc_id, - ty: WsDataType::NewDocUser, - data: bytes.to_vec(), - } - } -} - pub struct WsDocumentDataBuilder(); impl WsDocumentDataBuilder { // WsDataType::PushRev -> Revision diff --git a/shared-lib/flowy-collaboration/src/errors.rs b/shared-lib/flowy-collaboration/src/errors.rs index d438444db4..767367ae23 100644 --- a/shared-lib/flowy-collaboration/src/errors.rs +++ b/shared-lib/flowy-collaboration/src/errors.rs @@ -38,6 +38,8 @@ impl CollaborateError { static_doc_error!(undo, ErrorCode::UndoFail); static_doc_error!(redo, ErrorCode::RedoFail); static_doc_error!(out_of_bound, ErrorCode::OutOfBound); + static_doc_error!(record_not_found, ErrorCode::RecordNotFound); + static_doc_error!(revision_conflict, ErrorCode::RevisionConflict); } impl fmt::Display for CollaborateError { @@ -46,12 +48,14 @@ impl fmt::Display for CollaborateError { #[derive(Debug, Clone, Display, PartialEq, Eq)] pub enum ErrorCode { - DocIdInvalid = 0, - DocNotfound = 1, - UndoFail = 200, - RedoFail = 201, - OutOfBound = 202, - InternalError = 1000, + DocIdInvalid = 0, + DocNotfound = 1, + UndoFail = 200, + RedoFail = 201, + OutOfBound = 202, + RevisionConflict = 203, + RecordNotFound = 300, + InternalError = 1000, } impl std::convert::From for CollaborateError { diff --git a/shared-lib/flowy-collaboration/src/protobuf/model/ws.rs b/shared-lib/flowy-collaboration/src/protobuf/model/ws.rs index 8e9387f84e..dbdcbe6569 100644 --- a/shared-lib/flowy-collaboration/src/protobuf/model/ws.rs +++ b/shared-lib/flowy-collaboration/src/protobuf/model/ws.rs @@ -261,7 +261,6 @@ pub enum WsDataType { PushRev = 1, PullRev = 2, Conflict = 3, - NewDocUser = 4, } impl ::protobuf::ProtobufEnum for WsDataType { @@ -275,7 +274,6 @@ impl ::protobuf::ProtobufEnum for WsDataType { 1 => ::std::option::Option::Some(WsDataType::PushRev), 2 => ::std::option::Option::Some(WsDataType::PullRev), 3 => ::std::option::Option::Some(WsDataType::Conflict), - 4 => ::std::option::Option::Some(WsDataType::NewDocUser), _ => ::std::option::Option::None } } @@ -286,7 +284,6 @@ impl ::protobuf::ProtobufEnum for WsDataType { WsDataType::PushRev, WsDataType::PullRev, WsDataType::Conflict, - WsDataType::NewDocUser, ]; values } @@ -317,31 +314,28 @@ impl ::protobuf::reflect::ProtobufValue for WsDataType { static file_descriptor_proto_data: &'static [u8] = b"\ \n\x08ws.proto\"X\n\x0eWsDocumentData\x12\x15\n\x06doc_id\x18\x01\x20\ \x01(\tR\x05docId\x12\x1b\n\x02ty\x18\x02\x20\x01(\x0e2\x0b.WsDataTypeR\ - \x02ty\x12\x12\n\x04data\x18\x03\x20\x01(\x0cR\x04data*O\n\nWsDataType\ + \x02ty\x12\x12\n\x04data\x18\x03\x20\x01(\x0cR\x04data*?\n\nWsDataType\ \x12\t\n\x05Acked\x10\0\x12\x0b\n\x07PushRev\x10\x01\x12\x0b\n\x07PullRe\ - v\x10\x02\x12\x0c\n\x08Conflict\x10\x03\x12\x0e\n\nNewDocUser\x10\x04J\ - \xb4\x03\n\x06\x12\x04\0\0\r\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\ - \x02\x04\0\x12\x04\x02\0\x06\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\x16\n\x0c\n\x05\x04\0\x02\0\x05\ - \x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\x0b\x11\n\x0c\ - \n\x05\x04\0\x02\0\x03\x12\x03\x03\x14\x15\n\x0b\n\x04\x04\0\x02\x01\x12\ - \x03\x04\x04\x16\n\x0c\n\x05\x04\0\x02\x01\x06\x12\x03\x04\x04\x0e\n\x0c\ - \n\x05\x04\0\x02\x01\x01\x12\x03\x04\x0f\x11\n\x0c\n\x05\x04\0\x02\x01\ - \x03\x12\x03\x04\x14\x15\n\x0b\n\x04\x04\0\x02\x02\x12\x03\x05\x04\x13\n\ - \x0c\n\x05\x04\0\x02\x02\x05\x12\x03\x05\x04\t\n\x0c\n\x05\x04\0\x02\x02\ - \x01\x12\x03\x05\n\x0e\n\x0c\n\x05\x04\0\x02\x02\x03\x12\x03\x05\x11\x12\ - \n\n\n\x02\x05\0\x12\x04\x07\0\r\x01\n\n\n\x03\x05\0\x01\x12\x03\x07\x05\ - \x0f\n\x0b\n\x04\x05\0\x02\0\x12\x03\x08\x04\x0e\n\x0c\n\x05\x05\0\x02\0\ - \x01\x12\x03\x08\x04\t\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x08\x0c\r\n\ - \x0b\n\x04\x05\0\x02\x01\x12\x03\t\x04\x10\n\x0c\n\x05\x05\0\x02\x01\x01\ - \x12\x03\t\x04\x0b\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\t\x0e\x0f\n\x0b\ - \n\x04\x05\0\x02\x02\x12\x03\n\x04\x10\n\x0c\n\x05\x05\0\x02\x02\x01\x12\ - \x03\n\x04\x0b\n\x0c\n\x05\x05\0\x02\x02\x02\x12\x03\n\x0e\x0f\n\x0b\n\ - \x04\x05\0\x02\x03\x12\x03\x0b\x04\x11\n\x0c\n\x05\x05\0\x02\x03\x01\x12\ - \x03\x0b\x04\x0c\n\x0c\n\x05\x05\0\x02\x03\x02\x12\x03\x0b\x0f\x10\n\x0b\ - \n\x04\x05\0\x02\x04\x12\x03\x0c\x04\x13\n\x0c\n\x05\x05\0\x02\x04\x01\ - \x12\x03\x0c\x04\x0e\n\x0c\n\x05\x05\0\x02\x04\x02\x12\x03\x0c\x11\x12b\ - \x06proto3\ + v\x10\x02\x12\x0c\n\x08Conflict\x10\x03J\x8b\x03\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\x06\ + \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\x16\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\ + \x05\x04\0\x02\0\x01\x12\x03\x03\x0b\x11\n\x0c\n\x05\x04\0\x02\0\x03\x12\ + \x03\x03\x14\x15\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x04\x04\x16\n\x0c\n\ + \x05\x04\0\x02\x01\x06\x12\x03\x04\x04\x0e\n\x0c\n\x05\x04\0\x02\x01\x01\ + \x12\x03\x04\x0f\x11\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x04\x14\x15\n\ + \x0b\n\x04\x04\0\x02\x02\x12\x03\x05\x04\x13\n\x0c\n\x05\x04\0\x02\x02\ + \x05\x12\x03\x05\x04\t\n\x0c\n\x05\x04\0\x02\x02\x01\x12\x03\x05\n\x0e\n\ + \x0c\n\x05\x04\0\x02\x02\x03\x12\x03\x05\x11\x12\n\n\n\x02\x05\0\x12\x04\ + \x07\0\x0c\x01\n\n\n\x03\x05\0\x01\x12\x03\x07\x05\x0f\n\x0b\n\x04\x05\0\ + \x02\0\x12\x03\x08\x04\x0e\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\x08\x04\t\ + \n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x08\x0c\r\n\x0b\n\x04\x05\0\x02\x01\ + \x12\x03\t\x04\x10\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\t\x04\x0b\n\x0c\ + \n\x05\x05\0\x02\x01\x02\x12\x03\t\x0e\x0f\n\x0b\n\x04\x05\0\x02\x02\x12\ + \x03\n\x04\x10\n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\n\x04\x0b\n\x0c\n\ + \x05\x05\0\x02\x02\x02\x12\x03\n\x0e\x0f\n\x0b\n\x04\x05\0\x02\x03\x12\ + \x03\x0b\x04\x11\n\x0c\n\x05\x05\0\x02\x03\x01\x12\x03\x0b\x04\x0c\n\x0c\ + \n\x05\x05\0\x02\x03\x02\x12\x03\x0b\x0f\x10b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/shared-lib/flowy-collaboration/src/protobuf/proto/ws.proto b/shared-lib/flowy-collaboration/src/protobuf/proto/ws.proto index 4c7865fd1b..423a3e3869 100644 --- a/shared-lib/flowy-collaboration/src/protobuf/proto/ws.proto +++ b/shared-lib/flowy-collaboration/src/protobuf/proto/ws.proto @@ -10,5 +10,4 @@ enum WsDataType { PushRev = 1; PullRev = 2; Conflict = 3; - NewDocUser = 4; } diff --git a/shared-lib/lib-ot/src/revision/cache.rs b/shared-lib/lib-ot/src/revision/cache.rs deleted file mode 100644 index 4e2dd40673..0000000000 --- a/shared-lib/lib-ot/src/revision/cache.rs +++ /dev/null @@ -1,140 +0,0 @@ -use crate::{ - errors::OTError, - revision::{Revision, RevisionRange}, -}; -use dashmap::DashMap; -use std::{collections::VecDeque, fmt::Debug, sync::Arc}; -use tokio::sync::{broadcast, RwLock}; - -pub trait RevisionDiskCache: Sync + Send { - type Error: Debug; - fn create_revisions(&self, revisions: Vec) -> Result<(), Self::Error>; - fn revisions_in_range(&self, doc_id: &str, range: &RevisionRange) -> Result, Self::Error>; - fn read_revision(&self, doc_id: &str, rev_id: i64) -> Result, Self::Error>; - fn read_revisions(&self, doc_id: &str) -> Result, Self::Error>; -} - -pub struct RevisionMemoryCache { - revs_map: Arc>, - pending_revs: Arc>>, -} - -impl std::default::Default for RevisionMemoryCache { - fn default() -> Self { - let pending_revs = Arc::new(RwLock::new(VecDeque::new())); - RevisionMemoryCache { - revs_map: Arc::new(DashMap::new()), - pending_revs, - } - } -} - -impl RevisionMemoryCache { - pub fn new() -> Self { RevisionMemoryCache::default() } - - pub async fn add_revision(&self, revision: Revision) -> Result<(), OTError> { - // The last revision's rev_id must be greater than the new one. - if let Some(rev_id) = self.pending_revs.read().await.back() { - if *rev_id >= revision.rev_id { - return Err(OTError::revision_id_conflict() - .context(format!("The new revision's id must be greater than {}", rev_id))); - } - } - - self.pending_revs.write().await.push_back(revision.rev_id); - self.revs_map.insert(revision.rev_id, RevisionRecord::new(revision)); - Ok(()) - } - - pub fn remove_revisions(&self, ids: Vec) { self.revs_map.retain(|k, _| !ids.contains(k)); } - - pub async fn ack_revision(&self, rev_id: &i64) { - if let Some(mut m_revision) = self.revs_map.get_mut(rev_id) { - m_revision.value_mut().ack(); - match self.pending_revs.write().await.pop_front() { - None => log::error!("The pending_revs should not be empty"), - Some(cache_rev_id) => { - assert_eq!(&cache_rev_id, rev_id); - }, - } - } else { - log::error!("Can't find revision with id {}", rev_id); - } - } - - pub async fn revisions_in_range(&self, range: &RevisionRange) -> Result, OTError> { - let revs = range - .iter() - .flat_map(|rev_id| match self.revs_map.get(&rev_id) { - None => None, - Some(rev) => Some(rev.revision.clone()), - }) - .collect::>(); - - if revs.len() == range.len() as usize { - Ok(revs) - } else { - Ok(vec![]) - } - } - - pub fn contains(&self, rev_id: &i64) -> bool { self.revs_map.contains_key(rev_id) } - - pub fn is_empty(&self) -> bool { self.revs_map.is_empty() } - - pub fn revisions(&self) -> (Vec, Vec) { - let mut records: Vec = vec![]; - let mut ids: Vec = vec![]; - - self.revs_map.iter().for_each(|kv| { - records.push(kv.value().clone()); - ids.push(*kv.key()); - }); - (ids, records) - } - - pub async fn query_revision(&self, rev_id: &i64) -> Option { - self.revs_map.get(&rev_id).map(|r| r.value().clone()) - } - - pub async fn front_revision(&self) -> Option<(i64, RevisionRecord)> { - match self.pending_revs.read().await.front() { - None => None, - Some(rev_id) => self.revs_map.get(rev_id).map(|r| (*r.key(), r.value().clone())), - } - } - - pub async fn front_rev_id(&self) -> Option { self.pending_revs.read().await.front().copied() } -} - -pub type RevIdReceiver = broadcast::Receiver; -pub type RevIdSender = broadcast::Sender; - -#[derive(Debug, Clone, Eq, PartialEq)] -pub enum RevState { - Local = 0, - Acked = 1, -} - -#[derive(Clone)] -pub struct RevisionRecord { - pub revision: Revision, - pub state: RevState, -} - -impl RevisionRecord { - pub fn new(revision: Revision) -> Self { - Self { - revision, - state: RevState::Local, - } - } - - pub fn ack(&mut self) { self.state = RevState::Acked; } -} - -#[cfg(feature = "flowy_unit_test")] -impl RevisionMemoryCache { - pub fn revs_map(&self) -> Arc> { self.revs_map.clone() } - pub fn pending_revs(&self) -> Arc>> { self.pending_revs.clone() } -} diff --git a/shared-lib/lib-ot/src/revision/mod.rs b/shared-lib/lib-ot/src/revision/mod.rs index 9848b59af1..4a7ebf60c1 100644 --- a/shared-lib/lib-ot/src/revision/mod.rs +++ b/shared-lib/lib-ot/src/revision/mod.rs @@ -1,5 +1,3 @@ -mod cache; mod model; -pub use cache::*; pub use model::*; diff --git a/shared-lib/lib-ot/src/revision/model.rs b/shared-lib/lib-ot/src/revision/model.rs index 63a56fc314..71b0a4e7d5 100644 --- a/shared-lib/lib-ot/src/revision/model.rs +++ b/shared-lib/lib-ot/src/revision/model.rs @@ -31,6 +31,8 @@ impl Revision { pub fn pair_rev_id(&self) -> (i64, i64) { (self.base_rev_id, self.rev_id) } + pub fn is_initial(&self) -> bool { self.rev_id == 0 } + // pub fn from_pb(pb: &mut crate::protobuf::Revision) -> Self { // pb.try_into().unwrap() } @@ -155,3 +157,9 @@ pub fn md5>(data: T) -> String { let md5 = format!("{:x}", md5::compute(data)); md5 } + +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum RevState { + Local = 0, + Acked = 1, +} From 72a8f7a9e3ac9d62ec91bf74e383550abd94e9ba Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 14 Dec 2021 15:31:44 +0800 Subject: [PATCH 26/39] mv websocket to flowy-net crate --- backend/Cargo.lock | 25 +- backend/Cargo.toml | 1 + backend/tests/document/helper.rs | 7 +- .../user/infrastructure/network_monitor.dart | 4 +- .../flowy_sdk/lib/dispatch/code_gen.dart | 34 +- .../flowy_sdk/lib/dispatch/dispatch.dart | 6 +- .../flowy_sdk/lib/dispatch/error.dart | 12 +- .../lib/protobuf/flowy-error/errors.pb.dart | 74 +++++ .../protobuf/flowy-error/errors.pbenum.dart | 24 ++ .../protobuf/flowy-error/errors.pbjson.dart | 31 ++ .../protobuf/flowy-error/errors.pbserver.dart | 9 + .../lib/protobuf/flowy-error/protobuf.dart | 2 + .../cache.pb.dart => flowy-net/event.pb.dart} | 4 +- .../lib/protobuf/flowy-net/event.pbenum.dart | 24 ++ .../event.pbjson.dart} | 15 +- .../event.pbserver.dart} | 4 +- .../lib/protobuf/flowy-net/protobuf.dart | 1 + .../lib/protobuf/flowy-user/event.pbenum.dart | 2 - .../lib/protobuf/flowy-user/event.pbjson.dart | 3 +- .../lib/protobuf/lib-ot/cache.pbenum.dart | 26 -- .../lib/protobuf/lib-ot/model.pbenum.dart | 15 + .../lib/protobuf/lib-ot/model.pbjson.dart | 11 + .../lib/protobuf/lib-ot/protobuf.dart | 1 - frontend/rust-lib/Cargo.toml | 1 + frontend/rust-lib/flowy-document/Cargo.toml | 2 +- .../src/services/doc/revision/cache/cache.rs | 4 +- .../src/services/doc/revision/cache/memory.rs | 2 +- .../src/services/ws/ws_manager.rs | 4 +- .../src/sql_tables/doc/rev_table.rs | 4 +- .../tests/editor/revision_test.rs | 10 +- frontend/rust-lib/flowy-error/Cargo.toml | 13 + frontend/rust-lib/flowy-error/Flowy.toml | 3 + frontend/rust-lib/flowy-error/src/errors.rs | 84 +++++ frontend/rust-lib/flowy-error/src/lib.rs | 4 + .../rust-lib/flowy-error/src/protobuf/mod.rs | 4 + .../flowy-error/src/protobuf/model/errors.rs | 293 ++++++++++++++++++ .../flowy-error/src/protobuf/model/mod.rs | 5 + .../src/protobuf/proto/errors.proto | 9 + frontend/rust-lib/flowy-net/Cargo.toml | 19 +- frontend/rust-lib/flowy-net/Flowy.toml | 4 +- frontend/rust-lib/flowy-net/src/event.rs | 9 + .../rust-lib/flowy-net/src/handlers/mod.rs | 12 + frontend/rust-lib/flowy-net/src/lib.rs | 4 + frontend/rust-lib/flowy-net/src/module.rs | 10 + .../flowy-net/src/protobuf/model/event.rs | 41 ++- .../flowy-net/src/protobuf/model/mod.rs | 3 + .../flowy-net/src/protobuf/proto/event.proto | 5 + .../flowy-net/src/services/mock/mod.rs | 3 + .../src/services/mock}/ws_mock.rs | 26 +- .../rust-lib/flowy-net/src/services/mod.rs | 4 + .../flowy-net/src/services/ws/conn.rs | 18 ++ .../src/services/ws/manager.rs} | 94 +++--- .../rust-lib/flowy-net/src/services/ws/mod.rs | 15 + .../src/services/ws}/ws_local.rs | 16 +- .../src/deps_resolve/document_deps.rs | 33 +- frontend/rust-lib/flowy-sdk/src/lib.rs | 63 ++-- frontend/rust-lib/flowy-sdk/src/module.rs | 18 +- frontend/rust-lib/flowy-user/Cargo.toml | 6 +- frontend/rust-lib/flowy-user/src/errors.rs | 10 - frontend/rust-lib/flowy-user/src/event.rs | 17 +- .../flowy-user/src/handlers/user_handler.rs | 7 - frontend/rust-lib/flowy-user/src/module.rs | 1 - .../flowy-user/src/protobuf/model/event.rs | 46 ++- .../flowy-user/src/protobuf/proto/event.proto | 1 - .../flowy-user/src/services/server/mod.rs | 11 - .../flowy-user/src/services/user/mod.rs | 1 - .../flowy-user/src/services/user/notifier.rs | 15 +- .../src/services/user/user_session.rs | 39 +-- shared-lib/flowy-collaboration/src/lib.rs | 2 + .../src/derive_cache/derive_cache.rs | 3 + shared-lib/lib-ot/src/protobuf/model/mod.rs | 3 - shared-lib/lib-ot/src/protobuf/model/model.rs | 62 +++- .../lib-ot/src/protobuf/proto/cache.proto | 6 - .../lib-ot/src/protobuf/proto/model.proto | 4 + shared-lib/lib-ot/src/revision/model.rs | 10 +- 75 files changed, 1042 insertions(+), 376 deletions(-) create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/errors.pb.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/errors.pbenum.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/errors.pbjson.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/errors.pbserver.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/protobuf.dart rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{lib-ot/cache.pb.dart => flowy-net/event.pb.dart} (85%) create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/event.pbenum.dart rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{lib-ot/cache.pbjson.dart => flowy-net/event.pbjson.dart} (52%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{lib-ot/cache.pbserver.dart => flowy-net/event.pbserver.dart} (86%) delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pbenum.dart create mode 100644 frontend/rust-lib/flowy-error/Cargo.toml create mode 100644 frontend/rust-lib/flowy-error/Flowy.toml create mode 100644 frontend/rust-lib/flowy-error/src/errors.rs create mode 100644 frontend/rust-lib/flowy-error/src/lib.rs create mode 100644 frontend/rust-lib/flowy-error/src/protobuf/mod.rs create mode 100644 frontend/rust-lib/flowy-error/src/protobuf/model/errors.rs create mode 100644 frontend/rust-lib/flowy-error/src/protobuf/model/mod.rs create mode 100644 frontend/rust-lib/flowy-error/src/protobuf/proto/errors.proto create mode 100644 frontend/rust-lib/flowy-net/src/event.rs create mode 100644 frontend/rust-lib/flowy-net/src/handlers/mod.rs create mode 100644 frontend/rust-lib/flowy-net/src/module.rs rename shared-lib/lib-ot/src/protobuf/model/cache.rs => frontend/rust-lib/flowy-net/src/protobuf/model/event.rs (60%) create mode 100644 frontend/rust-lib/flowy-net/src/protobuf/proto/event.proto create mode 100644 frontend/rust-lib/flowy-net/src/services/mock/mod.rs rename frontend/rust-lib/{flowy-user/src/services/server => flowy-net/src/services/mock}/ws_mock.rs (88%) create mode 100644 frontend/rust-lib/flowy-net/src/services/mod.rs create mode 100644 frontend/rust-lib/flowy-net/src/services/ws/conn.rs rename frontend/rust-lib/{flowy-user/src/services/user/ws_manager.rs => flowy-net/src/services/ws/manager.rs} (63%) create mode 100644 frontend/rust-lib/flowy-net/src/services/ws/mod.rs rename frontend/rust-lib/{flowy-user/src/services/server => flowy-net/src/services/ws}/ws_local.rs (58%) delete mode 100644 shared-lib/lib-ot/src/protobuf/proto/cache.proto diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 95141607db..2da79b9ed7 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -458,6 +458,7 @@ dependencies = [ "flowy-collaboration", "flowy-core-infra", "flowy-document", + "flowy-net", "flowy-sdk", "flowy-test", "flowy-user", @@ -1339,14 +1340,35 @@ dependencies = [ ] [[package]] -name = "flowy-net" +name = "flowy-error" version = "0.1.0" dependencies = [ "bytes", + "derive_more", "flowy-derive", + "lib-dispatch", "protobuf", ] +[[package]] +name = "flowy-net" +version = "0.1.0" +dependencies = [ + "anyhow", + "bytes", + "flowy-derive", + "flowy-error", + "lib-dispatch", + "lib-infra", + "lib-ws", + "parking_lot", + "protobuf", + "strum", + "strum_macros", + "tokio", + "tracing", +] + [[package]] name = "flowy-sdk" version = "0.1.0" @@ -1416,7 +1438,6 @@ dependencies = [ "lib-dispatch", "lib-infra", "lib-sqlite", - "lib-ws", "log", "once_cell", "parking_lot", diff --git a/backend/Cargo.toml b/backend/Cargo.toml index dc601fce18..80db14c2cb 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -103,4 +103,5 @@ flowy-sdk = { path = "../frontend/rust-lib/flowy-sdk", features = ["http_server" flowy-user = { path = "../frontend/rust-lib/flowy-user", features = ["http_server"] } flowy-document = { path = "../frontend/rust-lib/flowy-document", features = ["flowy_unit_test", "http_server"] } flowy-test = { path = "../frontend/rust-lib/flowy-test" } +flowy-net = { path = "../frontend/rust-lib/flowy-net" } diff --git a/backend/tests/document/helper.rs b/backend/tests/document/helper.rs index 182bd32448..f8df4bbabf 100644 --- a/backend/tests/document/helper.rs +++ b/backend/tests/document/helper.rs @@ -16,6 +16,7 @@ use lib_ot::rich_text::{RichTextAttribute, RichTextDelta}; use parking_lot::RwLock; use lib_ot::core::Interval; use flowy_collaboration::core::sync::ServerDocManager; +use flowy_net::services::ws::WsManager; pub struct DocumentTest { server: TestServer, @@ -53,6 +54,7 @@ struct ScriptContext { client_edit_context: Option>, client_sdk: FlowySDKTest, client_user_session: Arc, + ws_manager: Arc, server_doc_manager: Arc, server_pg_pool: Data, doc_id: String, @@ -61,12 +63,14 @@ struct ScriptContext { impl ScriptContext { async fn new(client_sdk: FlowySDKTest, server: TestServer) -> Self { let user_session = client_sdk.user_session.clone(); + let ws_manager = client_sdk.ws_manager.clone(); let doc_id = create_doc(&client_sdk).await; Self { client_edit_context: None, client_sdk, client_user_session: user_session, + ws_manager, server_doc_manager: server.app_ctx.document_core.manager.clone(), server_pg_pool: Data::new(server.pg_pool.clone()), doc_id, @@ -99,9 +103,10 @@ async fn run_scripts(context: Arc>, scripts: Vec { // sleep(Duration::from_millis(300)).await; + let ws_manager = context.read().ws_manager.clone(); let user_session = context.read().client_user_session.clone(); let token = user_session.token().unwrap(); - let _ = user_session.start_ws_connection(&token).await.unwrap(); + let _ = ws_manager.start(token).await.unwrap(); }, DocScript::ClientOpenDoc => { context.write().open_doc().await; diff --git a/frontend/app_flowy/lib/user/infrastructure/network_monitor.dart b/frontend/app_flowy/lib/user/infrastructure/network_monitor.dart index acc7dbd070..dd00d49222 100644 --- a/frontend/app_flowy/lib/user/infrastructure/network_monitor.dart +++ b/frontend/app_flowy/lib/user/infrastructure/network_monitor.dart @@ -3,7 +3,7 @@ import 'dart:async'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; -import 'package:flowy_sdk/protobuf/lib-infra/protobuf.dart'; +import 'package:flowy_sdk/protobuf/flowy-net/network_state.pb.dart'; import 'package:flutter/services.dart'; class NetworkMonitor { @@ -45,7 +45,7 @@ class NetworkMonitor { }(); Log.info("Network type: $networkType"); final state = NetworkState.create()..ty = networkType; - UserEventUpdateNetworkType(state).send().then((result) { + NetworkEventUpdateNetworkType(state).send().then((result) { result.fold( (l) {}, (e) => Log.error(e), diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/code_gen.dart b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/code_gen.dart index 6bf25230db..b3ffb53705 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/code_gen.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/code_gen.dart @@ -412,6 +412,23 @@ class WorkspaceEventExportDocument { } } +class NetworkEventUpdateNetworkType { + NetworkState request; + NetworkEventUpdateNetworkType(this.request); + + Future> send() { + final request = FFIRequest.create() + ..event = NetworkEvent.UpdateNetworkType.toString() + ..payload = requestToBytes(this.request); + + return Dispatch.asyncRequest(request) + .then((bytesResult) => bytesResult.fold( + (bytes) => left(unit), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), + )); + } +} + class UserEventInitUser { UserEventInitUser(); @@ -519,20 +536,3 @@ class UserEventCheckUser { } } -class UserEventUpdateNetworkType { - NetworkState request; - UserEventUpdateNetworkType(this.request); - - Future> send() { - final request = FFIRequest.create() - ..event = UserEvent.UpdateNetworkType.toString() - ..payload = requestToBytes(this.request); - - return Dispatch.asyncRequest(request) - .then((bytesResult) => bytesResult.fold( - (bytes) => left(unit), - (errBytes) => right(UserError.fromBuffer(errBytes)), - )); - } -} - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart index cdfdad7631..157693177c 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart @@ -3,6 +3,8 @@ import 'package:dartz/dartz.dart'; import 'package:flowy_log/flowy_log.dart'; // ignore: unnecessary_import import 'package:flowy_sdk/protobuf/dart-ffi/ffi_response.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-net/event.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-net/network_state.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user/event.pb.dart'; @@ -53,7 +55,7 @@ class Dispatch { } } -Future> _extractPayload(Future> responseFuture) { +Future> _extractPayload(Future> responseFuture) { return responseFuture.then((result) { return result.fold( (response) { @@ -79,7 +81,7 @@ Future> _extractPayload(Future> _extractResponse(Completer bytesFuture) { +Future> _extractResponse(Completer bytesFuture) { return bytesFuture.future.then((bytes) { try { final response = FFIResponse.fromBuffer(bytes); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/error.dart b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/error.dart index ec1e06834b..b29a37f280 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/error.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/error.dart @@ -1,6 +1,6 @@ import 'package:flowy_sdk/protobuf/dart-ffi/protobuf.dart'; -class FlowyError { +class FlowyInternalError { late FFIStatusCode _statusCode; late String _error; @@ -20,13 +20,13 @@ class FlowyError { return "$_statusCode: $_error"; } - FlowyError({required FFIStatusCode statusCode, required String error}) { + FlowyInternalError({required FFIStatusCode statusCode, required String error}) { _statusCode = statusCode; _error = error; } - factory FlowyError.from(FFIResponse resp) { - return FlowyError(statusCode: resp.code, error: ""); + factory FlowyInternalError.from(FFIResponse resp) { + return FlowyInternalError(statusCode: resp.code, error: ""); } } @@ -38,8 +38,8 @@ class StackTraceError { this.trace, ); - FlowyError asFlowyError() { - return FlowyError(statusCode: FFIStatusCode.Err, error: this.toString()); + FlowyInternalError asFlowyError() { + return FlowyInternalError(statusCode: FFIStatusCode.Err, error: this.toString()); } String toString() { diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/errors.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/errors.pb.dart new file mode 100644 index 0000000000..7d0a6cb8f4 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/errors.pb.dart @@ -0,0 +1,74 @@ +/// +// Generated code. Do not modify. +// source: errors.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; + +export 'errors.pbenum.dart'; + +class FlowyError extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'FlowyError', createEmptyInstance: create) + ..a<$core.int>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'code', $pb.PbFieldType.O3) + ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'msg') + ..hasRequiredFields = false + ; + + FlowyError._() : super(); + factory FlowyError({ + $core.int? code, + $core.String? msg, + }) { + final _result = create(); + if (code != null) { + _result.code = code; + } + if (msg != null) { + _result.msg = msg; + } + return _result; + } + factory FlowyError.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory FlowyError.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + FlowyError clone() => FlowyError()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + FlowyError copyWith(void Function(FlowyError) updates) => super.copyWith((message) => updates(message as FlowyError)) as FlowyError; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static FlowyError create() => FlowyError._(); + FlowyError createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static FlowyError getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static FlowyError? _defaultInstance; + + @$pb.TagNumber(1) + $core.int get code => $_getIZ(0); + @$pb.TagNumber(1) + set code($core.int v) { $_setSignedInt32(0, v); } + @$pb.TagNumber(1) + $core.bool hasCode() => $_has(0); + @$pb.TagNumber(1) + void clearCode() => clearField(1); + + @$pb.TagNumber(2) + $core.String get msg => $_getSZ(1); + @$pb.TagNumber(2) + set msg($core.String v) { $_setString(1, v); } + @$pb.TagNumber(2) + $core.bool hasMsg() => $_has(1); + @$pb.TagNumber(2) + void clearMsg() => clearField(2); +} + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/errors.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/errors.pbenum.dart new file mode 100644 index 0000000000..8d31a7370b --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/errors.pbenum.dart @@ -0,0 +1,24 @@ +/// +// Generated code. Do not modify. +// source: errors.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields + +// ignore_for_file: UNDEFINED_SHOWN_NAME +import 'dart:core' as $core; +import 'package:protobuf/protobuf.dart' as $pb; + +class ErrorCode extends $pb.ProtobufEnum { + static const ErrorCode Internal = ErrorCode._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Internal'); + + static const $core.List values = [ + Internal, + ]; + + static final $core.Map<$core.int, ErrorCode> _byValue = $pb.ProtobufEnum.initByValue(values); + static ErrorCode? valueOf($core.int value) => _byValue[value]; + + const ErrorCode._($core.int v, $core.String n) : super(v, n); +} + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/errors.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/errors.pbjson.dart new file mode 100644 index 0000000000..b9209928ce --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/errors.pbjson.dart @@ -0,0 +1,31 @@ +/// +// Generated code. Do not modify. +// source: errors.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package + +import 'dart:core' as $core; +import 'dart:convert' as $convert; +import 'dart:typed_data' as $typed_data; +@$core.Deprecated('Use errorCodeDescriptor instead') +const ErrorCode$json = const { + '1': 'ErrorCode', + '2': const [ + const {'1': 'Internal', '2': 0}, + ], +}; + +/// Descriptor for `ErrorCode`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSDAoISW50ZXJuYWwQAA=='); +@$core.Deprecated('Use flowyErrorDescriptor instead') +const FlowyError$json = const { + '1': 'FlowyError', + '2': const [ + const {'1': 'code', '3': 1, '4': 1, '5': 5, '10': 'code'}, + const {'1': 'msg', '3': 2, '4': 1, '5': 9, '10': 'msg'}, + ], +}; + +/// Descriptor for `FlowyError`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List flowyErrorDescriptor = $convert.base64Decode('CgpGbG93eUVycm9yEhIKBGNvZGUYASABKAVSBGNvZGUSEAoDbXNnGAIgASgJUgNtc2c='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/errors.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/errors.pbserver.dart new file mode 100644 index 0000000000..18b02b9216 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/errors.pbserver.dart @@ -0,0 +1,9 @@ +/// +// Generated code. Do not modify. +// source: errors.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package + +export 'errors.pb.dart'; + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/protobuf.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/protobuf.dart new file mode 100644 index 0000000000..92eb134641 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/protobuf.dart @@ -0,0 +1,2 @@ +// Auto-generated, do not edit +export './errors.pb.dart'; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/event.pb.dart similarity index 85% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pb.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/event.pb.dart index e9456cbd1a..e8db14dba5 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/event.pb.dart @@ -1,11 +1,11 @@ /// // Generated code. Do not modify. -// source: cache.proto +// source: event.proto // // @dart = 2.12 // ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields import 'dart:core' as $core; -export 'cache.pbenum.dart'; +export 'event.pbenum.dart'; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/event.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/event.pbenum.dart new file mode 100644 index 0000000000..e62309f118 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/event.pbenum.dart @@ -0,0 +1,24 @@ +/// +// Generated code. Do not modify. +// source: event.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields + +// ignore_for_file: UNDEFINED_SHOWN_NAME +import 'dart:core' as $core; +import 'package:protobuf/protobuf.dart' as $pb; + +class NetworkEvent extends $pb.ProtobufEnum { + static const NetworkEvent UpdateNetworkType = NetworkEvent._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateNetworkType'); + + static const $core.List values = [ + UpdateNetworkType, + ]; + + static final $core.Map<$core.int, NetworkEvent> _byValue = $pb.ProtobufEnum.initByValue(values); + static NetworkEvent? valueOf($core.int value) => _byValue[value]; + + const NetworkEvent._($core.int v, $core.String n) : super(v, n); +} + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/event.pbjson.dart similarity index 52% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pbjson.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/event.pbjson.dart index 43aeaa15e4..1532f9d83d 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/event.pbjson.dart @@ -1,6 +1,6 @@ /// // Generated code. Do not modify. -// source: cache.proto +// source: event.proto // // @dart = 2.12 // ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package @@ -8,14 +8,13 @@ import 'dart:core' as $core; import 'dart:convert' as $convert; import 'dart:typed_data' as $typed_data; -@$core.Deprecated('Use revStateDescriptor instead') -const RevState$json = const { - '1': 'RevState', +@$core.Deprecated('Use networkEventDescriptor instead') +const NetworkEvent$json = const { + '1': 'NetworkEvent', '2': const [ - const {'1': 'Local', '2': 0}, - const {'1': 'Acked', '2': 1}, + const {'1': 'UpdateNetworkType', '2': 0}, ], }; -/// Descriptor for `RevState`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List revStateDescriptor = $convert.base64Decode('CghSZXZTdGF0ZRIJCgVMb2NhbBAAEgkKBUFja2VkEAE='); +/// Descriptor for `NetworkEvent`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List networkEventDescriptor = $convert.base64Decode('CgxOZXR3b3JrRXZlbnQSFQoRVXBkYXRlTmV0d29ya1R5cGUQAA=='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/event.pbserver.dart similarity index 86% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pbserver.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/event.pbserver.dart index 0bdfceba59..534f858805 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pbserver.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/event.pbserver.dart @@ -1,9 +1,9 @@ /// // Generated code. Do not modify. -// source: cache.proto +// source: event.proto // // @dart = 2.12 // ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package -export 'cache.pb.dart'; +export 'event.pb.dart'; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/protobuf.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/protobuf.dart index 53a97620cf..8d2a575e3c 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/protobuf.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-net/protobuf.dart @@ -1,2 +1,3 @@ // Auto-generated, do not edit export './network_state.pb.dart'; +export './event.pb.dart'; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/event.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/event.pbenum.dart index 34ad829d5d..d796c4d703 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/event.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/event.pbenum.dart @@ -17,7 +17,6 @@ class UserEvent extends $pb.ProtobufEnum { static const UserEvent UpdateUser = UserEvent._(4, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateUser'); static const UserEvent GetUserProfile = UserEvent._(5, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetUserProfile'); static const UserEvent CheckUser = UserEvent._(6, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CheckUser'); - static const UserEvent UpdateNetworkType = UserEvent._(10, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateNetworkType'); static const $core.List values = [ InitUser, @@ -27,7 +26,6 @@ class UserEvent extends $pb.ProtobufEnum { UpdateUser, GetUserProfile, CheckUser, - UpdateNetworkType, ]; static final $core.Map<$core.int, UserEvent> _byValue = $pb.ProtobufEnum.initByValue(values); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/event.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/event.pbjson.dart index 6fb8a1c3fe..ccdf428e2a 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/event.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/event.pbjson.dart @@ -19,9 +19,8 @@ const UserEvent$json = const { const {'1': 'UpdateUser', '2': 4}, const {'1': 'GetUserProfile', '2': 5}, const {'1': 'CheckUser', '2': 6}, - const {'1': 'UpdateNetworkType', '2': 10}, ], }; /// Descriptor for `UserEvent`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List userEventDescriptor = $convert.base64Decode('CglVc2VyRXZlbnQSDAoISW5pdFVzZXIQABIKCgZTaWduSW4QARIKCgZTaWduVXAQAhILCgdTaWduT3V0EAMSDgoKVXBkYXRlVXNlchAEEhIKDkdldFVzZXJQcm9maWxlEAUSDQoJQ2hlY2tVc2VyEAYSFQoRVXBkYXRlTmV0d29ya1R5cGUQCg=='); +final $typed_data.Uint8List userEventDescriptor = $convert.base64Decode('CglVc2VyRXZlbnQSDAoISW5pdFVzZXIQABIKCgZTaWduSW4QARIKCgZTaWduVXAQAhILCgdTaWduT3V0EAMSDgoKVXBkYXRlVXNlchAEEhIKDkdldFVzZXJQcm9maWxlEAUSDQoJQ2hlY2tVc2VyEAY='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pbenum.dart deleted file mode 100644 index 176438ae6f..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/cache.pbenum.dart +++ /dev/null @@ -1,26 +0,0 @@ -/// -// Generated code. Do not modify. -// source: cache.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields - -// ignore_for_file: UNDEFINED_SHOWN_NAME -import 'dart:core' as $core; -import 'package:protobuf/protobuf.dart' as $pb; - -class RevState extends $pb.ProtobufEnum { - static const RevState Local = RevState._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Local'); - static const RevState Acked = RevState._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Acked'); - - static const $core.List values = [ - Local, - Acked, - ]; - - static final $core.Map<$core.int, RevState> _byValue = $pb.ProtobufEnum.initByValue(values); - static RevState? valueOf($core.int value) => _byValue[value]; - - const RevState._($core.int v, $core.String n) : super(v, n); -} - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/model.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/model.pbenum.dart index cd22cc9f89..633223586d 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/model.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/model.pbenum.dart @@ -24,3 +24,18 @@ class RevType extends $pb.ProtobufEnum { const RevType._($core.int v, $core.String n) : super(v, n); } +class RevState extends $pb.ProtobufEnum { + static const RevState StateLocal = RevState._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'StateLocal'); + static const RevState Acked = RevState._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Acked'); + + static const $core.List values = [ + StateLocal, + Acked, + ]; + + static final $core.Map<$core.int, RevState> _byValue = $pb.ProtobufEnum.initByValue(values); + static RevState? valueOf($core.int value) => _byValue[value]; + + const RevState._($core.int v, $core.String n) : super(v, n); +} + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/model.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/model.pbjson.dart index 5cc16b7fec..df78b21498 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/model.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/model.pbjson.dart @@ -19,6 +19,17 @@ const RevType$json = const { /// Descriptor for `RevType`. Decode as a `google.protobuf.EnumDescriptorProto`. final $typed_data.Uint8List revTypeDescriptor = $convert.base64Decode('CgdSZXZUeXBlEgkKBUxvY2FsEAASCgoGUmVtb3RlEAE='); +@$core.Deprecated('Use revStateDescriptor instead') +const RevState$json = const { + '1': 'RevState', + '2': const [ + const {'1': 'StateLocal', '2': 0}, + const {'1': 'Acked', '2': 1}, + ], +}; + +/// Descriptor for `RevState`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List revStateDescriptor = $convert.base64Decode('CghSZXZTdGF0ZRIOCgpTdGF0ZUxvY2FsEAASCQoFQWNrZWQQAQ=='); @$core.Deprecated('Use revisionDescriptor instead') const Revision$json = const { '1': 'Revision', diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/protobuf.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/protobuf.dart index 53ea90df40..f524faf0c8 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/protobuf.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ot/protobuf.dart @@ -1,3 +1,2 @@ // Auto-generated, do not edit -export './cache.pb.dart'; export './model.pb.dart'; diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index ebbed5a541..166b328009 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -11,6 +11,7 @@ members = [ "flowy-core", "dart-notify", "flowy-document", + "flowy-error", ] exclude = ["../backend"] diff --git a/frontend/rust-lib/flowy-document/Cargo.toml b/frontend/rust-lib/flowy-document/Cargo.toml index aeb078946c..2f949ff0f9 100644 --- a/frontend/rust-lib/flowy-document/Cargo.toml +++ b/frontend/rust-lib/flowy-document/Cargo.toml @@ -52,7 +52,7 @@ color-eyre = { version = "0.5", default-features = false } criterion = "0.3" rand = "0.7.3" env_logger = "0.8.2" -flowy-user = { path = "../flowy-user", features = ["ws_mock"] } +flowy-net = { path = "../flowy-net", features = ["ws_mock"] } [features] http_server = [] diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs index 8d85696203..2eaeb75f63 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs @@ -63,7 +63,7 @@ impl RevisionCache { } let record = RevisionRecord { revision, - state: RevState::Local, + state: RevState::StateLocal, }; self.memory_cache.add_revision(record).await?; self.save_revisions().await; @@ -77,7 +77,7 @@ impl RevisionCache { } let record = RevisionRecord { revision, - state: RevState::Local, + state: RevState::StateLocal, }; self.memory_cache.add_revision(record).await?; self.save_revisions().await; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/memory.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/memory.rs index ca590e57cd..de33fb9af2 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/memory.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/memory.rs @@ -35,7 +35,7 @@ impl RevisionMemoryCache { } match record.state { - RevState::Local => { + RevState::StateLocal => { tracing::debug!("{}:add revision {}", record.revision.doc_id, record.revision.rev_id); self.local_revs.write().await.push_back(record.revision.rev_id); }, diff --git a/frontend/rust-lib/flowy-document/src/services/ws/ws_manager.rs b/frontend/rust-lib/flowy-document/src/services/ws/ws_manager.rs index 8a24549f2c..eb2c8cc0cb 100644 --- a/frontend/rust-lib/flowy-document/src/services/ws/ws_manager.rs +++ b/frontend/rust-lib/flowy-document/src/services/ws/ws_manager.rs @@ -13,7 +13,7 @@ pub(crate) trait WsDocumentHandler: Send + Sync { pub type WsStateReceiver = tokio::sync::broadcast::Receiver; pub trait DocumentWebSocket: Send + Sync { fn send(&self, data: WsDocumentData) -> Result<(), DocError>; - fn state_notify(&self) -> WsStateReceiver; + fn subscribe_state_changed(&self) -> WsStateReceiver; } pub struct WsDocumentManager { @@ -56,7 +56,7 @@ impl WsDocumentManager { #[tracing::instrument(level = "debug", skip(ws, handlers))] fn listen_ws_state_changed(ws: Arc, handlers: Arc>>) { - let mut notify = ws.state_notify(); + let mut notify = ws.subscribe_state_changed(); tokio::spawn(async move { while let Ok(state) = notify.recv().await { handlers.iter().for_each(|handle| { diff --git a/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_table.rs b/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_table.rs index 2db34d293a..d6ef355c5f 100644 --- a/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_table.rs +++ b/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_table.rs @@ -49,7 +49,7 @@ impl_sql_integer_expression!(RevTableState); impl std::convert::From for RevState { fn from(s: RevTableState) -> Self { match s { - RevTableState::Local => RevState::Local, + RevTableState::Local => RevState::StateLocal, RevTableState::Acked => RevState::Acked, } } @@ -58,7 +58,7 @@ impl std::convert::From for RevState { impl std::convert::From for RevTableState { fn from(s: RevState) -> Self { match s { - RevState::Local => RevTableState::Local, + RevState::StateLocal => RevTableState::Local, RevState::Acked => RevTableState::Acked, } } diff --git a/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs b/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs index aa2f425b4b..6071795d0c 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs @@ -6,7 +6,7 @@ async fn doc_rev_state_test1() { let scripts = vec![ InsertText("123", 0), AssertCurrentRevId(1), - AssertRevisionState(1, RevState::Local), + AssertRevisionState(1, RevState::StateLocal), SimulateAckedMessage(1), AssertRevisionState(1, RevState::Acked), AssertNextSendingRevision(None), @@ -22,9 +22,9 @@ async fn doc_rev_state_test2() { InsertText("2", 1), InsertText("3", 2), AssertCurrentRevId(3), - AssertRevisionState(1, RevState::Local), - AssertRevisionState(2, RevState::Local), - AssertRevisionState(3, RevState::Local), + AssertRevisionState(1, RevState::StateLocal), + AssertRevisionState(2, RevState::StateLocal), + AssertRevisionState(3, RevState::StateLocal), SimulateAckedMessage(1), AssertRevisionState(1, RevState::Acked), AssertNextSendingRevision(Some(2)), @@ -32,7 +32,7 @@ async fn doc_rev_state_test2() { AssertRevisionState(2, RevState::Acked), // AssertNextSendingRevision(Some(3)), - AssertRevisionState(3, RevState::Local), + AssertRevisionState(3, RevState::StateLocal), AssertJson(r#"[{"insert":"123\n"}]"#), ]; EditorTest::new().await.run_scripts(scripts).await; diff --git a/frontend/rust-lib/flowy-error/Cargo.toml b/frontend/rust-lib/flowy-error/Cargo.toml new file mode 100644 index 0000000000..b738a43422 --- /dev/null +++ b/frontend/rust-lib/flowy-error/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "flowy-error" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +flowy-derive = { path = "../../../shared-lib/flowy-derive" } +derive_more = {version = "0.99", features = ["display"]} +lib-dispatch = { path = "../lib-dispatch" } +protobuf = {version = "2.20.0"} +bytes = "1.0" \ No newline at end of file diff --git a/frontend/rust-lib/flowy-error/Flowy.toml b/frontend/rust-lib/flowy-error/Flowy.toml new file mode 100644 index 0000000000..1c5d489f5b --- /dev/null +++ b/frontend/rust-lib/flowy-error/Flowy.toml @@ -0,0 +1,3 @@ + +proto_crates = ["src/errors.rs",] +event_files = [] \ No newline at end of file diff --git a/frontend/rust-lib/flowy-error/src/errors.rs b/frontend/rust-lib/flowy-error/src/errors.rs new file mode 100644 index 0000000000..e79b08bee8 --- /dev/null +++ b/frontend/rust-lib/flowy-error/src/errors.rs @@ -0,0 +1,84 @@ +use crate::protobuf::ErrorCode as ProtoBufErrorCode; +use bytes::Bytes; +use derive_more::Display; +use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; +use lib_dispatch::prelude::{EventResponse, ResponseBuilder}; +use protobuf::ProtobufEnum; +use std::{ + convert::{TryFrom, TryInto}, + fmt::Debug, +}; + +#[derive(Debug, Default, Clone, ProtoBuf)] +pub struct FlowyError { + #[pb(index = 1)] + pub code: i32, + + #[pb(index = 2)] + pub msg: String, +} + +macro_rules! static_any_error { + ($name:ident, $code:expr) => { + #[allow(non_snake_case, missing_docs)] + pub fn $name() -> FlowyError { $code.into() } + }; +} + +impl FlowyError { + pub fn new(code: ErrorCode, msg: &str) -> Self { + Self { + code: code.value(), + msg: msg.to_owned(), + } + } + pub fn context(mut self, error: T) -> Self { + self.msg = format!("{:?}", error); + self + } + + static_any_error!(internal, ErrorCode::Internal); +} + +impl std::convert::From for FlowyError { + fn from(code: ErrorCode) -> Self { + FlowyError { + code: code.value(), + msg: format!("{}", code), + } + } +} + +#[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(e: T) -> FlowyError +where + T: std::fmt::Debug, +{ + FlowyError::internal().context(e) +} + +impl lib_dispatch::Error for FlowyError { + fn as_response(&self) -> EventResponse { + let bytes: Bytes = self.clone().try_into().unwrap(); + ResponseBuilder::Err().data(bytes).build() + } +} diff --git a/frontend/rust-lib/flowy-error/src/lib.rs b/frontend/rust-lib/flowy-error/src/lib.rs new file mode 100644 index 0000000000..e7c6be4852 --- /dev/null +++ b/frontend/rust-lib/flowy-error/src/lib.rs @@ -0,0 +1,4 @@ +mod errors; +pub mod protobuf; + +pub use errors::*; diff --git a/frontend/rust-lib/flowy-error/src/protobuf/mod.rs b/frontend/rust-lib/flowy-error/src/protobuf/mod.rs new file mode 100644 index 0000000000..da97aad28a --- /dev/null +++ b/frontend/rust-lib/flowy-error/src/protobuf/mod.rs @@ -0,0 +1,4 @@ +#![cfg_attr(rustfmt, rustfmt::skip)] +// Auto-generated, do not edit +mod model; +pub use model::*; \ No newline at end of file diff --git a/frontend/rust-lib/flowy-error/src/protobuf/model/errors.rs b/frontend/rust-lib/flowy-error/src/protobuf/model/errors.rs new file mode 100644 index 0000000000..e30f60612c --- /dev/null +++ b/frontend/rust-lib/flowy-error/src/protobuf/model/errors.rs @@ -0,0 +1,293 @@ +// 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 FlowyError { + // 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 FlowyError { + fn default() -> &'a FlowyError { + ::default_instance() + } +} + +impl FlowyError { + pub fn new() -> FlowyError { + ::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 FlowyError { + 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) -> ::std::boxed::Box { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + Self::descriptor_static() + } + + fn new() -> FlowyError { + FlowyError::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: &FlowyError| { &m.code }, + |m: &mut FlowyError| { &mut m.code }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "msg", + |m: &FlowyError| { &m.msg }, + |m: &mut FlowyError| { &mut m.msg }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "FlowyError", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static FlowyError { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(FlowyError::new) + } +} + +impl ::protobuf::Clear for FlowyError { + fn clear(&mut self) { + self.code = 0; + self.msg.clear(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for FlowyError { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for FlowyError { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + +#[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 { + 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", 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\ +"; + +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() + }) +} diff --git a/frontend/rust-lib/flowy-error/src/protobuf/model/mod.rs b/frontend/rust-lib/flowy-error/src/protobuf/model/mod.rs new file mode 100644 index 0000000000..dcfc5a14fe --- /dev/null +++ b/frontend/rust-lib/flowy-error/src/protobuf/model/mod.rs @@ -0,0 +1,5 @@ +#![cfg_attr(rustfmt, rustfmt::skip)] +// Auto-generated, do not edit + +mod errors; +pub use errors::*; diff --git a/frontend/rust-lib/flowy-error/src/protobuf/proto/errors.proto b/frontend/rust-lib/flowy-error/src/protobuf/proto/errors.proto new file mode 100644 index 0000000000..434258f108 --- /dev/null +++ b/frontend/rust-lib/flowy-error/src/protobuf/proto/errors.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +message FlowyError { + int32 code = 1; + string msg = 2; +} +enum ErrorCode { + Internal = 0; +} diff --git a/frontend/rust-lib/flowy-net/Cargo.toml b/frontend/rust-lib/flowy-net/Cargo.toml index df98fa11a2..c44ac9b67d 100644 --- a/frontend/rust-lib/flowy-net/Cargo.toml +++ b/frontend/rust-lib/flowy-net/Cargo.toml @@ -6,6 +6,23 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +lib-dispatch = { path = "../lib-dispatch" } +flowy-error = { path = "../flowy-error" } flowy-derive = { path = "../../../shared-lib/flowy-derive" } +lib-infra = { path = "../../../shared-lib/lib-infra" } +lib-ws = { path = "../../../shared-lib/lib-ws" } protobuf = {version = "2.18.0"} -bytes = { version = "1.0" } \ No newline at end of file +bytes = { version = "1.0" } +anyhow = "1.0" +tokio = {version = "1", features = ["sync"]} +parking_lot = "0.11" +strum = "0.21" +strum_macros = "0.21" +tracing = { version = "0.1", features = ["log"] } + +flowy-collaboration = { path = "../../../shared-lib/flowy-collaboration", optional = true} +lazy_static = {version = "1.4.0", optional = true} +dashmap = {version = "4.0", optional = true} + +[features] +ws_mock = ["flowy-collaboration", "lazy_static", "dashmap"] \ No newline at end of file diff --git a/frontend/rust-lib/flowy-net/Flowy.toml b/frontend/rust-lib/flowy-net/Flowy.toml index 9744b45163..e25305c348 100644 --- a/frontend/rust-lib/flowy-net/Flowy.toml +++ b/frontend/rust-lib/flowy-net/Flowy.toml @@ -1,2 +1,2 @@ -proto_crates = ["src/entities"] -event_files = [] \ No newline at end of file +proto_crates = ["src/event.rs", "src/entities"] +event_files = ["src/event.rs"] \ No newline at end of file diff --git a/frontend/rust-lib/flowy-net/src/event.rs b/frontend/rust-lib/flowy-net/src/event.rs new file mode 100644 index 0000000000..81b4060f68 --- /dev/null +++ b/frontend/rust-lib/flowy-net/src/event.rs @@ -0,0 +1,9 @@ +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 = "FlowyError"] +pub enum NetworkEvent { + #[event(input = "NetworkState")] + UpdateNetworkType = 0, +} diff --git a/frontend/rust-lib/flowy-net/src/handlers/mod.rs b/frontend/rust-lib/flowy-net/src/handlers/mod.rs new file mode 100644 index 0000000000..6e6486c28c --- /dev/null +++ b/frontend/rust-lib/flowy-net/src/handlers/mod.rs @@ -0,0 +1,12 @@ +use crate::{entities::NetworkState, services::ws::WsManager}; +use bytes::Bytes; +use flowy_error::FlowyError; +use lib_dispatch::prelude::{Data, Unit}; +use std::sync::Arc; + +#[tracing::instrument(skip(data, ws_manager))] +pub async fn update_network_ty(data: Data, ws_manager: Unit>) -> Result<(), FlowyError> { + let network_state = data.into_inner(); + ws_manager.update_network_type(&network_state.ty); + Ok(()) +} diff --git a/frontend/rust-lib/flowy-net/src/lib.rs b/frontend/rust-lib/flowy-net/src/lib.rs index 85976edd74..90aabe3fcc 100644 --- a/frontend/rust-lib/flowy-net/src/lib.rs +++ b/frontend/rust-lib/flowy-net/src/lib.rs @@ -1,2 +1,6 @@ pub mod entities; +mod event; +mod handlers; +pub mod module; pub mod protobuf; +pub mod services; diff --git a/frontend/rust-lib/flowy-net/src/module.rs b/frontend/rust-lib/flowy-net/src/module.rs new file mode 100644 index 0000000000..18b17ad8a5 --- /dev/null +++ b/frontend/rust-lib/flowy-net/src/module.rs @@ -0,0 +1,10 @@ +use crate::{event::NetworkEvent, handlers::*, services::ws::WsManager}; +use lib_dispatch::prelude::*; +use std::sync::Arc; + +pub fn create(ws_manager: Arc) -> Module { + Module::new() + .name("Flowy-Network") + .data(ws_manager.clone()) + .event(NetworkEvent::UpdateNetworkType, update_network_ty) +} diff --git a/shared-lib/lib-ot/src/protobuf/model/cache.rs b/frontend/rust-lib/flowy-net/src/protobuf/model/event.rs similarity index 60% rename from shared-lib/lib-ot/src/protobuf/model/cache.rs rename to frontend/rust-lib/flowy-net/src/protobuf/model/event.rs index d173ff7ef2..be330c2d33 100644 --- a/shared-lib/lib-ot/src/protobuf/model/cache.rs +++ b/frontend/rust-lib/flowy-net/src/protobuf/model/event.rs @@ -17,35 +17,32 @@ #![allow(trivial_casts)] #![allow(unused_imports)] #![allow(unused_results)] -//! Generated file from `cache.proto` +//! Generated file from `event.proto` /// Generated files are compatible only with the same version /// of protobuf runtime. // const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_22_1; #[derive(Clone,PartialEq,Eq,Debug,Hash)] -pub enum RevState { - Local = 0, - Acked = 1, +pub enum NetworkEvent { + UpdateNetworkType = 0, } -impl ::protobuf::ProtobufEnum for RevState { +impl ::protobuf::ProtobufEnum for NetworkEvent { fn value(&self) -> i32 { *self as i32 } - fn from_i32(value: i32) -> ::std::option::Option { + fn from_i32(value: i32) -> ::std::option::Option { match value { - 0 => ::std::option::Option::Some(RevState::Local), - 1 => ::std::option::Option::Some(RevState::Acked), + 0 => ::std::option::Option::Some(NetworkEvent::UpdateNetworkType), _ => ::std::option::Option::None } } fn values() -> &'static [Self] { - static values: &'static [RevState] = &[ - RevState::Local, - RevState::Acked, + static values: &'static [NetworkEvent] = &[ + NetworkEvent::UpdateNetworkType, ]; values } @@ -53,34 +50,32 @@ impl ::protobuf::ProtobufEnum for RevState { 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::("RevState", file_descriptor_proto()) + ::protobuf::reflect::EnumDescriptor::new_pb_name::("NetworkEvent", file_descriptor_proto()) }) } } -impl ::std::marker::Copy for RevState { +impl ::std::marker::Copy for NetworkEvent { } -impl ::std::default::Default for RevState { +impl ::std::default::Default for NetworkEvent { fn default() -> Self { - RevState::Local + NetworkEvent::UpdateNetworkType } } -impl ::protobuf::reflect::ProtobufValue for RevState { +impl ::protobuf::reflect::ProtobufValue for NetworkEvent { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { ::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self)) } } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x0bcache.proto*\x20\n\x08RevState\x12\t\n\x05Local\x10\0\x12\t\n\x05A\ - cked\x10\x01J|\n\x06\x12\x04\0\0\x05\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\ - \n\n\n\x02\x05\0\x12\x04\x02\0\x05\x01\n\n\n\x03\x05\0\x01\x12\x03\x02\ - \x05\r\n\x0b\n\x04\x05\0\x02\0\x12\x03\x03\x04\x0e\n\x0c\n\x05\x05\0\x02\ - \0\x01\x12\x03\x03\x04\t\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x03\x0c\r\n\ - \x0b\n\x04\x05\0\x02\x01\x12\x03\x04\x04\x0e\n\x0c\n\x05\x05\0\x02\x01\ - \x01\x12\x03\x04\x04\t\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x04\x0c\rb\ + \n\x0bevent.proto*%\n\x0cNetworkEvent\x12\x15\n\x11UpdateNetworkType\x10\ + \0JS\n\x06\x12\x04\0\0\x04\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\ + \x05\0\x12\x04\x02\0\x04\x01\n\n\n\x03\x05\0\x01\x12\x03\x02\x05\x11\n\ + \x0b\n\x04\x05\0\x02\0\x12\x03\x03\x04\x1a\n\x0c\n\x05\x05\0\x02\0\x01\ + \x12\x03\x03\x04\x15\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x03\x18\x19b\ \x06proto3\ "; diff --git a/frontend/rust-lib/flowy-net/src/protobuf/model/mod.rs b/frontend/rust-lib/flowy-net/src/protobuf/model/mod.rs index 0873fb624e..105757dc0c 100644 --- a/frontend/rust-lib/flowy-net/src/protobuf/model/mod.rs +++ b/frontend/rust-lib/flowy-net/src/protobuf/model/mod.rs @@ -3,3 +3,6 @@ mod network_state; pub use network_state::*; + +mod event; +pub use event::*; diff --git a/frontend/rust-lib/flowy-net/src/protobuf/proto/event.proto b/frontend/rust-lib/flowy-net/src/protobuf/proto/event.proto new file mode 100644 index 0000000000..700e67f655 --- /dev/null +++ b/frontend/rust-lib/flowy-net/src/protobuf/proto/event.proto @@ -0,0 +1,5 @@ +syntax = "proto3"; + +enum NetworkEvent { + UpdateNetworkType = 0; +} diff --git a/frontend/rust-lib/flowy-net/src/services/mock/mod.rs b/frontend/rust-lib/flowy-net/src/services/mock/mod.rs new file mode 100644 index 0000000000..844f414f32 --- /dev/null +++ b/frontend/rust-lib/flowy-net/src/services/mock/mod.rs @@ -0,0 +1,3 @@ +mod ws_mock; + +pub use ws_mock::*; diff --git a/frontend/rust-lib/flowy-user/src/services/server/ws_mock.rs b/frontend/rust-lib/flowy-net/src/services/mock/ws_mock.rs similarity index 88% rename from frontend/rust-lib/flowy-user/src/services/server/ws_mock.rs rename to frontend/rust-lib/flowy-net/src/services/mock/ws_mock.rs index dffb8bb710..b79b2c8f0b 100644 --- a/frontend/rust-lib/flowy-user/src/services/server/ws_mock.rs +++ b/frontend/rust-lib/flowy-net/src/services/mock/ws_mock.rs @@ -1,23 +1,19 @@ -use crate::{ - errors::UserError, - services::user::ws_manager::{FlowyWebSocket, FlowyWsSender}, -}; +use crate::services::ws::{FlowyError, FlowyWebSocket, FlowyWsSender, WsConnectState, WsMessage, WsMessageHandler}; use bytes::Bytes; use dashmap::DashMap; use flowy_collaboration::{ - core::sync::{ServerDocManager, ServerDocPersistence}, + core::sync::{RevisionUser, ServerDocManager, ServerDocPersistence, SyncResponse}, entities::{ doc::Doc, ws::{WsDataType, WsDocumentData}, }, errors::CollaborateError, + Revision, + RichTextDelta, }; use lazy_static::lazy_static; use lib_infra::future::{FutureResult, FutureResultSend}; -use lib_ot::{revision::Revision, rich_text::RichTextDelta}; -use lib_ws::{WsConnectState, WsMessage, WsMessageHandler, WsModule}; - -use flowy_collaboration::core::sync::{RevisionUser, SyncResponse}; +use lib_ws::WsModule; use std::{ convert::{TryFrom, TryInto}, sync::Arc, @@ -47,7 +43,7 @@ impl MockWebSocket { } impl FlowyWebSocket for Arc { - fn start_connect(&self, _addr: String) -> FutureResult<(), UserError> { + fn start_connect(&self, _addr: String) -> FutureResult<(), FlowyError> { let mut ws_receiver = self.ws_sender.subscribe(); let cloned_ws = self.clone(); tokio::spawn(async move { @@ -56,7 +52,7 @@ impl FlowyWebSocket for Arc { let mut rx = DOC_SERVER.handle_ws_data(ws_data).await; let new_ws_message = rx.recv().await.unwrap(); match cloned_ws.handlers.get(&new_ws_message.module) { - None => log::error!("Can't find any handler for message: {:?}", new_ws_message), + None => tracing::error!("Can't find any handler for message: {:?}", new_ws_message), Some(handler) => handler.receive_message(new_ws_message.clone()), } } @@ -67,18 +63,18 @@ impl FlowyWebSocket for Arc { fn conn_state_subscribe(&self) -> Receiver { self.state_sender.subscribe() } - fn reconnect(&self, _count: usize) -> FutureResult<(), UserError> { FutureResult::new(async { Ok(()) }) } + fn reconnect(&self, _count: usize) -> FutureResult<(), FlowyError> { FutureResult::new(async { Ok(()) }) } - fn add_handler(&self, handler: Arc) -> Result<(), UserError> { + fn add_handler(&self, handler: Arc) -> Result<(), FlowyError> { let source = handler.source(); if self.handlers.contains_key(&source) { - log::error!("WsSource's {:?} is already registered", source); + tracing::error!("WsSource's {:?} is already registered", source); } self.handlers.insert(source, handler); Ok(()) } - fn ws_sender(&self) -> Result, UserError> { Ok(Arc::new(self.ws_sender.clone())) } + fn ws_sender(&self) -> Result, FlowyError> { Ok(Arc::new(self.ws_sender.clone())) } } lazy_static! { diff --git a/frontend/rust-lib/flowy-net/src/services/mod.rs b/frontend/rust-lib/flowy-net/src/services/mod.rs new file mode 100644 index 0000000000..bd8f542936 --- /dev/null +++ b/frontend/rust-lib/flowy-net/src/services/mod.rs @@ -0,0 +1,4 @@ +pub mod ws; + +#[cfg(feature = "ws_mock")] +mod mock; diff --git a/frontend/rust-lib/flowy-net/src/services/ws/conn.rs b/frontend/rust-lib/flowy-net/src/services/ws/conn.rs new file mode 100644 index 0000000000..fc16da07fa --- /dev/null +++ b/frontend/rust-lib/flowy-net/src/services/ws/conn.rs @@ -0,0 +1,18 @@ +use lib_infra::future::FutureResult; +use std::sync::Arc; +use tokio::sync::broadcast; + +pub use flowy_error::FlowyError; +pub use lib_ws::{WsConnectState, WsMessage, WsMessageHandler}; + +pub trait FlowyWebSocket: Send + Sync { + fn start_connect(&self, addr: String) -> FutureResult<(), FlowyError>; + fn conn_state_subscribe(&self) -> broadcast::Receiver; + fn reconnect(&self, count: usize) -> FutureResult<(), FlowyError>; + fn add_handler(&self, handler: Arc) -> Result<(), FlowyError>; + fn ws_sender(&self) -> Result, FlowyError>; +} + +pub trait FlowyWsSender: Send + Sync { + fn send(&self, msg: WsMessage) -> Result<(), FlowyError>; +} diff --git a/frontend/rust-lib/flowy-user/src/services/user/ws_manager.rs b/frontend/rust-lib/flowy-net/src/services/ws/manager.rs similarity index 63% rename from frontend/rust-lib/flowy-user/src/services/user/ws_manager.rs rename to frontend/rust-lib/flowy-net/src/services/ws/manager.rs index b29d0cf36d..928f3464e9 100644 --- a/frontend/rust-lib/flowy-user/src/services/user/ws_manager.rs +++ b/frontend/rust-lib/flowy-net/src/services/ws/manager.rs @@ -1,42 +1,52 @@ -use crate::errors::UserError; - -use flowy_net::entities::NetworkType; +use crate::{ + entities::NetworkType, + services::ws::{local_web_socket, FlowyWebSocket, FlowyWsSender}, +}; +use flowy_error::{internal_error, FlowyError}; use lib_infra::future::FutureResult; use lib_ws::{WsConnectState, WsController, WsMessage, WsMessageHandler, WsSender}; use parking_lot::RwLock; use std::sync::Arc; use tokio::sync::{broadcast, broadcast::Receiver}; -pub trait FlowyWebSocket: Send + Sync { - fn start_connect(&self, addr: String) -> FutureResult<(), UserError>; - fn conn_state_subscribe(&self) -> broadcast::Receiver; - fn reconnect(&self, count: usize) -> FutureResult<(), UserError>; - fn add_handler(&self, handler: Arc) -> Result<(), UserError>; - fn ws_sender(&self) -> Result, UserError>; -} - -pub trait FlowyWsSender: Send + Sync { - fn send(&self, msg: WsMessage) -> Result<(), UserError>; -} - pub struct WsManager { inner: Arc, connect_type: RwLock, + status_notifier: broadcast::Sender, + addr: String, } impl WsManager { - pub fn new() -> Self { WsManager::default() } + pub fn new(addr: String) -> Self { + let ws: Arc = if cfg!(feature = "http_server") { + Arc::new(Arc::new(WsController::new())) + } else { + local_web_socket() + }; - pub async fn start(&self, addr: String) -> Result<(), UserError> { + let (status_notifier, _) = broadcast::channel(10); + WsManager { + inner: ws, + connect_type: RwLock::new(NetworkType::default()), + status_notifier, + addr, + } + } + + pub async fn start(&self, token: String) -> Result<(), FlowyError> { + let addr = format!("{}/{}", self.addr, token); self.listen_on_websocket(); let _ = self.inner.start_connect(addr).await?; Ok(()) } pub fn update_network_type(&self, new_type: &NetworkType) { + tracing::debug!("Network new state: {:?}", new_type); let old_type = self.connect_type.read().clone(); + let _ = self.status_notifier.send(new_type.clone()); + if &old_type != new_type { - log::debug!("Connect type switch from {:?} to {:?}", old_type, new_type); + tracing::debug!("Connect type switch from {:?} to {:?}", old_type, new_type); match (old_type.is_connect(), new_type.is_connect()) { (false, true) => { let ws_controller = self.inner.clone(); @@ -69,7 +79,7 @@ impl WsManager { } }, Err(e) => { - log::error!("Websocket state notify error: {:?}", e); + tracing::error!("Websocket state notify error: {:?}", e); break; }, } @@ -77,76 +87,60 @@ impl WsManager { }); } - pub fn state_subscribe(&self) -> broadcast::Receiver { self.inner.conn_state_subscribe() } + pub fn subscribe_websocket_state(&self) -> broadcast::Receiver { self.inner.conn_state_subscribe() } - pub fn add_handler(&self, handler: Arc) -> Result<(), UserError> { + pub fn subscribe_network_ty(&self) -> broadcast::Receiver { self.status_notifier.subscribe() } + + pub fn add_handler(&self, handler: Arc) -> Result<(), FlowyError> { let _ = self.inner.add_handler(handler)?; Ok(()) } - pub fn ws_sender(&self) -> Result, UserError> { - // - self.inner.ws_sender() - } + pub fn ws_sender(&self) -> Result, FlowyError> { self.inner.ws_sender() } } async fn retry_connect(ws: Arc, count: usize) { match ws.reconnect(count).await { Ok(_) => {}, Err(e) => { - log::error!("websocket connect failed: {:?}", e); + tracing::error!("websocket connect failed: {:?}", e); }, } } -impl std::default::Default for WsManager { - fn default() -> Self { - let ws: Arc = if cfg!(feature = "http_server") { - Arc::new(Arc::new(WsController::new())) - } else { - crate::services::server::local_web_socket() - }; - - WsManager { - inner: ws, - connect_type: RwLock::new(NetworkType::default()), - } - } -} - impl FlowyWebSocket for Arc { - fn start_connect(&self, addr: String) -> FutureResult<(), UserError> { + fn start_connect(&self, addr: String) -> FutureResult<(), FlowyError> { let cloned_ws = self.clone(); FutureResult::new(async move { - let _ = cloned_ws.start(addr).await?; + let _ = cloned_ws.start(addr).await.map_err(internal_error)?; Ok(()) }) } fn conn_state_subscribe(&self) -> Receiver { self.state_subscribe() } - fn reconnect(&self, count: usize) -> FutureResult<(), UserError> { + fn reconnect(&self, count: usize) -> FutureResult<(), FlowyError> { let cloned_ws = self.clone(); FutureResult::new(async move { - let _ = cloned_ws.retry(count).await?; + let _ = cloned_ws.retry(count).await.map_err(internal_error)?; Ok(()) }) } - fn add_handler(&self, handler: Arc) -> Result<(), UserError> { + fn add_handler(&self, handler: Arc) -> Result<(), FlowyError> { let _ = self.add_handler(handler)?; Ok(()) } - fn ws_sender(&self) -> Result, UserError> { - let sender = self.sender()?; + fn ws_sender(&self) -> Result, FlowyError> { + let sender = self.sender().map_err(internal_error)?; Ok(sender) } } impl FlowyWsSender for WsSender { - fn send(&self, msg: WsMessage) -> Result<(), UserError> { - let _ = self.send_msg(msg)?; + fn send(&self, msg: WsMessage) -> Result<(), FlowyError> { + let _ = self.send_msg(msg).map_err(internal_error)?; Ok(()) } } diff --git a/frontend/rust-lib/flowy-net/src/services/ws/mod.rs b/frontend/rust-lib/flowy-net/src/services/ws/mod.rs new file mode 100644 index 0000000000..aae5ecffdc --- /dev/null +++ b/frontend/rust-lib/flowy-net/src/services/ws/mod.rs @@ -0,0 +1,15 @@ +pub use conn::*; +pub use manager::*; +use std::sync::Arc; + +mod conn; +mod manager; +mod ws_local; + +#[cfg(not(feature = "ws_mock"))] +pub(crate) fn local_web_socket() -> Arc { Arc::new(Arc::new(ws_local::LocalWebSocket::default())) } + +#[cfg(feature = "ws_mock")] +pub(crate) fn local_web_socket() -> Arc { + Arc::new(Arc::new(crate::services::mock::MockWebSocket::default())) +} diff --git a/frontend/rust-lib/flowy-user/src/services/server/ws_local.rs b/frontend/rust-lib/flowy-net/src/services/ws/ws_local.rs similarity index 58% rename from frontend/rust-lib/flowy-user/src/services/server/ws_local.rs rename to frontend/rust-lib/flowy-net/src/services/ws/ws_local.rs index 418685a390..984dee7837 100644 --- a/frontend/rust-lib/flowy-user/src/services/server/ws_local.rs +++ b/frontend/rust-lib/flowy-net/src/services/ws/ws_local.rs @@ -1,9 +1,5 @@ -use crate::{ - errors::UserError, - services::user::ws_manager::{FlowyWebSocket, FlowyWsSender}, -}; +use crate::services::ws::{FlowyError, FlowyWebSocket, FlowyWsSender, WsConnectState, WsMessage, WsMessageHandler}; use lib_infra::future::FutureResult; -use lib_ws::{WsConnectState, WsMessage, WsMessageHandler}; use std::sync::Arc; use tokio::sync::{broadcast, broadcast::Receiver}; @@ -24,19 +20,19 @@ impl std::default::Default for LocalWebSocket { } impl FlowyWebSocket for Arc { - fn start_connect(&self, _addr: String) -> FutureResult<(), UserError> { FutureResult::new(async { Ok(()) }) } + fn start_connect(&self, _addr: String) -> FutureResult<(), FlowyError> { FutureResult::new(async { Ok(()) }) } fn conn_state_subscribe(&self) -> Receiver { self.state_sender.subscribe() } - fn reconnect(&self, _count: usize) -> FutureResult<(), UserError> { FutureResult::new(async { Ok(()) }) } + fn reconnect(&self, _count: usize) -> FutureResult<(), FlowyError> { FutureResult::new(async { Ok(()) }) } - fn add_handler(&self, _handler: Arc) -> Result<(), UserError> { Ok(()) } + fn add_handler(&self, _handler: Arc) -> Result<(), FlowyError> { Ok(()) } - fn ws_sender(&self) -> Result, UserError> { Ok(Arc::new(self.ws_sender.clone())) } + fn ws_sender(&self) -> Result, FlowyError> { Ok(Arc::new(self.ws_sender.clone())) } } impl FlowyWsSender for broadcast::Sender { - fn send(&self, msg: WsMessage) -> Result<(), UserError> { + fn send(&self, msg: WsMessage) -> Result<(), FlowyError> { let _ = self.send(msg); Ok(()) } diff --git a/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs b/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs index c1f329aa8c..150385f1f1 100644 --- a/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs +++ b/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs @@ -6,6 +6,7 @@ use flowy_document::{ module::DocumentUser, services::ws::{DocumentWebSocket, WsDocumentManager, WsStateReceiver}, }; +use flowy_net::services::ws::WsManager; use flowy_user::{ errors::{ErrorCode, UserError}, services::user::UserSession, @@ -13,27 +14,23 @@ use flowy_user::{ use lib_ws::{WsMessage, WsMessageHandler, WsModule}; use std::{convert::TryInto, path::Path, sync::Arc}; -pub struct DocumentDepsResolver { - user_session: Arc, -} - +pub struct DocumentDepsResolver(); impl DocumentDepsResolver { - pub fn new(user_session: Arc) -> Self { Self { user_session } } - - pub fn split_into(self) -> (Arc, Arc) { + pub fn resolve( + ws_manager: Arc, + user_session: Arc, + ) -> (Arc, Arc) { let user = Arc::new(DocumentUserImpl { - user: self.user_session.clone(), + user: user_session.clone(), }); let sender = Arc::new(WsSenderImpl { - user: self.user_session.clone(), + ws_manager: ws_manager.clone(), }); - let ws_manager = Arc::new(WsDocumentManager::new(sender)); - let ws_handler = Arc::new(DocumentWsMessageReceiver { - inner: ws_manager.clone(), - }); - self.user_session.add_ws_handler(ws_handler); - (user, ws_manager) + let ws_doc = Arc::new(WsDocumentManager::new(sender)); + let ws_handler = Arc::new(DocumentWsMessageReceiver { inner: ws_doc.clone() }); + ws_manager.add_handler(ws_handler); + (user, ws_doc) } } @@ -69,7 +66,7 @@ impl DocumentUser for DocumentUserImpl { } struct WsSenderImpl { - user: Arc, + ws_manager: Arc, } impl DocumentWebSocket for WsSenderImpl { @@ -79,13 +76,13 @@ impl DocumentWebSocket for WsSenderImpl { module: WsModule::Doc, data: bytes.to_vec(), }; - let sender = self.user.ws_sender().map_err(internal_error)?; + let sender = self.ws_manager.ws_sender().map_err(internal_error)?; sender.send(msg).map_err(internal_error)?; Ok(()) } - fn state_notify(&self) -> WsStateReceiver { self.user.ws_state_notifier() } + fn subscribe_state_changed(&self) -> WsStateReceiver { self.ws_manager.subscribe_websocket_state() } } struct DocumentWsMessageReceiver { diff --git a/frontend/rust-lib/flowy-sdk/src/lib.rs b/frontend/rust-lib/flowy-sdk/src/lib.rs index d03c3911b7..45cbb96a17 100644 --- a/frontend/rust-lib/flowy-sdk/src/lib.rs +++ b/frontend/rust-lib/flowy-sdk/src/lib.rs @@ -1,11 +1,11 @@ mod deps_resolve; // mod flowy_server; pub mod module; -use crate::deps_resolve::WorkspaceDepsResolver; +use crate::deps_resolve::{DocumentDepsResolver, WorkspaceDepsResolver}; use backend_service::configuration::ClientServerConfiguration; use flowy_core::{errors::WorkspaceError, module::init_core, prelude::CoreContext}; use flowy_document::module::FlowyDocument; -use flowy_net::entities::NetworkType; +use flowy_net::{entities::NetworkType, services::ws::WsManager}; use flowy_user::{ prelude::UserStatus, services::user::{UserSession, UserSessionConfig}, @@ -53,6 +53,7 @@ fn crate_log_filter(level: Option) -> String { filters.push(format!("flowy_user={}", level)); filters.push(format!("flowy_document={}", level)); filters.push(format!("flowy_document_infra={}", level)); + filters.push(format!("flowy_net={}", level)); filters.push(format!("dart_notify={}", level)); filters.push(format!("lib_ot={}", level)); filters.push(format!("lib_ws={}", level)); @@ -68,6 +69,7 @@ pub struct FlowySDK { pub flowy_document: Arc, pub core: Arc, pub dispatcher: Arc, + pub ws_manager: Arc, } impl FlowySDK { @@ -76,49 +78,59 @@ impl FlowySDK { init_kv(&config.root); tracing::debug!("🔥 {:?}", config); - let session_cache_key = format!("{}_session_cache", &config.name); + let ws_manager = Arc::new(WsManager::new(config.server_config.ws_addr())); + let user_session = mk_user_session(&config); + let flowy_document = mk_document(ws_manager.clone(), user_session.clone(), &config.server_config); + let core_ctx = mk_core_context(user_session.clone(), flowy_document.clone(), &config.server_config); - let user_config = UserSessionConfig::new(&config.root, &config.server_config, &session_cache_key); - let user_session = Arc::new(UserSession::new(user_config)); - let flowy_document = mk_document_module(user_session.clone(), &config.server_config); - let core = mk_core(user_session.clone(), flowy_document.clone(), &config.server_config); - - let modules = mk_modules(core.clone(), user_session.clone()); + // + let modules = mk_modules(ws_manager.clone(), core_ctx.clone(), user_session.clone()); let dispatcher = Arc::new(EventDispatcher::construct(|| modules)); - _init(&dispatcher, user_session.clone(), core.clone()); + _init(&dispatcher, ws_manager.clone(), user_session.clone(), core_ctx.clone()); Self { config, user_session, flowy_document, - core, + core: core_ctx, dispatcher, + ws_manager, } } pub fn dispatcher(&self) -> Arc { self.dispatcher.clone() } } -fn _init(dispatch: &EventDispatcher, user_session: Arc, core: Arc) { - let user_status_subscribe = user_session.notifier.user_status_subscribe(); - let network_status_subscribe = user_session.notifier.network_type_subscribe(); +fn _init( + dispatch: &EventDispatcher, + ws_manager: Arc, + user_session: Arc, + core: Arc, +) { + let subscribe_user_status = user_session.notifier.subscribe_user_status(); + let subscribe_network_type = ws_manager.subscribe_network_ty(); let cloned_core = core.clone(); dispatch.spawn(async move { user_session.init(); - _listen_user_status(user_status_subscribe, core.clone()).await; + _listen_user_status(ws_manager, subscribe_user_status, core.clone()).await; }); dispatch.spawn(async move { - _listen_network_status(network_status_subscribe, cloned_core).await; + _listen_network_status(subscribe_network_type, cloned_core).await; }); } -async fn _listen_user_status(mut subscribe: broadcast::Receiver, core: Arc) { +async fn _listen_user_status( + ws_manager: Arc, + mut subscribe: broadcast::Receiver, + core: Arc, +) { while let Ok(status) = subscribe.recv().await { let result = || async { match status { UserStatus::Login { token } => { let _ = core.user_did_sign_in(&token).await?; + let _ = ws_manager.start(token).await.unwrap(); }, UserStatus::Logout { .. } => { core.user_did_logout().await; @@ -164,7 +176,13 @@ fn init_log(config: &FlowySDKConfig) { } } -fn mk_core( +fn mk_user_session(config: &FlowySDKConfig) -> Arc { + let session_cache_key = format!("{}_session_cache", &config.name); + let user_config = UserSessionConfig::new(&config.root, &config.server_config, &session_cache_key); + Arc::new(UserSession::new(user_config)) +} + +fn mk_core_context( user_session: Arc, flowy_document: Arc, server_config: &ClientServerConfiguration, @@ -173,3 +191,12 @@ fn mk_core( let (user, database) = workspace_deps.split_into(); init_core(user, database, flowy_document, server_config) } + +pub fn mk_document( + ws_manager: Arc, + user_session: Arc, + server_config: &ClientServerConfiguration, +) -> Arc { + let (user, ws_doc) = DocumentDepsResolver::resolve(ws_manager, user_session); + Arc::new(FlowyDocument::new(user, ws_doc, server_config)) +} diff --git a/frontend/rust-lib/flowy-sdk/src/module.rs b/frontend/rust-lib/flowy-sdk/src/module.rs index 155a5e02ce..9c9af5e2e1 100644 --- a/frontend/rust-lib/flowy-sdk/src/module.rs +++ b/frontend/rust-lib/flowy-sdk/src/module.rs @@ -2,24 +2,20 @@ 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; use std::sync::Arc; -pub fn mk_modules(core: Arc, user_session: Arc) -> Vec { +pub fn mk_modules(ws_manager: Arc, core: Arc, user_session: Arc) -> Vec { let user_module = mk_user_module(user_session); - let workspace_module = mk_core_module(core); - vec![user_module, workspace_module] + let core_module = mk_core_module(core); + let network_module = mk_network_module(ws_manager); + vec![user_module, core_module, network_module] } fn mk_user_module(user_session: Arc) -> Module { flowy_user::module::create(user_session) } + fn mk_core_module(core: Arc) -> Module { flowy_core::module::create(core) } -pub fn mk_document_module( - user_session: Arc, - server_config: &ClientServerConfiguration, -) -> Arc { - let document_deps = DocumentDepsResolver::new(user_session); - let (user, ws_manager) = document_deps.split_into(); - Arc::new(FlowyDocument::new(user, ws_manager, server_config)) -} +fn mk_network_module(ws_manager: Arc) -> Module { flowy_net::module::create(ws_manager) } diff --git a/frontend/rust-lib/flowy-user/Cargo.toml b/frontend/rust-lib/flowy-user/Cargo.toml index 13aed3c9f9..d688229ed7 100644 --- a/frontend/rust-lib/flowy-user/Cargo.toml +++ b/frontend/rust-lib/flowy-user/Cargo.toml @@ -9,13 +9,10 @@ edition = "2018" flowy-user-infra = { path = "../../../shared-lib/flowy-user-infra" } backend-service = { path = "../../../shared-lib/backend-service" } flowy-derive = { path = "../../../shared-lib/flowy-derive" } -lib-ws = { path = "../../../shared-lib/lib-ws" } lib-sqlite = { path = "../../../shared-lib/lib-sqlite" } lib-infra = { path = "../../../shared-lib/lib-infra" } - flowy-collaboration = { path = "../../../shared-lib/flowy-collaboration", optional = true} -lib-ot = { path = "../../../shared-lib/lib-ot", optional = true } derive_more = {version = "0.99", features = ["display"]} flowy-database = { path = "../flowy-database" } @@ -51,5 +48,4 @@ futures = "0.3.15" serial_test = "0.5.1" [features] -http_server = [] -ws_mock = ["flowy-collaboration", "lib-ot"] \ No newline at end of file +http_server = [] \ No newline at end of file diff --git a/frontend/rust-lib/flowy-user/src/errors.rs b/frontend/rust-lib/flowy-user/src/errors.rs index 454f7aeffe..814c40d2d8 100644 --- a/frontend/rust-lib/flowy-user/src/errors.rs +++ b/frontend/rust-lib/flowy-user/src/errors.rs @@ -1,5 +1,4 @@ use bytes::Bytes; - use flowy_derive::ProtoBuf; pub use flowy_user_infra::errors::ErrorCode; use lib_dispatch::prelude::{EventResponse, ResponseBuilder}; @@ -77,15 +76,6 @@ impl std::convert::From<::r2d2::Error> for UserError { fn from(error: r2d2::Error) -> Self { UserError::internal().context(error) } } -impl std::convert::From for UserError { - fn from(error: lib_ws::errors::WsError) -> Self { - match error.code { - lib_ws::errors::ErrorCode::InternalError => UserError::internal().context(error.msg), - _ => UserError::internal().context(error), - } - } -} - // use diesel::result::{Error, DatabaseErrorKind}; // use lib_sqlite::ErrorKind; impl std::convert::From for UserError { diff --git a/frontend/rust-lib/flowy-user/src/event.rs b/frontend/rust-lib/flowy-user/src/event.rs index 9a8062e79c..efd8f42112 100644 --- a/frontend/rust-lib/flowy-user/src/event.rs +++ b/frontend/rust-lib/flowy-user/src/event.rs @@ -5,26 +5,23 @@ use strum_macros::Display; #[event_err = "UserError"] pub enum UserEvent { #[event()] - InitUser = 0, + InitUser = 0, #[event(input = "SignInRequest", output = "UserProfile")] - SignIn = 1, + SignIn = 1, #[event(input = "SignUpRequest", output = "UserProfile")] - SignUp = 2, + SignUp = 2, #[event(passthrough)] - SignOut = 3, + SignOut = 3, #[event(input = "UpdateUserRequest")] - UpdateUser = 4, + UpdateUser = 4, #[event(output = "UserProfile")] - GetUserProfile = 5, + GetUserProfile = 5, #[event(output = "UserProfile")] - CheckUser = 6, - - #[event(input = "NetworkState")] - UpdateNetworkType = 10, + CheckUser = 6, } diff --git a/frontend/rust-lib/flowy-user/src/handlers/user_handler.rs b/frontend/rust-lib/flowy-user/src/handlers/user_handler.rs index 531b79b696..4e3a18e11c 100644 --- a/frontend/rust-lib/flowy-user/src/handlers/user_handler.rs +++ b/frontend/rust-lib/flowy-user/src/handlers/user_handler.rs @@ -36,10 +36,3 @@ pub async fn update_user_handler( session.update_user(params).await?; Ok(()) } - -#[tracing::instrument(skip(data, session))] -pub async fn update_network_ty(data: Data, session: Unit>) -> Result<(), UserError> { - let network_state = data.into_inner(); - session.set_network_state(network_state); - Ok(()) -} diff --git a/frontend/rust-lib/flowy-user/src/module.rs b/frontend/rust-lib/flowy-user/src/module.rs index b372cd760f..0660602068 100644 --- a/frontend/rust-lib/flowy-user/src/module.rs +++ b/frontend/rust-lib/flowy-user/src/module.rs @@ -14,5 +14,4 @@ pub fn create(user_session: Arc) -> Module { .event(UserEvent::SignOut, sign_out) .event(UserEvent::UpdateUser, update_user_handler) .event(UserEvent::CheckUser, check_user_handler) - .event(UserEvent::UpdateNetworkType, update_network_ty) } diff --git a/frontend/rust-lib/flowy-user/src/protobuf/model/event.rs b/frontend/rust-lib/flowy-user/src/protobuf/model/event.rs index 009b58045a..81f4ebf2c1 100644 --- a/frontend/rust-lib/flowy-user/src/protobuf/model/event.rs +++ b/frontend/rust-lib/flowy-user/src/protobuf/model/event.rs @@ -32,7 +32,6 @@ pub enum UserEvent { UpdateUser = 4, GetUserProfile = 5, CheckUser = 6, - UpdateNetworkType = 10, } impl ::protobuf::ProtobufEnum for UserEvent { @@ -49,7 +48,6 @@ impl ::protobuf::ProtobufEnum for UserEvent { 4 => ::std::option::Option::Some(UserEvent::UpdateUser), 5 => ::std::option::Option::Some(UserEvent::GetUserProfile), 6 => ::std::option::Option::Some(UserEvent::CheckUser), - 10 => ::std::option::Option::Some(UserEvent::UpdateNetworkType), _ => ::std::option::Option::None } } @@ -63,7 +61,6 @@ impl ::protobuf::ProtobufEnum for UserEvent { UserEvent::UpdateUser, UserEvent::GetUserProfile, UserEvent::CheckUser, - UserEvent::UpdateNetworkType, ]; values } @@ -92,29 +89,26 @@ impl ::protobuf::reflect::ProtobufValue for UserEvent { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x0bevent.proto*\x88\x01\n\tUserEvent\x12\x0c\n\x08InitUser\x10\0\x12\ - \n\n\x06SignIn\x10\x01\x12\n\n\x06SignUp\x10\x02\x12\x0b\n\x07SignOut\ - \x10\x03\x12\x0e\n\nUpdateUser\x10\x04\x12\x12\n\x0eGetUserProfile\x10\ - \x05\x12\r\n\tCheckUser\x10\x06\x12\x15\n\x11UpdateNetworkType\x10\nJ\ - \xf2\x02\n\x06\x12\x04\0\0\x0b\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\ - \x02\x05\0\x12\x04\x02\0\x0b\x01\n\n\n\x03\x05\0\x01\x12\x03\x02\x05\x0e\ - \n\x0b\n\x04\x05\0\x02\0\x12\x03\x03\x04\x11\n\x0c\n\x05\x05\0\x02\0\x01\ - \x12\x03\x03\x04\x0c\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x03\x0f\x10\n\ - \x0b\n\x04\x05\0\x02\x01\x12\x03\x04\x04\x0f\n\x0c\n\x05\x05\0\x02\x01\ - \x01\x12\x03\x04\x04\n\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x04\r\x0e\n\ - \x0b\n\x04\x05\0\x02\x02\x12\x03\x05\x04\x0f\n\x0c\n\x05\x05\0\x02\x02\ - \x01\x12\x03\x05\x04\n\n\x0c\n\x05\x05\0\x02\x02\x02\x12\x03\x05\r\x0e\n\ - \x0b\n\x04\x05\0\x02\x03\x12\x03\x06\x04\x10\n\x0c\n\x05\x05\0\x02\x03\ - \x01\x12\x03\x06\x04\x0b\n\x0c\n\x05\x05\0\x02\x03\x02\x12\x03\x06\x0e\ - \x0f\n\x0b\n\x04\x05\0\x02\x04\x12\x03\x07\x04\x13\n\x0c\n\x05\x05\0\x02\ - \x04\x01\x12\x03\x07\x04\x0e\n\x0c\n\x05\x05\0\x02\x04\x02\x12\x03\x07\ - \x11\x12\n\x0b\n\x04\x05\0\x02\x05\x12\x03\x08\x04\x17\n\x0c\n\x05\x05\0\ - \x02\x05\x01\x12\x03\x08\x04\x12\n\x0c\n\x05\x05\0\x02\x05\x02\x12\x03\ - \x08\x15\x16\n\x0b\n\x04\x05\0\x02\x06\x12\x03\t\x04\x12\n\x0c\n\x05\x05\ - \0\x02\x06\x01\x12\x03\t\x04\r\n\x0c\n\x05\x05\0\x02\x06\x02\x12\x03\t\ - \x10\x11\n\x0b\n\x04\x05\0\x02\x07\x12\x03\n\x04\x1b\n\x0c\n\x05\x05\0\ - \x02\x07\x01\x12\x03\n\x04\x15\n\x0c\n\x05\x05\0\x02\x07\x02\x12\x03\n\ - \x18\x1ab\x06proto3\ + \n\x0bevent.proto*q\n\tUserEvent\x12\x0c\n\x08InitUser\x10\0\x12\n\n\x06\ + SignIn\x10\x01\x12\n\n\x06SignUp\x10\x02\x12\x0b\n\x07SignOut\x10\x03\ + \x12\x0e\n\nUpdateUser\x10\x04\x12\x12\n\x0eGetUserProfile\x10\x05\x12\r\ + \n\tCheckUser\x10\x06J\xc9\x02\n\x06\x12\x04\0\0\n\x01\n\x08\n\x01\x0c\ + \x12\x03\0\0\x12\n\n\n\x02\x05\0\x12\x04\x02\0\n\x01\n\n\n\x03\x05\0\x01\ + \x12\x03\x02\x05\x0e\n\x0b\n\x04\x05\0\x02\0\x12\x03\x03\x04\x11\n\x0c\n\ + \x05\x05\0\x02\0\x01\x12\x03\x03\x04\x0c\n\x0c\n\x05\x05\0\x02\0\x02\x12\ + \x03\x03\x0f\x10\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x04\x04\x0f\n\x0c\n\ + \x05\x05\0\x02\x01\x01\x12\x03\x04\x04\n\n\x0c\n\x05\x05\0\x02\x01\x02\ + \x12\x03\x04\r\x0e\n\x0b\n\x04\x05\0\x02\x02\x12\x03\x05\x04\x0f\n\x0c\n\ + \x05\x05\0\x02\x02\x01\x12\x03\x05\x04\n\n\x0c\n\x05\x05\0\x02\x02\x02\ + \x12\x03\x05\r\x0e\n\x0b\n\x04\x05\0\x02\x03\x12\x03\x06\x04\x10\n\x0c\n\ + \x05\x05\0\x02\x03\x01\x12\x03\x06\x04\x0b\n\x0c\n\x05\x05\0\x02\x03\x02\ + \x12\x03\x06\x0e\x0f\n\x0b\n\x04\x05\0\x02\x04\x12\x03\x07\x04\x13\n\x0c\ + \n\x05\x05\0\x02\x04\x01\x12\x03\x07\x04\x0e\n\x0c\n\x05\x05\0\x02\x04\ + \x02\x12\x03\x07\x11\x12\n\x0b\n\x04\x05\0\x02\x05\x12\x03\x08\x04\x17\n\ + \x0c\n\x05\x05\0\x02\x05\x01\x12\x03\x08\x04\x12\n\x0c\n\x05\x05\0\x02\ + \x05\x02\x12\x03\x08\x15\x16\n\x0b\n\x04\x05\0\x02\x06\x12\x03\t\x04\x12\ + \n\x0c\n\x05\x05\0\x02\x06\x01\x12\x03\t\x04\r\n\x0c\n\x05\x05\0\x02\x06\ + \x02\x12\x03\t\x10\x11b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/frontend/rust-lib/flowy-user/src/protobuf/proto/event.proto b/frontend/rust-lib/flowy-user/src/protobuf/proto/event.proto index e91bc8405e..c076b5816a 100644 --- a/frontend/rust-lib/flowy-user/src/protobuf/proto/event.proto +++ b/frontend/rust-lib/flowy-user/src/protobuf/proto/event.proto @@ -8,5 +8,4 @@ enum UserEvent { UpdateUser = 4; GetUserProfile = 5; CheckUser = 6; - UpdateNetworkType = 10; } diff --git a/frontend/rust-lib/flowy-user/src/services/server/mod.rs b/frontend/rust-lib/flowy-user/src/services/server/mod.rs index 9bb2a9b889..f6c4ea33f0 100644 --- a/frontend/rust-lib/flowy-user/src/services/server/mod.rs +++ b/frontend/rust-lib/flowy-user/src/services/server/mod.rs @@ -1,6 +1,5 @@ mod server_api; mod server_api_mock; -mod ws_local; pub use server_api::*; pub use server_api_mock::*; @@ -10,7 +9,6 @@ pub(crate) type Server = Arc; use crate::{ entities::{SignInParams, SignInResponse, SignUpParams, SignUpResponse, UpdateUserParams, UserProfile}, errors::UserError, - services::user::ws_manager::FlowyWebSocket, }; use backend_service::configuration::ClientServerConfiguration; use lib_infra::future::FutureResult; @@ -31,12 +29,3 @@ pub(crate) fn construct_user_server(config: &ClientServerConfiguration) -> Arc Arc { Arc::new(Arc::new(ws_local::LocalWebSocket::default())) } - -#[cfg(feature = "ws_mock")] -pub(crate) fn local_web_socket() -> Arc { Arc::new(Arc::new(ws_mock::MockWebSocket::default())) } diff --git a/frontend/rust-lib/flowy-user/src/services/user/mod.rs b/frontend/rust-lib/flowy-user/src/services/user/mod.rs index c8737d7a30..6e1b6c8838 100644 --- a/frontend/rust-lib/flowy-user/src/services/user/mod.rs +++ b/frontend/rust-lib/flowy-user/src/services/user/mod.rs @@ -3,4 +3,3 @@ pub use user_session::*; pub mod database; mod notifier; mod user_session; -pub mod ws_manager; diff --git a/frontend/rust-lib/flowy-user/src/services/user/notifier.rs b/frontend/rust-lib/flowy-user/src/services/user/notifier.rs index c25f2d3dbe..a8d86a0319 100644 --- a/frontend/rust-lib/flowy-user/src/services/user/notifier.rs +++ b/frontend/rust-lib/flowy-user/src/services/user/notifier.rs @@ -4,17 +4,12 @@ use tokio::sync::{broadcast, mpsc}; pub struct UserNotifier { user_status_notifier: broadcast::Sender, - network_status_notifier: broadcast::Sender, } impl std::default::Default for UserNotifier { fn default() -> Self { let (user_status_notifier, _) = broadcast::channel(10); - let (network_status_notifier, _) = broadcast::channel(10); - UserNotifier { - user_status_notifier, - network_status_notifier, - } + UserNotifier { user_status_notifier } } } @@ -40,11 +35,5 @@ impl UserNotifier { }); } - pub fn update_network_type(&self, ty: &NetworkType) { let _ = self.network_status_notifier.send(ty.clone()); } - - pub fn user_status_subscribe(&self) -> broadcast::Receiver { self.user_status_notifier.subscribe() } - - pub fn network_type_subscribe(&self) -> broadcast::Receiver { - self.network_status_notifier.subscribe() - } + pub fn subscribe_user_status(&self) -> broadcast::Receiver { self.user_status_notifier.subscribe() } } diff --git a/frontend/rust-lib/flowy-user/src/services/user/user_session.rs b/frontend/rust-lib/flowy-user/src/services/user/user_session.rs index dd49e239b9..d4774fa6b9 100644 --- a/frontend/rust-lib/flowy-user/src/services/user/user_session.rs +++ b/frontend/rust-lib/flowy-user/src/services/user/user_session.rs @@ -15,7 +15,6 @@ use flowy_database::{ }; use flowy_user_infra::entities::{SignInResponse, SignUpResponse}; use lib_sqlite::ConnectionPool; -use lib_ws::{WsConnectState, WsMessageHandler}; use crate::{ entities::{SignInParams, SignUpParams, UpdateUserParams, UserProfile}, @@ -23,11 +22,7 @@ use crate::{ notify::*, services::{ server::{construct_user_server, Server}, - user::{ - database::UserDB, - notifier::UserNotifier, - ws_manager::{FlowyWsSender, WsManager}, - }, + user::{database::UserDB, notifier::UserNotifier}, }, sql_tables::{UserTable, UserTableChangeset}, }; @@ -55,7 +50,6 @@ pub struct UserSession { #[allow(dead_code)] server: Server, session: RwLock>, - ws_manager: Arc, pub notifier: UserNotifier, } @@ -63,14 +57,12 @@ impl UserSession { pub fn new(config: UserSessionConfig) -> Self { let db = UserDB::new(&config.root_dir); let server = construct_user_server(&config.server_config); - let ws_manager = Arc::new(WsManager::new()); let notifier = UserNotifier::new(); Self { database: db, config, server, session: RwLock::new(None), - ws_manager, notifier, } } @@ -153,12 +145,7 @@ impl UserSession { Ok(()) } - pub async fn init_user(&self) -> Result<(), UserError> { - let (_, token) = self.get_session()?.into_part(); - let _ = self.start_ws_connection(&token).await?; - - Ok(()) - } + pub async fn init_user(&self) -> Result<(), UserError> { Ok(()) } pub async fn check_user(&self) -> Result { let (user_id, token) = self.get_session()?.into_part(); @@ -191,21 +178,6 @@ impl UserSession { pub fn user_name(&self) -> Result { Ok(self.get_session()?.name) } pub fn token(&self) -> Result { Ok(self.get_session()?.token) } - - pub fn add_ws_handler(&self, handler: Arc) { let _ = self.ws_manager.add_handler(handler); } - - pub fn set_network_state(&self, new_state: NetworkState) { - log::debug!("Network new state: {:?}", new_state); - self.ws_manager.update_network_type(&new_state.ty); - self.notifier.update_network_type(&new_state.ty); - } - - pub fn ws_sender(&self) -> Result, UserError> { - let sender = self.ws_manager.ws_sender()?; - Ok(sender) - } - - pub fn ws_state_notifier(&self) -> broadcast::Receiver { self.ws_manager.state_subscribe() } } impl UserSession { @@ -302,13 +274,6 @@ impl UserSession { Err(_) => false, } } - - #[tracing::instrument(level = "debug", skip(self, token))] - pub async fn start_ws_connection(&self, token: &str) -> Result<(), UserError> { - let addr = format!("{}/{}", self.server.ws_addr(), token); - let _ = self.ws_manager.start(addr).await?; - Ok(()) - } } pub async fn update_user( diff --git a/shared-lib/flowy-collaboration/src/lib.rs b/shared-lib/flowy-collaboration/src/lib.rs index 60ee3988b0..5873e1acc6 100644 --- a/shared-lib/flowy-collaboration/src/lib.rs +++ b/shared-lib/flowy-collaboration/src/lib.rs @@ -3,3 +3,5 @@ pub mod entities; pub mod errors; pub mod protobuf; pub mod util; + +pub use lib_ot::{revision::Revision, rich_text::RichTextDelta}; diff --git a/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs b/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs index 885b9475dd..57014f3213 100644 --- a/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs +++ b/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs @@ -20,6 +20,7 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { | "DocError" | "FFIRequest" | "FFIResponse" + | "FlowyError" | "SubscribeObject" | "NetworkState" | "UserError" @@ -84,6 +85,7 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { | "ErrorCode" | "DocObservable" | "FFIStatusCode" + | "NetworkEvent" | "NetworkType" | "UserEvent" | "UserNotification" @@ -93,6 +95,7 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { | "WsDataType" | "WsModule" | "RevType" + | "RevState" => TypeCategory::Enum, "Option" => TypeCategory::Opt, diff --git a/shared-lib/lib-ot/src/protobuf/model/mod.rs b/shared-lib/lib-ot/src/protobuf/model/mod.rs index 86c4fd5276..d30d09866a 100644 --- a/shared-lib/lib-ot/src/protobuf/model/mod.rs +++ b/shared-lib/lib-ot/src/protobuf/model/mod.rs @@ -1,8 +1,5 @@ #![cfg_attr(rustfmt, rustfmt::skip)] // Auto-generated, do not edit -mod cache; -pub use cache::*; - mod model; pub use model::*; diff --git a/shared-lib/lib-ot/src/protobuf/model/model.rs b/shared-lib/lib-ot/src/protobuf/model/model.rs index 6bf8f5490a..7453f9470c 100644 --- a/shared-lib/lib-ot/src/protobuf/model/model.rs +++ b/shared-lib/lib-ot/src/protobuf/model/model.rs @@ -840,6 +840,56 @@ impl ::protobuf::reflect::ProtobufValue for RevType { } } +#[derive(Clone,PartialEq,Eq,Debug,Hash)] +pub enum RevState { + StateLocal = 0, + Acked = 1, +} + +impl ::protobuf::ProtobufEnum for RevState { + fn value(&self) -> i32 { + *self as i32 + } + + fn from_i32(value: i32) -> ::std::option::Option { + match value { + 0 => ::std::option::Option::Some(RevState::StateLocal), + 1 => ::std::option::Option::Some(RevState::Acked), + _ => ::std::option::Option::None + } + } + + fn values() -> &'static [Self] { + static values: &'static [RevState] = &[ + RevState::StateLocal, + RevState::Acked, + ]; + 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::("RevState", file_descriptor_proto()) + }) + } +} + +impl ::std::marker::Copy for RevState { +} + +impl ::std::default::Default for RevState { + fn default() -> Self { + RevState::StateLocal + } +} + +impl ::protobuf::reflect::ProtobufValue for RevState { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self)) + } +} + static file_descriptor_proto_data: &'static [u8] = b"\ \n\x0bmodel.proto\"\xbc\x01\n\x08Revision\x12\x1e\n\x0bbase_rev_id\x18\ \x01\x20\x01(\x03R\tbaseRevId\x12\x15\n\x06rev_id\x18\x02\x20\x01(\x03R\ @@ -850,8 +900,9 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \x14\n\x05value\x18\x01\x20\x01(\x03R\x05value\"N\n\rRevisionRange\x12\ \x15\n\x06doc_id\x18\x01\x20\x01(\tR\x05docId\x12\x14\n\x05start\x18\x02\ \x20\x01(\x03R\x05start\x12\x10\n\x03end\x18\x03\x20\x01(\x03R\x03end*\ - \x20\n\x07RevType\x12\t\n\x05Local\x10\0\x12\n\n\x06Remote\x10\x01J\xa1\ - \x06\n\x06\x12\x04\0\0\x16\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\ + \x20\n\x07RevType\x12\t\n\x05Local\x10\0\x12\n\n\x06Remote\x10\x01*%\n\ + \x08RevState\x12\x0e\n\nStateLocal\x10\0\x12\t\n\x05Acked\x10\x01J\x8b\ + \x07\n\x06\x12\x04\0\0\x1a\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\ \x04\0\x12\x04\x02\0\n\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\x1a\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\x15\n\x0c\n\x05\ @@ -890,7 +941,12 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \0\x02\0\x01\x12\x03\x14\x04\t\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x14\ \x0c\r\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x15\x04\x0f\n\x0c\n\x05\x05\0\ \x02\x01\x01\x12\x03\x15\x04\n\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x15\ - \r\x0eb\x06proto3\ + \r\x0e\n\n\n\x02\x05\x01\x12\x04\x17\0\x1a\x01\n\n\n\x03\x05\x01\x01\x12\ + \x03\x17\x05\r\n\x0b\n\x04\x05\x01\x02\0\x12\x03\x18\x04\x13\n\x0c\n\x05\ + \x05\x01\x02\0\x01\x12\x03\x18\x04\x0e\n\x0c\n\x05\x05\x01\x02\0\x02\x12\ + \x03\x18\x11\x12\n\x0b\n\x04\x05\x01\x02\x01\x12\x03\x19\x04\x0e\n\x0c\n\ + \x05\x05\x01\x02\x01\x01\x12\x03\x19\x04\t\n\x0c\n\x05\x05\x01\x02\x01\ + \x02\x12\x03\x19\x0c\rb\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/shared-lib/lib-ot/src/protobuf/proto/cache.proto b/shared-lib/lib-ot/src/protobuf/proto/cache.proto deleted file mode 100644 index 9ff05aac2a..0000000000 --- a/shared-lib/lib-ot/src/protobuf/proto/cache.proto +++ /dev/null @@ -1,6 +0,0 @@ -syntax = "proto3"; - -enum RevState { - Local = 0; - Acked = 1; -} diff --git a/shared-lib/lib-ot/src/protobuf/proto/model.proto b/shared-lib/lib-ot/src/protobuf/proto/model.proto index f9c9f12bc2..cc9e9da777 100644 --- a/shared-lib/lib-ot/src/protobuf/proto/model.proto +++ b/shared-lib/lib-ot/src/protobuf/proto/model.proto @@ -21,3 +21,7 @@ enum RevType { Local = 0; Remote = 1; } +enum RevState { + StateLocal = 0; + Acked = 1; +} diff --git a/shared-lib/lib-ot/src/revision/model.rs b/shared-lib/lib-ot/src/revision/model.rs index 71b0a4e7d5..d4d1ea9ee7 100644 --- a/shared-lib/lib-ot/src/revision/model.rs +++ b/shared-lib/lib-ot/src/revision/model.rs @@ -32,12 +32,6 @@ impl Revision { pub fn pair_rev_id(&self) -> (i64, i64) { (self.base_rev_id, self.rev_id) } pub fn is_initial(&self) -> bool { self.rev_id == 0 } - - // pub fn from_pb(pb: &mut crate::protobuf::Revision) -> Self { - // pb.try_into().unwrap() } - - // pub fn from_pb(mut pb: crate::protobuf::Revision) -> Self { - // Revision::try_from(&mut pb).unwrap() } } impl std::fmt::Debug for Revision { @@ -160,6 +154,6 @@ pub fn md5>(data: T) -> String { #[derive(Debug, Clone, Eq, PartialEq)] pub enum RevState { - Local = 0, - Acked = 1, + StateLocal = 0, + Acked = 1, } From 013d8f753aa84f91dec2cfcba568886d17d10a91 Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 14 Dec 2021 18:04:51 +0800 Subject: [PATCH 27/39] refactor errors --- backend/Cargo.lock | 23 +- backend/src/services/doc/ws_actor.rs | 14 +- .../lib/user/application/sign_in_bloc.dart | 6 +- .../application/sign_in_bloc.freezed.dart | 18 +- .../lib/user/application/sign_up_bloc.dart | 6 +- .../application/sign_up_bloc.freezed.dart | 18 +- .../app_flowy/lib/user/domain/auth_state.dart | 4 +- .../lib/user/domain/auth_state.freezed.dart | 36 +- .../app_flowy/lib/user/domain/i_auth.dart | 8 +- .../lib/user/infrastructure/i_auth_impl.dart | 8 +- .../user/infrastructure/i_splash_impl.dart | 4 +- .../user/infrastructure/repos/auth_repo.dart | 8 +- .../lib/user/presentation/sign_in_screen.dart | 4 +- .../lib/user/presentation/sign_up_screen.dart | 4 +- .../user/presentation/skip_log_in_screen.dart | 4 +- .../workspace/application/app/app_bloc.dart | 6 +- .../application/app/app_bloc.freezed.dart | 18 +- .../workspace/application/doc/doc_bloc.dart | 4 +- .../application/doc/doc_bloc.freezed.dart | 30 +- .../workspace/application/doc/share_bloc.dart | 4 +- .../application/doc/share_bloc.freezed.dart | 36 +- .../application/home/home_listen_bloc.dart | 3 +- .../workspace/application/menu/menu_bloc.dart | 8 +- .../application/menu/menu_bloc.freezed.dart | 66 ++-- .../application/menu/menu_user_bloc.dart | 6 +- .../application/trash/trash_bloc.dart | 8 +- .../application/trash/trash_bloc.freezed.dart | 18 +- .../workspace/application/view/view_bloc.dart | 8 +- .../application/view/view_bloc.freezed.dart | 72 ++-- .../application/workspace/welcome_bloc.dart | 8 +- .../workspace/welcome_bloc.freezed.dart | 60 ++-- .../app_flowy/lib/workspace/domain/i_app.dart | 12 +- .../app_flowy/lib/workspace/domain/i_doc.dart | 8 +- .../lib/workspace/domain/i_share.dart | 8 +- .../lib/workspace/domain/i_trash.dart | 14 +- .../lib/workspace/domain/i_user.dart | 20 +- .../lib/workspace/domain/i_view.dart | 16 +- .../lib/workspace/domain/i_workspace.dart | 8 +- .../workspace/infrastructure/i_app_impl.dart | 10 +- .../workspace/infrastructure/i_doc_impl.dart | 8 +- .../infrastructure/i_share_impl.dart | 8 +- .../infrastructure/i_trash_impl.dart | 12 +- .../workspace/infrastructure/i_user_impl.dart | 18 +- .../workspace/infrastructure/i_view_impl.dart | 8 +- .../infrastructure/i_workspace_impl.dart | 6 +- .../infrastructure/repos/app_repo.dart | 14 +- .../infrastructure/repos/doc_repo.dart | 8 +- .../infrastructure/repos/helper.dart | 14 +- .../infrastructure/repos/share_repo.dart | 4 +- .../infrastructure/repos/trash_repo.dart | 14 +- .../infrastructure/repos/user_repo.dart | 16 +- .../infrastructure/repos/view_repo.dart | 12 +- .../infrastructure/repos/workspace_repo.dart | 12 +- .../stack_page/doc/doc_stack_page.dart | 4 +- .../flowy_sdk/lib/dispatch/code_gen.dart | 128 +++---- .../flowy_sdk/lib/dispatch/dispatch.dart | 2 - .../error_code.pb.dart} | 6 +- .../error-code/error_code.pbenum.dart | 82 +++++ .../error-code/error_code.pbjson.dart | 49 +++ .../error_code.pbserver.dart} | 4 +- .../lib/protobuf/error-code/protobuf.dart | 2 + .../lib/protobuf/flowy-core/errors.pb.dart | 72 ---- .../protobuf/flowy-core/errors.pbjson.dart | 21 -- .../protobuf/flowy-core/errors.pbserver.dart | 9 - .../lib/protobuf/flowy-core/protobuf.dart | 1 - .../protobuf/flowy-document/errors.pb.dart | 76 ----- .../flowy-document/errors.pbenum.dart | 32 -- .../flowy-document/errors.pbjson.dart | 35 -- .../lib/protobuf/flowy-document/protobuf.dart | 1 - .../lib/protobuf/flowy-error/errors.pb.dart | 2 - .../protobuf/flowy-error/errors.pbenum.dart | 17 - .../protobuf/flowy-error/errors.pbjson.dart | 10 - .../lib/protobuf/flowy-user/errors.pb.dart | 72 ---- .../protobuf/flowy-user/errors.pbenum.dart | 7 - .../protobuf/flowy-user/errors.pbjson.dart | 21 -- .../protobuf/flowy-user/errors.pbserver.dart | 9 - .../lib/protobuf/flowy-user/protobuf.dart | 1 - frontend/rust-lib/flowy-core/Cargo.toml | 1 + .../core/aggregate_tasks/workspace_task.rs | 8 +- .../flowy-core/src/core/core_context.rs | 8 +- .../flowy-core/src/core/event_handler.rs | 8 +- frontend/rust-lib/flowy-core/src/errors.rs | 106 ------ frontend/rust-lib/flowy-core/src/event.rs | 2 +- frontend/rust-lib/flowy-core/src/lib.rs | 6 +- frontend/rust-lib/flowy-core/src/macros.rs | 2 +- frontend/rust-lib/flowy-core/src/module.rs | 12 +- .../flowy-core/src/protobuf/model/errors.rs | 243 -------------- .../flowy-core/src/protobuf/model/mod.rs | 3 - .../src/protobuf/proto/errors.proto | 6 - .../flowy-core/src/services/app/controller.rs | 48 +-- .../src/services/app/event_handler.rs | 10 +- .../flowy-core/src/services/app/sql.rs | 16 +- .../flowy-core/src/services/server/mod.rs | 36 +- .../src/services/server/server_api.rs | 39 +-- .../src/services/server/server_api_mock.rs | 32 +- .../src/services/trash/controller.rs | 56 ++-- .../src/services/trash/event_handler.rs | 12 +- .../flowy-core/src/services/trash/sql.rs | 12 +- .../src/services/view/controller.rs | 65 ++-- .../src/services/view/event_handler.rs | 20 +- .../flowy-core/src/services/view/sql.rs | 14 +- .../src/services/workspace/controller.rs | 44 +-- .../src/services/workspace/event_handler.rs | 8 +- .../flowy-core/src/services/workspace/sql.rs | 10 +- frontend/rust-lib/flowy-document/Cargo.toml | 4 +- .../rust-lib/flowy-document/src/errors.rs | 138 -------- frontend/rust-lib/flowy-document/src/lib.rs | 5 +- .../rust-lib/flowy-document/src/module.rs | 22 +- .../src/protobuf/model/errors.rs | 312 ------------------ .../flowy-document/src/protobuf/model/mod.rs | 3 - .../src/protobuf/proto/errors.proto | 13 - .../src/services/doc/controller.rs | 27 +- .../src/services/doc/edit/editor.rs | 31 +- .../src/services/doc/edit/model.rs | 6 +- .../src/services/doc/revision/cache/cache.rs | 31 +- .../src/services/doc/revision/manager.rs | 15 +- .../src/services/doc/revision/sync.rs | 20 +- .../src/services/server/middleware.rs | 2 +- .../flowy-document/src/services/server/mod.rs | 8 +- .../src/services/server/server_api.rs | 14 +- .../src/services/server/server_api_mock.rs | 8 +- .../src/services/ws/ws_manager.rs | 4 +- .../src/sql_tables/doc/rev_sql.rs | 14 +- frontend/rust-lib/flowy-error/Cargo.toml | 20 +- frontend/rust-lib/flowy-error/src/errors.rs | 76 +++-- .../rust-lib/flowy-error/src/ext/backend.rs | 22 ++ .../flowy-error/src/ext/collaborate.rs | 5 + .../rust-lib/flowy-error/src/ext/database.rs | 15 + frontend/rust-lib/flowy-error/src/ext/mod.rs | 27 ++ frontend/rust-lib/flowy-error/src/ext/ot.rs | 5 + .../rust-lib/flowy-error/src/ext/serde.rs | 5 + frontend/rust-lib/flowy-error/src/lib.rs | 2 + .../flowy-error/src/protobuf/model/errors.rs | 68 +--- .../src/protobuf/proto/errors.proto | 3 - .../rust-lib/flowy-net/src/handlers/mod.rs | 2 +- frontend/rust-lib/flowy-net/src/module.rs | 2 +- .../src/deps_resolve/document_deps.rs | 35 +- .../src/deps_resolve/workspace_deps.rs | 16 +- frontend/rust-lib/flowy-sdk/src/lib.rs | 6 +- frontend/rust-lib/flowy-sdk/src/module.rs | 4 +- .../rust-lib/flowy-test/src/event_builder.rs | 24 +- frontend/rust-lib/flowy-test/src/helper.rs | 8 +- frontend/rust-lib/flowy-user/Cargo.toml | 1 + frontend/rust-lib/flowy-user/src/errors.rs | 117 ------- frontend/rust-lib/flowy-user/src/event.rs | 2 +- .../flowy-user/src/handlers/auth_handler.rs | 12 +- .../flowy-user/src/handlers/user_handler.rs | 14 +- frontend/rust-lib/flowy-user/src/lib.rs | 11 +- .../flowy-user/src/protobuf/model/errors.rs | 243 -------------- .../flowy-user/src/protobuf/model/mod.rs | 3 - .../src/protobuf/proto/errors.proto | 6 - .../flowy-user/src/services/server/mod.rs | 12 +- .../src/services/server/server_api.rs | 14 +- .../src/services/server/server_api_mock.rs | 12 +- .../flowy-user/src/services/user/database.rs | 24 +- .../flowy-user/src/services/user/notifier.rs | 2 +- .../src/services/user/user_session.rs | 51 ++- shared-lib/Cargo.lock | 11 + shared-lib/Cargo.toml | 1 + shared-lib/error-code/Cargo.toml | 11 + shared-lib/error-code/Flowy.toml | 3 + shared-lib/error-code/src/error_code.rs | 100 ++++++ shared-lib/error-code/src/lib.rs | 4 + shared-lib/error-code/src/protobuf/mod.rs | 4 + .../src/protobuf/model/error_code.rs | 253 ++++++++++++++ .../error-code/src/protobuf/model/mod.rs | 5 + .../src/protobuf/proto/error_code.proto | 34 ++ shared-lib/flowy-core-infra/Cargo.toml | 1 + shared-lib/flowy-core-infra/Flowy.toml | 2 +- .../src/entities/view/view_update.rs | 4 +- shared-lib/flowy-core-infra/src/errors.rs | 77 ----- shared-lib/flowy-core-infra/src/lib.rs | 5 +- .../src/derive_cache/derive_cache.rs | 7 +- shared-lib/flowy-user-infra/Cargo.toml | 1 + shared-lib/flowy-user-infra/src/errors.rs | 61 ---- shared-lib/flowy-user-infra/src/lib.rs | 6 +- .../flowy-user-infra/src/user_default.rs | 1 - 177 files changed, 1657 insertions(+), 2740 deletions(-) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core/errors.pbenum.dart => error-code/error_code.pb.dart} (74%) create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/error-code/error_code.pbenum.dart create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/error-code/error_code.pbjson.dart rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-document/errors.pbserver.dart => error-code/error_code.pbserver.dart} (84%) create mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/error-code/protobuf.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/errors.pb.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/errors.pbjson.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/errors.pbserver.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/errors.pb.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/errors.pbenum.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/errors.pbjson.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pb.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbenum.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbjson.dart delete mode 100644 frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbserver.dart delete mode 100644 frontend/rust-lib/flowy-core/src/errors.rs delete mode 100644 frontend/rust-lib/flowy-core/src/protobuf/model/errors.rs delete mode 100644 frontend/rust-lib/flowy-core/src/protobuf/proto/errors.proto delete mode 100644 frontend/rust-lib/flowy-document/src/errors.rs delete mode 100644 frontend/rust-lib/flowy-document/src/protobuf/model/errors.rs delete mode 100644 frontend/rust-lib/flowy-document/src/protobuf/proto/errors.proto create mode 100644 frontend/rust-lib/flowy-error/src/ext/backend.rs create mode 100644 frontend/rust-lib/flowy-error/src/ext/collaborate.rs create mode 100644 frontend/rust-lib/flowy-error/src/ext/database.rs create mode 100644 frontend/rust-lib/flowy-error/src/ext/mod.rs create mode 100644 frontend/rust-lib/flowy-error/src/ext/ot.rs create mode 100644 frontend/rust-lib/flowy-error/src/ext/serde.rs delete mode 100644 frontend/rust-lib/flowy-user/src/errors.rs delete mode 100644 frontend/rust-lib/flowy-user/src/protobuf/model/errors.rs delete mode 100644 frontend/rust-lib/flowy-user/src/protobuf/proto/errors.proto create mode 100644 shared-lib/error-code/Cargo.toml create mode 100644 shared-lib/error-code/Flowy.toml create mode 100644 shared-lib/error-code/src/error_code.rs create mode 100644 shared-lib/error-code/src/lib.rs create mode 100644 shared-lib/error-code/src/protobuf/mod.rs create mode 100644 shared-lib/error-code/src/protobuf/model/error_code.rs create mode 100644 shared-lib/error-code/src/protobuf/model/mod.rs create mode 100644 shared-lib/error-code/src/protobuf/proto/error_code.proto delete mode 100644 shared-lib/flowy-core-infra/src/errors.rs delete mode 100644 shared-lib/flowy-user-infra/src/errors.rs delete mode 100644 shared-lib/flowy-user-infra/src/user_default.rs diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 2da79b9ed7..6cba8fa609 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -1151,6 +1151,15 @@ dependencies = [ "backtrace", ] +[[package]] +name = "error-code" +version = "0.1.0" +dependencies = [ + "derive_more", + "flowy-derive", + "protobuf", +] + [[package]] name = "eyre" version = "0.6.5" @@ -1241,6 +1250,7 @@ dependencies = [ "flowy-database", "flowy-derive", "flowy-document", + "flowy-error", "flowy-net", "futures", "futures-core", @@ -1267,6 +1277,7 @@ dependencies = [ "bytes", "chrono", "derive_more", + "error-code", "flowy-collaboration", "flowy-derive", "log", @@ -1317,6 +1328,7 @@ dependencies = [ "flowy-collaboration", "flowy-database", "flowy-derive", + "flowy-error", "futures", "futures-core", "futures-util", @@ -1343,11 +1355,18 @@ dependencies = [ name = "flowy-error" version = "0.1.0" dependencies = [ + "backend-service", "bytes", - "derive_more", + "error-code", + "flowy-collaboration", + "flowy-database", "flowy-derive", "lib-dispatch", + "lib-ot", + "lib-sqlite", "protobuf", + "r2d2", + "serde_json", ] [[package]] @@ -1431,6 +1450,7 @@ dependencies = [ "diesel_derives", "flowy-database", "flowy-derive", + "flowy-error", "flowy-net", "flowy-user-infra", "futures-core", @@ -1460,6 +1480,7 @@ version = "0.1.0" dependencies = [ "bytes", "derive_more", + "error-code", "fancy-regex", "flowy-derive", "lazy_static", diff --git a/backend/src/services/doc/ws_actor.rs b/backend/src/services/doc/ws_actor.rs index 85b196dfb7..df93edaba5 100644 --- a/backend/src/services/doc/ws_actor.rs +++ b/backend/src/services/doc/ws_actor.rs @@ -8,7 +8,7 @@ use crate::{ use actix_rt::task::spawn_blocking; use actix_web::web::Data; use async_stream::stream; -use backend_service::errors::{internal_error, Result as DocResult, ServerError}; +use backend_service::errors::{internal_error, Result, ServerError}; use flowy_collaboration::{ core::sync::ServerDocManager, protobuf::{WsDataType, WsDocumentData}, @@ -23,7 +23,7 @@ pub enum DocWsMsg { ClientData { client_data: WsClientData, pool: Data, - ret: oneshot::Sender>, + ret: oneshot::Sender>, }, } @@ -66,11 +66,11 @@ impl DocWsActor { } } - async fn handle_client_data(&self, client_data: WsClientData, pool: Data) -> DocResult<()> { + async fn handle_client_data(&self, client_data: WsClientData, pool: Data) -> Result<()> { let WsClientData { user, socket, data } = client_data; let document_data = spawn_blocking(move || { let document_data: WsDocumentData = parse_from_bytes(&data)?; - DocResult::Ok(document_data) + Result::Ok(document_data) }) .await .map_err(internal_error)??; @@ -91,11 +91,11 @@ impl DocWsActor { socket: Socket, data: Vec, pg_pool: Data, - ) -> DocResult<()> { + ) -> Result<()> { let mut revision_pb = spawn_blocking(move || { let revision: Revision = parse_from_bytes(&data)?; let _ = verify_md5(&revision)?; - DocResult::Ok(revision) + Result::Ok(revision) }) .await .map_err(internal_error)??; @@ -116,7 +116,7 @@ impl DocWsActor { } } -fn verify_md5(revision: &Revision) -> DocResult<()> { +fn verify_md5(revision: &Revision) -> Result<()> { if md5(&revision.delta_data) != revision.md5 { return Err(ServerError::internal().context("Revision md5 not match")); } diff --git a/frontend/app_flowy/lib/user/application/sign_in_bloc.dart b/frontend/app_flowy/lib/user/application/sign_in_bloc.dart index f67bcae063..56452bf338 100644 --- a/frontend/app_flowy/lib/user/application/sign_in_bloc.dart +++ b/frontend/app_flowy/lib/user/application/sign_in_bloc.dart @@ -1,7 +1,7 @@ import 'package:app_flowy/user/domain/i_auth.dart'; import 'package:dartz/dartz.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile, ErrorCode; -import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -40,7 +40,7 @@ class SignInBloc extends Bloc { ); } - SignInState stateFromCode(UserError error) { + SignInState stateFromCode(FlowyError error) { switch (ErrorCode.valueOf(error.code)!) { case ErrorCode.EmailFormatInvalid: return state.copyWith(isSubmitting: false, emailError: some(error.msg), passwordError: none()); @@ -67,7 +67,7 @@ abstract class SignInState with _$SignInState { required bool isSubmitting, required Option passwordError, required Option emailError, - required Option> successOrFail, + required Option> successOrFail, }) = _SignInState; factory SignInState.initial() => SignInState( diff --git a/frontend/app_flowy/lib/user/application/sign_in_bloc.freezed.dart b/frontend/app_flowy/lib/user/application/sign_in_bloc.freezed.dart index 2f557809d5..29b67d3fa7 100644 --- a/frontend/app_flowy/lib/user/application/sign_in_bloc.freezed.dart +++ b/frontend/app_flowy/lib/user/application/sign_in_bloc.freezed.dart @@ -519,7 +519,7 @@ class _$SignInStateTearOff { required bool isSubmitting, required Option passwordError, required Option emailError, - required Option> successOrFail}) { + required Option> successOrFail}) { return _SignInState( email: email, password: password, @@ -541,7 +541,7 @@ mixin _$SignInState { bool get isSubmitting => throw _privateConstructorUsedError; Option get passwordError => throw _privateConstructorUsedError; Option get emailError => throw _privateConstructorUsedError; - Option> get successOrFail => + Option> get successOrFail => throw _privateConstructorUsedError; @JsonKey(ignore: true) @@ -560,7 +560,7 @@ abstract class $SignInStateCopyWith<$Res> { bool isSubmitting, Option passwordError, Option emailError, - Option> successOrFail}); + Option> successOrFail}); } /// @nodoc @@ -604,7 +604,7 @@ class _$SignInStateCopyWithImpl<$Res> implements $SignInStateCopyWith<$Res> { successOrFail: successOrFail == freezed ? _value.successOrFail : successOrFail // ignore: cast_nullable_to_non_nullable - as Option>, + as Option>, )); } } @@ -622,7 +622,7 @@ abstract class _$SignInStateCopyWith<$Res> bool isSubmitting, Option passwordError, Option emailError, - Option> successOrFail}); + Option> successOrFail}); } /// @nodoc @@ -668,7 +668,7 @@ class __$SignInStateCopyWithImpl<$Res> extends _$SignInStateCopyWithImpl<$Res> successOrFail: successOrFail == freezed ? _value.successOrFail : successOrFail // ignore: cast_nullable_to_non_nullable - as Option>, + as Option>, )); } } @@ -695,7 +695,7 @@ class _$_SignInState implements _SignInState { @override final Option emailError; @override - final Option> successOrFail; + final Option> successOrFail; @override String toString() { @@ -748,7 +748,7 @@ abstract class _SignInState implements SignInState { required bool isSubmitting, required Option passwordError, required Option emailError, - required Option> successOrFail}) = + required Option> successOrFail}) = _$_SignInState; @override @@ -762,7 +762,7 @@ abstract class _SignInState implements SignInState { @override Option get emailError => throw _privateConstructorUsedError; @override - Option> get successOrFail => + Option> get successOrFail => throw _privateConstructorUsedError; @override @JsonKey(ignore: true) diff --git a/frontend/app_flowy/lib/user/application/sign_up_bloc.dart b/frontend/app_flowy/lib/user/application/sign_up_bloc.dart index 0271de7309..a0ade691ea 100644 --- a/frontend/app_flowy/lib/user/application/sign_up_bloc.dart +++ b/frontend/app_flowy/lib/user/application/sign_up_bloc.dart @@ -2,7 +2,7 @@ import 'package:app_flowy/user/domain/i_auth.dart'; import 'package:dartz/dartz.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile, ErrorCode; -import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; @@ -78,7 +78,7 @@ class SignUpBloc extends Bloc { ); } - SignUpState stateFromCode(UserError error) { + SignUpState stateFromCode(FlowyError error) { switch (ErrorCode.valueOf(error.code)!) { case ErrorCode.EmailFormatInvalid: return state.copyWith( @@ -118,7 +118,7 @@ class SignUpState with _$SignUpState { required Option passwordError, required Option repeatPasswordError, required Option emailError, - required Option> successOrFail, + required Option> successOrFail, }) = _SignUpState; factory SignUpState.initial() => SignUpState( diff --git a/frontend/app_flowy/lib/user/application/sign_up_bloc.freezed.dart b/frontend/app_flowy/lib/user/application/sign_up_bloc.freezed.dart index ec7b4d9dac..ec6c377fd1 100644 --- a/frontend/app_flowy/lib/user/application/sign_up_bloc.freezed.dart +++ b/frontend/app_flowy/lib/user/application/sign_up_bloc.freezed.dart @@ -707,7 +707,7 @@ class _$SignUpStateTearOff { required Option passwordError, required Option repeatPasswordError, required Option emailError, - required Option> successOrFail}) { + required Option> successOrFail}) { return _SignUpState( email: email, password: password, @@ -733,7 +733,7 @@ mixin _$SignUpState { Option get passwordError => throw _privateConstructorUsedError; Option get repeatPasswordError => throw _privateConstructorUsedError; Option get emailError => throw _privateConstructorUsedError; - Option> get successOrFail => + Option> get successOrFail => throw _privateConstructorUsedError; @JsonKey(ignore: true) @@ -754,7 +754,7 @@ abstract class $SignUpStateCopyWith<$Res> { Option passwordError, Option repeatPasswordError, Option emailError, - Option> successOrFail}); + Option> successOrFail}); } /// @nodoc @@ -808,7 +808,7 @@ class _$SignUpStateCopyWithImpl<$Res> implements $SignUpStateCopyWith<$Res> { successOrFail: successOrFail == freezed ? _value.successOrFail : successOrFail // ignore: cast_nullable_to_non_nullable - as Option>, + as Option>, )); } } @@ -828,7 +828,7 @@ abstract class _$SignUpStateCopyWith<$Res> Option passwordError, Option repeatPasswordError, Option emailError, - Option> successOrFail}); + Option> successOrFail}); } /// @nodoc @@ -884,7 +884,7 @@ class __$SignUpStateCopyWithImpl<$Res> extends _$SignUpStateCopyWithImpl<$Res> successOrFail: successOrFail == freezed ? _value.successOrFail : successOrFail // ignore: cast_nullable_to_non_nullable - as Option>, + as Option>, )); } } @@ -917,7 +917,7 @@ class _$_SignUpState implements _SignUpState { @override final Option emailError; @override - final Option> successOrFail; + final Option> successOrFail; @override String toString() { @@ -980,7 +980,7 @@ abstract class _SignUpState implements SignUpState { required Option passwordError, required Option repeatPasswordError, required Option emailError, - required Option> successOrFail}) = + required Option> successOrFail}) = _$_SignUpState; @override @@ -998,7 +998,7 @@ abstract class _SignUpState implements SignUpState { @override Option get emailError => throw _privateConstructorUsedError; @override - Option> get successOrFail => + Option> get successOrFail => throw _privateConstructorUsedError; @override @JsonKey(ignore: true) diff --git a/frontend/app_flowy/lib/user/domain/auth_state.dart b/frontend/app_flowy/lib/user/domain/auth_state.dart index 6dc7d08e33..37916fbf7a 100644 --- a/frontend/app_flowy/lib/user/domain/auth_state.dart +++ b/frontend/app_flowy/lib/user/domain/auth_state.dart @@ -1,11 +1,11 @@ import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile; -import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; part 'auth_state.freezed.dart'; @freezed abstract class AuthState with _$AuthState { const factory AuthState.authenticated(UserProfile userProfile) = Authenticated; - const factory AuthState.unauthenticated(UserError error) = Unauthenticated; + const factory AuthState.unauthenticated(FlowyError error) = Unauthenticated; const factory AuthState.initial() = _Initial; } diff --git a/frontend/app_flowy/lib/user/domain/auth_state.freezed.dart b/frontend/app_flowy/lib/user/domain/auth_state.freezed.dart index 85e8fc3822..cf5aaa25c7 100644 --- a/frontend/app_flowy/lib/user/domain/auth_state.freezed.dart +++ b/frontend/app_flowy/lib/user/domain/auth_state.freezed.dart @@ -23,7 +23,7 @@ class _$AuthStateTearOff { ); } - Unauthenticated unauthenticated(UserError error) { + Unauthenticated unauthenticated(FlowyError error) { return Unauthenticated( error, ); @@ -42,21 +42,21 @@ mixin _$AuthState { @optionalTypeArgs TResult when({ required TResult Function(UserProfile userProfile) authenticated, - required TResult Function(UserError error) unauthenticated, + required TResult Function(FlowyError error) unauthenticated, required TResult Function() initial, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult? whenOrNull({ TResult Function(UserProfile userProfile)? authenticated, - TResult Function(UserError error)? unauthenticated, + TResult Function(FlowyError error)? unauthenticated, TResult Function()? initial, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult maybeWhen({ TResult Function(UserProfile userProfile)? authenticated, - TResult Function(UserError error)? unauthenticated, + TResult Function(FlowyError error)? unauthenticated, TResult Function()? initial, required TResult orElse(), }) => @@ -166,7 +166,7 @@ class _$Authenticated implements Authenticated { @optionalTypeArgs TResult when({ required TResult Function(UserProfile userProfile) authenticated, - required TResult Function(UserError error) unauthenticated, + required TResult Function(FlowyError error) unauthenticated, required TResult Function() initial, }) { return authenticated(userProfile); @@ -176,7 +176,7 @@ class _$Authenticated implements Authenticated { @optionalTypeArgs TResult? whenOrNull({ TResult Function(UserProfile userProfile)? authenticated, - TResult Function(UserError error)? unauthenticated, + TResult Function(FlowyError error)? unauthenticated, TResult Function()? initial, }) { return authenticated?.call(userProfile); @@ -186,7 +186,7 @@ class _$Authenticated implements Authenticated { @optionalTypeArgs TResult maybeWhen({ TResult Function(UserProfile userProfile)? authenticated, - TResult Function(UserError error)? unauthenticated, + TResult Function(FlowyError error)? unauthenticated, TResult Function()? initial, required TResult orElse(), }) { @@ -245,7 +245,7 @@ abstract class $UnauthenticatedCopyWith<$Res> { factory $UnauthenticatedCopyWith( Unauthenticated value, $Res Function(Unauthenticated) then) = _$UnauthenticatedCopyWithImpl<$Res>; - $Res call({UserError error}); + $Res call({FlowyError error}); } /// @nodoc @@ -266,7 +266,7 @@ class _$UnauthenticatedCopyWithImpl<$Res> extends _$AuthStateCopyWithImpl<$Res> error == freezed ? _value.error : error // ignore: cast_nullable_to_non_nullable - as UserError, + as FlowyError, )); } } @@ -277,7 +277,7 @@ class _$Unauthenticated implements Unauthenticated { const _$Unauthenticated(this.error); @override - final UserError error; + final FlowyError error; @override String toString() { @@ -305,7 +305,7 @@ class _$Unauthenticated implements Unauthenticated { @optionalTypeArgs TResult when({ required TResult Function(UserProfile userProfile) authenticated, - required TResult Function(UserError error) unauthenticated, + required TResult Function(FlowyError error) unauthenticated, required TResult Function() initial, }) { return unauthenticated(error); @@ -315,7 +315,7 @@ class _$Unauthenticated implements Unauthenticated { @optionalTypeArgs TResult? whenOrNull({ TResult Function(UserProfile userProfile)? authenticated, - TResult Function(UserError error)? unauthenticated, + TResult Function(FlowyError error)? unauthenticated, TResult Function()? initial, }) { return unauthenticated?.call(error); @@ -325,7 +325,7 @@ class _$Unauthenticated implements Unauthenticated { @optionalTypeArgs TResult maybeWhen({ TResult Function(UserProfile userProfile)? authenticated, - TResult Function(UserError error)? unauthenticated, + TResult Function(FlowyError error)? unauthenticated, TResult Function()? initial, required TResult orElse(), }) { @@ -371,9 +371,9 @@ class _$Unauthenticated implements Unauthenticated { } abstract class Unauthenticated implements AuthState { - const factory Unauthenticated(UserError error) = _$Unauthenticated; + const factory Unauthenticated(FlowyError error) = _$Unauthenticated; - UserError get error => throw _privateConstructorUsedError; + FlowyError get error => throw _privateConstructorUsedError; @JsonKey(ignore: true) $UnauthenticatedCopyWith get copyWith => throw _privateConstructorUsedError; @@ -417,7 +417,7 @@ class _$_Initial implements _Initial { @optionalTypeArgs TResult when({ required TResult Function(UserProfile userProfile) authenticated, - required TResult Function(UserError error) unauthenticated, + required TResult Function(FlowyError error) unauthenticated, required TResult Function() initial, }) { return initial(); @@ -427,7 +427,7 @@ class _$_Initial implements _Initial { @optionalTypeArgs TResult? whenOrNull({ TResult Function(UserProfile userProfile)? authenticated, - TResult Function(UserError error)? unauthenticated, + TResult Function(FlowyError error)? unauthenticated, TResult Function()? initial, }) { return initial?.call(); @@ -437,7 +437,7 @@ class _$_Initial implements _Initial { @optionalTypeArgs TResult maybeWhen({ TResult Function(UserProfile userProfile)? authenticated, - TResult Function(UserError error)? unauthenticated, + TResult Function(FlowyError error)? unauthenticated, TResult Function()? initial, required TResult orElse(), }) { diff --git a/frontend/app_flowy/lib/user/domain/i_auth.dart b/frontend/app_flowy/lib/user/domain/i_auth.dart index 3b557616e8..ecece96f3f 100644 --- a/frontend/app_flowy/lib/user/domain/i_auth.dart +++ b/frontend/app_flowy/lib/user/domain/i_auth.dart @@ -1,5 +1,5 @@ import 'package:dartz/dartz.dart'; -import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/protobuf.dart'; import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile; import 'package:flutter/material.dart'; @@ -14,9 +14,9 @@ class NewUser { } abstract class IAuth { - Future> signIn(String? email, String? password); - Future> signUp(String? name, String? password, String? email); - Future> signOut(); + Future> signIn(String? email, String? password); + Future> signUp(String? name, String? password, String? email); + Future> signOut(); } abstract class IAuthRouter { diff --git a/frontend/app_flowy/lib/user/infrastructure/i_auth_impl.dart b/frontend/app_flowy/lib/user/infrastructure/i_auth_impl.dart index b348d38c77..e94008cfb0 100644 --- a/frontend/app_flowy/lib/user/infrastructure/i_auth_impl.dart +++ b/frontend/app_flowy/lib/user/infrastructure/i_auth_impl.dart @@ -8,7 +8,7 @@ import 'package:flowy_infra_ui/widget/route/animation.dart'; import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile; import 'package:app_flowy/user/domain/i_auth.dart'; import 'package:app_flowy/user/infrastructure/repos/auth_repo.dart'; -import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/protobuf.dart'; import 'package:flutter/material.dart'; @@ -19,17 +19,17 @@ class AuthImpl extends IAuth { }); @override - Future> signIn(String? email, String? password) { + Future> signIn(String? email, String? password) { return repo.signIn(email: email, password: password); } @override - Future> signUp(String? name, String? password, String? email) { + Future> signUp(String? name, String? password, String? email) { return repo.signUp(name: name, password: password, email: email); } @override - Future> signOut() { + Future> signOut() { return repo.signOut(); } } diff --git a/frontend/app_flowy/lib/user/infrastructure/i_splash_impl.dart b/frontend/app_flowy/lib/user/infrastructure/i_splash_impl.dart index 79e8ce78e3..237b9ad60c 100644 --- a/frontend/app_flowy/lib/user/infrastructure/i_splash_impl.dart +++ b/frontend/app_flowy/lib/user/infrastructure/i_splash_impl.dart @@ -24,8 +24,8 @@ class SplashUserImpl implements ISplashUser { (userProfile) { return AuthState.authenticated(userProfile); }, - (userError) { - return AuthState.unauthenticated(userError); + (FlowyError) { + return AuthState.unauthenticated(FlowyError); }, ); }); diff --git a/frontend/app_flowy/lib/user/infrastructure/repos/auth_repo.dart b/frontend/app_flowy/lib/user/infrastructure/repos/auth_repo.dart index aea044d905..b42a5f7eda 100644 --- a/frontend/app_flowy/lib/user/infrastructure/repos/auth_repo.dart +++ b/frontend/app_flowy/lib/user/infrastructure/repos/auth_repo.dart @@ -1,10 +1,10 @@ import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show SignInRequest, SignUpRequest, UserProfile; -import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; class AuthRepository { - Future> signIn({required String? email, required String? password}) { + Future> signIn({required String? email, required String? password}) { // final request = SignInRequest.create() ..email = email ?? '' @@ -13,7 +13,7 @@ class AuthRepository { return UserEventSignIn(request).send(); } - Future> signUp( + Future> signUp( {required String? name, required String? password, required String? email}) { final request = SignUpRequest.create() ..email = email ?? '' @@ -35,7 +35,7 @@ class AuthRepository { // }); } - Future> signOut() { + Future> signOut() { return UserEventSignOut().send(); } } diff --git a/frontend/app_flowy/lib/user/presentation/sign_in_screen.dart b/frontend/app_flowy/lib/user/presentation/sign_in_screen.dart index 869c55e715..9dd984f278 100644 --- a/frontend/app_flowy/lib/user/presentation/sign_in_screen.dart +++ b/frontend/app_flowy/lib/user/presentation/sign_in_screen.dart @@ -9,7 +9,7 @@ import 'package:flowy_infra_ui/widget/rounded_button.dart'; import 'package:flowy_infra_ui/widget/rounded_input_field.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_infra_ui/style_widget/snap_bar.dart'; -import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -39,7 +39,7 @@ class SignInScreen extends StatelessWidget { ); } - void _handleSuccessOrFail(Either result, BuildContext context) { + void _handleSuccessOrFail(Either result, BuildContext context) { result.fold( (user) => router.pushWelcomeScreen(context, user), (error) => showSnapBar(context, error.msg), diff --git a/frontend/app_flowy/lib/user/presentation/sign_up_screen.dart b/frontend/app_flowy/lib/user/presentation/sign_up_screen.dart index 40aa18ef25..915fe6c505 100644 --- a/frontend/app_flowy/lib/user/presentation/sign_up_screen.dart +++ b/frontend/app_flowy/lib/user/presentation/sign_up_screen.dart @@ -7,7 +7,7 @@ import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/widget/rounded_button.dart'; import 'package:flowy_infra_ui/widget/rounded_input_field.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; -import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile; import 'package:flowy_infra_ui/style_widget/snap_bar.dart'; import 'package:flutter/material.dart'; @@ -36,7 +36,7 @@ class SignUpScreen extends StatelessWidget { ); } - void _handleSuccessOrFail(BuildContext context, Either result) { + void _handleSuccessOrFail(BuildContext context, Either result) { result.fold( (user) => router.pushWelcomeScreen(context, user), (error) => showSnapBar(context, error.msg), diff --git a/frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart b/frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart index 4c6df28b0f..c559c64371 100644 --- a/frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart +++ b/frontend/app_flowy/lib/user/presentation/skip_log_in_screen.dart @@ -10,7 +10,7 @@ import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/protobuf.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -113,7 +113,7 @@ class _SkipLogInScreenState extends State { void _openCurrentWorkspace( BuildContext context, UserProfile user, - dartz.Either workspacesOrError, + dartz.Either workspacesOrError, ) { workspacesOrError.fold( (workspaceSetting) { diff --git a/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart b/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart index a66eb5f56d..77888caa14 100644 --- a/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/app/app_bloc.dart @@ -2,7 +2,7 @@ import 'package:app_flowy/workspace/domain/i_app.dart'; import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/app_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:dartz/dartz.dart'; @@ -61,7 +61,7 @@ class AppBloc extends Bloc { return super.close(); } - void _handleViewsChanged(Either, WorkspaceError> result) { + void _handleViewsChanged(Either, FlowyError> result) { result.fold( (views) => add(AppEvent.didReceiveViews(views)), (error) { @@ -112,7 +112,7 @@ class AppState with _$AppState { required bool isLoading, required List? views, View? latestCreatedView, - required Either successOrFailure, + required Either successOrFailure, }) = _AppState; factory AppState.initial(App app) => AppState( diff --git a/frontend/app_flowy/lib/workspace/application/app/app_bloc.freezed.dart b/frontend/app_flowy/lib/workspace/application/app/app_bloc.freezed.dart index d795abad45..97c6987f07 100644 --- a/frontend/app_flowy/lib/workspace/application/app/app_bloc.freezed.dart +++ b/frontend/app_flowy/lib/workspace/application/app/app_bloc.freezed.dart @@ -1051,7 +1051,7 @@ class _$AppStateTearOff { required bool isLoading, required List? views, View? latestCreatedView, - required Either successOrFailure}) { + required Either successOrFailure}) { return _AppState( app: app, isLoading: isLoading, @@ -1071,7 +1071,7 @@ mixin _$AppState { bool get isLoading => throw _privateConstructorUsedError; List? get views => throw _privateConstructorUsedError; View? get latestCreatedView => throw _privateConstructorUsedError; - Either get successOrFailure => + Either get successOrFailure => throw _privateConstructorUsedError; @JsonKey(ignore: true) @@ -1088,7 +1088,7 @@ abstract class $AppStateCopyWith<$Res> { bool isLoading, List? views, View? latestCreatedView, - Either successOrFailure}); + Either successOrFailure}); } /// @nodoc @@ -1127,7 +1127,7 @@ class _$AppStateCopyWithImpl<$Res> implements $AppStateCopyWith<$Res> { successOrFailure: successOrFailure == freezed ? _value.successOrFailure : successOrFailure // ignore: cast_nullable_to_non_nullable - as Either, + as Either, )); } } @@ -1142,7 +1142,7 @@ abstract class _$AppStateCopyWith<$Res> implements $AppStateCopyWith<$Res> { bool isLoading, List? views, View? latestCreatedView, - Either successOrFailure}); + Either successOrFailure}); } /// @nodoc @@ -1182,7 +1182,7 @@ class __$AppStateCopyWithImpl<$Res> extends _$AppStateCopyWithImpl<$Res> successOrFailure: successOrFailure == freezed ? _value.successOrFailure : successOrFailure // ignore: cast_nullable_to_non_nullable - as Either, + as Either, )); } } @@ -1206,7 +1206,7 @@ class _$_AppState implements _AppState { @override final View? latestCreatedView; @override - final Either successOrFailure; + final Either successOrFailure; @override String toString() { @@ -1253,7 +1253,7 @@ abstract class _AppState implements AppState { required bool isLoading, required List? views, View? latestCreatedView, - required Either successOrFailure}) = _$_AppState; + required Either successOrFailure}) = _$_AppState; @override App get app => throw _privateConstructorUsedError; @@ -1264,7 +1264,7 @@ abstract class _AppState implements AppState { @override View? get latestCreatedView => throw _privateConstructorUsedError; @override - Either get successOrFailure => + Either get successOrFailure => throw _privateConstructorUsedError; @override @JsonKey(ignore: true) diff --git a/frontend/app_flowy/lib/workspace/application/doc/doc_bloc.dart b/frontend/app_flowy/lib/workspace/application/doc/doc_bloc.dart index 0ba9405b8f..e1c954cb89 100644 --- a/frontend/app_flowy/lib/workspace/application/doc/doc_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/doc/doc_bloc.dart @@ -4,7 +4,7 @@ import 'package:app_flowy/workspace/domain/i_trash.dart'; import 'package:app_flowy/workspace/domain/i_view.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/trash_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flutter_quill/flutter_quill.dart'; import 'package:flowy_log/flowy_log.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -155,5 +155,5 @@ class DocState with _$DocState { @freezed class DocLoadState with _$DocLoadState { const factory DocLoadState.loading() = _Loading; - const factory DocLoadState.finish(Either successOrFail) = _Finish; + const factory DocLoadState.finish(Either successOrFail) = _Finish; } diff --git a/frontend/app_flowy/lib/workspace/application/doc/doc_bloc.freezed.dart b/frontend/app_flowy/lib/workspace/application/doc/doc_bloc.freezed.dart index 02a1f50d94..4b6f63f3d6 100644 --- a/frontend/app_flowy/lib/workspace/application/doc/doc_bloc.freezed.dart +++ b/frontend/app_flowy/lib/workspace/application/doc/doc_bloc.freezed.dart @@ -909,7 +909,7 @@ class _$DocLoadStateTearOff { return const _Loading(); } - _Finish finish(Either successOrFail) { + _Finish finish(Either successOrFail) { return _Finish( successOrFail, ); @@ -924,20 +924,20 @@ mixin _$DocLoadState { @optionalTypeArgs TResult when({ required TResult Function() loading, - required TResult Function(Either successOrFail) + required TResult Function(Either successOrFail) finish, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult? whenOrNull({ TResult Function()? loading, - TResult Function(Either successOrFail)? finish, + TResult Function(Either successOrFail)? finish, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult maybeWhen({ TResult Function()? loading, - TResult Function(Either successOrFail)? finish, + TResult Function(Either successOrFail)? finish, required TResult orElse(), }) => throw _privateConstructorUsedError; @@ -1016,7 +1016,7 @@ class _$_Loading implements _Loading { @optionalTypeArgs TResult when({ required TResult Function() loading, - required TResult Function(Either successOrFail) + required TResult Function(Either successOrFail) finish, }) { return loading(); @@ -1026,7 +1026,7 @@ class _$_Loading implements _Loading { @optionalTypeArgs TResult? whenOrNull({ TResult Function()? loading, - TResult Function(Either successOrFail)? finish, + TResult Function(Either successOrFail)? finish, }) { return loading?.call(); } @@ -1035,7 +1035,7 @@ class _$_Loading implements _Loading { @optionalTypeArgs TResult maybeWhen({ TResult Function()? loading, - TResult Function(Either successOrFail)? finish, + TResult Function(Either successOrFail)? finish, required TResult orElse(), }) { if (loading != null) { @@ -1084,7 +1084,7 @@ abstract class _Loading implements DocLoadState { abstract class _$FinishCopyWith<$Res> { factory _$FinishCopyWith(_Finish value, $Res Function(_Finish) then) = __$FinishCopyWithImpl<$Res>; - $Res call({Either successOrFail}); + $Res call({Either successOrFail}); } /// @nodoc @@ -1104,7 +1104,7 @@ class __$FinishCopyWithImpl<$Res> extends _$DocLoadStateCopyWithImpl<$Res> successOrFail == freezed ? _value.successOrFail : successOrFail // ignore: cast_nullable_to_non_nullable - as Either, + as Either, )); } } @@ -1115,7 +1115,7 @@ class _$_Finish implements _Finish { const _$_Finish(this.successOrFail); @override - final Either successOrFail; + final Either successOrFail; @override String toString() { @@ -1144,7 +1144,7 @@ class _$_Finish implements _Finish { @optionalTypeArgs TResult when({ required TResult Function() loading, - required TResult Function(Either successOrFail) + required TResult Function(Either successOrFail) finish, }) { return finish(successOrFail); @@ -1154,7 +1154,7 @@ class _$_Finish implements _Finish { @optionalTypeArgs TResult? whenOrNull({ TResult Function()? loading, - TResult Function(Either successOrFail)? finish, + TResult Function(Either successOrFail)? finish, }) { return finish?.call(successOrFail); } @@ -1163,7 +1163,7 @@ class _$_Finish implements _Finish { @optionalTypeArgs TResult maybeWhen({ TResult Function()? loading, - TResult Function(Either successOrFail)? finish, + TResult Function(Either successOrFail)? finish, required TResult orElse(), }) { if (finish != null) { @@ -1205,9 +1205,9 @@ class _$_Finish implements _Finish { } abstract class _Finish implements DocLoadState { - const factory _Finish(Either successOrFail) = _$_Finish; + const factory _Finish(Either successOrFail) = _$_Finish; - Either get successOrFail => + Either get successOrFail => throw _privateConstructorUsedError; @JsonKey(ignore: true) _$FinishCopyWith<_Finish> get copyWith => throw _privateConstructorUsedError; diff --git a/frontend/app_flowy/lib/workspace/application/doc/share_bloc.dart b/frontend/app_flowy/lib/workspace/application/doc/share_bloc.dart index 48582082f3..c1504c4da7 100644 --- a/frontend/app_flowy/lib/workspace/application/doc/share_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/doc/share_bloc.dart @@ -2,7 +2,7 @@ import 'package:app_flowy/workspace/domain/i_share.dart'; import 'package:app_flowy/workspace/infrastructure/markdown/delta_markdown.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/export.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:dartz/dartz.dart'; @@ -48,5 +48,5 @@ class DocShareEvent with _$DocShareEvent { class DocShareState with _$DocShareState { const factory DocShareState.initial() = _Initial; const factory DocShareState.loading() = _Loading; - const factory DocShareState.finish(Either successOrFail) = _Finish; + const factory DocShareState.finish(Either successOrFail) = _Finish; } diff --git a/frontend/app_flowy/lib/workspace/application/doc/share_bloc.freezed.dart b/frontend/app_flowy/lib/workspace/application/doc/share_bloc.freezed.dart index ce72e660f2..2df633c426 100644 --- a/frontend/app_flowy/lib/workspace/application/doc/share_bloc.freezed.dart +++ b/frontend/app_flowy/lib/workspace/application/doc/share_bloc.freezed.dart @@ -434,7 +434,7 @@ class _$DocShareStateTearOff { return const _Loading(); } - _Finish finish(Either successOrFail) { + _Finish finish(Either successOrFail) { return _Finish( successOrFail, ); @@ -450,7 +450,7 @@ mixin _$DocShareState { TResult when({ required TResult Function() initial, required TResult Function() loading, - required TResult Function(Either successOrFail) + required TResult Function(Either successOrFail) finish, }) => throw _privateConstructorUsedError; @@ -458,14 +458,14 @@ mixin _$DocShareState { TResult? whenOrNull({ TResult Function()? initial, TResult Function()? loading, - TResult Function(Either successOrFail)? finish, + TResult Function(Either successOrFail)? finish, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult maybeWhen({ TResult Function()? initial, TResult Function()? loading, - TResult Function(Either successOrFail)? finish, + TResult Function(Either successOrFail)? finish, required TResult orElse(), }) => throw _privateConstructorUsedError; @@ -549,7 +549,7 @@ class _$_Initial implements _Initial { TResult when({ required TResult Function() initial, required TResult Function() loading, - required TResult Function(Either successOrFail) + required TResult Function(Either successOrFail) finish, }) { return initial(); @@ -560,7 +560,7 @@ class _$_Initial implements _Initial { TResult? whenOrNull({ TResult Function()? initial, TResult Function()? loading, - TResult Function(Either successOrFail)? finish, + TResult Function(Either successOrFail)? finish, }) { return initial?.call(); } @@ -570,7 +570,7 @@ class _$_Initial implements _Initial { TResult maybeWhen({ TResult Function()? initial, TResult Function()? loading, - TResult Function(Either successOrFail)? finish, + TResult Function(Either successOrFail)? finish, required TResult orElse(), }) { if (initial != null) { @@ -657,7 +657,7 @@ class _$_Loading implements _Loading { TResult when({ required TResult Function() initial, required TResult Function() loading, - required TResult Function(Either successOrFail) + required TResult Function(Either successOrFail) finish, }) { return loading(); @@ -668,7 +668,7 @@ class _$_Loading implements _Loading { TResult? whenOrNull({ TResult Function()? initial, TResult Function()? loading, - TResult Function(Either successOrFail)? finish, + TResult Function(Either successOrFail)? finish, }) { return loading?.call(); } @@ -678,7 +678,7 @@ class _$_Loading implements _Loading { TResult maybeWhen({ TResult Function()? initial, TResult Function()? loading, - TResult Function(Either successOrFail)? finish, + TResult Function(Either successOrFail)? finish, required TResult orElse(), }) { if (loading != null) { @@ -730,7 +730,7 @@ abstract class _Loading implements DocShareState { abstract class _$FinishCopyWith<$Res> { factory _$FinishCopyWith(_Finish value, $Res Function(_Finish) then) = __$FinishCopyWithImpl<$Res>; - $Res call({Either successOrFail}); + $Res call({Either successOrFail}); } /// @nodoc @@ -750,7 +750,7 @@ class __$FinishCopyWithImpl<$Res> extends _$DocShareStateCopyWithImpl<$Res> successOrFail == freezed ? _value.successOrFail : successOrFail // ignore: cast_nullable_to_non_nullable - as Either, + as Either, )); } } @@ -761,7 +761,7 @@ class _$_Finish implements _Finish { const _$_Finish(this.successOrFail); @override - final Either successOrFail; + final Either successOrFail; @override String toString() { @@ -791,7 +791,7 @@ class _$_Finish implements _Finish { TResult when({ required TResult Function() initial, required TResult Function() loading, - required TResult Function(Either successOrFail) + required TResult Function(Either successOrFail) finish, }) { return finish(successOrFail); @@ -802,7 +802,7 @@ class _$_Finish implements _Finish { TResult? whenOrNull({ TResult Function()? initial, TResult Function()? loading, - TResult Function(Either successOrFail)? finish, + TResult Function(Either successOrFail)? finish, }) { return finish?.call(successOrFail); } @@ -812,7 +812,7 @@ class _$_Finish implements _Finish { TResult maybeWhen({ TResult Function()? initial, TResult Function()? loading, - TResult Function(Either successOrFail)? finish, + TResult Function(Either successOrFail)? finish, required TResult orElse(), }) { if (finish != null) { @@ -857,10 +857,10 @@ class _$_Finish implements _Finish { } abstract class _Finish implements DocShareState { - const factory _Finish(Either successOrFail) = + const factory _Finish(Either successOrFail) = _$_Finish; - Either get successOrFail => + Either get successOrFail => throw _privateConstructorUsedError; @JsonKey(ignore: true) _$FinishCopyWith<_Finish> get copyWith => throw _privateConstructorUsedError; diff --git a/frontend/app_flowy/lib/workspace/application/home/home_listen_bloc.dart b/frontend/app_flowy/lib/workspace/application/home/home_listen_bloc.dart index 5e71b82380..e7ae03b094 100644 --- a/frontend/app_flowy/lib/workspace/application/home/home_listen_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/home/home_listen_bloc.dart @@ -1,5 +1,6 @@ import 'package:app_flowy/workspace/domain/i_user.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:dartz/dartz.dart'; @@ -31,7 +32,7 @@ class HomeListenBloc extends Bloc { super.close(); } - void _authDidChanged(Either errorOrNothing) { + void _authDidChanged(Either errorOrNothing) { errorOrNothing.fold((_) {}, (error) { if (error.code == ErrorCode.UserUnauthorized.value) { add(HomeListenEvent.unauthorized(error.msg)); diff --git a/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart b/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart index 84db381db7..651d569451 100644 --- a/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart @@ -5,7 +5,7 @@ import 'package:app_flowy/workspace/presentation/stack_page/blank/blank_page.dar import 'package:dartz/dartz.dart'; import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/app_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -77,7 +77,7 @@ class MenuBloc extends Bloc { ); } - void _handleAppsOrFail(Either, WorkspaceError> appsOrFail) { + void _handleAppsOrFail(Either, FlowyError> appsOrFail) { appsOrFail.fold( (apps) => add(MenuEvent.didReceiveApps(left(apps))), (error) => add(MenuEvent.didReceiveApps(right(error))), @@ -91,7 +91,7 @@ class MenuEvent with _$MenuEvent { const factory MenuEvent.collapse() = Collapse; const factory MenuEvent.openPage(HomeStackContext context) = OpenPage; const factory MenuEvent.createApp(String name, {String? desc}) = CreateApp; - const factory MenuEvent.didReceiveApps(Either, WorkspaceError> appsOrFail) = ReceiveApps; + const factory MenuEvent.didReceiveApps(Either, FlowyError> appsOrFail) = ReceiveApps; } @freezed @@ -99,7 +99,7 @@ class MenuState with _$MenuState { const factory MenuState({ required bool isCollapse, required Option> apps, - required Either successOrFailure, + required Either successOrFailure, required HomeStackContext stackContext, }) = _MenuState; diff --git a/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.freezed.dart b/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.freezed.dart index 3aa13660bc..a23f8bcd04 100644 --- a/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.freezed.dart +++ b/frontend/app_flowy/lib/workspace/application/menu/menu_bloc.freezed.dart @@ -38,7 +38,7 @@ class _$MenuEventTearOff { ); } - ReceiveApps didReceiveApps(Either, WorkspaceError> appsOrFail) { + ReceiveApps didReceiveApps(Either, FlowyError> appsOrFail) { return ReceiveApps( appsOrFail, ); @@ -57,7 +57,7 @@ mixin _$MenuEvent { required TResult Function(HomeStackContext context) openPage, required TResult Function(String name, String? desc) createApp, - required TResult Function(Either, WorkspaceError> appsOrFail) + required TResult Function(Either, FlowyError> appsOrFail) didReceiveApps, }) => throw _privateConstructorUsedError; @@ -67,7 +67,7 @@ mixin _$MenuEvent { TResult Function()? collapse, TResult Function(HomeStackContext context)? openPage, TResult Function(String name, String? desc)? createApp, - TResult Function(Either, WorkspaceError> appsOrFail)? + TResult Function(Either, FlowyError> appsOrFail)? didReceiveApps, }) => throw _privateConstructorUsedError; @@ -77,7 +77,7 @@ mixin _$MenuEvent { TResult Function()? collapse, TResult Function(HomeStackContext context)? openPage, TResult Function(String name, String? desc)? createApp, - TResult Function(Either, WorkspaceError> appsOrFail)? + TResult Function(Either, FlowyError> appsOrFail)? didReceiveApps, required TResult orElse(), }) => @@ -169,7 +169,7 @@ class _$_Initial implements _Initial { required TResult Function(HomeStackContext context) openPage, required TResult Function(String name, String? desc) createApp, - required TResult Function(Either, WorkspaceError> appsOrFail) + required TResult Function(Either, FlowyError> appsOrFail) didReceiveApps, }) { return initial(); @@ -182,7 +182,7 @@ class _$_Initial implements _Initial { TResult Function()? collapse, TResult Function(HomeStackContext context)? openPage, TResult Function(String name, String? desc)? createApp, - TResult Function(Either, WorkspaceError> appsOrFail)? + TResult Function(Either, FlowyError> appsOrFail)? didReceiveApps, }) { return initial?.call(); @@ -195,7 +195,7 @@ class _$_Initial implements _Initial { TResult Function()? collapse, TResult Function(HomeStackContext context)? openPage, TResult Function(String name, String? desc)? createApp, - TResult Function(Either, WorkspaceError> appsOrFail)? + TResult Function(Either, FlowyError> appsOrFail)? didReceiveApps, required TResult orElse(), }) { @@ -292,7 +292,7 @@ class _$Collapse implements Collapse { required TResult Function(HomeStackContext context) openPage, required TResult Function(String name, String? desc) createApp, - required TResult Function(Either, WorkspaceError> appsOrFail) + required TResult Function(Either, FlowyError> appsOrFail) didReceiveApps, }) { return collapse(); @@ -305,7 +305,7 @@ class _$Collapse implements Collapse { TResult Function()? collapse, TResult Function(HomeStackContext context)? openPage, TResult Function(String name, String? desc)? createApp, - TResult Function(Either, WorkspaceError> appsOrFail)? + TResult Function(Either, FlowyError> appsOrFail)? didReceiveApps, }) { return collapse?.call(); @@ -318,7 +318,7 @@ class _$Collapse implements Collapse { TResult Function()? collapse, TResult Function(HomeStackContext context)? openPage, TResult Function(String name, String? desc)? createApp, - TResult Function(Either, WorkspaceError> appsOrFail)? + TResult Function(Either, FlowyError> appsOrFail)? didReceiveApps, required TResult orElse(), }) { @@ -440,7 +440,7 @@ class _$OpenPage implements OpenPage { required TResult Function(HomeStackContext context) openPage, required TResult Function(String name, String? desc) createApp, - required TResult Function(Either, WorkspaceError> appsOrFail) + required TResult Function(Either, FlowyError> appsOrFail) didReceiveApps, }) { return openPage(context); @@ -453,7 +453,7 @@ class _$OpenPage implements OpenPage { TResult Function()? collapse, TResult Function(HomeStackContext context)? openPage, TResult Function(String name, String? desc)? createApp, - TResult Function(Either, WorkspaceError> appsOrFail)? + TResult Function(Either, FlowyError> appsOrFail)? didReceiveApps, }) { return openPage?.call(context); @@ -466,7 +466,7 @@ class _$OpenPage implements OpenPage { TResult Function()? collapse, TResult Function(HomeStackContext context)? openPage, TResult Function(String name, String? desc)? createApp, - TResult Function(Either, WorkspaceError> appsOrFail)? + TResult Function(Either, FlowyError> appsOrFail)? didReceiveApps, required TResult orElse(), }) { @@ -606,7 +606,7 @@ class _$CreateApp implements CreateApp { required TResult Function(HomeStackContext context) openPage, required TResult Function(String name, String? desc) createApp, - required TResult Function(Either, WorkspaceError> appsOrFail) + required TResult Function(Either, FlowyError> appsOrFail) didReceiveApps, }) { return createApp(name, desc); @@ -619,7 +619,7 @@ class _$CreateApp implements CreateApp { TResult Function()? collapse, TResult Function(HomeStackContext context)? openPage, TResult Function(String name, String? desc)? createApp, - TResult Function(Either, WorkspaceError> appsOrFail)? + TResult Function(Either, FlowyError> appsOrFail)? didReceiveApps, }) { return createApp?.call(name, desc); @@ -632,7 +632,7 @@ class _$CreateApp implements CreateApp { TResult Function()? collapse, TResult Function(HomeStackContext context)? openPage, TResult Function(String name, String? desc)? createApp, - TResult Function(Either, WorkspaceError> appsOrFail)? + TResult Function(Either, FlowyError> appsOrFail)? didReceiveApps, required TResult orElse(), }) { @@ -698,7 +698,7 @@ abstract class $ReceiveAppsCopyWith<$Res> { factory $ReceiveAppsCopyWith( ReceiveApps value, $Res Function(ReceiveApps) then) = _$ReceiveAppsCopyWithImpl<$Res>; - $Res call({Either, WorkspaceError> appsOrFail}); + $Res call({Either, FlowyError> appsOrFail}); } /// @nodoc @@ -719,7 +719,7 @@ class _$ReceiveAppsCopyWithImpl<$Res> extends _$MenuEventCopyWithImpl<$Res> appsOrFail == freezed ? _value.appsOrFail : appsOrFail // ignore: cast_nullable_to_non_nullable - as Either, WorkspaceError>, + as Either, FlowyError>, )); } } @@ -730,7 +730,7 @@ class _$ReceiveApps implements ReceiveApps { const _$ReceiveApps(this.appsOrFail); @override - final Either, WorkspaceError> appsOrFail; + final Either, FlowyError> appsOrFail; @override String toString() { @@ -763,7 +763,7 @@ class _$ReceiveApps implements ReceiveApps { required TResult Function(HomeStackContext context) openPage, required TResult Function(String name, String? desc) createApp, - required TResult Function(Either, WorkspaceError> appsOrFail) + required TResult Function(Either, FlowyError> appsOrFail) didReceiveApps, }) { return didReceiveApps(appsOrFail); @@ -776,7 +776,7 @@ class _$ReceiveApps implements ReceiveApps { TResult Function()? collapse, TResult Function(HomeStackContext context)? openPage, TResult Function(String name, String? desc)? createApp, - TResult Function(Either, WorkspaceError> appsOrFail)? + TResult Function(Either, FlowyError> appsOrFail)? didReceiveApps, }) { return didReceiveApps?.call(appsOrFail); @@ -789,7 +789,7 @@ class _$ReceiveApps implements ReceiveApps { TResult Function()? collapse, TResult Function(HomeStackContext context)? openPage, TResult Function(String name, String? desc)? createApp, - TResult Function(Either, WorkspaceError> appsOrFail)? + TResult Function(Either, FlowyError> appsOrFail)? didReceiveApps, required TResult orElse(), }) { @@ -841,10 +841,10 @@ class _$ReceiveApps implements ReceiveApps { } abstract class ReceiveApps implements MenuEvent { - const factory ReceiveApps(Either, WorkspaceError> appsOrFail) = + const factory ReceiveApps(Either, FlowyError> appsOrFail) = _$ReceiveApps; - Either, WorkspaceError> get appsOrFail => + Either, FlowyError> get appsOrFail => throw _privateConstructorUsedError; @JsonKey(ignore: true) $ReceiveAppsCopyWith get copyWith => @@ -858,7 +858,7 @@ class _$MenuStateTearOff { _MenuState call( {required bool isCollapse, required Option> apps, - required Either successOrFailure, + required Either successOrFailure, required HomeStackContext stackContext}) { return _MenuState( isCollapse: isCollapse, @@ -876,7 +876,7 @@ const $MenuState = _$MenuStateTearOff(); mixin _$MenuState { bool get isCollapse => throw _privateConstructorUsedError; Option> get apps => throw _privateConstructorUsedError; - Either get successOrFailure => + Either get successOrFailure => throw _privateConstructorUsedError; HomeStackContext get stackContext => throw _privateConstructorUsedError; @@ -893,7 +893,7 @@ abstract class $MenuStateCopyWith<$Res> { $Res call( {bool isCollapse, Option> apps, - Either successOrFailure, + Either successOrFailure, HomeStackContext stackContext}); } @@ -924,7 +924,7 @@ class _$MenuStateCopyWithImpl<$Res> implements $MenuStateCopyWith<$Res> { successOrFailure: successOrFailure == freezed ? _value.successOrFailure : successOrFailure // ignore: cast_nullable_to_non_nullable - as Either, + as Either, stackContext: stackContext == freezed ? _value.stackContext : stackContext // ignore: cast_nullable_to_non_nullable @@ -942,7 +942,7 @@ abstract class _$MenuStateCopyWith<$Res> implements $MenuStateCopyWith<$Res> { $Res call( {bool isCollapse, Option> apps, - Either successOrFailure, + Either successOrFailure, HomeStackContext stackContext}); } @@ -974,7 +974,7 @@ class __$MenuStateCopyWithImpl<$Res> extends _$MenuStateCopyWithImpl<$Res> successOrFailure: successOrFailure == freezed ? _value.successOrFailure : successOrFailure // ignore: cast_nullable_to_non_nullable - as Either, + as Either, stackContext: stackContext == freezed ? _value.stackContext : stackContext // ignore: cast_nullable_to_non_nullable @@ -997,7 +997,7 @@ class _$_MenuState implements _MenuState { @override final Option> apps; @override - final Either successOrFailure; + final Either successOrFailure; @override final HomeStackContext stackContext; @@ -1041,7 +1041,7 @@ abstract class _MenuState implements MenuState { const factory _MenuState( {required bool isCollapse, required Option> apps, - required Either successOrFailure, + required Either successOrFailure, required HomeStackContext stackContext}) = _$_MenuState; @override @@ -1049,7 +1049,7 @@ abstract class _MenuState implements MenuState { @override Option> get apps => throw _privateConstructorUsedError; @override - Either get successOrFailure => + Either get successOrFailure => throw _privateConstructorUsedError; @override HomeStackContext get stackContext => diff --git a/frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart b/frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart index b68700f4d8..f66da0262e 100644 --- a/frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart @@ -1,7 +1,7 @@ import 'package:app_flowy/workspace/domain/i_user.dart'; import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/workspace_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:dartz/dartz.dart'; @@ -39,8 +39,8 @@ class MenuUserBloc extends Bloc { result.fold((l) => null, (error) => Log.error(error)); } - void _profileUpdated(Either userOrFailed) {} - void _workspacesUpdated(Either, WorkspaceError> workspacesOrFailed) { + void _profileUpdated(Either userOrFailed) {} + void _workspacesUpdated(Either, FlowyError> workspacesOrFailed) { // fetch workspaces // iUserImpl.fetchWorkspaces().then((result) { // result.fold( diff --git a/frontend/app_flowy/lib/workspace/application/trash/trash_bloc.dart b/frontend/app_flowy/lib/workspace/application/trash/trash_bloc.dart index cd20a56a97..3eda6e3eaa 100644 --- a/frontend/app_flowy/lib/workspace/application/trash/trash_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/trash/trash_bloc.dart @@ -2,7 +2,7 @@ import 'package:app_flowy/workspace/domain/i_trash.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/trash_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; part 'trash_bloc.freezed.dart'; @@ -45,14 +45,14 @@ class TrashBloc extends Bloc { ); } - Stream _handleResult(Either result) async* { + Stream _handleResult(Either result) async* { yield result.fold( (l) => state.copyWith(successOrFailure: left(unit)), (error) => state.copyWith(successOrFailure: right(error)), ); } - void _listenTrashUpdated(Either, WorkspaceError> trashOrFailed) { + void _listenTrashUpdated(Either, FlowyError> trashOrFailed) { trashOrFailed.fold( (trash) { add(TrashEvent.didReceiveTrash(trash)); @@ -84,7 +84,7 @@ class TrashEvent with _$TrashEvent { class TrashState with _$TrashState { const factory TrashState({ required List objects, - required Either successOrFailure, + required Either successOrFailure, }) = _TrashState; factory TrashState.init() => TrashState( diff --git a/frontend/app_flowy/lib/workspace/application/trash/trash_bloc.freezed.dart b/frontend/app_flowy/lib/workspace/application/trash/trash_bloc.freezed.dart index aa26cda8b8..5fc468749e 100644 --- a/frontend/app_flowy/lib/workspace/application/trash/trash_bloc.freezed.dart +++ b/frontend/app_flowy/lib/workspace/application/trash/trash_bloc.freezed.dart @@ -980,7 +980,7 @@ class _$TrashStateTearOff { _TrashState call( {required List objects, - required Either successOrFailure}) { + required Either successOrFailure}) { return _TrashState( objects: objects, successOrFailure: successOrFailure, @@ -994,7 +994,7 @@ const $TrashState = _$TrashStateTearOff(); /// @nodoc mixin _$TrashState { List get objects => throw _privateConstructorUsedError; - Either get successOrFailure => + Either get successOrFailure => throw _privateConstructorUsedError; @JsonKey(ignore: true) @@ -1008,7 +1008,7 @@ abstract class $TrashStateCopyWith<$Res> { TrashState value, $Res Function(TrashState) then) = _$TrashStateCopyWithImpl<$Res>; $Res call( - {List objects, Either successOrFailure}); + {List objects, Either successOrFailure}); } /// @nodoc @@ -1032,7 +1032,7 @@ class _$TrashStateCopyWithImpl<$Res> implements $TrashStateCopyWith<$Res> { successOrFailure: successOrFailure == freezed ? _value.successOrFailure : successOrFailure // ignore: cast_nullable_to_non_nullable - as Either, + as Either, )); } } @@ -1044,7 +1044,7 @@ abstract class _$TrashStateCopyWith<$Res> implements $TrashStateCopyWith<$Res> { __$TrashStateCopyWithImpl<$Res>; @override $Res call( - {List objects, Either successOrFailure}); + {List objects, Either successOrFailure}); } /// @nodoc @@ -1070,7 +1070,7 @@ class __$TrashStateCopyWithImpl<$Res> extends _$TrashStateCopyWithImpl<$Res> successOrFailure: successOrFailure == freezed ? _value.successOrFailure : successOrFailure // ignore: cast_nullable_to_non_nullable - as Either, + as Either, )); } } @@ -1083,7 +1083,7 @@ class _$_TrashState implements _TrashState { @override final List objects; @override - final Either successOrFailure; + final Either successOrFailure; @override String toString() { @@ -1117,12 +1117,12 @@ class _$_TrashState implements _TrashState { abstract class _TrashState implements TrashState { const factory _TrashState( {required List objects, - required Either successOrFailure}) = _$_TrashState; + required Either successOrFailure}) = _$_TrashState; @override List get objects => throw _privateConstructorUsedError; @override - Either get successOrFailure => + Either get successOrFailure => throw _privateConstructorUsedError; @override @JsonKey(ignore: true) diff --git a/frontend/app_flowy/lib/workspace/application/view/view_bloc.dart b/frontend/app_flowy/lib/workspace/application/view/view_bloc.dart index 579c3d4165..92f0fc6a31 100644 --- a/frontend/app_flowy/lib/workspace/application/view/view_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/view/view_bloc.dart @@ -1,6 +1,6 @@ import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:app_flowy/workspace/domain/i_view.dart'; @@ -56,7 +56,7 @@ class ViewBloc extends Bloc { ); } - Stream _handleViewDidUpdate(Either result) async* { + Stream _handleViewDidUpdate(Either result) async* { yield result.fold( (view) => state.copyWith(view: view, successOrFailure: left(unit)), (error) => state.copyWith(successOrFailure: right(error)), @@ -77,7 +77,7 @@ class ViewEvent with _$ViewEvent { const factory ViewEvent.rename(String newName) = Rename; const factory ViewEvent.delete() = Delete; const factory ViewEvent.duplicate() = Duplicate; - const factory ViewEvent.viewDidUpdate(Either result) = ViewDidUpdate; + const factory ViewEvent.viewDidUpdate(Either result) = ViewDidUpdate; } @freezed @@ -85,7 +85,7 @@ class ViewState with _$ViewState { const factory ViewState({ required View view, required bool isEditing, - required Either successOrFailure, + required Either successOrFailure, }) = _ViewState; factory ViewState.init(View view) => ViewState( diff --git a/frontend/app_flowy/lib/workspace/application/view/view_bloc.freezed.dart b/frontend/app_flowy/lib/workspace/application/view/view_bloc.freezed.dart index 2a25991d3c..4f1fe4b838 100644 --- a/frontend/app_flowy/lib/workspace/application/view/view_bloc.freezed.dart +++ b/frontend/app_flowy/lib/workspace/application/view/view_bloc.freezed.dart @@ -41,7 +41,7 @@ class _$ViewEventTearOff { return const Duplicate(); } - ViewDidUpdate viewDidUpdate(Either result) { + ViewDidUpdate viewDidUpdate(Either result) { return ViewDidUpdate( result, ); @@ -60,7 +60,7 @@ mixin _$ViewEvent { required TResult Function(String newName) rename, required TResult Function() delete, required TResult Function() duplicate, - required TResult Function(Either result) + required TResult Function(Either result) viewDidUpdate, }) => throw _privateConstructorUsedError; @@ -71,7 +71,7 @@ mixin _$ViewEvent { TResult Function(String newName)? rename, TResult Function()? delete, TResult Function()? duplicate, - TResult Function(Either result)? viewDidUpdate, + TResult Function(Either result)? viewDidUpdate, }) => throw _privateConstructorUsedError; @optionalTypeArgs @@ -81,7 +81,7 @@ mixin _$ViewEvent { TResult Function(String newName)? rename, TResult Function()? delete, TResult Function()? duplicate, - TResult Function(Either result)? viewDidUpdate, + TResult Function(Either result)? viewDidUpdate, required TResult orElse(), }) => throw _privateConstructorUsedError; @@ -175,7 +175,7 @@ class _$Initial implements Initial { required TResult Function(String newName) rename, required TResult Function() delete, required TResult Function() duplicate, - required TResult Function(Either result) + required TResult Function(Either result) viewDidUpdate, }) { return initial(); @@ -189,7 +189,7 @@ class _$Initial implements Initial { TResult Function(String newName)? rename, TResult Function()? delete, TResult Function()? duplicate, - TResult Function(Either result)? viewDidUpdate, + TResult Function(Either result)? viewDidUpdate, }) { return initial?.call(); } @@ -202,7 +202,7 @@ class _$Initial implements Initial { TResult Function(String newName)? rename, TResult Function()? delete, TResult Function()? duplicate, - TResult Function(Either result)? viewDidUpdate, + TResult Function(Either result)? viewDidUpdate, required TResult orElse(), }) { if (initial != null) { @@ -328,7 +328,7 @@ class _$SetEditing implements SetEditing { required TResult Function(String newName) rename, required TResult Function() delete, required TResult Function() duplicate, - required TResult Function(Either result) + required TResult Function(Either result) viewDidUpdate, }) { return setIsEditing(isEditing); @@ -342,7 +342,7 @@ class _$SetEditing implements SetEditing { TResult Function(String newName)? rename, TResult Function()? delete, TResult Function()? duplicate, - TResult Function(Either result)? viewDidUpdate, + TResult Function(Either result)? viewDidUpdate, }) { return setIsEditing?.call(isEditing); } @@ -355,7 +355,7 @@ class _$SetEditing implements SetEditing { TResult Function(String newName)? rename, TResult Function()? delete, TResult Function()? duplicate, - TResult Function(Either result)? viewDidUpdate, + TResult Function(Either result)? viewDidUpdate, required TResult orElse(), }) { if (setIsEditing != null) { @@ -484,7 +484,7 @@ class _$Rename implements Rename { required TResult Function(String newName) rename, required TResult Function() delete, required TResult Function() duplicate, - required TResult Function(Either result) + required TResult Function(Either result) viewDidUpdate, }) { return rename(newName); @@ -498,7 +498,7 @@ class _$Rename implements Rename { TResult Function(String newName)? rename, TResult Function()? delete, TResult Function()? duplicate, - TResult Function(Either result)? viewDidUpdate, + TResult Function(Either result)? viewDidUpdate, }) { return rename?.call(newName); } @@ -511,7 +511,7 @@ class _$Rename implements Rename { TResult Function(String newName)? rename, TResult Function()? delete, TResult Function()? duplicate, - TResult Function(Either result)? viewDidUpdate, + TResult Function(Either result)? viewDidUpdate, required TResult orElse(), }) { if (rename != null) { @@ -614,7 +614,7 @@ class _$Delete implements Delete { required TResult Function(String newName) rename, required TResult Function() delete, required TResult Function() duplicate, - required TResult Function(Either result) + required TResult Function(Either result) viewDidUpdate, }) { return delete(); @@ -628,7 +628,7 @@ class _$Delete implements Delete { TResult Function(String newName)? rename, TResult Function()? delete, TResult Function()? duplicate, - TResult Function(Either result)? viewDidUpdate, + TResult Function(Either result)? viewDidUpdate, }) { return delete?.call(); } @@ -641,7 +641,7 @@ class _$Delete implements Delete { TResult Function(String newName)? rename, TResult Function()? delete, TResult Function()? duplicate, - TResult Function(Either result)? viewDidUpdate, + TResult Function(Either result)? viewDidUpdate, required TResult orElse(), }) { if (delete != null) { @@ -740,7 +740,7 @@ class _$Duplicate implements Duplicate { required TResult Function(String newName) rename, required TResult Function() delete, required TResult Function() duplicate, - required TResult Function(Either result) + required TResult Function(Either result) viewDidUpdate, }) { return duplicate(); @@ -754,7 +754,7 @@ class _$Duplicate implements Duplicate { TResult Function(String newName)? rename, TResult Function()? delete, TResult Function()? duplicate, - TResult Function(Either result)? viewDidUpdate, + TResult Function(Either result)? viewDidUpdate, }) { return duplicate?.call(); } @@ -767,7 +767,7 @@ class _$Duplicate implements Duplicate { TResult Function(String newName)? rename, TResult Function()? delete, TResult Function()? duplicate, - TResult Function(Either result)? viewDidUpdate, + TResult Function(Either result)? viewDidUpdate, required TResult orElse(), }) { if (duplicate != null) { @@ -829,7 +829,7 @@ abstract class $ViewDidUpdateCopyWith<$Res> { factory $ViewDidUpdateCopyWith( ViewDidUpdate value, $Res Function(ViewDidUpdate) then) = _$ViewDidUpdateCopyWithImpl<$Res>; - $Res call({Either result}); + $Res call({Either result}); } /// @nodoc @@ -850,7 +850,7 @@ class _$ViewDidUpdateCopyWithImpl<$Res> extends _$ViewEventCopyWithImpl<$Res> result == freezed ? _value.result : result // ignore: cast_nullable_to_non_nullable - as Either, + as Either, )); } } @@ -861,7 +861,7 @@ class _$ViewDidUpdate implements ViewDidUpdate { const _$ViewDidUpdate(this.result); @override - final Either result; + final Either result; @override String toString() { @@ -893,7 +893,7 @@ class _$ViewDidUpdate implements ViewDidUpdate { required TResult Function(String newName) rename, required TResult Function() delete, required TResult Function() duplicate, - required TResult Function(Either result) + required TResult Function(Either result) viewDidUpdate, }) { return viewDidUpdate(result); @@ -907,7 +907,7 @@ class _$ViewDidUpdate implements ViewDidUpdate { TResult Function(String newName)? rename, TResult Function()? delete, TResult Function()? duplicate, - TResult Function(Either result)? viewDidUpdate, + TResult Function(Either result)? viewDidUpdate, }) { return viewDidUpdate?.call(result); } @@ -920,7 +920,7 @@ class _$ViewDidUpdate implements ViewDidUpdate { TResult Function(String newName)? rename, TResult Function()? delete, TResult Function()? duplicate, - TResult Function(Either result)? viewDidUpdate, + TResult Function(Either result)? viewDidUpdate, required TResult orElse(), }) { if (viewDidUpdate != null) { @@ -974,10 +974,10 @@ class _$ViewDidUpdate implements ViewDidUpdate { } abstract class ViewDidUpdate implements ViewEvent { - const factory ViewDidUpdate(Either result) = + const factory ViewDidUpdate(Either result) = _$ViewDidUpdate; - Either get result => throw _privateConstructorUsedError; + Either get result => throw _privateConstructorUsedError; @JsonKey(ignore: true) $ViewDidUpdateCopyWith get copyWith => throw _privateConstructorUsedError; @@ -990,7 +990,7 @@ class _$ViewStateTearOff { _ViewState call( {required View view, required bool isEditing, - required Either successOrFailure}) { + required Either successOrFailure}) { return _ViewState( view: view, isEditing: isEditing, @@ -1006,7 +1006,7 @@ const $ViewState = _$ViewStateTearOff(); mixin _$ViewState { View get view => throw _privateConstructorUsedError; bool get isEditing => throw _privateConstructorUsedError; - Either get successOrFailure => + Either get successOrFailure => throw _privateConstructorUsedError; @JsonKey(ignore: true) @@ -1021,7 +1021,7 @@ abstract class $ViewStateCopyWith<$Res> { $Res call( {View view, bool isEditing, - Either successOrFailure}); + Either successOrFailure}); } /// @nodoc @@ -1050,7 +1050,7 @@ class _$ViewStateCopyWithImpl<$Res> implements $ViewStateCopyWith<$Res> { successOrFailure: successOrFailure == freezed ? _value.successOrFailure : successOrFailure // ignore: cast_nullable_to_non_nullable - as Either, + as Either, )); } } @@ -1064,7 +1064,7 @@ abstract class _$ViewStateCopyWith<$Res> implements $ViewStateCopyWith<$Res> { $Res call( {View view, bool isEditing, - Either successOrFailure}); + Either successOrFailure}); } /// @nodoc @@ -1094,7 +1094,7 @@ class __$ViewStateCopyWithImpl<$Res> extends _$ViewStateCopyWithImpl<$Res> successOrFailure: successOrFailure == freezed ? _value.successOrFailure : successOrFailure // ignore: cast_nullable_to_non_nullable - as Either, + as Either, )); } } @@ -1112,7 +1112,7 @@ class _$_ViewState implements _ViewState { @override final bool isEditing; @override - final Either successOrFailure; + final Either successOrFailure; @override String toString() { @@ -1150,14 +1150,14 @@ abstract class _ViewState implements ViewState { const factory _ViewState( {required View view, required bool isEditing, - required Either successOrFailure}) = _$_ViewState; + required Either successOrFailure}) = _$_ViewState; @override View get view => throw _privateConstructorUsedError; @override bool get isEditing => throw _privateConstructorUsedError; @override - Either get successOrFailure => + Either get successOrFailure => throw _privateConstructorUsedError; @override @JsonKey(ignore: true) diff --git a/frontend/app_flowy/lib/workspace/application/workspace/welcome_bloc.dart b/frontend/app_flowy/lib/workspace/application/workspace/welcome_bloc.dart index 16fc9805ff..8f563344a8 100644 --- a/frontend/app_flowy/lib/workspace/application/workspace/welcome_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/workspace/welcome_bloc.dart @@ -2,7 +2,7 @@ import 'package:app_flowy/workspace/domain/i_user.dart'; import 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart'; import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/workspace_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:dartz/dartz.dart'; @@ -76,7 +76,7 @@ class WelcomeBloc extends Bloc { ); } - void _workspacesUpdated(Either, WorkspaceError> workspacesOrFail) { + void _workspacesUpdated(Either, FlowyError> workspacesOrFail) { add(WelcomeEvent.workspacesReveived(workspacesOrFail)); } } @@ -87,7 +87,7 @@ class WelcomeEvent with _$WelcomeEvent { // const factory WelcomeEvent.fetchWorkspaces() = FetchWorkspace; const factory WelcomeEvent.createWorkspace(String name, String desc) = CreateWorkspace; const factory WelcomeEvent.openWorkspace(Workspace workspace) = OpenWorkspace; - const factory WelcomeEvent.workspacesReveived(Either, WorkspaceError> workspacesOrFail) = + const factory WelcomeEvent.workspacesReveived(Either, FlowyError> workspacesOrFail) = WorkspacesReceived; } @@ -96,7 +96,7 @@ class WelcomeState with _$WelcomeState { const factory WelcomeState({ required bool isLoading, required List workspaces, - required Either successOrFailure, + required Either successOrFailure, }) = _WelcomeState; factory WelcomeState.initial() => WelcomeState( diff --git a/frontend/app_flowy/lib/workspace/application/workspace/welcome_bloc.freezed.dart b/frontend/app_flowy/lib/workspace/application/workspace/welcome_bloc.freezed.dart index d0b7ebac29..6bd2c9bf4f 100644 --- a/frontend/app_flowy/lib/workspace/application/workspace/welcome_bloc.freezed.dart +++ b/frontend/app_flowy/lib/workspace/application/workspace/welcome_bloc.freezed.dart @@ -35,7 +35,7 @@ class _$WelcomeEventTearOff { } WorkspacesReceived workspacesReveived( - Either, WorkspaceError> workspacesOrFail) { + Either, FlowyError> workspacesOrFail) { return WorkspacesReceived( workspacesOrFail, ); @@ -53,7 +53,7 @@ mixin _$WelcomeEvent { required TResult Function(String name, String desc) createWorkspace, required TResult Function(Workspace workspace) openWorkspace, required TResult Function( - Either, WorkspaceError> workspacesOrFail) + Either, FlowyError> workspacesOrFail) workspacesReveived, }) => throw _privateConstructorUsedError; @@ -62,7 +62,7 @@ mixin _$WelcomeEvent { TResult Function()? initial, TResult Function(String name, String desc)? createWorkspace, TResult Function(Workspace workspace)? openWorkspace, - TResult Function(Either, WorkspaceError> workspacesOrFail)? + TResult Function(Either, FlowyError> workspacesOrFail)? workspacesReveived, }) => throw _privateConstructorUsedError; @@ -71,7 +71,7 @@ mixin _$WelcomeEvent { TResult Function()? initial, TResult Function(String name, String desc)? createWorkspace, TResult Function(Workspace workspace)? openWorkspace, - TResult Function(Either, WorkspaceError> workspacesOrFail)? + TResult Function(Either, FlowyError> workspacesOrFail)? workspacesReveived, required TResult orElse(), }) => @@ -160,7 +160,7 @@ class _$Initial implements Initial { required TResult Function(String name, String desc) createWorkspace, required TResult Function(Workspace workspace) openWorkspace, required TResult Function( - Either, WorkspaceError> workspacesOrFail) + Either, FlowyError> workspacesOrFail) workspacesReveived, }) { return initial(); @@ -172,7 +172,7 @@ class _$Initial implements Initial { TResult Function()? initial, TResult Function(String name, String desc)? createWorkspace, TResult Function(Workspace workspace)? openWorkspace, - TResult Function(Either, WorkspaceError> workspacesOrFail)? + TResult Function(Either, FlowyError> workspacesOrFail)? workspacesReveived, }) { return initial?.call(); @@ -184,7 +184,7 @@ class _$Initial implements Initial { TResult Function()? initial, TResult Function(String name, String desc)? createWorkspace, TResult Function(Workspace workspace)? openWorkspace, - TResult Function(Either, WorkspaceError> workspacesOrFail)? + TResult Function(Either, FlowyError> workspacesOrFail)? workspacesReveived, required TResult orElse(), }) { @@ -316,7 +316,7 @@ class _$CreateWorkspace implements CreateWorkspace { required TResult Function(String name, String desc) createWorkspace, required TResult Function(Workspace workspace) openWorkspace, required TResult Function( - Either, WorkspaceError> workspacesOrFail) + Either, FlowyError> workspacesOrFail) workspacesReveived, }) { return createWorkspace(name, desc); @@ -328,7 +328,7 @@ class _$CreateWorkspace implements CreateWorkspace { TResult Function()? initial, TResult Function(String name, String desc)? createWorkspace, TResult Function(Workspace workspace)? openWorkspace, - TResult Function(Either, WorkspaceError> workspacesOrFail)? + TResult Function(Either, FlowyError> workspacesOrFail)? workspacesReveived, }) { return createWorkspace?.call(name, desc); @@ -340,7 +340,7 @@ class _$CreateWorkspace implements CreateWorkspace { TResult Function()? initial, TResult Function(String name, String desc)? createWorkspace, TResult Function(Workspace workspace)? openWorkspace, - TResult Function(Either, WorkspaceError> workspacesOrFail)? + TResult Function(Either, FlowyError> workspacesOrFail)? workspacesReveived, required TResult orElse(), }) { @@ -467,7 +467,7 @@ class _$OpenWorkspace implements OpenWorkspace { required TResult Function(String name, String desc) createWorkspace, required TResult Function(Workspace workspace) openWorkspace, required TResult Function( - Either, WorkspaceError> workspacesOrFail) + Either, FlowyError> workspacesOrFail) workspacesReveived, }) { return openWorkspace(workspace); @@ -479,7 +479,7 @@ class _$OpenWorkspace implements OpenWorkspace { TResult Function()? initial, TResult Function(String name, String desc)? createWorkspace, TResult Function(Workspace workspace)? openWorkspace, - TResult Function(Either, WorkspaceError> workspacesOrFail)? + TResult Function(Either, FlowyError> workspacesOrFail)? workspacesReveived, }) { return openWorkspace?.call(workspace); @@ -491,7 +491,7 @@ class _$OpenWorkspace implements OpenWorkspace { TResult Function()? initial, TResult Function(String name, String desc)? createWorkspace, TResult Function(Workspace workspace)? openWorkspace, - TResult Function(Either, WorkspaceError> workspacesOrFail)? + TResult Function(Either, FlowyError> workspacesOrFail)? workspacesReveived, required TResult orElse(), }) { @@ -553,7 +553,7 @@ abstract class $WorkspacesReceivedCopyWith<$Res> { factory $WorkspacesReceivedCopyWith( WorkspacesReceived value, $Res Function(WorkspacesReceived) then) = _$WorkspacesReceivedCopyWithImpl<$Res>; - $Res call({Either, WorkspaceError> workspacesOrFail}); + $Res call({Either, FlowyError> workspacesOrFail}); } /// @nodoc @@ -575,7 +575,7 @@ class _$WorkspacesReceivedCopyWithImpl<$Res> workspacesOrFail == freezed ? _value.workspacesOrFail : workspacesOrFail // ignore: cast_nullable_to_non_nullable - as Either, WorkspaceError>, + as Either, FlowyError>, )); } } @@ -586,7 +586,7 @@ class _$WorkspacesReceived implements WorkspacesReceived { const _$WorkspacesReceived(this.workspacesOrFail); @override - final Either, WorkspaceError> workspacesOrFail; + final Either, FlowyError> workspacesOrFail; @override String toString() { @@ -619,7 +619,7 @@ class _$WorkspacesReceived implements WorkspacesReceived { required TResult Function(String name, String desc) createWorkspace, required TResult Function(Workspace workspace) openWorkspace, required TResult Function( - Either, WorkspaceError> workspacesOrFail) + Either, FlowyError> workspacesOrFail) workspacesReveived, }) { return workspacesReveived(workspacesOrFail); @@ -631,7 +631,7 @@ class _$WorkspacesReceived implements WorkspacesReceived { TResult Function()? initial, TResult Function(String name, String desc)? createWorkspace, TResult Function(Workspace workspace)? openWorkspace, - TResult Function(Either, WorkspaceError> workspacesOrFail)? + TResult Function(Either, FlowyError> workspacesOrFail)? workspacesReveived, }) { return workspacesReveived?.call(workspacesOrFail); @@ -643,7 +643,7 @@ class _$WorkspacesReceived implements WorkspacesReceived { TResult Function()? initial, TResult Function(String name, String desc)? createWorkspace, TResult Function(Workspace workspace)? openWorkspace, - TResult Function(Either, WorkspaceError> workspacesOrFail)? + TResult Function(Either, FlowyError> workspacesOrFail)? workspacesReveived, required TResult orElse(), }) { @@ -693,10 +693,10 @@ class _$WorkspacesReceived implements WorkspacesReceived { abstract class WorkspacesReceived implements WelcomeEvent { const factory WorkspacesReceived( - Either, WorkspaceError> workspacesOrFail) = + Either, FlowyError> workspacesOrFail) = _$WorkspacesReceived; - Either, WorkspaceError> get workspacesOrFail => + Either, FlowyError> get workspacesOrFail => throw _privateConstructorUsedError; @JsonKey(ignore: true) $WorkspacesReceivedCopyWith get copyWith => @@ -710,7 +710,7 @@ class _$WelcomeStateTearOff { _WelcomeState call( {required bool isLoading, required List workspaces, - required Either successOrFailure}) { + required Either successOrFailure}) { return _WelcomeState( isLoading: isLoading, workspaces: workspaces, @@ -726,7 +726,7 @@ const $WelcomeState = _$WelcomeStateTearOff(); mixin _$WelcomeState { bool get isLoading => throw _privateConstructorUsedError; List get workspaces => throw _privateConstructorUsedError; - Either get successOrFailure => + Either get successOrFailure => throw _privateConstructorUsedError; @JsonKey(ignore: true) @@ -742,7 +742,7 @@ abstract class $WelcomeStateCopyWith<$Res> { $Res call( {bool isLoading, List workspaces, - Either successOrFailure}); + Either successOrFailure}); } /// @nodoc @@ -771,7 +771,7 @@ class _$WelcomeStateCopyWithImpl<$Res> implements $WelcomeStateCopyWith<$Res> { successOrFailure: successOrFailure == freezed ? _value.successOrFailure : successOrFailure // ignore: cast_nullable_to_non_nullable - as Either, + as Either, )); } } @@ -786,7 +786,7 @@ abstract class _$WelcomeStateCopyWith<$Res> $Res call( {bool isLoading, List workspaces, - Either successOrFailure}); + Either successOrFailure}); } /// @nodoc @@ -817,7 +817,7 @@ class __$WelcomeStateCopyWithImpl<$Res> extends _$WelcomeStateCopyWithImpl<$Res> successOrFailure: successOrFailure == freezed ? _value.successOrFailure : successOrFailure // ignore: cast_nullable_to_non_nullable - as Either, + as Either, )); } } @@ -835,7 +835,7 @@ class _$_WelcomeState implements _WelcomeState { @override final List workspaces; @override - final Either successOrFailure; + final Either successOrFailure; @override String toString() { @@ -874,7 +874,7 @@ abstract class _WelcomeState implements WelcomeState { const factory _WelcomeState( {required bool isLoading, required List workspaces, - required Either successOrFailure}) = + required Either successOrFailure}) = _$_WelcomeState; @override @@ -882,7 +882,7 @@ abstract class _WelcomeState implements WelcomeState { @override List get workspaces => throw _privateConstructorUsedError; @override - Either get successOrFailure => + Either get successOrFailure => throw _privateConstructorUsedError; @override @JsonKey(ignore: true) diff --git a/frontend/app_flowy/lib/workspace/domain/i_app.dart b/frontend/app_flowy/lib/workspace/domain/i_app.dart index 3073809dc5..0c0d76d0c9 100644 --- a/frontend/app_flowy/lib/workspace/domain/i_app.dart +++ b/frontend/app_flowy/lib/workspace/domain/i_app.dart @@ -1,18 +1,18 @@ import 'package:flowy_sdk/protobuf/flowy-core-infra/protobuf.dart'; import 'package:dartz/dartz.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; typedef AppUpdatedCallback = void Function(App app); -typedef AppViewsChangeCallback = void Function(Either, WorkspaceError> viewsOrFailed); +typedef AppViewsChangeCallback = void Function(Either, FlowyError> viewsOrFailed); abstract class IApp { - Future, WorkspaceError>> getViews(); + Future, FlowyError>> getViews(); - Future> createView({required String name, String? desc, required ViewType viewType}); + Future> createView({required String name, String? desc, required ViewType viewType}); - Future> delete(); + Future> delete(); - Future> rename(String newName); + Future> rename(String newName); } abstract class IAppListenr { diff --git a/frontend/app_flowy/lib/workspace/domain/i_doc.dart b/frontend/app_flowy/lib/workspace/domain/i_doc.dart index 14c99c5118..3d65996189 100644 --- a/frontend/app_flowy/lib/workspace/domain/i_doc.dart +++ b/frontend/app_flowy/lib/workspace/domain/i_doc.dart @@ -1,10 +1,10 @@ import 'dart:async'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/protobuf/flowy-collaboration/doc.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; abstract class IDoc { - Future> readDoc(); - Future> composeDelta({required String json}); - Future> closeDoc(); + Future> readDoc(); + Future> composeDelta({required String json}); + Future> closeDoc(); } diff --git a/frontend/app_flowy/lib/workspace/domain/i_share.dart b/frontend/app_flowy/lib/workspace/domain/i_share.dart index cd24047807..11f119e9db 100644 --- a/frontend/app_flowy/lib/workspace/domain/i_share.dart +++ b/frontend/app_flowy/lib/workspace/domain/i_share.dart @@ -1,12 +1,12 @@ import 'dart:async'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/protobuf.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; abstract class IShare { - Future> exportText(String docId); + Future> exportText(String docId); - Future> exportMarkdown(String docId); + Future> exportMarkdown(String docId); - Future> exportURL(String docId); + Future> exportURL(String docId); } diff --git a/frontend/app_flowy/lib/workspace/domain/i_trash.dart b/frontend/app_flowy/lib/workspace/domain/i_trash.dart index 5ab660f081..b72d815217 100644 --- a/frontend/app_flowy/lib/workspace/domain/i_trash.dart +++ b/frontend/app_flowy/lib/workspace/domain/i_trash.dart @@ -1,21 +1,21 @@ import 'dart:async'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/trash_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; abstract class ITrash { - Future, WorkspaceError>> readTrash(); + Future, FlowyError>> readTrash(); - Future> putback(String trashId); + Future> putback(String trashId); - Future> deleteViews(List> trashList); + Future> deleteViews(List> trashList); - Future> restoreAll(); + Future> restoreAll(); - Future> deleteAll(); + Future> deleteAll(); } -typedef TrashUpdatedCallback = void Function(Either, WorkspaceError> trashOrFailed); +typedef TrashUpdatedCallback = void Function(Either, FlowyError> trashOrFailed); abstract class ITrashListener { void start(TrashUpdatedCallback updateCallback); diff --git a/frontend/app_flowy/lib/workspace/domain/i_user.dart b/frontend/app_flowy/lib/workspace/domain/i_user.dart index 4fc5ecab1d..c035da9b3c 100644 --- a/frontend/app_flowy/lib/workspace/domain/i_user.dart +++ b/frontend/app_flowy/lib/workspace/domain/i_user.dart @@ -1,24 +1,22 @@ import 'package:dartz/dartz.dart'; import 'package:flowy_infra/notifier.dart'; -import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile; import 'package:flowy_sdk/protobuf/flowy-core-infra/workspace_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; -export 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart'; export 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProfile; abstract class IUser { UserProfile get user; - Future> fetchUserProfile(String userId); - Future, WorkspaceError>> fetchWorkspaces(); - Future> deleteWorkspace(String workspaceId); - Future> signOut(); - Future> initUser(); + Future> fetchUserProfile(String userId); + Future, FlowyError>> fetchWorkspaces(); + Future> deleteWorkspace(String workspaceId); + Future> signOut(); + Future> initUser(); } -typedef UserProfileUpdatedNotifierValue = Either; -typedef AuthNotifierValue = Either; -typedef WorkspaceUpdatedNotifierValue = Either, WorkspaceError>; +typedef UserProfileUpdatedNotifierValue = Either; +typedef AuthNotifierValue = Either; +typedef WorkspaceUpdatedNotifierValue = Either, FlowyError>; abstract class IUserListener { void start(); diff --git a/frontend/app_flowy/lib/workspace/domain/i_view.dart b/frontend/app_flowy/lib/workspace/domain/i_view.dart index d982baf00f..5675dbda80 100644 --- a/frontend/app_flowy/lib/workspace/domain/i_view.dart +++ b/frontend/app_flowy/lib/workspace/domain/i_view.dart @@ -1,22 +1,22 @@ import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_infra/notifier.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; -typedef ViewUpdatedCallback = void Function(Either); +typedef ViewUpdatedCallback = void Function(Either); -typedef DeleteNotifierValue = Either; -typedef UpdateNotifierValue = Either; -typedef RestoreNotifierValue = Either; +typedef DeleteNotifierValue = Either; +typedef UpdateNotifierValue = Either; +typedef RestoreNotifierValue = Either; abstract class IView { View get view; - Future> delete(); + Future> delete(); - Future> rename(String newName); + Future> rename(String newName); - Future> duplicate(); + Future> duplicate(); } abstract class IViewListener { diff --git a/frontend/app_flowy/lib/workspace/domain/i_workspace.dart b/frontend/app_flowy/lib/workspace/domain/i_workspace.dart index beb85d0115..0b9e016fb2 100644 --- a/frontend/app_flowy/lib/workspace/domain/i_workspace.dart +++ b/frontend/app_flowy/lib/workspace/domain/i_workspace.dart @@ -1,15 +1,15 @@ import 'package:flowy_sdk/protobuf/flowy-core-infra/protobuf.dart'; import 'package:dartz/dartz.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; -typedef WorkspaceAppsChangedCallback = void Function(Either, WorkspaceError> appsOrFail); +typedef WorkspaceAppsChangedCallback = void Function(Either, FlowyError> appsOrFail); typedef WorkspaceUpdatedCallback = void Function(String name, String desc); abstract class IWorkspace { - Future> createApp({required String name, String? desc}); + Future> createApp({required String name, String? desc}); - Future, WorkspaceError>> getApps(); + Future, FlowyError>> getApps(); } abstract class IWorkspaceListener { diff --git a/frontend/app_flowy/lib/workspace/infrastructure/i_app_impl.dart b/frontend/app_flowy/lib/workspace/infrastructure/i_app_impl.dart index 2dec77f617..2960f6acec 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/i_app_impl.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/i_app_impl.dart @@ -2,7 +2,7 @@ import 'package:app_flowy/workspace/infrastructure/repos/app_repo.dart'; import 'package:dartz/dartz.dart'; import 'package:app_flowy/workspace/domain/i_app.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; export 'package:app_flowy/workspace/domain/i_app.dart'; class IAppImpl extends IApp { @@ -12,12 +12,12 @@ class IAppImpl extends IApp { }); @override - Future, WorkspaceError>> getViews() { + Future, FlowyError>> getViews() { return repo.getViews(); } @override - Future> createView({required String name, String? desc, required ViewType viewType}) { + Future> createView({required String name, String? desc, required ViewType viewType}) { return repo.createView(name, desc ?? "", viewType).then((result) { return result.fold( (view) => left(view), @@ -27,12 +27,12 @@ class IAppImpl extends IApp { } @override - Future> delete() { + Future> delete() { return repo.delete(); } @override - Future> rename(String newName) { + Future> rename(String newName) { return repo.updateApp(name: newName); } } diff --git a/frontend/app_flowy/lib/workspace/infrastructure/i_doc_impl.dart b/frontend/app_flowy/lib/workspace/infrastructure/i_doc_impl.dart index a1f281bea0..d188b579f8 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/i_doc_impl.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/i_doc_impl.dart @@ -5,7 +5,7 @@ import 'package:dartz/dartz.dart'; import 'package:app_flowy/workspace/domain/i_doc.dart'; import 'package:app_flowy/workspace/infrastructure/repos/doc_repo.dart'; import 'package:flowy_sdk/protobuf/flowy-collaboration/doc.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; class IDocImpl extends IDoc { DocRepository repo; @@ -13,18 +13,18 @@ class IDocImpl extends IDoc { IDocImpl({required this.repo}); @override - Future> closeDoc() { + Future> closeDoc() { return repo.closeDoc(); } @override - Future> readDoc() async { + Future> readDoc() async { final docOrFail = await repo.readDoc(); return docOrFail; } @override - Future> composeDelta({required String json}) { + Future> composeDelta({required String json}) { return repo.composeDelta(data: json); } } diff --git a/frontend/app_flowy/lib/workspace/infrastructure/i_share_impl.dart b/frontend/app_flowy/lib/workspace/infrastructure/i_share_impl.dart index 12ed9722c4..5b2b4bc20d 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/i_share_impl.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/i_share_impl.dart @@ -1,6 +1,6 @@ import 'package:app_flowy/workspace/domain/i_share.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/protobuf.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:dartz/dartz.dart'; import 'repos/share_repo.dart'; @@ -11,17 +11,17 @@ class IShareImpl extends IShare { IShareImpl({required this.repo}); @override - Future> exportText(String docId) { + Future> exportText(String docId) { return repo.export(docId, ExportType.Text); } @override - Future> exportMarkdown(String docId) { + Future> exportMarkdown(String docId) { return repo.export(docId, ExportType.Markdown); } @override - Future> exportURL(String docId) { + Future> exportURL(String docId) { return repo.export(docId, ExportType.Link); } } diff --git a/frontend/app_flowy/lib/workspace/infrastructure/i_trash_impl.dart b/frontend/app_flowy/lib/workspace/infrastructure/i_trash_impl.dart index 26a44ba169..c20c3c639a 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/i_trash_impl.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/i_trash_impl.dart @@ -2,7 +2,7 @@ import 'package:app_flowy/workspace/domain/i_trash.dart'; import 'package:app_flowy/workspace/infrastructure/repos/trash_repo.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/trash_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; class ITrashImpl implements ITrash { TrashRepo repo; @@ -10,7 +10,7 @@ class ITrashImpl implements ITrash { ITrashImpl({required this.repo}); @override - Future, WorkspaceError>> readTrash() { + Future, FlowyError>> readTrash() { return repo.readTrash().then((result) { return result.fold( (repeatedTrash) => left(repeatedTrash.items), @@ -20,22 +20,22 @@ class ITrashImpl implements ITrash { } @override - Future> putback(String trashId) { + Future> putback(String trashId) { return repo.putback(trashId); } @override - Future> deleteAll() { + Future> deleteAll() { return repo.deleteAll(); } @override - Future> restoreAll() { + Future> restoreAll() { return repo.restoreAll(); } @override - Future> deleteViews(List> trashList) { + Future> deleteViews(List> trashList) { return repo.deleteViews(trashList); } } diff --git a/frontend/app_flowy/lib/workspace/infrastructure/i_user_impl.dart b/frontend/app_flowy/lib/workspace/infrastructure/i_user_impl.dart index 08d7e3e12e..73e85d1b9f 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/i_user_impl.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/i_user_impl.dart @@ -10,7 +10,7 @@ import 'package:flowy_sdk/protobuf/flowy-user-infra/errors.pb.dart'; // import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart' as user_error; import 'package:flowy_sdk/protobuf/flowy-user/observable.pb.dart' as user; import 'package:flowy_sdk/protobuf/flowy-core-infra/workspace_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/observable.pb.dart'; export 'package:app_flowy/workspace/domain/i_user.dart'; export 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart'; @@ -24,17 +24,17 @@ class IUserImpl extends IUser { }); @override - Future> deleteWorkspace(String workspaceId) { + Future> deleteWorkspace(String workspaceId) { return repo.deleteWorkspace(workspaceId: workspaceId); } @override - Future> fetchUserProfile(String userId) { + Future> fetchUserProfile(String userId) { return repo.fetchUserProfile(userId: userId); } @override - Future> signOut() { + Future> signOut() { return repo.signOut(); } @@ -42,12 +42,12 @@ class IUserImpl extends IUser { UserProfile get user => repo.user; @override - Future, WorkspaceError>> fetchWorkspaces() { + Future, FlowyError>> fetchWorkspaces() { return repo.getWorkspaces(); } @override - Future> initUser() { + Future> initUser() { return repo.initUser(); } } @@ -88,7 +88,7 @@ class IUserListenerImpl extends IUserListener { await _subscription?.cancel(); } - void _notificationCallback(WorkspaceNotification ty, Either result) { + void _notificationCallback(WorkspaceNotification ty, Either result) { switch (ty) { case WorkspaceNotification.UserCreateWorkspace: case WorkspaceNotification.UserDeleteWorkspace: @@ -101,7 +101,7 @@ class IUserListenerImpl extends IUserListener { case WorkspaceNotification.UserUnauthorized: result.fold( (_) {}, - (error) => authDidChangedNotifier.value = right(UserError.create()..code = ErrorCode.UserUnauthorized.value), + (error) => authDidChangedNotifier.value = right(FlowyError.create()..code = ErrorCode.UserUnauthorized.value), ); break; default: @@ -109,7 +109,7 @@ class IUserListenerImpl extends IUserListener { } } - void _userNotificationCallback(user.UserNotification ty, Either result) { + void _userNotificationCallback(user.UserNotification ty, Either result) { switch (ty) { case user.UserNotification.UserUnauthorized: result.fold( diff --git a/frontend/app_flowy/lib/workspace/infrastructure/i_view_impl.dart b/frontend/app_flowy/lib/workspace/infrastructure/i_view_impl.dart index 84bc049b33..3d1b4c3232 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/i_view_impl.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/i_view_impl.dart @@ -3,7 +3,7 @@ import 'package:app_flowy/workspace/infrastructure/repos/view_repo.dart'; import 'package:flowy_infra/notifier.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; class IViewImpl extends IView { ViewRepository repo; @@ -14,7 +14,7 @@ class IViewImpl extends IView { View get view => repo.view; @override - Future> delete() { + Future> delete() { return repo.delete().then((result) { return result.fold( (_) => left(unit), @@ -24,12 +24,12 @@ class IViewImpl extends IView { } @override - Future> rename(String newName) { + Future> rename(String newName) { return repo.updateView(name: newName); } @override - Future> duplicate() { + Future> duplicate() { return repo.duplicate(); } } diff --git a/frontend/app_flowy/lib/workspace/infrastructure/i_workspace_impl.dart b/frontend/app_flowy/lib/workspace/infrastructure/i_workspace_impl.dart index a90e9b62c3..8be815a11d 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/i_workspace_impl.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/i_workspace_impl.dart @@ -2,7 +2,7 @@ import 'package:app_flowy/workspace/domain/i_workspace.dart'; import 'package:app_flowy/workspace/infrastructure/repos/workspace_repo.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/app_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; export 'package:app_flowy/workspace/domain/i_workspace.dart'; @@ -13,12 +13,12 @@ class IWorkspaceImpl extends IWorkspace { }); @override - Future> createApp({required String name, String? desc}) { + Future> createApp({required String name, String? desc}) { return repo.createApp(name, desc ?? ""); } @override - Future, WorkspaceError>> getApps() { + Future, FlowyError>> getApps() { return repo.getApps().then((result) { return result.fold( (apps) => left(apps), diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/app_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/app_repo.dart index d5cb40af1c..836ac852cf 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/app_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/app_repo.dart @@ -9,7 +9,7 @@ import 'package:flowy_sdk/protobuf/flowy-core-infra/app_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/app_query.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/app_update.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/observable.pb.dart'; import 'package:flowy_sdk/rust_stream.dart'; import 'helper.dart'; @@ -20,13 +20,13 @@ class AppRepository { required this.appId, }); - Future> getAppDesc() { + Future> getAppDesc() { final request = QueryAppRequest.create()..appIds.add(appId); return WorkspaceEventReadApp(request).send(); } - Future> createView(String name, String desc, ViewType viewType) { + Future> createView(String name, String desc, ViewType viewType) { final request = CreateViewRequest.create() ..belongToId = appId ..name = name @@ -36,7 +36,7 @@ class AppRepository { return WorkspaceEventCreateView(request).send(); } - Future, WorkspaceError>> getViews() { + Future, FlowyError>> getViews() { final request = QueryAppRequest.create()..appIds.add(appId); return WorkspaceEventReadApp(request).send().then((result) { @@ -47,12 +47,12 @@ class AppRepository { }); } - Future> delete() { + Future> delete() { final request = QueryAppRequest.create()..appIds.add(appId); return WorkspaceEventDeleteApp(request).send(); } - Future> updateApp({String? name}) { + Future> updateApp({String? name}) { UpdateAppRequest request = UpdateAppRequest.create()..appId = appId; if (name != null) { @@ -80,7 +80,7 @@ class AppListenerRepository { _subscription = RustStreamReceiver.listen((observable) => _parser.parse(observable)); } - void _bservableCallback(WorkspaceNotification ty, Either result) { + void _bservableCallback(WorkspaceNotification ty, Either result) { switch (ty) { case WorkspaceNotification.AppViewsChanged: if (_viewsChanged != null) { diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/doc_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/doc_repo.dart index 696143f6fd..76d640d60d 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/doc_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/doc_repo.dart @@ -2,7 +2,7 @@ import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-collaboration/doc.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/view_query.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; class DocRepository { final String docId; @@ -10,19 +10,19 @@ class DocRepository { required this.docId, }); - Future> readDoc() { + Future> readDoc() { final request = QueryViewRequest(viewIds: [docId]); return WorkspaceEventOpenView(request).send(); } - Future> composeDelta({required String data}) { + Future> composeDelta({required String data}) { final request = DocDelta.create() ..docId = docId ..data = data; return WorkspaceEventApplyDocDelta(request).send(); } - Future> closeDoc() { + Future> closeDoc() { final request = QueryViewRequest(viewIds: [docId]); return WorkspaceEventCloseView(request).send(); } diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/helper.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/helper.dart index 2110e6f725..2894bdd771 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/helper.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/helper.dart @@ -2,30 +2,30 @@ import 'dart:typed_data'; import 'package:flowy_sdk/protobuf/dart-notify/protobuf.dart'; import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart'; import 'package:dartz/dartz.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/observable.pb.dart'; -typedef UserNotificationCallback = void Function(UserNotification, Either); +typedef UserNotificationCallback = void Function(UserNotification, Either); -class UserNotificationParser extends NotificationParser { +class UserNotificationParser extends NotificationParser { UserNotificationParser({required String id, required UserNotificationCallback callback}) : super( id: id, callback: callback, tyParser: (ty) => UserNotification.valueOf(ty), - errorParser: (bytes) => UserError.fromBuffer(bytes), + errorParser: (bytes) => FlowyError.fromBuffer(bytes), ); } -typedef NotificationCallback = void Function(WorkspaceNotification, Either); +typedef NotificationCallback = void Function(WorkspaceNotification, Either); -class WorkspaceNotificationParser extends NotificationParser { +class WorkspaceNotificationParser extends NotificationParser { WorkspaceNotificationParser({String? id, required NotificationCallback callback}) : super( id: id, callback: callback, tyParser: (ty) => WorkspaceNotification.valueOf(ty), - errorParser: (bytes) => WorkspaceError.fromBuffer(bytes), + errorParser: (bytes) => FlowyError.fromBuffer(bytes), ); } diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/share_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/share_repo.dart index 85f8334316..8289f4a97c 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/share_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/share_repo.dart @@ -2,10 +2,10 @@ import 'dart:async'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/protobuf.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; class ShareRepo { - Future> export(String docId, ExportType type) { + Future> export(String docId, ExportType type) { final request = ExportRequest.create() ..docId = docId ..exportType = type; diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/trash_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/trash_repo.dart index 821c1db7af..9656f1432d 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/trash_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/trash_repo.dart @@ -6,22 +6,22 @@ import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/dart-notify/subject.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/trash_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/observable.pb.dart'; import 'package:flowy_sdk/rust_stream.dart'; class TrashRepo { - Future> readTrash() { + Future> readTrash() { return WorkspaceEventReadTrash().send(); } - Future> putback(String trashId) { + Future> putback(String trashId) { final id = TrashIdentifier.create()..id = trashId; return WorkspaceEventPutbackTrash(id).send(); } - Future> deleteViews(List> trashList) { + Future> deleteViews(List> trashList) { final items = trashList.map((trash) { return TrashIdentifier.create() ..id = trash.value1 @@ -32,11 +32,11 @@ class TrashRepo { return WorkspaceEventDeleteTrash(trashIdentifiers).send(); } - Future> restoreAll() { + Future> restoreAll() { return WorkspaceEventRestoreAll().send(); } - Future> deleteAll() { + Future> deleteAll() { return WorkspaceEventDeleteAll().send(); } } @@ -52,7 +52,7 @@ class TrashListenerRepo { _subscription = RustStreamReceiver.listen((observable) => _parser.parse(observable)); } - void _bservableCallback(WorkspaceNotification ty, Either result) { + void _bservableCallback(WorkspaceNotification ty, Either result) { switch (ty) { case WorkspaceNotification.TrashUpdated: if (_trashUpdated != null) { diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/user_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/user_repo.dart index 2d5411739a..b35a771b47 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/user_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/user_repo.dart @@ -4,7 +4,7 @@ import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/workspace_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/workspace_query.pb.dart'; import 'package:app_flowy/workspace/domain/i_user.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; class UserRepo { final UserProfile user; @@ -12,23 +12,23 @@ class UserRepo { required this.user, }); - Future> fetchUserProfile({required String userId}) { + Future> fetchUserProfile({required String userId}) { return UserEventGetUserProfile().send(); } - Future> deleteWorkspace({required String workspaceId}) { + Future> deleteWorkspace({required String workspaceId}) { throw UnimplementedError(); } - Future> signOut() { + Future> signOut() { return UserEventSignOut().send(); } - Future> initUser() async { + Future> initUser() async { return UserEventInitUser().send(); } - Future, WorkspaceError>> getWorkspaces() { + Future, FlowyError>> getWorkspaces() { final request = QueryWorkspaceRequest.create(); return WorkspaceEventReadWorkspaces(request).send().then((result) { @@ -39,7 +39,7 @@ class UserRepo { }); } - Future> openWorkspace(String workspaceId) { + Future> openWorkspace(String workspaceId) { final request = QueryWorkspaceRequest.create()..workspaceId = workspaceId; return WorkspaceEventOpenWorkspace(request).send().then((result) { return result.fold( @@ -49,7 +49,7 @@ class UserRepo { }); } - Future> createWorkspace(String name, String desc) { + Future> createWorkspace(String name, String desc) { final request = CreateWorkspaceRequest.create() ..name = name ..desc = desc; diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/view_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/view_repo.dart index 96d19d80b8..2a2629f09f 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/view_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/view_repo.dart @@ -6,7 +6,7 @@ import 'package:flowy_sdk/protobuf/dart-notify/subject.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/view_query.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/view_update.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/observable.pb.dart'; import 'package:flowy_sdk/rust_stream.dart'; @@ -21,12 +21,12 @@ class ViewRepository { required this.view, }); - Future> readView() { + Future> readView() { final request = QueryViewRequest(viewIds: [view.id]); return WorkspaceEventReadView(request).send(); } - Future> updateView({String? name, String? desc}) { + Future> updateView({String? name, String? desc}) { final request = UpdateViewRequest.create()..viewId = view.id; if (name != null) { @@ -40,12 +40,12 @@ class ViewRepository { return WorkspaceEventUpdateView(request).send(); } - Future> delete() { + Future> delete() { final request = QueryViewRequest.create()..viewIds.add(view.id); return WorkspaceEventDeleteView(request).send(); } - Future> duplicate() { + Future> duplicate() { final request = QueryViewRequest.create()..viewIds.add(view.id); return WorkspaceEventDuplicateView(request).send(); } @@ -74,7 +74,7 @@ class ViewListenerRepository { _subscription = RustStreamReceiver.listen((observable) => _parser.parse(observable)); } - void _handleObservableType(WorkspaceNotification ty, Either result) { + void _handleObservableType(WorkspaceNotification ty, Either result) { switch (ty) { case WorkspaceNotification.ViewUpdated: result.fold( diff --git a/frontend/app_flowy/lib/workspace/infrastructure/repos/workspace_repo.dart b/frontend/app_flowy/lib/workspace/infrastructure/repos/workspace_repo.dart index c9d192c370..c14a5d75d1 100644 --- a/frontend/app_flowy/lib/workspace/infrastructure/repos/workspace_repo.dart +++ b/frontend/app_flowy/lib/workspace/infrastructure/repos/workspace_repo.dart @@ -10,7 +10,7 @@ import 'package:flowy_sdk/protobuf/flowy-user-infra/protobuf.dart' show UserProf import 'package:flowy_sdk/protobuf/flowy-core-infra/app_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/workspace_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/workspace_query.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/observable.pb.dart'; import 'package:flowy_sdk/rust_stream.dart'; @@ -27,7 +27,7 @@ class WorkspaceRepo { required this.workspaceId, }); - Future> createApp(String appName, String desc) { + Future> createApp(String appName, String desc) { final request = CreateAppRequest.create() ..name = appName ..workspaceId = workspaceId @@ -35,7 +35,7 @@ class WorkspaceRepo { return WorkspaceEventCreateApp(request).send(); } - Future> getWorkspace() { + Future> getWorkspace() { final request = QueryWorkspaceRequest.create()..workspaceId = workspaceId; return WorkspaceEventReadWorkspaces(request).send().then((result) { return result.fold( @@ -43,7 +43,7 @@ class WorkspaceRepo { assert(workspaces.items.length == 1); if (workspaces.items.isEmpty) { - return right(WorkspaceError.create()..msg = LocaleKeys.workspace_notFoundError.tr()); + return right(FlowyError.create()..msg = LocaleKeys.workspace_notFoundError.tr()); } else { return left(workspaces.items[0]); } @@ -53,7 +53,7 @@ class WorkspaceRepo { }); } - Future, WorkspaceError>> getApps() { + Future, FlowyError>> getApps() { final request = QueryWorkspaceRequest.create()..workspaceId = workspaceId; return WorkspaceEventReadWorkspaceApps(request).send().then((result) { return result.fold( @@ -94,7 +94,7 @@ class WorkspaceListenerRepo { _subscription = RustStreamReceiver.listen((observable) => _parser.parse(observable)); } - void _handleObservableType(WorkspaceNotification ty, Either result) { + void _handleObservableType(WorkspaceNotification ty, Either result) { switch (ty) { case WorkspaceNotification.WorkspaceUpdated: if (_update != null) { diff --git a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart index 65ca557600..d6d960423b 100644 --- a/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/stack_page/doc/doc_stack_page.dart @@ -14,7 +14,7 @@ import 'package:flowy_infra_ui/widget/rounded_button.dart'; import 'package:flowy_log/flowy_log.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/export.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core-infra/view_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flutter/material.dart'; import 'package:dartz/dartz.dart' as dartz; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -200,7 +200,7 @@ class DocShareButton extends StatelessWidget { } } - void _handleExportError(WorkspaceError error) {} + void _handleExportError(FlowyError error) {} void _showActionList(BuildContext context, Offset offset) { final actionList = ShareActions(onSelected: (result) { diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/code_gen.dart b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/code_gen.dart index b3ffb53705..fdf3cddf4f 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/code_gen.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/code_gen.dart @@ -6,7 +6,7 @@ class WorkspaceEventCreateWorkspace { CreateWorkspaceRequest request; WorkspaceEventCreateWorkspace(this.request); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = WorkspaceEvent.CreateWorkspace.toString() ..payload = requestToBytes(this.request); @@ -14,7 +14,7 @@ class WorkspaceEventCreateWorkspace { return Dispatch.asyncRequest(request) .then((bytesResult) => bytesResult.fold( (okBytes) => left(Workspace.fromBuffer(okBytes)), - (errBytes) => right(WorkspaceError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -22,13 +22,13 @@ class WorkspaceEventCreateWorkspace { class WorkspaceEventReadCurWorkspace { WorkspaceEventReadCurWorkspace(); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = WorkspaceEvent.ReadCurWorkspace.toString(); return Dispatch.asyncRequest(request).then((bytesResult) => bytesResult.fold( (okBytes) => left(CurrentWorkspaceSetting.fromBuffer(okBytes)), - (errBytes) => right(WorkspaceError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -37,7 +37,7 @@ class WorkspaceEventReadWorkspaces { QueryWorkspaceRequest request; WorkspaceEventReadWorkspaces(this.request); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = WorkspaceEvent.ReadWorkspaces.toString() ..payload = requestToBytes(this.request); @@ -45,7 +45,7 @@ class WorkspaceEventReadWorkspaces { return Dispatch.asyncRequest(request) .then((bytesResult) => bytesResult.fold( (okBytes) => left(RepeatedWorkspace.fromBuffer(okBytes)), - (errBytes) => right(WorkspaceError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -54,7 +54,7 @@ class WorkspaceEventDeleteWorkspace { QueryWorkspaceRequest request; WorkspaceEventDeleteWorkspace(this.request); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = WorkspaceEvent.DeleteWorkspace.toString() ..payload = requestToBytes(this.request); @@ -62,7 +62,7 @@ class WorkspaceEventDeleteWorkspace { return Dispatch.asyncRequest(request) .then((bytesResult) => bytesResult.fold( (bytes) => left(unit), - (errBytes) => right(WorkspaceError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -71,7 +71,7 @@ class WorkspaceEventOpenWorkspace { QueryWorkspaceRequest request; WorkspaceEventOpenWorkspace(this.request); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = WorkspaceEvent.OpenWorkspace.toString() ..payload = requestToBytes(this.request); @@ -79,7 +79,7 @@ class WorkspaceEventOpenWorkspace { return Dispatch.asyncRequest(request) .then((bytesResult) => bytesResult.fold( (okBytes) => left(Workspace.fromBuffer(okBytes)), - (errBytes) => right(WorkspaceError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -88,7 +88,7 @@ class WorkspaceEventReadWorkspaceApps { QueryWorkspaceRequest request; WorkspaceEventReadWorkspaceApps(this.request); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = WorkspaceEvent.ReadWorkspaceApps.toString() ..payload = requestToBytes(this.request); @@ -96,7 +96,7 @@ class WorkspaceEventReadWorkspaceApps { return Dispatch.asyncRequest(request) .then((bytesResult) => bytesResult.fold( (okBytes) => left(RepeatedApp.fromBuffer(okBytes)), - (errBytes) => right(WorkspaceError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -105,7 +105,7 @@ class WorkspaceEventCreateApp { CreateAppRequest request; WorkspaceEventCreateApp(this.request); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = WorkspaceEvent.CreateApp.toString() ..payload = requestToBytes(this.request); @@ -113,7 +113,7 @@ class WorkspaceEventCreateApp { return Dispatch.asyncRequest(request) .then((bytesResult) => bytesResult.fold( (okBytes) => left(App.fromBuffer(okBytes)), - (errBytes) => right(WorkspaceError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -122,7 +122,7 @@ class WorkspaceEventDeleteApp { QueryAppRequest request; WorkspaceEventDeleteApp(this.request); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = WorkspaceEvent.DeleteApp.toString() ..payload = requestToBytes(this.request); @@ -130,7 +130,7 @@ class WorkspaceEventDeleteApp { return Dispatch.asyncRequest(request) .then((bytesResult) => bytesResult.fold( (bytes) => left(unit), - (errBytes) => right(WorkspaceError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -139,7 +139,7 @@ class WorkspaceEventReadApp { QueryAppRequest request; WorkspaceEventReadApp(this.request); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = WorkspaceEvent.ReadApp.toString() ..payload = requestToBytes(this.request); @@ -147,7 +147,7 @@ class WorkspaceEventReadApp { return Dispatch.asyncRequest(request) .then((bytesResult) => bytesResult.fold( (okBytes) => left(App.fromBuffer(okBytes)), - (errBytes) => right(WorkspaceError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -156,7 +156,7 @@ class WorkspaceEventUpdateApp { UpdateAppRequest request; WorkspaceEventUpdateApp(this.request); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = WorkspaceEvent.UpdateApp.toString() ..payload = requestToBytes(this.request); @@ -164,7 +164,7 @@ class WorkspaceEventUpdateApp { return Dispatch.asyncRequest(request) .then((bytesResult) => bytesResult.fold( (bytes) => left(unit), - (errBytes) => right(WorkspaceError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -173,7 +173,7 @@ class WorkspaceEventCreateView { CreateViewRequest request; WorkspaceEventCreateView(this.request); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = WorkspaceEvent.CreateView.toString() ..payload = requestToBytes(this.request); @@ -181,7 +181,7 @@ class WorkspaceEventCreateView { return Dispatch.asyncRequest(request) .then((bytesResult) => bytesResult.fold( (okBytes) => left(View.fromBuffer(okBytes)), - (errBytes) => right(WorkspaceError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -190,7 +190,7 @@ class WorkspaceEventReadView { QueryViewRequest request; WorkspaceEventReadView(this.request); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = WorkspaceEvent.ReadView.toString() ..payload = requestToBytes(this.request); @@ -198,7 +198,7 @@ class WorkspaceEventReadView { return Dispatch.asyncRequest(request) .then((bytesResult) => bytesResult.fold( (okBytes) => left(View.fromBuffer(okBytes)), - (errBytes) => right(WorkspaceError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -207,7 +207,7 @@ class WorkspaceEventUpdateView { UpdateViewRequest request; WorkspaceEventUpdateView(this.request); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = WorkspaceEvent.UpdateView.toString() ..payload = requestToBytes(this.request); @@ -215,7 +215,7 @@ class WorkspaceEventUpdateView { return Dispatch.asyncRequest(request) .then((bytesResult) => bytesResult.fold( (okBytes) => left(View.fromBuffer(okBytes)), - (errBytes) => right(WorkspaceError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -224,7 +224,7 @@ class WorkspaceEventDeleteView { QueryViewRequest request; WorkspaceEventDeleteView(this.request); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = WorkspaceEvent.DeleteView.toString() ..payload = requestToBytes(this.request); @@ -232,7 +232,7 @@ class WorkspaceEventDeleteView { return Dispatch.asyncRequest(request) .then((bytesResult) => bytesResult.fold( (bytes) => left(unit), - (errBytes) => right(WorkspaceError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -241,7 +241,7 @@ class WorkspaceEventDuplicateView { QueryViewRequest request; WorkspaceEventDuplicateView(this.request); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = WorkspaceEvent.DuplicateView.toString() ..payload = requestToBytes(this.request); @@ -249,7 +249,7 @@ class WorkspaceEventDuplicateView { return Dispatch.asyncRequest(request) .then((bytesResult) => bytesResult.fold( (bytes) => left(unit), - (errBytes) => right(WorkspaceError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -257,13 +257,13 @@ class WorkspaceEventDuplicateView { class WorkspaceEventCopyLink { WorkspaceEventCopyLink(); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = WorkspaceEvent.CopyLink.toString(); return Dispatch.asyncRequest(request).then((bytesResult) => bytesResult.fold( (bytes) => left(unit), - (errBytes) => right(WorkspaceError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -272,7 +272,7 @@ class WorkspaceEventOpenView { QueryViewRequest request; WorkspaceEventOpenView(this.request); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = WorkspaceEvent.OpenView.toString() ..payload = requestToBytes(this.request); @@ -280,7 +280,7 @@ class WorkspaceEventOpenView { return Dispatch.asyncRequest(request) .then((bytesResult) => bytesResult.fold( (okBytes) => left(DocDelta.fromBuffer(okBytes)), - (errBytes) => right(WorkspaceError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -289,7 +289,7 @@ class WorkspaceEventCloseView { QueryViewRequest request; WorkspaceEventCloseView(this.request); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = WorkspaceEvent.CloseView.toString() ..payload = requestToBytes(this.request); @@ -297,7 +297,7 @@ class WorkspaceEventCloseView { return Dispatch.asyncRequest(request) .then((bytesResult) => bytesResult.fold( (bytes) => left(unit), - (errBytes) => right(WorkspaceError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -305,13 +305,13 @@ class WorkspaceEventCloseView { class WorkspaceEventReadTrash { WorkspaceEventReadTrash(); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = WorkspaceEvent.ReadTrash.toString(); return Dispatch.asyncRequest(request).then((bytesResult) => bytesResult.fold( (okBytes) => left(RepeatedTrash.fromBuffer(okBytes)), - (errBytes) => right(WorkspaceError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -320,7 +320,7 @@ class WorkspaceEventPutbackTrash { TrashIdentifier request; WorkspaceEventPutbackTrash(this.request); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = WorkspaceEvent.PutbackTrash.toString() ..payload = requestToBytes(this.request); @@ -328,7 +328,7 @@ class WorkspaceEventPutbackTrash { return Dispatch.asyncRequest(request) .then((bytesResult) => bytesResult.fold( (bytes) => left(unit), - (errBytes) => right(WorkspaceError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -337,7 +337,7 @@ class WorkspaceEventDeleteTrash { TrashIdentifiers request; WorkspaceEventDeleteTrash(this.request); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = WorkspaceEvent.DeleteTrash.toString() ..payload = requestToBytes(this.request); @@ -345,7 +345,7 @@ class WorkspaceEventDeleteTrash { return Dispatch.asyncRequest(request) .then((bytesResult) => bytesResult.fold( (bytes) => left(unit), - (errBytes) => right(WorkspaceError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -353,13 +353,13 @@ class WorkspaceEventDeleteTrash { class WorkspaceEventRestoreAll { WorkspaceEventRestoreAll(); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = WorkspaceEvent.RestoreAll.toString(); return Dispatch.asyncRequest(request).then((bytesResult) => bytesResult.fold( (bytes) => left(unit), - (errBytes) => right(WorkspaceError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -367,13 +367,13 @@ class WorkspaceEventRestoreAll { class WorkspaceEventDeleteAll { WorkspaceEventDeleteAll(); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = WorkspaceEvent.DeleteAll.toString(); return Dispatch.asyncRequest(request).then((bytesResult) => bytesResult.fold( (bytes) => left(unit), - (errBytes) => right(WorkspaceError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -382,7 +382,7 @@ class WorkspaceEventApplyDocDelta { DocDelta request; WorkspaceEventApplyDocDelta(this.request); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = WorkspaceEvent.ApplyDocDelta.toString() ..payload = requestToBytes(this.request); @@ -390,7 +390,7 @@ class WorkspaceEventApplyDocDelta { return Dispatch.asyncRequest(request) .then((bytesResult) => bytesResult.fold( (okBytes) => left(DocDelta.fromBuffer(okBytes)), - (errBytes) => right(WorkspaceError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -399,7 +399,7 @@ class WorkspaceEventExportDocument { ExportRequest request; WorkspaceEventExportDocument(this.request); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = WorkspaceEvent.ExportDocument.toString() ..payload = requestToBytes(this.request); @@ -407,7 +407,7 @@ class WorkspaceEventExportDocument { return Dispatch.asyncRequest(request) .then((bytesResult) => bytesResult.fold( (okBytes) => left(ExportData.fromBuffer(okBytes)), - (errBytes) => right(WorkspaceError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -432,13 +432,13 @@ class NetworkEventUpdateNetworkType { class UserEventInitUser { UserEventInitUser(); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = UserEvent.InitUser.toString(); return Dispatch.asyncRequest(request).then((bytesResult) => bytesResult.fold( (bytes) => left(unit), - (errBytes) => right(UserError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -447,7 +447,7 @@ class UserEventSignIn { SignInRequest request; UserEventSignIn(this.request); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = UserEvent.SignIn.toString() ..payload = requestToBytes(this.request); @@ -455,7 +455,7 @@ class UserEventSignIn { return Dispatch.asyncRequest(request) .then((bytesResult) => bytesResult.fold( (okBytes) => left(UserProfile.fromBuffer(okBytes)), - (errBytes) => right(UserError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -464,7 +464,7 @@ class UserEventSignUp { SignUpRequest request; UserEventSignUp(this.request); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = UserEvent.SignUp.toString() ..payload = requestToBytes(this.request); @@ -472,7 +472,7 @@ class UserEventSignUp { return Dispatch.asyncRequest(request) .then((bytesResult) => bytesResult.fold( (okBytes) => left(UserProfile.fromBuffer(okBytes)), - (errBytes) => right(UserError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -480,13 +480,13 @@ class UserEventSignUp { class UserEventSignOut { UserEventSignOut(); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = UserEvent.SignOut.toString(); return Dispatch.asyncRequest(request).then((bytesResult) => bytesResult.fold( (bytes) => left(unit), - (errBytes) => right(UserError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -495,7 +495,7 @@ class UserEventUpdateUser { UpdateUserRequest request; UserEventUpdateUser(this.request); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = UserEvent.UpdateUser.toString() ..payload = requestToBytes(this.request); @@ -503,7 +503,7 @@ class UserEventUpdateUser { return Dispatch.asyncRequest(request) .then((bytesResult) => bytesResult.fold( (bytes) => left(unit), - (errBytes) => right(UserError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -511,13 +511,13 @@ class UserEventUpdateUser { class UserEventGetUserProfile { UserEventGetUserProfile(); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = UserEvent.GetUserProfile.toString(); return Dispatch.asyncRequest(request).then((bytesResult) => bytesResult.fold( (okBytes) => left(UserProfile.fromBuffer(okBytes)), - (errBytes) => right(UserError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } @@ -525,13 +525,13 @@ class UserEventGetUserProfile { class UserEventCheckUser { UserEventCheckUser(); - Future> send() { + Future> send() { final request = FFIRequest.create() ..event = UserEvent.CheckUser.toString(); return Dispatch.asyncRequest(request).then((bytesResult) => bytesResult.fold( (okBytes) => left(UserProfile.fromBuffer(okBytes)), - (errBytes) => right(UserError.fromBuffer(errBytes)), + (errBytes) => right(FlowyError.fromBuffer(errBytes)), )); } } diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart index 157693177c..9768873400 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/dispatch/dispatch.dart @@ -6,9 +6,7 @@ import 'package:flowy_sdk/protobuf/dart-ffi/ffi_response.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-net/event.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-net/network_state.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user/event.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-core/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-core/event.pb.dart'; import 'package:isolates/isolates.dart'; import 'package:isolates/ports.dart'; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/errors.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/error-code/error_code.pb.dart similarity index 74% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/errors.pbenum.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/error-code/error_code.pb.dart index 2bb3f5b53b..6817422f70 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/errors.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/error-code/error_code.pb.dart @@ -1,7 +1,11 @@ /// // Generated code. Do not modify. -// source: errors.proto +// source: error_code.proto // // @dart = 2.12 // ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields +import 'dart:core' as $core; + +export 'error_code.pbenum.dart'; + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/error-code/error_code.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/error-code/error_code.pbenum.dart new file mode 100644 index 0000000000..5cc919914a --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/error-code/error_code.pbenum.dart @@ -0,0 +1,82 @@ +/// +// Generated code. Do not modify. +// source: error_code.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields + +// ignore_for_file: UNDEFINED_SHOWN_NAME +import 'dart:core' as $core; +import 'package:protobuf/protobuf.dart' as $pb; + +class ErrorCode extends $pb.ProtobufEnum { + static const ErrorCode Internal = ErrorCode._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Internal'); + static const ErrorCode UserUnauthorized = ErrorCode._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserUnauthorized'); + static const ErrorCode RecordNotFound = ErrorCode._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'RecordNotFound'); + static const ErrorCode WorkspaceNameInvalid = ErrorCode._(100, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceNameInvalid'); + static const ErrorCode WorkspaceIdInvalid = ErrorCode._(101, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceIdInvalid'); + static const ErrorCode AppColorStyleInvalid = ErrorCode._(102, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppColorStyleInvalid'); + static const ErrorCode WorkspaceDescTooLong = ErrorCode._(103, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceDescTooLong'); + static const ErrorCode WorkspaceNameTooLong = ErrorCode._(104, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceNameTooLong'); + static const ErrorCode AppIdInvalid = ErrorCode._(110, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppIdInvalid'); + static const ErrorCode AppNameInvalid = ErrorCode._(111, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppNameInvalid'); + static const ErrorCode ViewNameInvalid = ErrorCode._(120, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewNameInvalid'); + static const ErrorCode ViewThumbnailInvalid = ErrorCode._(121, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewThumbnailInvalid'); + static const ErrorCode ViewIdInvalid = ErrorCode._(122, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewIdInvalid'); + static const ErrorCode ViewDescTooLong = ErrorCode._(123, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewDescTooLong'); + static const ErrorCode ViewDataInvalid = ErrorCode._(124, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewDataInvalid'); + static const ErrorCode ViewNameTooLong = ErrorCode._(125, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewNameTooLong'); + static const ErrorCode ConnectError = ErrorCode._(200, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ConnectError'); + static const ErrorCode EmailIsEmpty = ErrorCode._(300, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EmailIsEmpty'); + static const ErrorCode EmailFormatInvalid = ErrorCode._(301, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EmailFormatInvalid'); + static const ErrorCode EmailAlreadyExists = ErrorCode._(302, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EmailAlreadyExists'); + static const ErrorCode PasswordIsEmpty = ErrorCode._(303, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PasswordIsEmpty'); + static const ErrorCode PasswordTooLong = ErrorCode._(304, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PasswordTooLong'); + static const ErrorCode PasswordContainsForbidCharacters = ErrorCode._(305, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PasswordContainsForbidCharacters'); + static const ErrorCode PasswordFormatInvalid = ErrorCode._(306, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PasswordFormatInvalid'); + static const ErrorCode PasswordNotMatch = ErrorCode._(307, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PasswordNotMatch'); + static const ErrorCode UserNameTooLong = ErrorCode._(308, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNameTooLong'); + static const ErrorCode UserNameContainForbiddenCharacters = ErrorCode._(309, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNameContainForbiddenCharacters'); + static const ErrorCode UserNameIsEmpty = ErrorCode._(310, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNameIsEmpty'); + static const ErrorCode UserIdInvalid = ErrorCode._(311, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserIdInvalid'); + static const ErrorCode UserNotExist = ErrorCode._(312, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNotExist'); + + static const $core.List values = [ + Internal, + UserUnauthorized, + RecordNotFound, + WorkspaceNameInvalid, + WorkspaceIdInvalid, + AppColorStyleInvalid, + WorkspaceDescTooLong, + WorkspaceNameTooLong, + AppIdInvalid, + AppNameInvalid, + ViewNameInvalid, + ViewThumbnailInvalid, + ViewIdInvalid, + ViewDescTooLong, + ViewDataInvalid, + ViewNameTooLong, + ConnectError, + EmailIsEmpty, + EmailFormatInvalid, + EmailAlreadyExists, + PasswordIsEmpty, + PasswordTooLong, + PasswordContainsForbidCharacters, + PasswordFormatInvalid, + PasswordNotMatch, + UserNameTooLong, + UserNameContainForbiddenCharacters, + UserNameIsEmpty, + UserIdInvalid, + UserNotExist, + ]; + + static final $core.Map<$core.int, ErrorCode> _byValue = $pb.ProtobufEnum.initByValue(values); + static ErrorCode? valueOf($core.int value) => _byValue[value]; + + const ErrorCode._($core.int v, $core.String n) : super(v, n); +} + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/error-code/error_code.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/error-code/error_code.pbjson.dart new file mode 100644 index 0000000000..5d30b04f64 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/error-code/error_code.pbjson.dart @@ -0,0 +1,49 @@ +/// +// Generated code. Do not modify. +// source: error_code.proto +// +// @dart = 2.12 +// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package + +import 'dart:core' as $core; +import 'dart:convert' as $convert; +import 'dart:typed_data' as $typed_data; +@$core.Deprecated('Use errorCodeDescriptor instead') +const ErrorCode$json = const { + '1': 'ErrorCode', + '2': const [ + const {'1': 'Internal', '2': 0}, + const {'1': 'UserUnauthorized', '2': 2}, + const {'1': 'RecordNotFound', '2': 3}, + const {'1': 'WorkspaceNameInvalid', '2': 100}, + const {'1': 'WorkspaceIdInvalid', '2': 101}, + const {'1': 'AppColorStyleInvalid', '2': 102}, + const {'1': 'WorkspaceDescTooLong', '2': 103}, + const {'1': 'WorkspaceNameTooLong', '2': 104}, + const {'1': 'AppIdInvalid', '2': 110}, + const {'1': 'AppNameInvalid', '2': 111}, + const {'1': 'ViewNameInvalid', '2': 120}, + const {'1': 'ViewThumbnailInvalid', '2': 121}, + const {'1': 'ViewIdInvalid', '2': 122}, + const {'1': 'ViewDescTooLong', '2': 123}, + const {'1': 'ViewDataInvalid', '2': 124}, + const {'1': 'ViewNameTooLong', '2': 125}, + const {'1': 'ConnectError', '2': 200}, + const {'1': 'EmailIsEmpty', '2': 300}, + const {'1': 'EmailFormatInvalid', '2': 301}, + const {'1': 'EmailAlreadyExists', '2': 302}, + const {'1': 'PasswordIsEmpty', '2': 303}, + const {'1': 'PasswordTooLong', '2': 304}, + const {'1': 'PasswordContainsForbidCharacters', '2': 305}, + const {'1': 'PasswordFormatInvalid', '2': 306}, + const {'1': 'PasswordNotMatch', '2': 307}, + const {'1': 'UserNameTooLong', '2': 308}, + const {'1': 'UserNameContainForbiddenCharacters', '2': 309}, + const {'1': 'UserNameIsEmpty', '2': 310}, + const {'1': 'UserIdInvalid', '2': 311}, + const {'1': 'UserNotExist', '2': 312}, + ], +}; + +/// Descriptor for `ErrorCode`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSDAoISW50ZXJuYWwQABIUChBVc2VyVW5hdXRob3JpemVkEAISEgoOUmVjb3JkTm90Rm91bmQQAxIYChRXb3Jrc3BhY2VOYW1lSW52YWxpZBBkEhYKEldvcmtzcGFjZUlkSW52YWxpZBBlEhgKFEFwcENvbG9yU3R5bGVJbnZhbGlkEGYSGAoUV29ya3NwYWNlRGVzY1Rvb0xvbmcQZxIYChRXb3Jrc3BhY2VOYW1lVG9vTG9uZxBoEhAKDEFwcElkSW52YWxpZBBuEhIKDkFwcE5hbWVJbnZhbGlkEG8SEwoPVmlld05hbWVJbnZhbGlkEHgSGAoUVmlld1RodW1ibmFpbEludmFsaWQQeRIRCg1WaWV3SWRJbnZhbGlkEHoSEwoPVmlld0Rlc2NUb29Mb25nEHsSEwoPVmlld0RhdGFJbnZhbGlkEHwSEwoPVmlld05hbWVUb29Mb25nEH0SEQoMQ29ubmVjdEVycm9yEMgBEhEKDEVtYWlsSXNFbXB0eRCsAhIXChJFbWFpbEZvcm1hdEludmFsaWQQrQISFwoSRW1haWxBbHJlYWR5RXhpc3RzEK4CEhQKD1Bhc3N3b3JkSXNFbXB0eRCvAhIUCg9QYXNzd29yZFRvb0xvbmcQsAISJQogUGFzc3dvcmRDb250YWluc0ZvcmJpZENoYXJhY3RlcnMQsQISGgoVUGFzc3dvcmRGb3JtYXRJbnZhbGlkELICEhUKEFBhc3N3b3JkTm90TWF0Y2gQswISFAoPVXNlck5hbWVUb29Mb25nELQCEicKIlVzZXJOYW1lQ29udGFpbkZvcmJpZGRlbkNoYXJhY3RlcnMQtQISFAoPVXNlck5hbWVJc0VtcHR5ELYCEhIKDVVzZXJJZEludmFsaWQQtwISEQoMVXNlck5vdEV4aXN0ELgC'); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/errors.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/error-code/error_code.pbserver.dart similarity index 84% rename from frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/errors.pbserver.dart rename to frontend/app_flowy/packages/flowy_sdk/lib/protobuf/error-code/error_code.pbserver.dart index 18b02b9216..a38de6d5a4 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/errors.pbserver.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/error-code/error_code.pbserver.dart @@ -1,9 +1,9 @@ /// // Generated code. Do not modify. -// source: errors.proto +// source: error_code.proto // // @dart = 2.12 // ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package -export 'errors.pb.dart'; +export 'error_code.pb.dart'; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/error-code/protobuf.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/error-code/protobuf.dart new file mode 100644 index 0000000000..379334caf0 --- /dev/null +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/error-code/protobuf.dart @@ -0,0 +1,2 @@ +// Auto-generated, do not edit +export './error_code.pb.dart'; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/errors.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/errors.pb.dart deleted file mode 100644 index b03dd960be..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/errors.pb.dart +++ /dev/null @@ -1,72 +0,0 @@ -/// -// Generated code. Do not modify. -// source: errors.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields - -import 'dart:core' as $core; - -import 'package:protobuf/protobuf.dart' as $pb; - -class WorkspaceError extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'WorkspaceError', createEmptyInstance: create) - ..a<$core.int>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'code', $pb.PbFieldType.O3) - ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'msg') - ..hasRequiredFields = false - ; - - WorkspaceError._() : super(); - factory WorkspaceError({ - $core.int? code, - $core.String? msg, - }) { - final _result = create(); - if (code != null) { - _result.code = code; - } - if (msg != null) { - _result.msg = msg; - } - return _result; - } - factory WorkspaceError.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory WorkspaceError.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' - 'Will be removed in next major version') - WorkspaceError clone() => WorkspaceError()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - WorkspaceError copyWith(void Function(WorkspaceError) updates) => super.copyWith((message) => updates(message as WorkspaceError)) as WorkspaceError; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static WorkspaceError create() => WorkspaceError._(); - WorkspaceError createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static WorkspaceError getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static WorkspaceError? _defaultInstance; - - @$pb.TagNumber(1) - $core.int get code => $_getIZ(0); - @$pb.TagNumber(1) - set code($core.int v) { $_setSignedInt32(0, v); } - @$pb.TagNumber(1) - $core.bool hasCode() => $_has(0); - @$pb.TagNumber(1) - void clearCode() => clearField(1); - - @$pb.TagNumber(2) - $core.String get msg => $_getSZ(1); - @$pb.TagNumber(2) - set msg($core.String v) { $_setString(1, v); } - @$pb.TagNumber(2) - $core.bool hasMsg() => $_has(1); - @$pb.TagNumber(2) - void clearMsg() => clearField(2); -} - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/errors.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/errors.pbjson.dart deleted file mode 100644 index dd6a45e8d9..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/errors.pbjson.dart +++ /dev/null @@ -1,21 +0,0 @@ -/// -// Generated code. Do not modify. -// source: errors.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package - -import 'dart:core' as $core; -import 'dart:convert' as $convert; -import 'dart:typed_data' as $typed_data; -@$core.Deprecated('Use workspaceErrorDescriptor instead') -const WorkspaceError$json = const { - '1': 'WorkspaceError', - '2': const [ - const {'1': 'code', '3': 1, '4': 1, '5': 5, '10': 'code'}, - const {'1': 'msg', '3': 2, '4': 1, '5': 9, '10': 'msg'}, - ], -}; - -/// Descriptor for `WorkspaceError`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List workspaceErrorDescriptor = $convert.base64Decode('Cg5Xb3Jrc3BhY2VFcnJvchISCgRjb2RlGAEgASgFUgRjb2RlEhAKA21zZxgCIAEoCVIDbXNn'); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/errors.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/errors.pbserver.dart deleted file mode 100644 index 18b02b9216..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/errors.pbserver.dart +++ /dev/null @@ -1,9 +0,0 @@ -/// -// Generated code. Do not modify. -// source: errors.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package - -export 'errors.pb.dart'; - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/protobuf.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/protobuf.dart index bb4f1f6e45..0cd5547d0a 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/protobuf.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core/protobuf.dart @@ -1,4 +1,3 @@ // Auto-generated, do not edit export './observable.pb.dart'; -export './errors.pb.dart'; export './event.pb.dart'; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/errors.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/errors.pb.dart deleted file mode 100644 index fbb5affe8e..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/errors.pb.dart +++ /dev/null @@ -1,76 +0,0 @@ -/// -// Generated code. Do not modify. -// source: errors.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields - -import 'dart:core' as $core; - -import 'package:protobuf/protobuf.dart' as $pb; - -import 'errors.pbenum.dart'; - -export 'errors.pbenum.dart'; - -class DocError extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DocError', createEmptyInstance: create) - ..e(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'code', $pb.PbFieldType.OE, defaultOrMaker: ErrorCode.WsConnectError, valueOf: ErrorCode.valueOf, enumValues: ErrorCode.values) - ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'msg') - ..hasRequiredFields = false - ; - - DocError._() : super(); - factory DocError({ - ErrorCode? code, - $core.String? msg, - }) { - final _result = create(); - if (code != null) { - _result.code = code; - } - if (msg != null) { - _result.msg = msg; - } - return _result; - } - factory DocError.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory DocError.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' - 'Will be removed in next major version') - DocError clone() => DocError()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - DocError copyWith(void Function(DocError) updates) => super.copyWith((message) => updates(message as DocError)) as DocError; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static DocError create() => DocError._(); - DocError createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static DocError getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static DocError? _defaultInstance; - - @$pb.TagNumber(1) - ErrorCode get code => $_getN(0); - @$pb.TagNumber(1) - set code(ErrorCode v) { setField(1, v); } - @$pb.TagNumber(1) - $core.bool hasCode() => $_has(0); - @$pb.TagNumber(1) - void clearCode() => clearField(1); - - @$pb.TagNumber(2) - $core.String get msg => $_getSZ(1); - @$pb.TagNumber(2) - set msg($core.String v) { $_setString(1, v); } - @$pb.TagNumber(2) - $core.bool hasMsg() => $_has(1); - @$pb.TagNumber(2) - void clearMsg() => clearField(2); -} - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/errors.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/errors.pbenum.dart deleted file mode 100644 index 5933af7967..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/errors.pbenum.dart +++ /dev/null @@ -1,32 +0,0 @@ -/// -// Generated code. Do not modify. -// source: errors.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields - -// ignore_for_file: UNDEFINED_SHOWN_NAME -import 'dart:core' as $core; -import 'package:protobuf/protobuf.dart' as $pb; - -class ErrorCode extends $pb.ProtobufEnum { - static const ErrorCode WsConnectError = ErrorCode._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WsConnectError'); - static const ErrorCode DocNotfound = ErrorCode._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DocNotfound'); - static const ErrorCode DuplicateRevision = ErrorCode._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DuplicateRevision'); - static const ErrorCode UserUnauthorized = ErrorCode._(10, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserUnauthorized'); - static const ErrorCode InternalError = ErrorCode._(1000, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'InternalError'); - - static const $core.List values = [ - WsConnectError, - DocNotfound, - DuplicateRevision, - UserUnauthorized, - InternalError, - ]; - - static final $core.Map<$core.int, ErrorCode> _byValue = $pb.ProtobufEnum.initByValue(values); - static ErrorCode? valueOf($core.int value) => _byValue[value]; - - const ErrorCode._($core.int v, $core.String n) : super(v, n); -} - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/errors.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/errors.pbjson.dart deleted file mode 100644 index a707e66df7..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/errors.pbjson.dart +++ /dev/null @@ -1,35 +0,0 @@ -/// -// Generated code. Do not modify. -// source: errors.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package - -import 'dart:core' as $core; -import 'dart:convert' as $convert; -import 'dart:typed_data' as $typed_data; -@$core.Deprecated('Use errorCodeDescriptor instead') -const ErrorCode$json = const { - '1': 'ErrorCode', - '2': const [ - const {'1': 'WsConnectError', '2': 0}, - const {'1': 'DocNotfound', '2': 1}, - const {'1': 'DuplicateRevision', '2': 2}, - const {'1': 'UserUnauthorized', '2': 10}, - const {'1': 'InternalError', '2': 1000}, - ], -}; - -/// Descriptor for `ErrorCode`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSEgoOV3NDb25uZWN0RXJyb3IQABIPCgtEb2NOb3Rmb3VuZBABEhUKEUR1cGxpY2F0ZVJldmlzaW9uEAISFAoQVXNlclVuYXV0aG9yaXplZBAKEhIKDUludGVybmFsRXJyb3IQ6Ac='); -@$core.Deprecated('Use docErrorDescriptor instead') -const DocError$json = const { - '1': 'DocError', - '2': const [ - const {'1': 'code', '3': 1, '4': 1, '5': 14, '6': '.ErrorCode', '10': 'code'}, - const {'1': 'msg', '3': 2, '4': 1, '5': 9, '10': 'msg'}, - ], -}; - -/// Descriptor for `DocError`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List docErrorDescriptor = $convert.base64Decode('CghEb2NFcnJvchIeCgRjb2RlGAEgASgOMgouRXJyb3JDb2RlUgRjb2RlEhAKA21zZxgCIAEoCVIDbXNn'); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/protobuf.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/protobuf.dart index 463cec0dc3..7353db8c64 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/protobuf.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-document/protobuf.dart @@ -1,3 +1,2 @@ // Auto-generated, do not edit export './observable.pb.dart'; -export './errors.pb.dart'; diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/errors.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/errors.pb.dart index 7d0a6cb8f4..95122bdd41 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/errors.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/errors.pb.dart @@ -9,8 +9,6 @@ import 'dart:core' as $core; import 'package:protobuf/protobuf.dart' as $pb; -export 'errors.pbenum.dart'; - class FlowyError extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'FlowyError', createEmptyInstance: create) ..a<$core.int>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'code', $pb.PbFieldType.O3) diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/errors.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/errors.pbenum.dart index 8d31a7370b..2bb3f5b53b 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/errors.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/errors.pbenum.dart @@ -5,20 +5,3 @@ // @dart = 2.12 // ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields -// ignore_for_file: UNDEFINED_SHOWN_NAME -import 'dart:core' as $core; -import 'package:protobuf/protobuf.dart' as $pb; - -class ErrorCode extends $pb.ProtobufEnum { - static const ErrorCode Internal = ErrorCode._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Internal'); - - static const $core.List values = [ - Internal, - ]; - - static final $core.Map<$core.int, ErrorCode> _byValue = $pb.ProtobufEnum.initByValue(values); - static ErrorCode? valueOf($core.int value) => _byValue[value]; - - const ErrorCode._($core.int v, $core.String n) : super(v, n); -} - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/errors.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/errors.pbjson.dart index b9209928ce..18f397fbe8 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/errors.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-error/errors.pbjson.dart @@ -8,16 +8,6 @@ import 'dart:core' as $core; import 'dart:convert' as $convert; import 'dart:typed_data' as $typed_data; -@$core.Deprecated('Use errorCodeDescriptor instead') -const ErrorCode$json = const { - '1': 'ErrorCode', - '2': const [ - const {'1': 'Internal', '2': 0}, - ], -}; - -/// Descriptor for `ErrorCode`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSDAoISW50ZXJuYWwQAA=='); @$core.Deprecated('Use flowyErrorDescriptor instead') const FlowyError$json = const { '1': 'FlowyError', diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pb.dart deleted file mode 100644 index a6bf94f671..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pb.dart +++ /dev/null @@ -1,72 +0,0 @@ -/// -// Generated code. Do not modify. -// source: errors.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields - -import 'dart:core' as $core; - -import 'package:protobuf/protobuf.dart' as $pb; - -class UserError extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'UserError', createEmptyInstance: create) - ..a<$core.int>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'code', $pb.PbFieldType.O3) - ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'msg') - ..hasRequiredFields = false - ; - - UserError._() : super(); - factory UserError({ - $core.int? code, - $core.String? msg, - }) { - final _result = create(); - if (code != null) { - _result.code = code; - } - if (msg != null) { - _result.msg = msg; - } - return _result; - } - factory UserError.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory UserError.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' - 'Will be removed in next major version') - UserError clone() => UserError()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - UserError copyWith(void Function(UserError) updates) => super.copyWith((message) => updates(message as UserError)) as UserError; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static UserError create() => UserError._(); - UserError createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static UserError getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static UserError? _defaultInstance; - - @$pb.TagNumber(1) - $core.int get code => $_getIZ(0); - @$pb.TagNumber(1) - set code($core.int v) { $_setSignedInt32(0, v); } - @$pb.TagNumber(1) - $core.bool hasCode() => $_has(0); - @$pb.TagNumber(1) - void clearCode() => clearField(1); - - @$pb.TagNumber(2) - $core.String get msg => $_getSZ(1); - @$pb.TagNumber(2) - set msg($core.String v) { $_setString(1, v); } - @$pb.TagNumber(2) - $core.bool hasMsg() => $_has(1); - @$pb.TagNumber(2) - void clearMsg() => clearField(2); -} - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbenum.dart deleted file mode 100644 index 2bb3f5b53b..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbenum.dart +++ /dev/null @@ -1,7 +0,0 @@ -/// -// Generated code. Do not modify. -// source: errors.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbjson.dart deleted file mode 100644 index c9eaa6f189..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbjson.dart +++ /dev/null @@ -1,21 +0,0 @@ -/// -// Generated code. Do not modify. -// source: errors.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package - -import 'dart:core' as $core; -import 'dart:convert' as $convert; -import 'dart:typed_data' as $typed_data; -@$core.Deprecated('Use userErrorDescriptor instead') -const UserError$json = const { - '1': 'UserError', - '2': const [ - const {'1': 'code', '3': 1, '4': 1, '5': 5, '10': 'code'}, - const {'1': 'msg', '3': 2, '4': 1, '5': 9, '10': 'msg'}, - ], -}; - -/// Descriptor for `UserError`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List userErrorDescriptor = $convert.base64Decode('CglVc2VyRXJyb3ISEgoEY29kZRgBIAEoBVIEY29kZRIQCgNtc2cYAiABKAlSA21zZw=='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbserver.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbserver.dart deleted file mode 100644 index 18b02b9216..0000000000 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/errors.pbserver.dart +++ /dev/null @@ -1,9 +0,0 @@ -/// -// Generated code. Do not modify. -// source: errors.proto -// -// @dart = 2.12 -// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package - -export 'errors.pb.dart'; - diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/protobuf.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/protobuf.dart index bb4f1f6e45..0cd5547d0a 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/protobuf.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-user/protobuf.dart @@ -1,4 +1,3 @@ // Auto-generated, do not edit export './observable.pb.dart'; -export './errors.pb.dart'; export './event.pb.dart'; diff --git a/frontend/rust-lib/flowy-core/Cargo.toml b/frontend/rust-lib/flowy-core/Cargo.toml index 6a464bd687..44e1523c6d 100644 --- a/frontend/rust-lib/flowy-core/Cargo.toml +++ b/frontend/rust-lib/flowy-core/Cargo.toml @@ -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" } diff --git a/frontend/rust-lib/flowy-core/src/core/aggregate_tasks/workspace_task.rs b/frontend/rust-lib/flowy-core/src/core/aggregate_tasks/workspace_task.rs index 39cffec56e..747a4e81c9 100644 --- a/frontend/rust-lib/flowy-core/src/core/aggregate_tasks/workspace_task.rs +++ b/frontend/rust-lib/flowy-core/src/core/aggregate_tasks/workspace_task.rs @@ -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>, 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(()) diff --git a/frontend/rust-lib/flowy-core/src/core/core_context.rs b/frontend/rust-lib/flowy-core/src/core/core_context.rs index 0f94565e39..2b9a4431ca 100644 --- a/frontend/rust-lib/flowy-core/src/core/core_context.rs +++ b/frontend/rust-lib/flowy-core/src/core/core_context.rs @@ -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(()); diff --git a/frontend/rust-lib/flowy-core/src/core/event_handler.rs b/frontend/rust-lib/flowy-core/src/core/event_handler.rs index 9d9a7b7bb4..e7686c9620 100644 --- a/frontend/rust-lib/flowy-core/src/core/event_handler.rs +++ b/frontend/rust-lib/flowy-core/src/core/event_handler.rs @@ -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, core: Unit>, -) -> DataResult { +) -> DataResult { 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>, -) -> DataResult { +) -> DataResult { let workspace_id = get_current_workspace()?; let user_id = core.user.user_id()?; let params = WorkspaceIdentifier { diff --git a/frontend/rust-lib/flowy-core/src/errors.rs b/frontend/rust-lib/flowy-core/src/errors.rs deleted file mode 100644 index c0240ad2c5..0000000000 --- a/frontend/rust-lib/flowy-core/src/errors.rs +++ /dev/null @@ -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 = std::result::Result; - -#[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(mut self, error: T) -> Self { - self.msg = format!("{:?}", error); - self - } -} - -pub fn internal_error(e: T) -> WorkspaceError -where - T: std::fmt::Debug, -{ - WorkspaceError::internal().context(e) -} - -impl std::convert::From for WorkspaceError { - fn from(code: ErrorCode) -> Self { - WorkspaceError { - code: code.value(), - msg: format!("{}", code), - } - } -} - -impl std::convert::From for WorkspaceError { - fn from(error: DocError) -> Self { WorkspaceError::internal().context(error) } -} - -impl std::convert::From 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 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, - } -} diff --git a/frontend/rust-lib/flowy-core/src/event.rs b/frontend/rust-lib/flowy-core/src/event.rs index e89a638275..a6e23a5458 100644 --- a/frontend/rust-lib/flowy-core/src/event.rs +++ b/frontend/rust-lib/flowy-core/src/event.rs @@ -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, diff --git a/frontend/rust-lib/flowy-core/src/lib.rs b/frontend/rust-lib/flowy-core/src/lib.rs index 8de43ec141..5629b3b38e 100644 --- a/frontend/rust-lib/flowy-core/src/lib.rs +++ b/frontend/rust-lib/flowy-core/src/lib.rs @@ -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}; +} diff --git a/frontend/rust-lib/flowy-core/src/macros.rs b/frontend/rust-lib/flowy-core/src/macros.rs index 44bae654bb..a02007d694 100644 --- a/frontend/rust-lib/flowy-core/src/macros.rs +++ b/frontend/rust-lib/flowy-core/src/macros.rs @@ -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))?; diff --git a/frontend/rust-lib/flowy-core/src/module.rs b/frontend/rust-lib/flowy-core/src/module.rs index 6ea6b64f8d..bb98d8080a 100644 --- a/frontend/rust-lib/flowy-core/src/module.rs +++ b/frontend/rust-lib/flowy-core/src/module.rs @@ -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; - fn token(&self) -> Result; + fn user_id(&self) -> Result; + fn token(&self) -> Result; } pub trait WorkspaceDatabase: Send + Sync { - fn db_pool(&self) -> Result, WorkspaceError>; + fn db_pool(&self) -> Result, FlowyError>; - fn db_connection(&self) -> Result { + fn db_connection(&self) -> Result { 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) } } diff --git a/frontend/rust-lib/flowy-core/src/protobuf/model/errors.rs b/frontend/rust-lib/flowy-core/src/protobuf/model/errors.rs deleted file mode 100644 index 4fd34284af..0000000000 --- a/frontend/rust-lib/flowy-core/src/protobuf/model/errors.rs +++ /dev/null @@ -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 { - ::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) -> ::std::boxed::Box { - 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", - fields, - file_descriptor_proto() - ) - }) - } - - fn default_instance() -> &'static WorkspaceError { - static instance: ::protobuf::rt::LazyV2 = ::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() - }) -} diff --git a/frontend/rust-lib/flowy-core/src/protobuf/model/mod.rs b/frontend/rust-lib/flowy-core/src/protobuf/model/mod.rs index cd35f2090b..b9a7e246fd 100644 --- a/frontend/rust-lib/flowy-core/src/protobuf/model/mod.rs +++ b/frontend/rust-lib/flowy-core/src/protobuf/model/mod.rs @@ -4,8 +4,5 @@ mod observable; pub use observable::*; -mod errors; -pub use errors::*; - mod event; pub use event::*; diff --git a/frontend/rust-lib/flowy-core/src/protobuf/proto/errors.proto b/frontend/rust-lib/flowy-core/src/protobuf/proto/errors.proto deleted file mode 100644 index b67c663608..0000000000 --- a/frontend/rust-lib/flowy-core/src/protobuf/proto/errors.proto +++ /dev/null @@ -1,6 +0,0 @@ -syntax = "proto3"; - -message WorkspaceError { - int32 code = 1; - string msg = 2; -} diff --git a/frontend/rust-lib/flowy-core/src/services/app/controller.rs b/frontend/rust-lib/flowy-core/src/services/app/controller.rs index e35b2f9f7b..97065ba8d0 100644 --- a/frontend/rust-lib/flowy-core/src/services/app/controller.rs +++ b/frontend/rust-lib/flowy-core/src/services/app/controller.rs @@ -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 { + pub(crate) async fn create_app_from_params(&self, params: CreateAppParams) -> Result { let app = self.create_app_on_server(params).await?; self.create_app(app).await } - pub(crate) async fn create_app(&self, app: App) -> Result { + pub(crate) async fn create_app(&self, app: App) -> Result { 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 { + pub(crate) async fn read_app(&self, params: AppIdentifier) -> Result { 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) -> Result, WorkspaceError> { + pub(crate) fn read_app_tables(&self, ids: Vec) -> Result, 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 { + async fn create_app_on_server(&self, params: CreateAppParams) -> Result { 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, 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, 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, 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, conn: &SqliteConnection, -) -> Result { +) -> Result { 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>(()) // // } // // }); // // diff --git a/frontend/rust-lib/flowy-core/src/services/app/event_handler.rs b/frontend/rust-lib/flowy-core/src/services/app/event_handler.rs index 011af97ade..5c9cc6f78d 100644 --- a/frontend/rust-lib/flowy-core/src/services/app/event_handler.rs +++ b/frontend/rust-lib/flowy-core/src/services/app/event_handler.rs @@ -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, controller: Unit>, -) -> DataResult { +) -> DataResult { 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, controller: Unit>, trash_can: Unit>, -) -> 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, controller: Unit>, -) -> 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, app_controller: Unit>, view_controller: Unit>, -) -> DataResult { +) -> DataResult { 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?; diff --git a/frontend/rust-lib/flowy-core/src/services/app/sql.rs b/frontend/rust-lib/flowy-core/src/services/app/sql.rs index 12b08d55e9..204e3950f6 100644 --- a/frontend/rust-lib/flowy-core/src/services/app/sql.rs +++ b/frontend/rust-lib/flowy-core/src/services/app/sql.rs @@ -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 { + pub(crate) fn read_app(app_id: &str, conn: &SqliteConnection) -> Result { let filter = dsl::app_table.filter(app_table::id.eq(app_id)).into_boxed(); let app_table = filter.first::(conn)?; Ok(app_table) @@ -46,7 +46,7 @@ impl AppTableSql { workspace_id: &str, is_trash: bool, conn: &SqliteConnection, - ) -> Result, WorkspaceError> { + ) -> Result, 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 { + pub(crate) fn delete_app(app_id: &str, conn: &SqliteConnection) -> Result { let app_table = dsl::app_table .filter(app_table::id.eq(app_id)) .first::(conn)?; @@ -67,10 +67,10 @@ impl AppTableSql { // pub(crate) fn read_views_belong_to_app( // &self, // app_id: &str, - // ) -> Result, WorkspaceError> { + // ) -> Result, 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::(&*(conn))?; diff --git a/frontend/rust-lib/flowy-core/src/services/server/mod.rs b/frontend/rust-lib/flowy-core/src/services/server/mod.rs index 940ba5d6d3..ad47f5201a 100644 --- a/frontend/rust-lib/flowy-core/src/services/server/mod.rs +++ b/frontend/rust-lib/flowy-core/src/services/server/mod.rs @@ -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; + fn create_workspace(&self, token: &str, params: CreateWorkspaceParams) -> FutureResult; - fn read_workspace( - &self, - token: &str, - params: WorkspaceIdentifier, - ) -> FutureResult; + fn read_workspace(&self, token: &str, params: WorkspaceIdentifier) -> FutureResult; - 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; + fn create_view(&self, token: &str, params: CreateViewParams) -> FutureResult; - fn read_view(&self, token: &str, params: ViewIdentifier) -> FutureResult, WorkspaceError>; + fn read_view(&self, token: &str, params: ViewIdentifier) -> FutureResult, 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; + fn create_app(&self, token: &str, params: CreateAppParams) -> FutureResult; - fn read_app(&self, token: &str, params: AppIdentifier) -> FutureResult, WorkspaceError>; + fn read_app(&self, token: &str, params: AppIdentifier) -> FutureResult, 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; + fn read_trash(&self, token: &str) -> FutureResult; } pub(crate) fn construct_workspace_server( diff --git a/frontend/rust-lib/flowy-core/src/services/server/server_api.rs b/frontend/rust-lib/flowy-core/src/services/server/server_api.rs index 68fadd59af..d3bee512fb 100644 --- a/frontend/rust-lib/flowy-core/src/services/server/server_api.rs +++ b/frontend/rust-lib/flowy-core/src/services/server/server_api.rs @@ -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 { + fn create_workspace(&self, token: &str, params: CreateWorkspaceParams) -> FutureResult { 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 { + fn read_workspace(&self, token: &str, params: WorkspaceIdentifier) -> FutureResult { 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 { + fn create_view(&self, token: &str, params: CreateViewParams) -> FutureResult { 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, WorkspaceError> { + fn read_view(&self, token: &str, params: ViewIdentifier) -> FutureResult, 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 { + fn create_app(&self, token: &str, params: CreateAppParams) -> FutureResult { 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, WorkspaceError> { + fn read_app(&self, token: &str, params: AppIdentifier) -> FutureResult, 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 { + fn read_trash(&self, token: &str) -> FutureResult { let token = token.to_owned(); let url = self.config.trash_url(); FutureResult::new(async move { diff --git a/frontend/rust-lib/flowy-core/src/services/server/server_api_mock.rs b/frontend/rust-lib/flowy-core/src/services/server/server_api_mock.rs index 336d0d9c53..dabc9dd055 100644 --- a/frontend/rust-lib/flowy-core/src/services/server/server_api_mock.rs +++ b/frontend/rust-lib/flowy-core/src/services/server/server_api_mock.rs @@ -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 { + fn create_workspace(&self, _token: &str, params: CreateWorkspaceParams) -> FutureResult { let time = timestamp(); let workspace = Workspace { id: uuid(), @@ -33,22 +33,22 @@ impl WorkspaceServerAPI for WorkspaceServerMock { &self, _token: &str, _params: WorkspaceIdentifier, - ) -> FutureResult { + ) -> FutureResult { 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 { + fn create_view(&self, _token: &str, params: CreateViewParams) -> FutureResult { 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, WorkspaceError> { + fn read_view(&self, _token: &str, _params: ViewIdentifier) -> FutureResult, 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 { + fn create_app(&self, _token: &str, params: CreateAppParams) -> FutureResult { 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, WorkspaceError> { + fn read_app(&self, _token: &str, _params: AppIdentifier) -> FutureResult, 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 { + fn read_trash(&self, _token: &str) -> FutureResult { FutureResult::new(async { let repeated_trash = RepeatedTrash { items: vec![] }; Ok(repeated_trash) diff --git a/frontend/rust-lib/flowy-core/src/services/trash/controller.rs b/frontend/rust-lib/flowy-core/src/services/trash/controller.rs index 670111860b..b878baac59 100644 --- a/frontend/rust-lib/flowy-core/src/services/trash/controller.rs +++ b/frontend/rust-lib/flowy-core/src/services/trash/controller.rs @@ -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::>(1); + pub async fn putback(&self, trash_id: &str) -> FlowyResult<()> { + let (tx, mut rx) = mpsc::channel::>(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::>(1); + let (tx, mut rx) = mpsc::channel::>(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::>(1); + pub async fn delete_with_identifiers(&self, trash_identifiers: TrashIdentifiers) -> FlowyResult<()> { + let (tx, mut rx) = mpsc::channel::>(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>(&self, trash: Vec) -> Result<(), WorkspaceError> { - let (tx, mut rx) = mpsc::channel::>(1); + pub async fn add>(&self, trash: Vec) -> Result<(), FlowyError> { + let (tx, mut rx) = mpsc::channel::>(1); let repeated_trash = trash.into_iter().map(|t| t.into()).collect::>(); 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 { self.notify.subscribe() } - pub fn read_trash(&self, conn: &SqliteConnection) -> Result { + pub fn read_trash(&self, conn: &SqliteConnection) -> Result { let repeated_trash = TrashTableSql::read_all(&*conn)?; let _ = self.read_trash_on_server()?; Ok(repeated_trash) } - pub fn trash_ids(&self, conn: &SqliteConnection) -> Result, WorkspaceError> { + pub fn trash_ids(&self, conn: &SqliteConnection) -> Result, 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>(&self, trash: T) -> WorkspaceResult<()> { + fn create_trash_on_server>(&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>(&self, trash: T) -> WorkspaceResult<()> { + fn delete_trash_on_server>(&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>), - Putback(TrashIdentifiers, mpsc::Sender>), - Delete(TrashIdentifiers, mpsc::Sender>), + NewTrash(TrashIdentifiers, mpsc::Sender>), + Putback(TrashIdentifiers, mpsc::Sender>), + Delete(TrashIdentifiers, mpsc::Sender>), } impl std::fmt::Debug for TrashEvent { diff --git a/frontend/rust-lib/flowy-core/src/services/trash/event_handler.rs b/frontend/rust-lib/flowy-core/src/services/trash/event_handler.rs index 3b72f630c0..10656ae8b3 100644 --- a/frontend/rust-lib/flowy-core/src/services/trash/event_handler.rs +++ b/frontend/rust-lib/flowy-core/src/services/trash/event_handler.rs @@ -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>, -) -> DataResult { +) -> DataResult { 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, controller: Unit>, -) -> 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, controller: Unit>, -) -> 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>) -> Result<(), WorkspaceError> { +pub(crate) async fn restore_all_handler(controller: Unit>) -> Result<(), FlowyError> { let _ = controller.restore_all().await?; Ok(()) } #[tracing::instrument(skip(controller), err)] -pub(crate) async fn delete_all_handler(controller: Unit>) -> Result<(), WorkspaceError> { +pub(crate) async fn delete_all_handler(controller: Unit>) -> Result<(), FlowyError> { let _ = controller.delete_all().await?; Ok(()) } diff --git a/frontend/rust-lib/flowy-core/src/services/trash/sql.rs b/frontend/rust-lib/flowy-core/src/services/trash/sql.rs index b65b448a96..092cbe4ff4 100644 --- a/frontend/rust-lib/flowy-core/src/services/trash/sql.rs +++ b/frontend/rust-lib/flowy-core/src/services/trash/sql.rs @@ -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, conn: &SqliteConnection) -> Result<(), WorkspaceError> { + pub(crate) fn create_trash(repeated_trash: Vec, 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 { + pub(crate) fn read_all(conn: &SqliteConnection) -> Result { let trash_tables = dsl::trash_table.load::(conn)?; let items = trash_tables.into_iter().map(|t| t.into()).collect::>(); 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 { + pub(crate) fn read(trash_id: &str, conn: &SqliteConnection) -> Result { let trash_table = dsl::trash_table .filter(trash_table::id.eq(trash_id)) .first::(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(()) } diff --git a/frontend/rust-lib/flowy-core/src/services/view/controller.rs b/frontend/rust-lib/flowy-core/src/services/view/controller.rs index d6ff221383..da9370fc96 100644 --- a/frontend/rust-lib/flowy-core/src/services/view/controller.rs +++ b/frontend/rust-lib/flowy-core/src/services/view/controller.rs @@ -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 { + pub(crate) async fn create_view_from_params(&self, params: CreateViewParams) -> Result { 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 { + pub(crate) async fn create_view(&self, view: View) -> Result { 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 { + pub(crate) async fn read_view(&self, params: ViewIdentifier) -> Result { 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) -> Result, WorkspaceError> { + pub(crate) fn read_view_tables(&self, ids: Vec) -> Result, 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 { + pub(crate) async fn open_view(&self, params: DocIdentifier) -> Result { 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 { + pub(crate) async fn export_doc(&self, params: ExportParams) -> Result { 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 { + pub(crate) async fn read_views_belong_to(&self, belong_to_id: &str) -> Result { // 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 { + pub(crate) async fn update_view(&self, params: UpdateViewParams) -> Result { 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 { + pub(crate) async fn apply_doc_delta(&self, params: DocDelta) -> Result { let doc = self.document.apply_doc_delta(params).await?; Ok(doc) } - pub(crate) fn latest_visit_view(&self) -> WorkspaceResult> { + pub(crate) fn latest_visit_view(&self) -> FlowyResult> { 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 { + async fn create_view_on_server(&self, params: CreateViewParams) -> Result { 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, WorkspaceError> { +fn get_view_table_from(identifiers: TrashIdentifiers, conn: &SqliteConnection) -> Result, 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, 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, conn: &SqliteConnection, -) -> WorkspaceResult { +) -> FlowyResult { 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)); diff --git a/frontend/rust-lib/flowy-core/src/services/view/event_handler.rs b/frontend/rust-lib/flowy-core/src/services/view/event_handler.rs index 1f5a1e3b80..b042e8e670 100644 --- a/frontend/rust-lib/flowy-core/src/services/view/event_handler.rs +++ b/frontend/rust-lib/flowy-core/src/services/view/event_handler.rs @@ -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, controller: Unit>, -) -> DataResult { +) -> DataResult { 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, controller: Unit>, -) -> DataResult { +) -> DataResult { 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, controller: Unit>, -) -> 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, controller: Unit>, -) -> DataResult { +) -> DataResult { // 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, controller: Unit>, trash_can: Unit>, -) -> 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, controller: Unit>, -) -> DataResult { +) -> DataResult { 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, controller: Unit>, -) -> 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, controller: Unit>, -) -> 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, controller: Unit>, -) -> DataResult { +) -> DataResult { let params: ExportParams = data.into_inner().try_into()?; let data = controller.export_doc(params).await?; data_result(data) diff --git a/frontend/rust-lib/flowy-core/src/services/view/sql.rs b/frontend/rust-lib/flowy-core/src/services/view/sql.rs index fedd6310bb..b33c6fbb18 100644 --- a/frontend/rust-lib/flowy-core/src/services/view/sql.rs +++ b/frontend/rust-lib/flowy-core/src/services/view/sql.rs @@ -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 { + pub(crate) fn read_view(view_id: &str, conn: &SqliteConnection) -> Result { // 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, WorkspaceError> { + pub(crate) fn read_views(belong_to_id: &str, conn: &SqliteConnection) -> Result, 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, // conn: &SqliteConnection, -// ) -> Result { +// ) -> Result { // 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)) diff --git a/frontend/rust-lib/flowy-core/src/services/workspace/controller.rs b/frontend/rust-lib/flowy-core/src/services/workspace/controller.rs index aebda93def..0c04928707 100644 --- a/frontend/rust-lib/flowy-core/src/services/workspace/controller.rs +++ b/frontend/rust-lib/flowy-core/src/services/workspace/controller.rs @@ -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 { + ) -> Result { 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 { + pub(crate) async fn create_workspace(&self, workspace: Workspace) -> Result { 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 { + pub(crate) async fn open_workspace(&self, params: WorkspaceIdentifier) -> Result { 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 { + pub(crate) async fn read_current_workspace_apps(&self) -> Result { 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, user_id: &str, conn: &SqliteConnection, - ) -> Result { + ) -> Result { 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 { + ) -> Result { // 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 { + fn read_local_apps(&self, workspace_id: &str, conn: &SqliteConnection) -> Result { 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 { + async fn create_workspace_on_server(&self, params: CreateWorkspaceParams) -> Result { 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 { +pub fn get_current_workspace() -> Result { 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), } } diff --git a/frontend/rust-lib/flowy-core/src/services/workspace/event_handler.rs b/frontend/rust-lib/flowy-core/src/services/workspace/event_handler.rs index 7f04b7f56c..8d7eaf9658 100644 --- a/frontend/rust-lib/flowy-core/src/services/workspace/event_handler.rs +++ b/frontend/rust-lib/flowy-core/src/services/workspace/event_handler.rs @@ -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, controller: Unit>, -) -> DataResult { +) -> DataResult { 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>, -) -> DataResult { +) -> DataResult { 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, controller: Unit>, -) -> DataResult { +) -> DataResult { let params: WorkspaceIdentifier = data.into_inner().try_into()?; let workspaces = controller.open_workspace(params).await?; data_result(workspaces) diff --git a/frontend/rust-lib/flowy-core/src/services/workspace/sql.rs b/frontend/rust-lib/flowy-core/src/services/workspace/sql.rs index bda1a8def9..6c0cf294ab 100644 --- a/frontend/rust-lib/flowy-core/src/services/workspace/sql.rs +++ b/frontend/rust-lib/flowy-core/src/services/workspace/sql.rs @@ -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, user_id: &str, conn: &SqliteConnection, - ) -> Result, WorkspaceError> { + ) -> Result, 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(()) } diff --git a/frontend/rust-lib/flowy-document/Cargo.toml b/frontend/rust-lib/flowy-document/Cargo.toml index 2f949ff0f9..6c01690360 100644 --- a/frontend/rust-lib/flowy-document/Cargo.toml +++ b/frontend/rust-lib/flowy-document/Cargo.toml @@ -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"} diff --git a/frontend/rust-lib/flowy-document/src/errors.rs b/frontend/rust-lib/flowy-document/src/errors.rs deleted file mode 100644 index 526799dcb5..0000000000 --- a/frontend/rust-lib/flowy-document/src/errors.rs +++ /dev/null @@ -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 = std::result::Result; - -#[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(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(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 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 for DocError { - fn from(error: lib_ot::errors::OTError) -> Self { DocError::internal().context(error) } -} - -impl std::convert::From for DocError { - fn from(error: flowy_collaboration::errors::CollaborateError) -> Self { DocError::internal().context(error) } -} - -impl std::convert::From for DocError { - fn from(error: std::io::Error) -> Self { DocError::internal().context(error) } -} - -impl std::convert::From for DocError { - fn from(error: serde_json::Error) -> Self { DocError::internal().context(error) } -} - -impl std::convert::From for DocError { - fn from(e: protobuf::ProtobufError) -> Self { DocError::internal().context(e) } -} - -impl std::convert::From 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) } -} diff --git a/frontend/rust-lib/flowy-document/src/lib.rs b/frontend/rust-lib/flowy-document/src/lib.rs index c3ffb87b3d..c176ca4083 100644 --- a/frontend/rust-lib/flowy-document/src/lib.rs +++ b/frontend/rust-lib/flowy-document/src/lib.rs @@ -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}; +} diff --git a/frontend/rust-lib/flowy-document/src/module.rs b/frontend/rust-lib/flowy-document/src/module.rs index adda90094c..b590b5dc43 100644 --- a/frontend/rust-lib/flowy-document/src/module.rs +++ b/frontend/rust-lib/flowy-document/src/module.rs @@ -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; - fn user_id(&self) -> Result; - fn token(&self) -> Result; - fn db_pool(&self) -> Result, DocError>; + fn user_dir(&self) -> Result; + fn user_id(&self) -> Result; + fn token(&self) -> Result; + fn db_pool(&self) -> Result, 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, DocError> { + pub async fn open(&self, params: DocIdentifier) -> Result, 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, - ) -> Result { + ) -> Result { 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 { + pub async fn apply_doc_delta(&self, params: DocDelta) -> Result { // workaround: compare the rust's delta with flutter's delta. Will be removed // very soon let doc = self diff --git a/frontend/rust-lib/flowy-document/src/protobuf/model/errors.rs b/frontend/rust-lib/flowy-document/src/protobuf/model/errors.rs deleted file mode 100644 index 61831522d9..0000000000 --- a/frontend/rust-lib/flowy-document/src/protobuf/model/errors.rs +++ /dev/null @@ -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 { - ::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) -> ::std::boxed::Box { - 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>( - "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", - fields, - file_descriptor_proto() - ) - }) - } - - fn default_instance() -> &'static DocError { - static instance: ::protobuf::rt::LazyV2 = ::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 { - 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", 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() - }) -} diff --git a/frontend/rust-lib/flowy-document/src/protobuf/model/mod.rs b/frontend/rust-lib/flowy-document/src/protobuf/model/mod.rs index 2145302222..08899a0b2d 100644 --- a/frontend/rust-lib/flowy-document/src/protobuf/model/mod.rs +++ b/frontend/rust-lib/flowy-document/src/protobuf/model/mod.rs @@ -3,6 +3,3 @@ mod observable; pub use observable::*; - -mod errors; -pub use errors::*; diff --git a/frontend/rust-lib/flowy-document/src/protobuf/proto/errors.proto b/frontend/rust-lib/flowy-document/src/protobuf/proto/errors.proto deleted file mode 100644 index b2bbb6dd62..0000000000 --- a/frontend/rust-lib/flowy-document/src/protobuf/proto/errors.proto +++ /dev/null @@ -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; -} diff --git a/frontend/rust-lib/flowy-document/src/services/doc/controller.rs b/frontend/rust-lib/flowy-document/src/services/doc/controller.rs index cab76400b4..0185af24af 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/controller.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/controller.rs @@ -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, - ) -> Result, DocError> { + ) -> Result, 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, - ) -> Result { + ) -> Result { 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, - ) -> Result, DocError> { + ) -> Result, 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) -> Result { + fn make_rev_manager(&self, doc_id: &str, pool: Arc) -> Result { // 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 { + fn fetch_document(&self, doc_id: &str) -> FutureResult { 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, DocError> { + pub(crate) fn get(&self, doc_id: &str) -> Result, 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") +} diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs index f60a7d5e86..673c637c25 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs @@ -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, mut rev_manager: RevisionManager, ws_sender: Arc, - ) -> DocResult> { + ) -> FlowyResult> { 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(&self, index: usize, data: T) -> Result<(), DocError> { + pub async fn insert(&self, index: usize, data: T) -> Result<(), FlowyError> { let (ret, rx) = oneshot::channel::>(); 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::>(); 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::>(); let msg = EditCommand::Format { interval, @@ -104,7 +105,7 @@ impl ClientDocEditor { Ok(()) } - pub async fn replace(&self, interval: Interval, data: T) -> Result<(), DocError> { + pub async fn replace(&self, interval: Interval, data: T) -> Result<(), FlowyError> { let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::Replace { interval, @@ -131,7 +132,7 @@ impl ClientDocEditor { rx.await.unwrap_or(false) } - pub async fn undo(&self) -> Result { + pub async fn undo(&self) -> Result { let (ret, rx) = oneshot::channel::>(); 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 { + pub async fn redo(&self) -> Result { let (ret, rx) = oneshot::channel::>(); 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 { + pub async fn delta(&self) -> FlowyResult { let (ret, rx) = oneshot::channel::>(); 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 { + async fn save_local_delta(&self, delta: RichTextDelta) -> Result { 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::>(); 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::>(); 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 { + pub async fn doc_json(&self) -> FlowyResult { let (ret, rx) = oneshot::channel::>(); 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 { + pub async fn doc_delta(&self) -> FlowyResult { let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::ReadDocDelta { ret }; let _ = self.edit_cmd_tx.send(msg); diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/model.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/model.rs index c2454c267e..71a6bb195a 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/model.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/model.rs @@ -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>; 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>(()))) } } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs index 2eaeb75f63..e4d8bbbe48 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs @@ -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, DocError>; + fn next(&self) -> FutureResult, FlowyError>; } -type DocRevisionDeskCache = dyn RevisionDiskCache; +type DocRevisionDeskCache = dyn RevisionDiskCache; 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> { + pub async fn revisions_in_range(&self, range: RevisionRange) -> FlowyResult> { 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 { + pub async fn load_document(&self) -> FlowyResult { // 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, DocError> { + fn next(&self) -> FutureResult, 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, disk_cache: Arc, -) -> DocResult { +) -> FlowyResult { 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::::Ok(Doc { + Result::::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) -> 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(()) }) diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs index 434badcfd8..0ff47cbc2f 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs @@ -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; + fn fetch_document(&self, doc_id: &str) -> FutureResult; } pub struct RevisionManager { @@ -38,23 +39,23 @@ impl RevisionManager { } } - pub async fn load_document(&mut self) -> DocResult { + pub async fn load_document(&mut self) -> FlowyResult { 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 { + pub async fn mk_revisions(&self, range: RevisionRange) -> Result { debug_assert!(range.doc_id == self.doc_id); let revisions = self.cache.revisions_in_range(range.clone()).await?; let mut new_delta = RichTextDelta::new(); diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs index 9fccdd2512..f42b8ac28d 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs @@ -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) => { diff --git a/frontend/rust-lib/flowy-document/src/services/server/middleware.rs b/frontend/rust-lib/flowy-document/src/services/server/middleware.rs index d4875c1c89..38b3c917df 100644 --- a/frontend/rust-lib/flowy-document/src/services/server/middleware.rs +++ b/frontend/rust-lib/flowy-document/src/services/server/middleware.rs @@ -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() diff --git a/frontend/rust-lib/flowy-document/src/services/server/mod.rs b/frontend/rust-lib/flowy-document/src/services/server/mod.rs index 864eed78ac..4f19269cb0 100644 --- a/frontend/rust-lib/flowy-document/src/services/server/mod.rs +++ b/frontend/rust-lib/flowy-document/src/services/server/mod.rs @@ -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; 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, DocError>; + fn read_doc(&self, token: &str, params: DocIdentifier) -> FutureResult, 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( diff --git a/frontend/rust-lib/flowy-document/src/services/server/server_api.rs b/frontend/rust-lib/flowy-document/src/services/server/server_api.rs index c5a56aaa5c..c12f0a9662 100644 --- a/frontend/rust-lib/flowy-document/src/services/server/server_api.rs +++ b/frontend/rust-lib/flowy-document/src/services/server/server_api.rs @@ -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, DocError> { + fn read_doc(&self, token: &str, params: DocIdentifier) -> FutureResult, 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, DocError> { +pub async fn read_doc_request(token: &str, params: DocIdentifier, url: &str) -> Result, 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) diff --git a/frontend/rust-lib/flowy-document/src/services/server/server_api_mock.rs b/frontend/rust-lib/flowy-document/src/services/server/server_api_mock.rs index faf728f195..b2bdd3b7ed 100644 --- a/frontend/rust-lib/flowy-document/src/services/server/server_api_mock.rs +++ b/frontend/rust-lib/flowy-document/src/services/server/server_api_mock.rs @@ -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, DocError> { + fn read_doc(&self, _token: &str, params: DocIdentifier) -> FutureResult, 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(()) }) } } diff --git a/frontend/rust-lib/flowy-document/src/services/ws/ws_manager.rs b/frontend/rust-lib/flowy-document/src/services/ws/ws_manager.rs index eb2c8cc0cb..efccc18ece 100644 --- a/frontend/rust-lib/flowy-document/src/services/ws/ws_manager.rs +++ b/frontend/rust-lib/flowy-document/src/services/ws/ws_manager.rs @@ -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; 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; } diff --git a/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_sql.rs b/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_sql.rs index 61077c26fd..80a9f106bf 100644 --- a/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_sql.rs +++ b/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_sql.rs @@ -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, conn: &SqliteConnection) -> Result<(), DocError> { + pub(crate) fn create_rev_table(revisions: Vec, 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, DocError> { + ) -> Result, 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, DocError> { + ) -> Result, 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, DocError> { + ) -> Result, 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)); diff --git a/frontend/rust-lib/flowy-error/Cargo.toml b/frontend/rust-lib/flowy-error/Cargo.toml index b738a43422..5ec55b475e 100644 --- a/frontend/rust-lib/flowy-error/Cargo.toml +++ b/frontend/rust-lib/flowy-error/Cargo.toml @@ -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" \ No newline at end of file +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"] diff --git a/frontend/rust-lib/flowy-error/src/errors.rs b/frontend/rust-lib/flowy-error/src/errors.rs index e79b08bee8..c8459b9d4e 100644 --- a/frontend/rust-lib/flowy-error/src/errors.rs +++ b/frontend/rust-lib/flowy-error/src/errors.rs @@ -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 = std::result::Result; #[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 for FlowyError { @@ -49,26 +73,6 @@ impl std::convert::From 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(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 for FlowyError { + fn from(error: std::io::Error) -> Self { FlowyError::internal().context(error) } +} + +impl std::convert::From for FlowyError { + fn from(e: protobuf::ProtobufError) -> Self { FlowyError::internal().context(e) } +} diff --git a/frontend/rust-lib/flowy-error/src/ext/backend.rs b/frontend/rust-lib/flowy-error/src/ext/backend.rs new file mode 100644 index 0000000000..68cc9dca45 --- /dev/null +++ b/frontend/rust-lib/flowy-error/src/ext/backend.rs @@ -0,0 +1,22 @@ +use crate::FlowyError; +use backend_service::errors::{ErrorCode as ServerErrorCode, ServerError}; +use error_code::ErrorCode; + +impl std::convert::From 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, + } +} diff --git a/frontend/rust-lib/flowy-error/src/ext/collaborate.rs b/frontend/rust-lib/flowy-error/src/ext/collaborate.rs new file mode 100644 index 0000000000..82246f7792 --- /dev/null +++ b/frontend/rust-lib/flowy-error/src/ext/collaborate.rs @@ -0,0 +1,5 @@ +use crate::FlowyError; + +impl std::convert::From for FlowyError { + fn from(error: flowy_collaboration::errors::CollaborateError) -> Self { FlowyError::internal().context(error) } +} diff --git a/frontend/rust-lib/flowy-error/src/ext/database.rs b/frontend/rust-lib/flowy-error/src/ext/database.rs new file mode 100644 index 0000000000..f395a0235c --- /dev/null +++ b/frontend/rust-lib/flowy-error/src/ext/database.rs @@ -0,0 +1,15 @@ +use crate::FlowyError; + +impl std::convert::From 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 for FlowyError { + fn from(error: lib_sqlite::Error) -> Self { FlowyError::internal().context(error) } +} diff --git a/frontend/rust-lib/flowy-error/src/ext/mod.rs b/frontend/rust-lib/flowy-error/src/ext/mod.rs new file mode 100644 index 0000000000..8bd455de93 --- /dev/null +++ b/frontend/rust-lib/flowy-error/src/ext/mod.rs @@ -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::*; diff --git a/frontend/rust-lib/flowy-error/src/ext/ot.rs b/frontend/rust-lib/flowy-error/src/ext/ot.rs new file mode 100644 index 0000000000..bfce081953 --- /dev/null +++ b/frontend/rust-lib/flowy-error/src/ext/ot.rs @@ -0,0 +1,5 @@ +use crate::FlowyError; + +impl std::convert::From for FlowyError { + fn from(error: lib_ot::errors::OTError) -> Self { FlowyError::internal().context(error) } +} diff --git a/frontend/rust-lib/flowy-error/src/ext/serde.rs b/frontend/rust-lib/flowy-error/src/ext/serde.rs new file mode 100644 index 0000000000..87c7d55178 --- /dev/null +++ b/frontend/rust-lib/flowy-error/src/ext/serde.rs @@ -0,0 +1,5 @@ +use crate::FlowyError; + +impl std::convert::From for FlowyError { + fn from(error: serde_json::Error) -> Self { FlowyError::internal().context(error) } +} diff --git a/frontend/rust-lib/flowy-error/src/lib.rs b/frontend/rust-lib/flowy-error/src/lib.rs index e7c6be4852..756eb4e82c 100644 --- a/frontend/rust-lib/flowy-error/src/lib.rs +++ b/frontend/rust-lib/flowy-error/src/lib.rs @@ -1,4 +1,6 @@ mod errors; +mod ext; pub mod protobuf; +pub use error_code::ErrorCode; pub use errors::*; diff --git a/frontend/rust-lib/flowy-error/src/protobuf/model/errors.rs b/frontend/rust-lib/flowy-error/src/protobuf/model/errors.rs index e30f60612c..a3dcaf639b 100644 --- a/frontend/rust-lib/flowy-error/src/protobuf/model/errors.rs +++ b/frontend/rust-lib/flowy-error/src/protobuf/model/errors.rs @@ -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 { - 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", 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; diff --git a/frontend/rust-lib/flowy-error/src/protobuf/proto/errors.proto b/frontend/rust-lib/flowy-error/src/protobuf/proto/errors.proto index 434258f108..2be9375a15 100644 --- a/frontend/rust-lib/flowy-error/src/protobuf/proto/errors.proto +++ b/frontend/rust-lib/flowy-error/src/protobuf/proto/errors.proto @@ -4,6 +4,3 @@ message FlowyError { int32 code = 1; string msg = 2; } -enum ErrorCode { - Internal = 0; -} diff --git a/frontend/rust-lib/flowy-net/src/handlers/mod.rs b/frontend/rust-lib/flowy-net/src/handlers/mod.rs index 6e6486c28c..d02093db8d 100644 --- a/frontend/rust-lib/flowy-net/src/handlers/mod.rs +++ b/frontend/rust-lib/flowy-net/src/handlers/mod.rs @@ -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; diff --git a/frontend/rust-lib/flowy-net/src/module.rs b/frontend/rust-lib/flowy-net/src/module.rs index 18b17ad8a5..888fb2316b 100644 --- a/frontend/rust-lib/flowy-net/src/module.rs +++ b/frontend/rust-lib/flowy-net/src/module.rs @@ -5,6 +5,6 @@ use std::sync::Arc; pub fn create(ws_manager: Arc) -> Module { Module::new() .name("Flowy-Network") - .data(ws_manager.clone()) + .data(ws_manager) .event(NetworkEvent::UpdateNetworkType, update_network_ty) } diff --git a/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs b/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs index 150385f1f1..b320f13b53 100644 --- a/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs +++ b/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs @@ -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, user_session: Arc, ) -> (Arc, Arc) { - 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 { - let dir = self.user.user_dir().map_err(|e| DocError::unauthorized().context(e))?; + fn user_dir(&self) -> Result { + 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 { self.user.user_id().map_err(map_user_error) } + fn user_id(&self) -> Result { self.user.user_id() } - fn token(&self) -> Result { self.user.token().map_err(map_user_error) } + fn token(&self) -> Result { self.user.token() } - fn db_pool(&self) -> Result, DocError> { self.user.db_pool().map_err(map_user_error) } + fn db_pool(&self) -> Result, 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, diff --git a/frontend/rust-lib/flowy-sdk/src/deps_resolve/workspace_deps.rs b/frontend/rust-lib/flowy-sdk/src/deps_resolve/workspace_deps.rs index e89ad9138a..f44b45568e 100644 --- a/frontend/rust-lib/flowy-sdk/src/deps_resolve/workspace_deps.rs +++ b/frontend/rust-lib/flowy-sdk/src/deps_resolve/workspace_deps.rs @@ -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, WorkspaceError> { + fn db_pool(&self) -> Result, 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 { + fn user_id(&self) -> Result { self.user_session .user_id() - .map_err(|e| WorkspaceError::internal().context(e)) + .map_err(|e| FlowyError::internal().context(e)) } - fn token(&self) -> Result { - self.user_session - .token() - .map_err(|e| WorkspaceError::internal().context(e)) + fn token(&self) -> Result { + self.user_session.token().map_err(|e| FlowyError::internal().context(e)) } } diff --git a/frontend/rust-lib/flowy-sdk/src/lib.rs b/frontend/rust-lib/flowy-sdk/src/lib.rs index 45cbb96a17..55efc14fa8 100644 --- a/frontend/rust-lib/flowy-sdk/src/lib.rs +++ b/frontend/rust-lib/flowy-sdk/src/lib.rs @@ -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 { diff --git a/frontend/rust-lib/flowy-sdk/src/module.rs b/frontend/rust-lib/flowy-sdk/src/module.rs index 9c9af5e2e1..572373b761 100644 --- a/frontend/rust-lib/flowy-sdk/src/module.rs +++ b/frontend/rust-lib/flowy-sdk/src/module.rs @@ -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; diff --git a/frontend/rust-lib/flowy-test/src/event_builder.rs b/frontend/rust-lib/flowy-test/src/event_builder.rs index 0cacef01af..ca17453417 100644 --- a/frontend/rust-lib/flowy-test/src/event_builder.rs +++ b/frontend/rust-lib/flowy-test/src/event_builder.rs @@ -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; +pub type CoreModuleEventBuilder = EventBuilder; impl CoreModuleEventBuilder { pub fn new(sdk: FlowySDKTest) -> Self { EventBuilder::test(TestContext::new(sdk)) } -} - -pub type UserModuleEventBuilder = EventBuilder; -impl UserModuleEventBuilder { - pub fn new(sdk: FlowySDKTest) -> Self { EventBuilder::test(TestContext::new(sdk)) } pub fn user_profile(&self) -> &Option { &self.user_profile } } +pub type UserModuleEventBuilder = CoreModuleEventBuilder; + #[derive(Clone)] pub struct EventBuilder { context: TestContext, diff --git a/frontend/rust-lib/flowy-test/src/helper.rs b/frontend/rust-lib/flowy-test/src/helper.rs index a533e8473f..c276462630 100644 --- a/frontend/rust-lib/flowy-test/src/helper.rs +++ b/frontend/rust-lib/flowy-test/src/helper.rs @@ -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) -> SignUpContext { let request = ModuleRequest::new(SignUp).payload(payload); let user_profile = EventDispatcher::sync_send(dispatch, request) - .parse::() + .parse::() .unwrap() .unwrap(); @@ -336,7 +336,7 @@ pub async fn async_sign_up(dispatch: Arc) -> SignUpContext { let request = ModuleRequest::new(SignUp).payload(payload); let user_profile = EventDispatcher::async_send(dispatch.clone(), request) .await - .parse::() + .parse::() .unwrap() .unwrap(); @@ -361,7 +361,7 @@ fn sign_in(dispatch: Arc) -> UserProfile { let request = ModuleRequest::new(SignIn).payload(payload); EventDispatcher::sync_send(dispatch, request) - .parse::() + .parse::() .unwrap() .unwrap() } diff --git a/frontend/rust-lib/flowy-user/Cargo.toml b/frontend/rust-lib/flowy-user/Cargo.toml index d688229ed7..c6532cfbb0 100644 --- a/frontend/rust-lib/flowy-user/Cargo.toml +++ b/frontend/rust-lib/flowy-user/Cargo.toml @@ -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"] } diff --git a/frontend/rust-lib/flowy-user/src/errors.rs b/frontend/rust-lib/flowy-user/src/errors.rs deleted file mode 100644 index 814c40d2d8..0000000000 --- a/frontend/rust-lib/flowy-user/src/errors.rs +++ /dev/null @@ -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(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 for UserError { - fn from(code: ErrorCode) -> Self { - UserError { - code: code.value(), - msg: format!("{}", code), - } - } -} - -impl std::convert::From 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 for UserError { - fn from(error: lib_sqlite::Error) -> Self { UserError::internal().context(error) } -} - -impl std::convert::From 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() - } -} diff --git a/frontend/rust-lib/flowy-user/src/event.rs b/frontend/rust-lib/flowy-user/src/event.rs index efd8f42112..0a2357fb26 100644 --- a/frontend/rust-lib/flowy-user/src/event.rs +++ b/frontend/rust-lib/flowy-user/src/event.rs @@ -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, diff --git a/frontend/rust-lib/flowy-user/src/handlers/auth_handler.rs b/frontend/rust-lib/flowy-user/src/handlers/auth_handler.rs index 1fdcb67f96..fa99f19b06 100644 --- a/frontend/rust-lib/flowy-user/src/handlers/auth_handler.rs +++ b/frontend/rust-lib/flowy-user/src/handlers/auth_handler.rs @@ -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, session: Unit>) -> DataResult { +pub async fn sign_in( + data: Data, + session: Unit>, +) -> DataResult { 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, session: Unit>) ), err )] -pub async fn sign_up(data: Data, session: Unit>) -> DataResult { +pub async fn sign_up( + data: Data, + session: Unit>, +) -> DataResult { let params: SignUpParams = data.into_inner().try_into()?; let user_profile = session.sign_up(params).await?; diff --git a/frontend/rust-lib/flowy-user/src/handlers/user_handler.rs b/frontend/rust-lib/flowy-user/src/handlers/user_handler.rs index 4e3a18e11c..e282632c36 100644 --- a/frontend/rust-lib/flowy-user/src/handlers/user_handler.rs +++ b/frontend/rust-lib/flowy-user/src/handlers/user_handler.rs @@ -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>) -> Result<(), UserError> { +pub async fn init_user_handler(session: Unit>) -> Result<(), FlowyError> { let _ = session.init_user().await?; Ok(()) } #[tracing::instrument(skip(session))] -pub async fn check_user_handler(session: Unit>) -> DataResult { +pub async fn check_user_handler(session: Unit>) -> DataResult { let user_profile = session.check_user().await?; data_result(user_profile) } #[tracing::instrument(skip(session))] -pub async fn get_user_profile_handler(session: Unit>) -> DataResult { +pub async fn get_user_profile_handler(session: Unit>) -> DataResult { 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>) -> Result<(), UserError> { +pub async fn sign_out(session: Unit>) -> Result<(), FlowyError> { let _ = session.sign_out().await?; Ok(()) } @@ -31,7 +31,7 @@ pub async fn sign_out(session: Unit>) -> Result<(), UserError> pub async fn update_user_handler( data: Data, session: Unit>, -) -> Result<(), UserError> { +) -> Result<(), FlowyError> { let params: UpdateUserParams = data.into_inner().try_into()?; session.update_user(params).await?; Ok(()) diff --git a/frontend/rust-lib/flowy-user/src/lib.rs b/frontend/rust-lib/flowy-user/src/lib.rs index 33a922fa34..5484162948 100644 --- a/frontend/rust-lib/flowy-user/src/lib.rs +++ b/frontend/rust-lib/flowy-user/src/lib.rs @@ -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}; +} diff --git a/frontend/rust-lib/flowy-user/src/protobuf/model/errors.rs b/frontend/rust-lib/flowy-user/src/protobuf/model/errors.rs deleted file mode 100644 index 2e50c10899..0000000000 --- a/frontend/rust-lib/flowy-user/src/protobuf/model/errors.rs +++ /dev/null @@ -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 { - ::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) -> ::std::boxed::Box { - 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", - fields, - file_descriptor_proto() - ) - }) - } - - fn default_instance() -> &'static UserError { - static instance: ::protobuf::rt::LazyV2 = ::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() - }) -} diff --git a/frontend/rust-lib/flowy-user/src/protobuf/model/mod.rs b/frontend/rust-lib/flowy-user/src/protobuf/model/mod.rs index cd35f2090b..b9a7e246fd 100644 --- a/frontend/rust-lib/flowy-user/src/protobuf/model/mod.rs +++ b/frontend/rust-lib/flowy-user/src/protobuf/model/mod.rs @@ -4,8 +4,5 @@ mod observable; pub use observable::*; -mod errors; -pub use errors::*; - mod event; pub use event::*; diff --git a/frontend/rust-lib/flowy-user/src/protobuf/proto/errors.proto b/frontend/rust-lib/flowy-user/src/protobuf/proto/errors.proto deleted file mode 100644 index b2dec22eb0..0000000000 --- a/frontend/rust-lib/flowy-user/src/protobuf/proto/errors.proto +++ /dev/null @@ -1,6 +0,0 @@ -syntax = "proto3"; - -message UserError { - int32 code = 1; - string msg = 2; -} diff --git a/frontend/rust-lib/flowy-user/src/services/server/mod.rs b/frontend/rust-lib/flowy-user/src/services/server/mod.rs index f6c4ea33f0..6178abd3dd 100644 --- a/frontend/rust-lib/flowy-user/src/services/server/mod.rs +++ b/frontend/rust-lib/flowy-user/src/services/server/mod.rs @@ -8,17 +8,17 @@ use std::sync::Arc; pub(crate) type Server = Arc; 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; - fn sign_in(&self, params: SignInParams) -> FutureResult; - 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; + fn sign_up(&self, params: SignUpParams) -> FutureResult; + fn sign_in(&self, params: SignInParams) -> FutureResult; + 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; fn ws_addr(&self) -> String; } diff --git a/frontend/rust-lib/flowy-user/src/services/server/server_api.rs b/frontend/rust-lib/flowy-user/src/services/server/server_api.rs index 72d54a7319..58e16e7765 100644 --- a/frontend/rust-lib/flowy-user/src/services/server/server_api.rs +++ b/frontend/rust-lib/flowy-user/src/services/server/server_api.rs @@ -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 { + fn sign_up(&self, params: SignUpParams) -> FutureResult { 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 { + fn sign_in(&self, params: SignInParams) -> FutureResult { 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 { + fn get_user(&self, token: &str) -> FutureResult { 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() // }, diff --git a/frontend/rust-lib/flowy-user/src/services/server/server_api_mock.rs b/frontend/rust-lib/flowy-user/src/services/server/server_api_mock.rs index 435020e856..ae8c68da47 100644 --- a/frontend/rust-lib/flowy-user/src/services/server/server_api_mock.rs +++ b/frontend/rust-lib/flowy-user/src/services/server/server_api_mock.rs @@ -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 { + fn sign_up(&self, params: SignUpParams) -> FutureResult { let uid = uuid(); FutureResult::new(async move { Ok(SignUpResponse { @@ -23,7 +23,7 @@ impl UserServerAPI for UserServerMock { }) } - fn sign_in(&self, params: SignInParams) -> FutureResult { + fn sign_in(&self, params: SignInParams) -> FutureResult { 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 { + fn get_user(&self, _token: &str) -> FutureResult { FutureResult::new(async { Ok(UserProfile::default()) }) } diff --git a/frontend/rust-lib/flowy-user/src/services/user/database.rs b/frontend/rust-lib/flowy-user/src/services/user/database.rs index a3a450c792..aa4c603349 100644 --- a/frontend/rust-lib/flowy-user/src/services/user/database.rs +++ b/frontend/rust-lib/flowy-user/src/services/user/database.rs @@ -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 { + pub(crate) fn get_connection(&self, user_id: &str) -> Result { let conn = self.get_pool(user_id)?.get()?; Ok(conn) } - pub(crate) fn get_pool(&self, user_id: &str) -> Result, UserError> { + pub(crate) fn get_pool(&self, user_id: &str) -> Result, 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()), }, } diff --git a/frontend/rust-lib/flowy-user/src/services/user/notifier.rs b/frontend/rust-lib/flowy-user/src/services/user/notifier.rs index a8d86a0319..eadb2fcc5b 100644 --- a/frontend/rust-lib/flowy-user/src/services/user/notifier.rs +++ b/frontend/rust-lib/flowy-user/src/services/user/notifier.rs @@ -1,5 +1,5 @@ use crate::entities::{UserProfile, UserStatus}; -use flowy_net::entities::NetworkType; + use tokio::sync::{broadcast, mpsc}; pub struct UserNotifier { diff --git a/frontend/rust-lib/flowy-user/src/services/user/user_session.rs b/frontend/rust-lib/flowy-user/src/services/user/user_session.rs index d4774fa6b9..5cb571ac52 100644 --- a/frontend/rust-lib/flowy-user/src/services/user/user_session.rs +++ b/frontend/rust-lib/flowy-user/src/services/user/user_session.rs @@ -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 { + pub fn db_connection(&self) -> Result { 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 = pool.get()?; - pub fn db_pool(&self) -> Result, UserError> { + pub fn db_pool(&self) -> Result, 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 { + pub async fn sign_in(&self, params: SignInParams) -> Result { 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 { + pub async fn sign_up(&self, params: SignUpParams) -> Result { 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 { + pub async fn check_user(&self) -> Result { 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 { + pub async fn user_profile(&self) -> Result { 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 { + pub fn user_dir(&self) -> Result { let session = self.get_session()?; Ok(format!("{}/{}", self.config.root_dir, session.user_id)) } - pub fn user_id(&self) -> Result { Ok(self.get_session()?.user_id) } + pub fn user_id(&self) -> Result { Ok(self.get_session()?.user_id) } - pub fn user_name(&self) -> Result { Ok(self.get_session()?.name) } + pub fn user_name(&self) -> Result { Ok(self.get_session()?.name) } - pub fn token(&self) -> Result { Ok(self.get_session()?.token) } + pub fn token(&self) -> Result { 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 { + async fn save_user(&self, user: UserTable) -> Result { 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) -> Result<(), UserError> { + fn set_session(&self, session: Option) -> 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 { + fn get_session(&self) -> Result { 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, params: UpdateUserParams, -) -> Result<(), UserError> { +) -> Result<(), FlowyError> { let changeset = UserTableChangeset::new(params); let conn = pool.get()?; diesel_update_table!(user_table, changeset, &*conn); diff --git a/shared-lib/Cargo.lock b/shared-lib/Cargo.lock index 9c0c172f00..b840c8332f 100644 --- a/shared-lib/Cargo.lock +++ b/shared-lib/Cargo.lock @@ -633,6 +633,15 @@ dependencies = [ "backtrace", ] +[[package]] +name = "error-code" +version = "0.1.0" +dependencies = [ + "derive_more", + "flowy-derive", + "protobuf", +] + [[package]] name = "fake" version = "2.3.0" @@ -710,6 +719,7 @@ dependencies = [ "bytes", "chrono", "derive_more", + "error-code", "flowy-collaboration", "flowy-derive", "log", @@ -740,6 +750,7 @@ dependencies = [ "bytes", "claim", "derive_more", + "error-code", "fake", "fancy-regex", "flowy-derive", diff --git a/shared-lib/Cargo.toml b/shared-lib/Cargo.toml index d48aa6532e..c923acbfb2 100644 --- a/shared-lib/Cargo.toml +++ b/shared-lib/Cargo.toml @@ -10,6 +10,7 @@ members = [ "backend-service", "flowy-derive", "flowy-ast", + "error-code", ] [profile.dev] diff --git a/shared-lib/error-code/Cargo.toml b/shared-lib/error-code/Cargo.toml new file mode 100644 index 0000000000..5688c869ee --- /dev/null +++ b/shared-lib/error-code/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "error-code" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +flowy-derive = { path = "../flowy-derive" } +protobuf = {version = "2.18.0"} +derive_more = {version = "0.99", features = ["display"]} \ No newline at end of file diff --git a/shared-lib/error-code/Flowy.toml b/shared-lib/error-code/Flowy.toml new file mode 100644 index 0000000000..1c788f7599 --- /dev/null +++ b/shared-lib/error-code/Flowy.toml @@ -0,0 +1,3 @@ + +proto_crates = ["src/error_code.rs"] +event_files = [] \ No newline at end of file diff --git a/shared-lib/error-code/src/error_code.rs b/shared-lib/error-code/src/error_code.rs new file mode 100644 index 0000000000..2868a5fa7c --- /dev/null +++ b/shared-lib/error-code/src/error_code.rs @@ -0,0 +1,100 @@ +use crate::protobuf::ErrorCode as ProtoBufErrorCode; +use derive_more::Display; +use flowy_derive::ProtoBuf_Enum; +use protobuf::ProtobufEnum; +use std::convert::{TryFrom, TryInto}; + +#[derive(Debug, Clone, ProtoBuf_Enum, Display, PartialEq, Eq)] +pub enum ErrorCode { + #[display(fmt = "Internal error")] + Internal = 0, + + #[display(fmt = "UserUnauthorized")] + UserUnauthorized = 2, + + #[display(fmt = "RecordNotFound")] + RecordNotFound = 3, + + #[display(fmt = "Workspace name can not be empty or whitespace")] + WorkspaceNameInvalid = 100, + + #[display(fmt = "Workspace id can not be empty or whitespace")] + WorkspaceIdInvalid = 101, + + #[display(fmt = "Color style of the App is invalid")] + AppColorStyleInvalid = 102, + + #[display(fmt = "Workspace desc is invalid")] + WorkspaceDescTooLong = 103, + + #[display(fmt = "Workspace description too long")] + WorkspaceNameTooLong = 104, + + #[display(fmt = "App id can not be empty or whitespace")] + AppIdInvalid = 110, + + #[display(fmt = "App name can not be empty or whitespace")] + AppNameInvalid = 111, + + #[display(fmt = "View name can not be empty or whitespace")] + ViewNameInvalid = 120, + + #[display(fmt = "Thumbnail of the view is invalid")] + ViewThumbnailInvalid = 121, + + #[display(fmt = "View id can not be empty or whitespace")] + ViewIdInvalid = 122, + + #[display(fmt = "View desc too long")] + ViewDescTooLong = 123, + + #[display(fmt = "View data is invalid")] + ViewDataInvalid = 124, + + #[display(fmt = "View name too long")] + ViewNameTooLong = 125, + + #[display(fmt = "Connection error")] + ConnectError = 200, + + #[display(fmt = "Email can not be empty or whitespace")] + EmailIsEmpty = 300, + #[display(fmt = "Email format is not valid")] + EmailFormatInvalid = 301, + #[display(fmt = "Email already exists")] + EmailAlreadyExists = 302, + #[display(fmt = "Password can not be empty or whitespace")] + PasswordIsEmpty = 303, + #[display(fmt = "Password format too long")] + PasswordTooLong = 304, + #[display(fmt = "Password contains forbidden characters.")] + PasswordContainsForbidCharacters = 305, + #[display(fmt = "Password should contain a minimum of 6 characters with 1 special 1 letter and 1 numeric")] + PasswordFormatInvalid = 306, + #[display(fmt = "Password not match")] + PasswordNotMatch = 307, + #[display(fmt = "User name is too long")] + UserNameTooLong = 308, + #[display(fmt = "User name contain forbidden characters")] + UserNameContainForbiddenCharacters = 309, + #[display(fmt = "User name can not be empty or whitespace")] + UserNameIsEmpty = 310, + #[display(fmt = "user id is empty or whitespace")] + UserIdInvalid = 311, + #[display(fmt = "User not exist")] + UserNotExist = 312, +} + +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(), + } + } +} diff --git a/shared-lib/error-code/src/lib.rs b/shared-lib/error-code/src/lib.rs new file mode 100644 index 0000000000..90a67f9c77 --- /dev/null +++ b/shared-lib/error-code/src/lib.rs @@ -0,0 +1,4 @@ +mod error_code; +mod protobuf; + +pub use error_code::*; diff --git a/shared-lib/error-code/src/protobuf/mod.rs b/shared-lib/error-code/src/protobuf/mod.rs new file mode 100644 index 0000000000..da97aad28a --- /dev/null +++ b/shared-lib/error-code/src/protobuf/mod.rs @@ -0,0 +1,4 @@ +#![cfg_attr(rustfmt, rustfmt::skip)] +// Auto-generated, do not edit +mod model; +pub use model::*; \ No newline at end of file diff --git a/shared-lib/error-code/src/protobuf/model/error_code.rs b/shared-lib/error-code/src/protobuf/model/error_code.rs new file mode 100644 index 0000000000..0fe3afbf55 --- /dev/null +++ b/shared-lib/error-code/src/protobuf/model/error_code.rs @@ -0,0 +1,253 @@ +// 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 `error_code.proto` + +/// Generated files are compatible only with the same version +/// of protobuf runtime. +// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_22_1; + +#[derive(Clone,PartialEq,Eq,Debug,Hash)] +pub enum ErrorCode { + Internal = 0, + UserUnauthorized = 2, + RecordNotFound = 3, + WorkspaceNameInvalid = 100, + WorkspaceIdInvalid = 101, + AppColorStyleInvalid = 102, + WorkspaceDescTooLong = 103, + WorkspaceNameTooLong = 104, + AppIdInvalid = 110, + AppNameInvalid = 111, + ViewNameInvalid = 120, + ViewThumbnailInvalid = 121, + ViewIdInvalid = 122, + ViewDescTooLong = 123, + ViewDataInvalid = 124, + ViewNameTooLong = 125, + ConnectError = 200, + EmailIsEmpty = 300, + EmailFormatInvalid = 301, + EmailAlreadyExists = 302, + PasswordIsEmpty = 303, + PasswordTooLong = 304, + PasswordContainsForbidCharacters = 305, + PasswordFormatInvalid = 306, + PasswordNotMatch = 307, + UserNameTooLong = 308, + UserNameContainForbiddenCharacters = 309, + UserNameIsEmpty = 310, + UserIdInvalid = 311, + UserNotExist = 312, +} + +impl ::protobuf::ProtobufEnum for ErrorCode { + fn value(&self) -> i32 { + *self as i32 + } + + fn from_i32(value: i32) -> ::std::option::Option { + match value { + 0 => ::std::option::Option::Some(ErrorCode::Internal), + 2 => ::std::option::Option::Some(ErrorCode::UserUnauthorized), + 3 => ::std::option::Option::Some(ErrorCode::RecordNotFound), + 100 => ::std::option::Option::Some(ErrorCode::WorkspaceNameInvalid), + 101 => ::std::option::Option::Some(ErrorCode::WorkspaceIdInvalid), + 102 => ::std::option::Option::Some(ErrorCode::AppColorStyleInvalid), + 103 => ::std::option::Option::Some(ErrorCode::WorkspaceDescTooLong), + 104 => ::std::option::Option::Some(ErrorCode::WorkspaceNameTooLong), + 110 => ::std::option::Option::Some(ErrorCode::AppIdInvalid), + 111 => ::std::option::Option::Some(ErrorCode::AppNameInvalid), + 120 => ::std::option::Option::Some(ErrorCode::ViewNameInvalid), + 121 => ::std::option::Option::Some(ErrorCode::ViewThumbnailInvalid), + 122 => ::std::option::Option::Some(ErrorCode::ViewIdInvalid), + 123 => ::std::option::Option::Some(ErrorCode::ViewDescTooLong), + 124 => ::std::option::Option::Some(ErrorCode::ViewDataInvalid), + 125 => ::std::option::Option::Some(ErrorCode::ViewNameTooLong), + 200 => ::std::option::Option::Some(ErrorCode::ConnectError), + 300 => ::std::option::Option::Some(ErrorCode::EmailIsEmpty), + 301 => ::std::option::Option::Some(ErrorCode::EmailFormatInvalid), + 302 => ::std::option::Option::Some(ErrorCode::EmailAlreadyExists), + 303 => ::std::option::Option::Some(ErrorCode::PasswordIsEmpty), + 304 => ::std::option::Option::Some(ErrorCode::PasswordTooLong), + 305 => ::std::option::Option::Some(ErrorCode::PasswordContainsForbidCharacters), + 306 => ::std::option::Option::Some(ErrorCode::PasswordFormatInvalid), + 307 => ::std::option::Option::Some(ErrorCode::PasswordNotMatch), + 308 => ::std::option::Option::Some(ErrorCode::UserNameTooLong), + 309 => ::std::option::Option::Some(ErrorCode::UserNameContainForbiddenCharacters), + 310 => ::std::option::Option::Some(ErrorCode::UserNameIsEmpty), + 311 => ::std::option::Option::Some(ErrorCode::UserIdInvalid), + 312 => ::std::option::Option::Some(ErrorCode::UserNotExist), + _ => ::std::option::Option::None + } + } + + fn values() -> &'static [Self] { + static values: &'static [ErrorCode] = &[ + ErrorCode::Internal, + ErrorCode::UserUnauthorized, + ErrorCode::RecordNotFound, + ErrorCode::WorkspaceNameInvalid, + ErrorCode::WorkspaceIdInvalid, + ErrorCode::AppColorStyleInvalid, + ErrorCode::WorkspaceDescTooLong, + ErrorCode::WorkspaceNameTooLong, + ErrorCode::AppIdInvalid, + ErrorCode::AppNameInvalid, + ErrorCode::ViewNameInvalid, + ErrorCode::ViewThumbnailInvalid, + ErrorCode::ViewIdInvalid, + ErrorCode::ViewDescTooLong, + ErrorCode::ViewDataInvalid, + ErrorCode::ViewNameTooLong, + ErrorCode::ConnectError, + ErrorCode::EmailIsEmpty, + ErrorCode::EmailFormatInvalid, + ErrorCode::EmailAlreadyExists, + ErrorCode::PasswordIsEmpty, + ErrorCode::PasswordTooLong, + ErrorCode::PasswordContainsForbidCharacters, + ErrorCode::PasswordFormatInvalid, + ErrorCode::PasswordNotMatch, + ErrorCode::UserNameTooLong, + ErrorCode::UserNameContainForbiddenCharacters, + ErrorCode::UserNameIsEmpty, + ErrorCode::UserIdInvalid, + ErrorCode::UserNotExist, + ]; + 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", 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\x10error_code.proto*\xc4\x05\n\tErrorCode\x12\x0c\n\x08Internal\x10\0\ + \x12\x14\n\x10UserUnauthorized\x10\x02\x12\x12\n\x0eRecordNotFound\x10\ + \x03\x12\x18\n\x14WorkspaceNameInvalid\x10d\x12\x16\n\x12WorkspaceIdInva\ + lid\x10e\x12\x18\n\x14AppColorStyleInvalid\x10f\x12\x18\n\x14WorkspaceDe\ + scTooLong\x10g\x12\x18\n\x14WorkspaceNameTooLong\x10h\x12\x10\n\x0cAppId\ + Invalid\x10n\x12\x12\n\x0eAppNameInvalid\x10o\x12\x13\n\x0fViewNameInval\ + id\x10x\x12\x18\n\x14ViewThumbnailInvalid\x10y\x12\x11\n\rViewIdInvalid\ + \x10z\x12\x13\n\x0fViewDescTooLong\x10{\x12\x13\n\x0fViewDataInvalid\x10\ + |\x12\x13\n\x0fViewNameTooLong\x10}\x12\x11\n\x0cConnectError\x10\xc8\ + \x01\x12\x11\n\x0cEmailIsEmpty\x10\xac\x02\x12\x17\n\x12EmailFormatInval\ + id\x10\xad\x02\x12\x17\n\x12EmailAlreadyExists\x10\xae\x02\x12\x14\n\x0f\ + PasswordIsEmpty\x10\xaf\x02\x12\x14\n\x0fPasswordTooLong\x10\xb0\x02\x12\ + %\n\x20PasswordContainsForbidCharacters\x10\xb1\x02\x12\x1a\n\x15Passwor\ + dFormatInvalid\x10\xb2\x02\x12\x15\n\x10PasswordNotMatch\x10\xb3\x02\x12\ + \x14\n\x0fUserNameTooLong\x10\xb4\x02\x12'\n\"UserNameContainForbiddenCh\ + aracters\x10\xb5\x02\x12\x14\n\x0fUserNameIsEmpty\x10\xb6\x02\x12\x12\n\ + \rUserIdInvalid\x10\xb7\x02\x12\x11\n\x0cUserNotExist\x10\xb8\x02J\xf8\t\ + \n\x06\x12\x04\0\0!\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x05\0\ + \x12\x04\x02\0!\x01\n\n\n\x03\x05\0\x01\x12\x03\x02\x05\x0e\n\x0b\n\x04\ + \x05\0\x02\0\x12\x03\x03\x04\x11\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\x03\ + \x04\x0c\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x03\x0f\x10\n\x0b\n\x04\x05\ + \0\x02\x01\x12\x03\x04\x04\x19\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x04\ + \x04\x14\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x04\x17\x18\n\x0b\n\x04\ + \x05\0\x02\x02\x12\x03\x05\x04\x17\n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\ + \x05\x04\x12\n\x0c\n\x05\x05\0\x02\x02\x02\x12\x03\x05\x15\x16\n\x0b\n\ + \x04\x05\0\x02\x03\x12\x03\x06\x04\x1f\n\x0c\n\x05\x05\0\x02\x03\x01\x12\ + \x03\x06\x04\x18\n\x0c\n\x05\x05\0\x02\x03\x02\x12\x03\x06\x1b\x1e\n\x0b\ + \n\x04\x05\0\x02\x04\x12\x03\x07\x04\x1d\n\x0c\n\x05\x05\0\x02\x04\x01\ + \x12\x03\x07\x04\x16\n\x0c\n\x05\x05\0\x02\x04\x02\x12\x03\x07\x19\x1c\n\ + \x0b\n\x04\x05\0\x02\x05\x12\x03\x08\x04\x1f\n\x0c\n\x05\x05\0\x02\x05\ + \x01\x12\x03\x08\x04\x18\n\x0c\n\x05\x05\0\x02\x05\x02\x12\x03\x08\x1b\ + \x1e\n\x0b\n\x04\x05\0\x02\x06\x12\x03\t\x04\x1f\n\x0c\n\x05\x05\0\x02\ + \x06\x01\x12\x03\t\x04\x18\n\x0c\n\x05\x05\0\x02\x06\x02\x12\x03\t\x1b\ + \x1e\n\x0b\n\x04\x05\0\x02\x07\x12\x03\n\x04\x1f\n\x0c\n\x05\x05\0\x02\ + \x07\x01\x12\x03\n\x04\x18\n\x0c\n\x05\x05\0\x02\x07\x02\x12\x03\n\x1b\ + \x1e\n\x0b\n\x04\x05\0\x02\x08\x12\x03\x0b\x04\x17\n\x0c\n\x05\x05\0\x02\ + \x08\x01\x12\x03\x0b\x04\x10\n\x0c\n\x05\x05\0\x02\x08\x02\x12\x03\x0b\ + \x13\x16\n\x0b\n\x04\x05\0\x02\t\x12\x03\x0c\x04\x19\n\x0c\n\x05\x05\0\ + \x02\t\x01\x12\x03\x0c\x04\x12\n\x0c\n\x05\x05\0\x02\t\x02\x12\x03\x0c\ + \x15\x18\n\x0b\n\x04\x05\0\x02\n\x12\x03\r\x04\x1a\n\x0c\n\x05\x05\0\x02\ + \n\x01\x12\x03\r\x04\x13\n\x0c\n\x05\x05\0\x02\n\x02\x12\x03\r\x16\x19\n\ + \x0b\n\x04\x05\0\x02\x0b\x12\x03\x0e\x04\x1f\n\x0c\n\x05\x05\0\x02\x0b\ + \x01\x12\x03\x0e\x04\x18\n\x0c\n\x05\x05\0\x02\x0b\x02\x12\x03\x0e\x1b\ + \x1e\n\x0b\n\x04\x05\0\x02\x0c\x12\x03\x0f\x04\x18\n\x0c\n\x05\x05\0\x02\ + \x0c\x01\x12\x03\x0f\x04\x11\n\x0c\n\x05\x05\0\x02\x0c\x02\x12\x03\x0f\ + \x14\x17\n\x0b\n\x04\x05\0\x02\r\x12\x03\x10\x04\x1a\n\x0c\n\x05\x05\0\ + \x02\r\x01\x12\x03\x10\x04\x13\n\x0c\n\x05\x05\0\x02\r\x02\x12\x03\x10\ + \x16\x19\n\x0b\n\x04\x05\0\x02\x0e\x12\x03\x11\x04\x1a\n\x0c\n\x05\x05\0\ + \x02\x0e\x01\x12\x03\x11\x04\x13\n\x0c\n\x05\x05\0\x02\x0e\x02\x12\x03\ + \x11\x16\x19\n\x0b\n\x04\x05\0\x02\x0f\x12\x03\x12\x04\x1a\n\x0c\n\x05\ + \x05\0\x02\x0f\x01\x12\x03\x12\x04\x13\n\x0c\n\x05\x05\0\x02\x0f\x02\x12\ + \x03\x12\x16\x19\n\x0b\n\x04\x05\0\x02\x10\x12\x03\x13\x04\x17\n\x0c\n\ + \x05\x05\0\x02\x10\x01\x12\x03\x13\x04\x10\n\x0c\n\x05\x05\0\x02\x10\x02\ + \x12\x03\x13\x13\x16\n\x0b\n\x04\x05\0\x02\x11\x12\x03\x14\x04\x17\n\x0c\ + \n\x05\x05\0\x02\x11\x01\x12\x03\x14\x04\x10\n\x0c\n\x05\x05\0\x02\x11\ + \x02\x12\x03\x14\x13\x16\n\x0b\n\x04\x05\0\x02\x12\x12\x03\x15\x04\x1d\n\ + \x0c\n\x05\x05\0\x02\x12\x01\x12\x03\x15\x04\x16\n\x0c\n\x05\x05\0\x02\ + \x12\x02\x12\x03\x15\x19\x1c\n\x0b\n\x04\x05\0\x02\x13\x12\x03\x16\x04\ + \x1d\n\x0c\n\x05\x05\0\x02\x13\x01\x12\x03\x16\x04\x16\n\x0c\n\x05\x05\0\ + \x02\x13\x02\x12\x03\x16\x19\x1c\n\x0b\n\x04\x05\0\x02\x14\x12\x03\x17\ + \x04\x1a\n\x0c\n\x05\x05\0\x02\x14\x01\x12\x03\x17\x04\x13\n\x0c\n\x05\ + \x05\0\x02\x14\x02\x12\x03\x17\x16\x19\n\x0b\n\x04\x05\0\x02\x15\x12\x03\ + \x18\x04\x1a\n\x0c\n\x05\x05\0\x02\x15\x01\x12\x03\x18\x04\x13\n\x0c\n\ + \x05\x05\0\x02\x15\x02\x12\x03\x18\x16\x19\n\x0b\n\x04\x05\0\x02\x16\x12\ + \x03\x19\x04+\n\x0c\n\x05\x05\0\x02\x16\x01\x12\x03\x19\x04$\n\x0c\n\x05\ + \x05\0\x02\x16\x02\x12\x03\x19'*\n\x0b\n\x04\x05\0\x02\x17\x12\x03\x1a\ + \x04\x20\n\x0c\n\x05\x05\0\x02\x17\x01\x12\x03\x1a\x04\x19\n\x0c\n\x05\ + \x05\0\x02\x17\x02\x12\x03\x1a\x1c\x1f\n\x0b\n\x04\x05\0\x02\x18\x12\x03\ + \x1b\x04\x1b\n\x0c\n\x05\x05\0\x02\x18\x01\x12\x03\x1b\x04\x14\n\x0c\n\ + \x05\x05\0\x02\x18\x02\x12\x03\x1b\x17\x1a\n\x0b\n\x04\x05\0\x02\x19\x12\ + \x03\x1c\x04\x1a\n\x0c\n\x05\x05\0\x02\x19\x01\x12\x03\x1c\x04\x13\n\x0c\ + \n\x05\x05\0\x02\x19\x02\x12\x03\x1c\x16\x19\n\x0b\n\x04\x05\0\x02\x1a\ + \x12\x03\x1d\x04-\n\x0c\n\x05\x05\0\x02\x1a\x01\x12\x03\x1d\x04&\n\x0c\n\ + \x05\x05\0\x02\x1a\x02\x12\x03\x1d),\n\x0b\n\x04\x05\0\x02\x1b\x12\x03\ + \x1e\x04\x1a\n\x0c\n\x05\x05\0\x02\x1b\x01\x12\x03\x1e\x04\x13\n\x0c\n\ + \x05\x05\0\x02\x1b\x02\x12\x03\x1e\x16\x19\n\x0b\n\x04\x05\0\x02\x1c\x12\ + \x03\x1f\x04\x18\n\x0c\n\x05\x05\0\x02\x1c\x01\x12\x03\x1f\x04\x11\n\x0c\ + \n\x05\x05\0\x02\x1c\x02\x12\x03\x1f\x14\x17\n\x0b\n\x04\x05\0\x02\x1d\ + \x12\x03\x20\x04\x17\n\x0c\n\x05\x05\0\x02\x1d\x01\x12\x03\x20\x04\x10\n\ + \x0c\n\x05\x05\0\x02\x1d\x02\x12\x03\x20\x13\x16b\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() + }) +} diff --git a/shared-lib/error-code/src/protobuf/model/mod.rs b/shared-lib/error-code/src/protobuf/model/mod.rs new file mode 100644 index 0000000000..e6c7f34086 --- /dev/null +++ b/shared-lib/error-code/src/protobuf/model/mod.rs @@ -0,0 +1,5 @@ +#![cfg_attr(rustfmt, rustfmt::skip)] +// Auto-generated, do not edit + +mod error_code; +pub use error_code::*; diff --git a/shared-lib/error-code/src/protobuf/proto/error_code.proto b/shared-lib/error-code/src/protobuf/proto/error_code.proto new file mode 100644 index 0000000000..ed12d58848 --- /dev/null +++ b/shared-lib/error-code/src/protobuf/proto/error_code.proto @@ -0,0 +1,34 @@ +syntax = "proto3"; + +enum ErrorCode { + Internal = 0; + UserUnauthorized = 2; + RecordNotFound = 3; + WorkspaceNameInvalid = 100; + WorkspaceIdInvalid = 101; + AppColorStyleInvalid = 102; + WorkspaceDescTooLong = 103; + WorkspaceNameTooLong = 104; + AppIdInvalid = 110; + AppNameInvalid = 111; + ViewNameInvalid = 120; + ViewThumbnailInvalid = 121; + ViewIdInvalid = 122; + ViewDescTooLong = 123; + ViewDataInvalid = 124; + ViewNameTooLong = 125; + ConnectError = 200; + EmailIsEmpty = 300; + EmailFormatInvalid = 301; + EmailAlreadyExists = 302; + PasswordIsEmpty = 303; + PasswordTooLong = 304; + PasswordContainsForbidCharacters = 305; + PasswordFormatInvalid = 306; + PasswordNotMatch = 307; + UserNameTooLong = 308; + UserNameContainForbiddenCharacters = 309; + UserNameIsEmpty = 310; + UserIdInvalid = 311; + UserNotExist = 312; +} diff --git a/shared-lib/flowy-core-infra/Cargo.toml b/shared-lib/flowy-core-infra/Cargo.toml index 28898dabf7..e3420abe0a 100644 --- a/shared-lib/flowy-core-infra/Cargo.toml +++ b/shared-lib/flowy-core-infra/Cargo.toml @@ -17,6 +17,7 @@ log = "0.4.14" flowy-collaboration = { path = "../flowy-collaboration" } uuid = { version = "0.8", features = ["serde", "v4"] } chrono = { version = "0.4" } +error-code = { path = "../error-code" } [features] default = [] diff --git a/shared-lib/flowy-core-infra/Flowy.toml b/shared-lib/flowy-core-infra/Flowy.toml index d1411c4d2b..5e88aadda5 100644 --- a/shared-lib/flowy-core-infra/Flowy.toml +++ b/shared-lib/flowy-core-infra/Flowy.toml @@ -1,3 +1,3 @@ -proto_crates = ["src/entities", "src/errors.rs"] +proto_crates = ["src/entities",] event_files = [] \ No newline at end of file diff --git a/shared-lib/flowy-core-infra/src/entities/view/view_update.rs b/shared-lib/flowy-core-infra/src/entities/view/view_update.rs index 7205f6c39c..5a3b10df93 100644 --- a/shared-lib/flowy-core-infra/src/entities/view/view_update.rs +++ b/shared-lib/flowy-core-infra/src/entities/view/view_update.rs @@ -93,11 +93,11 @@ impl TryInto for UpdateViewRequest { // } // // impl TryInto for DocDeltaRequest { -// type Error = WorkspaceError; +// type Error = FlowyError; // // fn try_into(self) -> Result { // let view_id = ViewId::parse(self.view_id) -// .map_err(|e| WorkspaceError::view_id().context(e))? +// .map_err(|e| FlowyError::view_id().context(e))? // .0; // // Ok(DocDelta { doc_id: view_id, data: self.data }) diff --git a/shared-lib/flowy-core-infra/src/errors.rs b/shared-lib/flowy-core-infra/src/errors.rs deleted file mode 100644 index a9a07a99a6..0000000000 --- a/shared-lib/flowy-core-infra/src/errors.rs +++ /dev/null @@ -1,77 +0,0 @@ -use crate::protobuf::ErrorCode as ProtoBufErrorCode; - -use derive_more::Display; -use flowy_derive::ProtoBuf_Enum; -use protobuf::ProtobufEnum; -use std::convert::{TryFrom, TryInto}; - -#[derive(Debug, Clone, ProtoBuf_Enum, Display, PartialEq, Eq)] -pub enum ErrorCode { - #[display(fmt = "Workspace name can not be empty or whitespace")] - WorkspaceNameInvalid = 0, - - #[display(fmt = "Workspace id can not be empty or whitespace")] - WorkspaceIdInvalid = 1, - - #[display(fmt = "Color style of the App is invalid")] - AppColorStyleInvalid = 2, - - #[display(fmt = "Workspace desc is invalid")] - WorkspaceDescTooLong = 3, - - #[display(fmt = "Workspace description too long")] - WorkspaceNameTooLong = 4, - - #[display(fmt = "App id can not be empty or whitespace")] - AppIdInvalid = 10, - - #[display(fmt = "App name can not be empty or whitespace")] - AppNameInvalid = 11, - - #[display(fmt = "View name can not be empty or whitespace")] - ViewNameInvalid = 20, - - #[display(fmt = "Thumbnail of the view is invalid")] - ViewThumbnailInvalid = 21, - - #[display(fmt = "View id can not be empty or whitespace")] - ViewIdInvalid = 22, - - #[display(fmt = "View desc too long")] - ViewDescTooLong = 23, - - #[display(fmt = "View data is invalid")] - ViewDataInvalid = 24, - - #[display(fmt = "View name too long")] - ViewNameTooLong = 25, - - #[display(fmt = "User unauthorized")] - UserUnauthorized = 100, - - #[display(fmt = "Workspace websocket error")] - WsConnectError = 200, - - #[display(fmt = "Server error")] - InternalError = 1000, - #[display(fmt = "Record not found")] - RecordNotFound = 1001, -} - -impl std::default::Default for ErrorCode { - fn default() -> Self { ErrorCode::InternalError } -} - -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::InternalError, - Some(code) => ErrorCode::try_from(&code).unwrap(), - } - } -} diff --git a/shared-lib/flowy-core-infra/src/lib.rs b/shared-lib/flowy-core-infra/src/lib.rs index 631fdf050b..841c93b8d7 100644 --- a/shared-lib/flowy-core-infra/src/lib.rs +++ b/shared-lib/flowy-core-infra/src/lib.rs @@ -1,5 +1,4 @@ pub mod entities; -pub mod errors; pub mod parser; #[macro_use] @@ -8,3 +7,7 @@ mod macros; // #[cfg(feature = "backend")] pub mod protobuf; pub mod user_default; + +pub mod errors { + pub use error_code::ErrorCode; +} diff --git a/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs b/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs index 57014f3213..3e314e6a7f 100644 --- a/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs +++ b/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs @@ -16,14 +16,11 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { "HashMap" => TypeCategory::Map, "u8" => TypeCategory::Bytes, "String" => TypeCategory::Str, - "WorkspaceError" - | "DocError" - | "FFIRequest" + "FFIRequest" | "FFIResponse" | "FlowyError" | "SubscribeObject" | "NetworkState" - | "UserError" | "QueryAppRequest" | "AppIdentifier" | "CreateAppRequest" @@ -82,7 +79,6 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { => TypeCategory::Protobuf, "WorkspaceEvent" | "WorkspaceNotification" - | "ErrorCode" | "DocObservable" | "FFIStatusCode" | "NetworkEvent" @@ -93,6 +89,7 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { | "ViewType" | "ExportType" | "WsDataType" + | "ErrorCode" | "WsModule" | "RevType" | "RevState" diff --git a/shared-lib/flowy-user-infra/Cargo.toml b/shared-lib/flowy-user-infra/Cargo.toml index 918516780c..5e0afba7c9 100644 --- a/shared-lib/flowy-user-infra/Cargo.toml +++ b/shared-lib/flowy-user-infra/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" [dependencies] flowy-derive = { path = "../flowy-derive" } +error-code = { path = "../error-code" } protobuf = {version = "2.18.0"} bytes = "1.0" unicode-segmentation = "1.8" diff --git a/shared-lib/flowy-user-infra/src/errors.rs b/shared-lib/flowy-user-infra/src/errors.rs deleted file mode 100644 index 2fe57dc53f..0000000000 --- a/shared-lib/flowy-user-infra/src/errors.rs +++ /dev/null @@ -1,61 +0,0 @@ -use crate::protobuf::ErrorCode as ProtoBufErrorCode; -use derive_more::Display; -use flowy_derive::ProtoBuf_Enum; -use protobuf::ProtobufEnum; -use std::convert::{TryFrom, TryInto}; - -#[derive(Debug, Clone, ProtoBuf_Enum, Display, PartialEq, Eq)] -pub enum ErrorCode { - #[display(fmt = "Email can not be empty or whitespace")] - EmailIsEmpty = 0, - #[display(fmt = "Email format is not valid")] - EmailFormatInvalid = 1, - #[display(fmt = "Email already exists")] - EmailAlreadyExists = 2, - #[display(fmt = "Password can not be empty or whitespace")] - PasswordIsEmpty = 10, - #[display(fmt = "Password format too long")] - PasswordTooLong = 11, - #[display(fmt = "Password contains forbidden characters.")] - PasswordContainsForbidCharacters = 12, - #[display(fmt = "Password should contain a minimum of 6 characters with 1 special 1 letter and 1 numeric")] - PasswordFormatInvalid = 13, - #[display(fmt = "Password not match")] - PasswordNotMatch = 14, - #[display(fmt = "User name is too long")] - UserNameTooLong = 20, - #[display(fmt = "User name contain forbidden characters")] - UserNameContainForbiddenCharacters = 21, - #[display(fmt = "User name can not be empty or whitespace")] - UserNameIsEmpty = 22, - #[display(fmt = "user id is empty or whitespace")] - UserIdInvalid = 23, - #[display(fmt = "User token is invalid")] - UserUnauthorized = 24, - #[display(fmt = "User not exist")] - UserNotExist = 25, - - #[display(fmt = "Server error")] - ServerError = 99, - - #[display(fmt = "Internal error")] - InternalError = 100, -} - -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::InternalError, - Some(code) => ErrorCode::try_from(&code).unwrap(), - } - } -} - -impl std::default::Default for ErrorCode { - fn default() -> Self { ErrorCode::InternalError } -} diff --git a/shared-lib/flowy-user-infra/src/lib.rs b/shared-lib/flowy-user-infra/src/lib.rs index 3ee07bd886..706b26a74f 100644 --- a/shared-lib/flowy-user-infra/src/lib.rs +++ b/shared-lib/flowy-user-infra/src/lib.rs @@ -1,5 +1,7 @@ pub mod entities; -pub mod errors; pub mod parser; pub mod protobuf; -pub mod user_default; + +pub mod errors { + pub use error_code::ErrorCode; +} diff --git a/shared-lib/flowy-user-infra/src/user_default.rs b/shared-lib/flowy-user-infra/src/user_default.rs deleted file mode 100644 index 8b13789179..0000000000 --- a/shared-lib/flowy-user-infra/src/user_default.rs +++ /dev/null @@ -1 +0,0 @@ - From 84d5d2c2f19e929b91606bdde9f2feadd0bead39 Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 14 Dec 2021 20:50:07 +0800 Subject: [PATCH 28/39] start ws connect after sign up --- .../flowy-net/src/services/mock/ws_mock.rs | 4 +- .../flowy-net/src/services/ws/conn.rs | 3 +- .../flowy-net/src/services/ws/manager.rs | 68 +++++++++++-------- .../flowy-net/src/services/ws/ws_local.rs | 4 +- frontend/rust-lib/flowy-sdk/src/lib.rs | 3 + shared-lib/lib-ws/src/ws.rs | 9 +-- 6 files changed, 56 insertions(+), 35 deletions(-) diff --git a/frontend/rust-lib/flowy-net/src/services/mock/ws_mock.rs b/frontend/rust-lib/flowy-net/src/services/mock/ws_mock.rs index b79b2c8f0b..db1981654a 100644 --- a/frontend/rust-lib/flowy-net/src/services/mock/ws_mock.rs +++ b/frontend/rust-lib/flowy-net/src/services/mock/ws_mock.rs @@ -61,7 +61,9 @@ impl FlowyWebSocket for Arc { FutureResult::new(async { Ok(()) }) } - fn conn_state_subscribe(&self) -> Receiver { self.state_sender.subscribe() } + fn stop_connect(&self) -> FutureResult<(), FlowyError> { FutureResult::new(async { Ok(()) }) } + + fn subscribe_connect_state(&self) -> Receiver { self.state_sender.subscribe() } fn reconnect(&self, _count: usize) -> FutureResult<(), FlowyError> { FutureResult::new(async { Ok(()) }) } diff --git a/frontend/rust-lib/flowy-net/src/services/ws/conn.rs b/frontend/rust-lib/flowy-net/src/services/ws/conn.rs index fc16da07fa..b8faaa273a 100644 --- a/frontend/rust-lib/flowy-net/src/services/ws/conn.rs +++ b/frontend/rust-lib/flowy-net/src/services/ws/conn.rs @@ -7,7 +7,8 @@ pub use lib_ws::{WsConnectState, WsMessage, WsMessageHandler}; pub trait FlowyWebSocket: Send + Sync { fn start_connect(&self, addr: String) -> FutureResult<(), FlowyError>; - fn conn_state_subscribe(&self) -> broadcast::Receiver; + fn stop_connect(&self) -> FutureResult<(), FlowyError>; + fn subscribe_connect_state(&self) -> broadcast::Receiver; fn reconnect(&self, count: usize) -> FutureResult<(), FlowyError>; fn add_handler(&self, handler: Arc) -> Result<(), FlowyError>; fn ws_sender(&self) -> Result, FlowyError>; diff --git a/frontend/rust-lib/flowy-net/src/services/ws/manager.rs b/frontend/rust-lib/flowy-net/src/services/ws/manager.rs index 928f3464e9..d8b1d00e01 100644 --- a/frontend/rust-lib/flowy-net/src/services/ws/manager.rs +++ b/frontend/rust-lib/flowy-net/src/services/ws/manager.rs @@ -23,8 +23,8 @@ impl WsManager { } else { local_web_socket() }; - let (status_notifier, _) = broadcast::channel(10); + listen_on_websocket(ws.clone()); WsManager { inner: ws, connect_type: RwLock::new(NetworkType::default()), @@ -35,11 +35,14 @@ impl WsManager { pub async fn start(&self, token: String) -> Result<(), FlowyError> { let addr = format!("{}/{}", self.addr, token); - self.listen_on_websocket(); + self.inner.stop_connect().await; + let _ = self.inner.start_connect(addr).await?; Ok(()) } + pub async fn stop(&self) { self.inner.stop_connect().await; } + pub fn update_network_type(&self, new_type: &NetworkType) { tracing::debug!("Network new state: {:?}", new_type); let old_type = self.connect_type.read().clone(); @@ -62,33 +65,10 @@ impl WsManager { } } - #[tracing::instrument(level = "debug", skip(self))] - fn listen_on_websocket(&self) { - let mut notify = self.inner.conn_state_subscribe(); - let ws = self.inner.clone(); - let _ = tokio::spawn(async move { - loop { - match notify.recv().await { - Ok(state) => { - tracing::info!("Websocket state changed: {}", state); - match state { - WsConnectState::Init => {}, - WsConnectState::Connected => {}, - WsConnectState::Connecting => {}, - WsConnectState::Disconnected => retry_connect(ws.clone(), 100).await, - } - }, - Err(e) => { - tracing::error!("Websocket state notify error: {:?}", e); - break; - }, - } - } - }); + pub fn subscribe_websocket_state(&self) -> broadcast::Receiver { + self.inner.subscribe_connect_state() } - pub fn subscribe_websocket_state(&self) -> broadcast::Receiver { self.inner.conn_state_subscribe() } - pub fn subscribe_network_ty(&self) -> broadcast::Receiver { self.status_notifier.subscribe() } pub fn add_handler(&self, handler: Arc) -> Result<(), FlowyError> { @@ -99,6 +79,30 @@ impl WsManager { pub fn ws_sender(&self) -> Result, FlowyError> { self.inner.ws_sender() } } +#[tracing::instrument(level = "debug", skip(ws))] +fn listen_on_websocket(ws: Arc) { + let mut notify = ws.subscribe_connect_state(); + let _ = tokio::spawn(async move { + loop { + match notify.recv().await { + Ok(state) => { + tracing::info!("Websocket state changed: {}", state); + match state { + WsConnectState::Init => {}, + WsConnectState::Connected => {}, + WsConnectState::Connecting => {}, + WsConnectState::Disconnected => retry_connect(ws.clone(), 100).await, + } + }, + Err(e) => { + tracing::error!("Websocket state notify error: {:?}", e); + break; + }, + } + } + }); +} + async fn retry_connect(ws: Arc, count: usize) { match ws.reconnect(count).await { Ok(_) => {}, @@ -117,7 +121,15 @@ impl FlowyWebSocket for Arc { }) } - fn conn_state_subscribe(&self) -> Receiver { self.state_subscribe() } + fn stop_connect(&self) -> FutureResult<(), FlowyError> { + let controller = self.clone(); + FutureResult::new(async move { + controller.stop().await; + Ok(()) + }) + } + + fn subscribe_connect_state(&self) -> Receiver { self.subscribe_state() } fn reconnect(&self, count: usize) -> FutureResult<(), FlowyError> { let cloned_ws = self.clone(); diff --git a/frontend/rust-lib/flowy-net/src/services/ws/ws_local.rs b/frontend/rust-lib/flowy-net/src/services/ws/ws_local.rs index 984dee7837..fdace175b8 100644 --- a/frontend/rust-lib/flowy-net/src/services/ws/ws_local.rs +++ b/frontend/rust-lib/flowy-net/src/services/ws/ws_local.rs @@ -22,7 +22,9 @@ impl std::default::Default for LocalWebSocket { impl FlowyWebSocket for Arc { fn start_connect(&self, _addr: String) -> FutureResult<(), FlowyError> { FutureResult::new(async { Ok(()) }) } - fn conn_state_subscribe(&self) -> Receiver { self.state_sender.subscribe() } + fn stop_connect(&self) -> FutureResult<(), FlowyError> { FutureResult::new(async { Ok(()) }) } + + fn subscribe_connect_state(&self) -> Receiver { self.state_sender.subscribe() } fn reconnect(&self, _count: usize) -> FutureResult<(), FlowyError> { FutureResult::new(async { Ok(()) }) } diff --git a/frontend/rust-lib/flowy-sdk/src/lib.rs b/frontend/rust-lib/flowy-sdk/src/lib.rs index 55efc14fa8..68c15436aa 100644 --- a/frontend/rust-lib/flowy-sdk/src/lib.rs +++ b/frontend/rust-lib/flowy-sdk/src/lib.rs @@ -134,12 +134,15 @@ async fn _listen_user_status( }, UserStatus::Logout { .. } => { core.user_did_logout().await; + let _ = ws_manager.stop().await; }, UserStatus::Expired { .. } => { core.user_session_expired().await; + let _ = ws_manager.stop().await; }, UserStatus::SignUp { profile, ret } => { let _ = core.user_did_sign_up(&profile.token).await?; + let _ = ws_manager.start(profile.token.clone()).await?; let _ = ret.send(()); }, } diff --git a/shared-lib/lib-ws/src/ws.rs b/shared-lib/lib-ws/src/ws.rs index 8b1459ba1c..b33870dca9 100644 --- a/shared-lib/lib-ws/src/ws.rs +++ b/shared-lib/lib-ws/src/ws.rs @@ -70,11 +70,12 @@ impl WsController { pub async fn start(&self, addr: String) -> Result<(), ServerError> { *self.addr.write() = Some(addr.clone()); - let strategy = FixedInterval::from_millis(5000).take(3); self.connect(addr, strategy).await } + pub async fn stop(&self) { self.sender_ctrl.write().set_state(WsConnectState::Disconnected); } + async fn connect(&self, addr: String, strategy: T) -> Result<(), ServerError> where T: IntoIterator, @@ -130,7 +131,7 @@ impl WsController { self.connect(addr, strategy).await } - pub fn state_subscribe(&self) -> broadcast::Receiver { self.state_notify.subscribe() } + pub fn subscribe_state(&self) -> broadcast::Receiver { self.state_notify.subscribe() } pub fn sender(&self) -> Result, WsError> { match self.sender_ctrl.read().sender() { @@ -359,8 +360,8 @@ impl WsSenderController { self.sender = None; } - self.state = state.clone(); - let _ = self.state_notify.send(state); + self.state = state; + let _ = self.state_notify.send(self.state.clone()); } fn set_error(&mut self, error: WsError) { From ef6e777ec057c474f7d32ca5d114271a086c430f Mon Sep 17 00:00:00 2001 From: appflowy Date: Wed, 15 Dec 2021 16:28:18 +0800 Subject: [PATCH 29/39] fix warnings --- backend/Cargo.lock | 1 + backend/Cargo.toml | 2 +- backend/src/services/doc/editor.rs | 2 +- backend/tests/document/edit.rs | 2 +- backend/tests/document/helper.rs | 2 +- frontend/rust-lib/flowy-document/Cargo.toml | 3 +- .../rust-lib/flowy-document/src/module.rs | 3 +- .../src/services/doc/controller.rs | 2 +- .../src/services/doc/edit/editor.rs | 17 +++++---- .../src/services/doc/edit/model.rs | 4 +-- .../flowy-document/src/services/doc/mod.rs | 5 +++ .../src/services/doc/revision/cache/cache.rs | 13 +++---- .../src/services/doc/revision/cache/memory.rs | 2 +- .../src/services/doc/revision/manager.rs | 6 ++-- .../src/services/doc/revision/sync.rs | 26 +++++++------- .../src/services/{ws => doc}/ws_manager.rs | 0 .../flowy-document/src/services/mod.rs | 1 - .../flowy-document/src/services/ws/mod.rs | 2 -- .../tests/editor/revision_test.rs | 35 +++++++++++++++++-- frontend/rust-lib/flowy-net/Cargo.toml | 3 +- .../flowy-net/src/services/mock/ws_mock.rs | 28 ++++++++++----- .../flowy-net/src/services/ws/conn.rs | 2 +- .../flowy-net/src/services/ws/manager.rs | 10 +++--- .../flowy-net/src/services/ws/ws_local.rs | 2 +- .../src/deps_resolve/document_deps.rs | 2 +- frontend/rust-lib/flowy-test/Cargo.toml | 1 + frontend/rust-lib/flowy-test/src/editor.rs | 27 +++++++++++--- 27 files changed, 132 insertions(+), 71 deletions(-) rename frontend/rust-lib/flowy-document/src/services/{ws => doc}/ws_manager.rs (100%) delete mode 100644 frontend/rust-lib/flowy-document/src/services/ws/mod.rs diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 6cba8fa609..873027ad1d 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -1423,6 +1423,7 @@ dependencies = [ "flowy-collaboration", "flowy-core", "flowy-document", + "flowy-net", "flowy-sdk", "flowy-user", "futures-util", diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 80db14c2cb..defc585ff0 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -103,5 +103,5 @@ flowy-sdk = { path = "../frontend/rust-lib/flowy-sdk", features = ["http_server" flowy-user = { path = "../frontend/rust-lib/flowy-user", features = ["http_server"] } flowy-document = { path = "../frontend/rust-lib/flowy-document", features = ["flowy_unit_test", "http_server"] } flowy-test = { path = "../frontend/rust-lib/flowy-test" } -flowy-net = { path = "../frontend/rust-lib/flowy-net" } +flowy-net = { path = "../frontend/rust-lib/flowy-net", features = ["http_server"] } diff --git a/backend/src/services/doc/editor.rs b/backend/src/services/doc/editor.rs index 33aac0be76..06b8d8cde2 100644 --- a/backend/src/services/doc/editor.rs +++ b/backend/src/services/doc/editor.rs @@ -59,7 +59,7 @@ impl RevisionUser for ServerDocUser { match result { Ok(_) => {}, - Err(e) => log::error!("{}", e), + Err(e) => log::error!("[ServerDocUser]: {}", e), } } } diff --git a/backend/tests/document/edit.rs b/backend/tests/document/edit.rs index 274cf85579..b6d9e9b49e 100644 --- a/backend/tests/document/edit.rs +++ b/backend/tests/document/edit.rs @@ -197,7 +197,7 @@ async fn delta_sync_while_local_rev_greater_than_server_rev() { DocScript::ClientInsertText(6, "efg"), DocScript::ClientConnectWs, DocScript::AssertClient(r#"[{"insert":"123abcefg\n"}]"#), - // DocScript::AssertServer(r#"[{"insert":"123abcefg\n"}]"#, 3), + DocScript::AssertServer(r#"[{"insert":"123abcefg\n"}]"#, 3), ]) .await; } diff --git a/backend/tests/document/helper.rs b/backend/tests/document/helper.rs index f8df4bbabf..7d68123dd1 100644 --- a/backend/tests/document/helper.rs +++ b/backend/tests/document/helper.rs @@ -123,7 +123,7 @@ async fn run_scripts(context: Arc>, scripts: Vec { - sleep(Duration::from_millis(100)).await; + sleep(Duration::from_millis(2000)).await; let json = context.read().client_edit_context().doc_json().await.unwrap(); assert_eq(s, &json); }, diff --git a/frontend/rust-lib/flowy-document/Cargo.toml b/frontend/rust-lib/flowy-document/Cargo.toml index 6c01690360..0f288b2dc2 100644 --- a/frontend/rust-lib/flowy-document/Cargo.toml +++ b/frontend/rust-lib/flowy-document/Cargo.toml @@ -48,11 +48,12 @@ pin-project = "1.0.0" [dev-dependencies] flowy-test = { path = "../flowy-test" } flowy-document = { path = "../flowy-document", features = ["flowy_unit_test"]} +flowy-net = { path = "../flowy-net", features = ["ws_mock"] } color-eyre = { version = "0.5", default-features = false } criterion = "0.3" rand = "0.7.3" env_logger = "0.8.2" -flowy-net = { path = "../flowy-net", features = ["ws_mock"] } + [features] http_server = [] diff --git a/frontend/rust-lib/flowy-document/src/module.rs b/frontend/rust-lib/flowy-document/src/module.rs index b590b5dc43..4144f3dcb0 100644 --- a/frontend/rust-lib/flowy-document/src/module.rs +++ b/frontend/rust-lib/flowy-document/src/module.rs @@ -1,9 +1,8 @@ use crate::{ errors::FlowyError, services::{ - doc::{controller::DocController, edit::ClientDocEditor}, + doc::{controller::DocController, edit::ClientDocEditor, WsDocumentManager}, server::construct_doc_server, - ws::WsDocumentManager, }, }; use backend_service::configuration::ClientServerConfiguration; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/controller.rs b/frontend/rust-lib/flowy-document/src/services/doc/controller.rs index 0185af24af..5f2886778c 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/controller.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/controller.rs @@ -5,9 +5,9 @@ use crate::{ doc::{ edit::{ClientDocEditor, EditDocWsHandler}, revision::{RevisionCache, RevisionManager, RevisionServer}, + WsDocumentManager, }, server::Server, - ws::WsDocumentManager, }, }; use bytes::Bytes; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs index 673c637c25..7783e2187d 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs @@ -1,12 +1,11 @@ use crate::{ errors::FlowyError, module::DocumentUser, - services::{ - doc::{ - edit::{EditCommand, EditCommandQueue, OpenDocAction, TransformDeltas}, - revision::{RevisionDownStream, RevisionManager, SteamStopTx}, - }, - ws::{DocumentWebSocket, WsDocumentHandler}, + services::doc::{ + edit::{EditCommand, EditCommandQueue, OpenDocAction, TransformDeltas}, + revision::{RevisionDownStream, RevisionManager, SteamStopTx}, + DocumentWebSocket, + WsDocumentHandler, }, }; use bytes::Bytes; @@ -64,7 +63,7 @@ impl ClientDocEditor { stop_sync_tx, }); - // edit_doc.notify_open_doc(); + edit_doc.connect_to_doc(); start_sync(edit_doc.clone(), ws_msg_rx, cloned_stop_sync_tx); Ok(edit_doc) @@ -192,7 +191,7 @@ impl ClientDocEditor { } #[tracing::instrument(level = "debug", skip(self))] - fn notify_open_doc(&self) { + fn connect_to_doc(&self) { let rev_id: RevId = self.rev_manager.rev_id().into(); if let Ok(user_id) = self.user.user_id() { let action = OpenDocAction::new(&user_id, &self.doc_id, &rev_id, &self.ws_sender); @@ -294,7 +293,7 @@ impl WsDocumentHandler for EditDocWsHandler { match state { WsConnectState::Init => {}, WsConnectState::Connecting => {}, - WsConnectState::Connected => self.notify_open_doc(), + WsConnectState::Connected => self.connect_to_doc(), WsConnectState::Disconnected => {}, } } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/model.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/model.rs index 71a6bb195a..12e1d2fc28 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/model.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/model.rs @@ -1,11 +1,11 @@ #![allow(clippy::all)] #![cfg_attr(rustfmt, rustfmt::skip)] -use crate::{errors::FlowyError, services::ws::DocumentWebSocket}; - +use crate::{errors::FlowyError}; use futures::future::BoxFuture; use lib_infra::retry::Action; use lib_ot::revision::RevId; use std::{future, sync::Arc}; +use crate::services::doc::DocumentWebSocket; #[allow(dead_code)] pub(crate) struct OpenDocAction { diff --git a/frontend/rust-lib/flowy-document/src/services/doc/mod.rs b/frontend/rust-lib/flowy-document/src/services/doc/mod.rs index 9b554e2e17..9188a3f339 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/mod.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/mod.rs @@ -2,3 +2,8 @@ pub mod edit; pub mod revision; pub(crate) mod controller; + +mod ws_manager; +pub use ws_manager::*; + +pub const SYNC_INTERVAL_IN_MILLIS: u64 = 500; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs index e4d8bbbe48..c76f300d24 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs @@ -177,15 +177,12 @@ impl RevisionIterator for RevisionCache { let doc_id = self.doc_id.clone(); FutureResult::new(async move { match memory_cache.front_local_revision().await { - None => { - // - match memory_cache.front_local_rev_id().await { + None => match memory_cache.front_local_rev_id().await { + None => Ok(None), + Some(rev_id) => match disk_cache.read_revision(&doc_id, rev_id)? { None => Ok(None), - Some(rev_id) => match disk_cache.read_revision(&doc_id, rev_id)? { - None => Ok(None), - Some(record) => Ok(Some(record)), - }, - } + Some(record) => Ok(Some(record)), + }, }, Some((_, record)) => Ok(Some(record)), } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/memory.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/memory.rs index de33fb9af2..618a20db90 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/memory.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/memory.rs @@ -56,7 +56,7 @@ impl RevisionMemoryCache { } match self.local_revs.write().await.pop_front() { - None => tracing::error!("❌The local_revs should not be empty"), + None => {}, Some(pop_rev_id) => { if &pop_rev_id != rev_id { tracing::error!("The front rev_id:{} not equal to ack rev_id: {}", pop_rev_id, rev_id); diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs index 0ff47cbc2f..cd1852c544 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs @@ -1,8 +1,8 @@ use crate::{ errors::FlowyError, - services::{ - doc::revision::{RevisionCache, RevisionUpStream, SteamStopRx}, - ws::DocumentWebSocket, + services::doc::{ + revision::{RevisionCache, RevisionUpStream, SteamStopRx}, + DocumentWebSocket, }, }; use flowy_collaboration::{entities::doc::Doc, util::RevIdCounter}; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs index f42b8ac28d..fd839ff98a 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs @@ -1,9 +1,8 @@ -use crate::services::{ - doc::{ - edit::ClientDocEditor, - revision::{RevisionIterator, RevisionManager}, - }, - ws::DocumentWebSocket, +use crate::services::doc::{ + edit::ClientDocEditor, + revision::{RevisionIterator, RevisionManager}, + DocumentWebSocket, + SYNC_INTERVAL_IN_MILLIS, }; use async_stream::stream; use bytes::Bytes; @@ -161,7 +160,7 @@ impl RevisionUpStream { .for_each(|msg| async { match self.handle_msg(msg).await { Ok(_) => {}, - Err(e) => log::error!("{:?}", e), + Err(e) => log::error!("[RevisionUpStream]: send msg failed, {:?}", e), } }) .await; @@ -175,23 +174,26 @@ impl RevisionUpStream { async fn send_next_revision(&self) -> FlowyResult<()> { match self.revisions.next().await? { - None => Ok(()), + None => { + tracing::debug!("Finish synchronizing revisions"); + Ok(()) + }, Some(record) => { tracing::debug!( "[RevisionUpStream]: processes revision: {}:{:?}", record.revision.doc_id, record.revision.rev_id ); - let _ = self.ws_sender.send(record.revision.into()).map_err(internal_error); - // let _ = tokio::time::timeout(Duration::from_millis(2000), ret.recv()).await; - Ok(()) + self.ws_sender.send(record.revision.into()).map_err(internal_error) + // let _ = tokio::time::timeout(Duration::from_millis(2000), + // ret.recv()).await; }, } } } async fn tick(sender: mpsc::UnboundedSender) { - let mut i = interval(Duration::from_secs(2)); + let mut i = interval(Duration::from_millis(SYNC_INTERVAL_IN_MILLIS)); while sender.send(UpStreamMsg::Tick).is_ok() { i.tick().await; } diff --git a/frontend/rust-lib/flowy-document/src/services/ws/ws_manager.rs b/frontend/rust-lib/flowy-document/src/services/doc/ws_manager.rs similarity index 100% rename from frontend/rust-lib/flowy-document/src/services/ws/ws_manager.rs rename to frontend/rust-lib/flowy-document/src/services/doc/ws_manager.rs diff --git a/frontend/rust-lib/flowy-document/src/services/mod.rs b/frontend/rust-lib/flowy-document/src/services/mod.rs index a9a801a0b8..82dbce10c4 100644 --- a/frontend/rust-lib/flowy-document/src/services/mod.rs +++ b/frontend/rust-lib/flowy-document/src/services/mod.rs @@ -1,3 +1,2 @@ pub mod doc; pub mod server; -pub mod ws; diff --git a/frontend/rust-lib/flowy-document/src/services/ws/mod.rs b/frontend/rust-lib/flowy-document/src/services/ws/mod.rs deleted file mode 100644 index 1df96efcd7..0000000000 --- a/frontend/rust-lib/flowy-document/src/services/ws/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -mod ws_manager; -pub use ws_manager::*; diff --git a/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs b/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs index 6071795d0c..c4e453c78e 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs @@ -9,7 +9,7 @@ async fn doc_rev_state_test1() { AssertRevisionState(1, RevState::StateLocal), SimulateAckedMessage(1), AssertRevisionState(1, RevState::Acked), - AssertNextSendingRevision(None), + AssertNextRevId(None), AssertJson(r#"[{"insert":"123\n"}]"#), ]; EditorTest::new().await.run_scripts(scripts).await; @@ -27,11 +27,11 @@ async fn doc_rev_state_test2() { AssertRevisionState(3, RevState::StateLocal), SimulateAckedMessage(1), AssertRevisionState(1, RevState::Acked), - AssertNextSendingRevision(Some(2)), + AssertNextRevId(Some(2)), SimulateAckedMessage(2), AssertRevisionState(2, RevState::Acked), // - AssertNextSendingRevision(Some(3)), + AssertNextRevId(Some(3)), AssertRevisionState(3, RevState::StateLocal), AssertJson(r#"[{"insert":"123\n"}]"#), ]; @@ -57,6 +57,35 @@ async fn doc_sync_test() { InsertText("2", 1), InsertText("3", 2), AssertJson(r#"[{"insert":"123\n"}]"#), + AssertNextRevId(None), + ]; + EditorTest::new().await.run_scripts(scripts).await; +} + +#[tokio::test] +async fn doc_sync_lost_ws_conn() { + let scripts = vec![ + InsertText("1", 0), + StopWs, + InsertText("2", 1), + AssertNextRevId(Some(2)), + InsertText("3", 2), + AssertJson(r#"[{"insert":"123\n"}]"#), + ]; + EditorTest::new().await.run_scripts(scripts).await; +} + +#[tokio::test] +async fn doc_sync_retry_ws_conn() { + let scripts = vec![ + InsertText("1", 0), + StopWs, + InsertText("2", 1), + InsertText("3", 2), + StartWs, + WaitSyncFinished, + AssertNextRevId(None), + AssertJson(r#"[{"insert":"123\n"}]"#), ]; EditorTest::new().await.run_scripts(scripts).await; } diff --git a/frontend/rust-lib/flowy-net/Cargo.toml b/frontend/rust-lib/flowy-net/Cargo.toml index c44ac9b67d..24268edc08 100644 --- a/frontend/rust-lib/flowy-net/Cargo.toml +++ b/frontend/rust-lib/flowy-net/Cargo.toml @@ -25,4 +25,5 @@ lazy_static = {version = "1.4.0", optional = true} dashmap = {version = "4.0", optional = true} [features] -ws_mock = ["flowy-collaboration", "lazy_static", "dashmap"] \ No newline at end of file +ws_mock = ["flowy-collaboration", "lazy_static", "dashmap"] +http_server = [] \ No newline at end of file diff --git a/frontend/rust-lib/flowy-net/src/services/mock/ws_mock.rs b/frontend/rust-lib/flowy-net/src/services/mock/ws_mock.rs index db1981654a..419aaf3454 100644 --- a/frontend/rust-lib/flowy-net/src/services/mock/ws_mock.rs +++ b/frontend/rust-lib/flowy-net/src/services/mock/ws_mock.rs @@ -14,6 +14,7 @@ use flowy_collaboration::{ use lazy_static::lazy_static; use lib_infra::future::{FutureResult, FutureResultSend}; use lib_ws::WsModule; +use parking_lot::RwLock; use std::{ convert::{TryFrom, TryInto}, sync::Arc, @@ -24,6 +25,7 @@ pub struct MockWebSocket { handlers: DashMap>, state_sender: broadcast::Sender, ws_sender: broadcast::Sender, + is_stop: RwLock, } impl std::default::Default for MockWebSocket { @@ -34,6 +36,7 @@ impl std::default::Default for MockWebSocket { handlers: DashMap::new(), state_sender, ws_sender, + is_stop: RwLock::new(false), } } } @@ -44,16 +47,22 @@ impl MockWebSocket { impl FlowyWebSocket for Arc { fn start_connect(&self, _addr: String) -> FutureResult<(), FlowyError> { + *self.is_stop.write() = false; + let mut ws_receiver = self.ws_sender.subscribe(); let cloned_ws = self.clone(); tokio::spawn(async move { while let Ok(message) = ws_receiver.recv().await { - let ws_data = WsDocumentData::try_from(Bytes::from(message.data.clone())).unwrap(); - let mut rx = DOC_SERVER.handle_ws_data(ws_data).await; - let new_ws_message = rx.recv().await.unwrap(); - match cloned_ws.handlers.get(&new_ws_message.module) { - None => tracing::error!("Can't find any handler for message: {:?}", new_ws_message), - Some(handler) => handler.receive_message(new_ws_message.clone()), + if *cloned_ws.is_stop.read() { + // do nothing + } else { + let ws_data = WsDocumentData::try_from(Bytes::from(message.data.clone())).unwrap(); + let mut rx = DOC_SERVER.handle_ws_data(ws_data).await; + let new_ws_message = rx.recv().await.unwrap(); + match cloned_ws.handlers.get(&new_ws_message.module) { + None => tracing::error!("Can't find any handler for message: {:?}", new_ws_message), + Some(handler) => handler.receive_message(new_ws_message.clone()), + } } } }); @@ -61,13 +70,16 @@ impl FlowyWebSocket for Arc { FutureResult::new(async { Ok(()) }) } - fn stop_connect(&self) -> FutureResult<(), FlowyError> { FutureResult::new(async { Ok(()) }) } + fn stop_connect(&self) -> FutureResult<(), FlowyError> { + *self.is_stop.write() = true; + FutureResult::new(async { Ok(()) }) + } fn subscribe_connect_state(&self) -> Receiver { self.state_sender.subscribe() } fn reconnect(&self, _count: usize) -> FutureResult<(), FlowyError> { FutureResult::new(async { Ok(()) }) } - fn add_handler(&self, handler: Arc) -> Result<(), FlowyError> { + fn add_ws_message_handler(&self, handler: Arc) -> Result<(), FlowyError> { let source = handler.source(); if self.handlers.contains_key(&source) { tracing::error!("WsSource's {:?} is already registered", source); diff --git a/frontend/rust-lib/flowy-net/src/services/ws/conn.rs b/frontend/rust-lib/flowy-net/src/services/ws/conn.rs index b8faaa273a..0013ea8cbd 100644 --- a/frontend/rust-lib/flowy-net/src/services/ws/conn.rs +++ b/frontend/rust-lib/flowy-net/src/services/ws/conn.rs @@ -10,7 +10,7 @@ pub trait FlowyWebSocket: Send + Sync { fn stop_connect(&self) -> FutureResult<(), FlowyError>; fn subscribe_connect_state(&self) -> broadcast::Receiver; fn reconnect(&self, count: usize) -> FutureResult<(), FlowyError>; - fn add_handler(&self, handler: Arc) -> Result<(), FlowyError>; + fn add_ws_message_handler(&self, handler: Arc) -> Result<(), FlowyError>; fn ws_sender(&self) -> Result, FlowyError>; } diff --git a/frontend/rust-lib/flowy-net/src/services/ws/manager.rs b/frontend/rust-lib/flowy-net/src/services/ws/manager.rs index d8b1d00e01..138e281a95 100644 --- a/frontend/rust-lib/flowy-net/src/services/ws/manager.rs +++ b/frontend/rust-lib/flowy-net/src/services/ws/manager.rs @@ -35,13 +35,13 @@ impl WsManager { pub async fn start(&self, token: String) -> Result<(), FlowyError> { let addr = format!("{}/{}", self.addr, token); - self.inner.stop_connect().await; + self.inner.stop_connect().await?; let _ = self.inner.start_connect(addr).await?; Ok(()) } - pub async fn stop(&self) { self.inner.stop_connect().await; } + pub async fn stop(&self) { let _ = self.inner.stop_connect().await; } pub fn update_network_type(&self, new_type: &NetworkType) { tracing::debug!("Network new state: {:?}", new_type); @@ -72,7 +72,7 @@ impl WsManager { pub fn subscribe_network_ty(&self) -> broadcast::Receiver { self.status_notifier.subscribe() } pub fn add_handler(&self, handler: Arc) -> Result<(), FlowyError> { - let _ = self.inner.add_handler(handler)?; + let _ = self.inner.add_ws_message_handler(handler)?; Ok(()) } @@ -139,8 +139,8 @@ impl FlowyWebSocket for Arc { }) } - fn add_handler(&self, handler: Arc) -> Result<(), FlowyError> { - let _ = self.add_handler(handler)?; + fn add_ws_message_handler(&self, handler: Arc) -> Result<(), FlowyError> { + let _ = self.add_handler(handler).map_err(internal_error)?; Ok(()) } diff --git a/frontend/rust-lib/flowy-net/src/services/ws/ws_local.rs b/frontend/rust-lib/flowy-net/src/services/ws/ws_local.rs index fdace175b8..20d73eb0ef 100644 --- a/frontend/rust-lib/flowy-net/src/services/ws/ws_local.rs +++ b/frontend/rust-lib/flowy-net/src/services/ws/ws_local.rs @@ -28,7 +28,7 @@ impl FlowyWebSocket for Arc { fn reconnect(&self, _count: usize) -> FutureResult<(), FlowyError> { FutureResult::new(async { Ok(()) }) } - fn add_handler(&self, _handler: Arc) -> Result<(), FlowyError> { Ok(()) } + fn add_ws_message_handler(&self, _handler: Arc) -> Result<(), FlowyError> { Ok(()) } fn ws_sender(&self) -> Result, FlowyError> { Ok(Arc::new(self.ws_sender.clone())) } } diff --git a/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs b/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs index b320f13b53..4cf1606b40 100644 --- a/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs +++ b/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs @@ -4,7 +4,7 @@ use flowy_database::ConnectionPool; use flowy_document::{ errors::{internal_error, FlowyError}, module::DocumentUser, - services::ws::{DocumentWebSocket, WsDocumentManager, WsStateReceiver}, + services::doc::{DocumentWebSocket, WsDocumentManager, WsStateReceiver}, }; use flowy_net::services::ws::WsManager; use flowy_user::services::user::UserSession; diff --git a/frontend/rust-lib/flowy-test/Cargo.toml b/frontend/rust-lib/flowy-test/Cargo.toml index f9f9a681da..6f384264ef 100644 --- a/frontend/rust-lib/flowy-test/Cargo.toml +++ b/frontend/rust-lib/flowy-test/Cargo.toml @@ -8,6 +8,7 @@ edition = "2018" [dependencies] flowy-sdk = { path = "../flowy-sdk"} flowy-user = { path = "../flowy-user"} +flowy-net = { path = "../flowy-net"} flowy-core = { path = "../flowy-core", default-features = false} flowy-document = { path = "../flowy-document"} lib-dispatch = { path = "../lib-dispatch" } diff --git a/frontend/rust-lib/flowy-test/src/editor.rs b/frontend/rust-lib/flowy-test/src/editor.rs index c326cb5ce9..66b8c894c9 100644 --- a/frontend/rust-lib/flowy-test/src/editor.rs +++ b/frontend/rust-lib/flowy-test/src/editor.rs @@ -3,7 +3,8 @@ use flowy_collaboration::entities::{ doc::DocIdentifier, ws::{WsDocumentData, WsDocumentDataBuilder}, }; -use flowy_document::services::doc::{edit::ClientDocEditor, revision::RevisionIterator}; +use flowy_document::services::doc::{edit::ClientDocEditor, revision::RevisionIterator, SYNC_INTERVAL_IN_MILLIS}; + use lib_ot::{ core::Interval, revision::{RevState, RevType, Revision, RevisionRange}, @@ -13,16 +14,19 @@ use std::sync::Arc; use tokio::time::{sleep, Duration}; pub enum EditorScript { + StartWs, + StopWs, InsertText(&'static str, usize), Delete(Interval), Replace(Interval, &'static str), Undo(), Redo(), + WaitSyncFinished, SimulatePushRevisionMessageWithDelta(RichTextDelta), SimulatePullRevisionMessage(RevisionRange), SimulateAckedMessage(i64), AssertRevisionState(i64, RevState), - AssertNextSendingRevision(Option), + AssertNextRevId(Option), AssertCurrentRevId(i64), AssertJson(&'static str), } @@ -47,7 +51,7 @@ impl EditorTest { self.run_script(script).await; } - sleep(Duration::from_secs(10)).await; + sleep(Duration::from_secs(5)).await; } async fn run_script(&mut self, script: EditorScript) { @@ -57,11 +61,20 @@ impl EditorTest { let _disk_cache = cache.dish_cache(); let doc_id = self.editor.doc_id.clone(); let user_id = self.sdk.user_session.user_id().unwrap(); + let ws_manager = self.sdk.ws_manager.clone(); + let token = self.sdk.user_session.token().unwrap(); match script { + EditorScript::StartWs => { + ws_manager.start(token.clone()).await.unwrap(); + }, + EditorScript::StopWs => { + sleep(Duration::from_millis(SYNC_INTERVAL_IN_MILLIS)).await; + ws_manager.stop().await; + }, EditorScript::InsertText(s, offset) => { self.editor.insert(offset, s).await.unwrap(); - sleep(Duration::from_millis(200)).await; + sleep(Duration::from_millis(SYNC_INTERVAL_IN_MILLIS)).await; }, EditorScript::Delete(interval) => { self.editor.delete(interval).await.unwrap(); @@ -75,6 +88,9 @@ impl EditorTest { EditorScript::Redo() => { self.editor.redo().await.unwrap(); }, + EditorScript::WaitSyncFinished => { + sleep(Duration::from_millis(1000)).await; + }, EditorScript::AssertRevisionState(rev_id, state) => { let record = cache.query_revision(&doc_id, rev_id).await.unwrap(); assert_eq!(record.state, state); @@ -82,10 +98,11 @@ impl EditorTest { EditorScript::AssertCurrentRevId(rev_id) => { assert_eq!(self.editor.rev_manager().rev_id(), rev_id); }, - EditorScript::AssertNextSendingRevision(rev_id) => { + EditorScript::AssertNextRevId(rev_id) => { let next_revision = cache.next().await.unwrap(); if rev_id.is_none() { assert_eq!(next_revision.is_none(), true); + return; } let next_revision = next_revision.unwrap(); From 511b6658a45d18fb2b731c18ef4ec3c7106292a5 Mon Sep 17 00:00:00 2001 From: appflowy Date: Wed, 15 Dec 2021 23:01:50 +0800 Subject: [PATCH 30/39] md5 for consistency check --- backend/Cargo.lock | 4 +- .../document/{helper.rs => edit_script.rs} | 0 .../tests/document/{edit.rs => edit_test.rs} | 2 +- backend/tests/document/mod.rs | 4 +- frontend/rust-lib/flowy-document/Cargo.toml | 2 +- .../src/services/doc/edit/editor.rs | 71 +++++++++------ .../src/services/doc/edit/queue.rs | 63 ++++++++----- .../src/services/doc/revision/cache/cache.rs | 13 ++- .../src/services/doc/revision/manager.rs | 13 ++- .../flowy-document/tests/editor/mod.rs | 1 - .../tests/editor/revision_test.rs | 91 ------------------- frontend/rust-lib/flowy-test/Cargo.toml | 5 +- .../src/{editor.rs => doc_script.rs} | 67 +++----------- frontend/rust-lib/flowy-test/src/lib.rs | 2 +- frontend/rust-lib/flowy-test/tests/main.rs | 1 + .../flowy-test/tests/revision_test.rs | 44 +++++++++ .../src/core/document/document.rs | 6 ++ .../core/document/extensions/format/mod.rs | 1 - .../extensions/format/resolve_block_format.rs | 5 +- .../format/resolve_inline_format.rs | 3 +- .../src/core/document/extensions/mod.rs | 2 +- .../flowy-derive/src/proto_buf/deserialize.rs | 2 +- shared-lib/lib-ot/src/revision/model.rs | 24 +++-- shared-lib/lib-ot/tests/main.rs | 1 + 24 files changed, 194 insertions(+), 233 deletions(-) rename backend/tests/document/{helper.rs => edit_script.rs} (100%) rename backend/tests/document/{edit.rs => edit_test.rs} (99%) delete mode 100644 frontend/rust-lib/flowy-document/tests/editor/revision_test.rs rename frontend/rust-lib/flowy-test/src/{editor.rs => doc_script.rs} (63%) create mode 100644 frontend/rust-lib/flowy-test/tests/main.rs create mode 100644 frontend/rust-lib/flowy-test/tests/revision_test.rs diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 873027ad1d..45622458a5 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -671,9 +671,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" dependencies = [ "serde", ] diff --git a/backend/tests/document/helper.rs b/backend/tests/document/edit_script.rs similarity index 100% rename from backend/tests/document/helper.rs rename to backend/tests/document/edit_script.rs diff --git a/backend/tests/document/edit.rs b/backend/tests/document/edit_test.rs similarity index 99% rename from backend/tests/document/edit.rs rename to backend/tests/document/edit_test.rs index b6d9e9b49e..cdb36ee94e 100644 --- a/backend/tests/document/edit.rs +++ b/backend/tests/document/edit_test.rs @@ -1,4 +1,4 @@ -use crate::document::helper::{DocScript, DocumentTest}; +use crate::document::edit_script::{DocScript, DocumentTest}; use flowy_collaboration::core::document::{Document, FlowyDoc}; use lib_ot::{core::Interval, rich_text::RichTextAttribute}; diff --git a/backend/tests/document/mod.rs b/backend/tests/document/mod.rs index 4c57cb510a..7ffb40d9b8 100644 --- a/backend/tests/document/mod.rs +++ b/backend/tests/document/mod.rs @@ -1,2 +1,2 @@ -mod edit; -mod helper; +mod edit_script; +mod edit_test; diff --git a/frontend/rust-lib/flowy-document/Cargo.toml b/frontend/rust-lib/flowy-document/Cargo.toml index 0f288b2dc2..bd5c8763d4 100644 --- a/frontend/rust-lib/flowy-document/Cargo.toml +++ b/frontend/rust-lib/flowy-document/Cargo.toml @@ -28,7 +28,7 @@ lazy_static = "1.4.0" log = "0.4.14" tokio = {version = "1", features = ["sync"]} tracing = { version = "0.1", features = ["log"] } -bytes = { version = "1.0" } +bytes = { version = "1.1" } strum = "0.21" strum_macros = "0.21" dashmap = "4.0" diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs index 7783e2187d..00162f1d0a 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs @@ -2,7 +2,7 @@ use crate::{ errors::FlowyError, module::DocumentUser, services::doc::{ - edit::{EditCommand, EditCommandQueue, OpenDocAction, TransformDeltas}, + edit::{DocumentMD5, EditCommand, EditCommandQueue, NewDelta, OpenDocAction, TransformDeltas}, revision::{RevisionDownStream, RevisionManager, SteamStopTx}, DocumentWebSocket, WsDocumentHandler, @@ -70,50 +70,50 @@ impl ClientDocEditor { } pub async fn insert(&self, index: usize, data: T) -> Result<(), FlowyError> { - let (ret, rx) = oneshot::channel::>(); + let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::Insert { index, data: data.to_string(), ret, }; let _ = self.edit_cmd_tx.send(msg); - let delta = rx.await.map_err(internal_error)??; - let _ = self.save_local_delta(delta).await?; + let (delta, md5) = rx.await.map_err(internal_error)??; + let _ = self.save_local_delta(delta, md5).await?; Ok(()) } pub async fn delete(&self, interval: Interval) -> Result<(), FlowyError> { - let (ret, rx) = oneshot::channel::>(); + let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::Delete { interval, ret }; let _ = self.edit_cmd_tx.send(msg); - let delta = rx.await.map_err(internal_error)??; - let _ = self.save_local_delta(delta).await?; + let (delta, md5) = rx.await.map_err(internal_error)??; + let _ = self.save_local_delta(delta, md5).await?; Ok(()) } pub async fn format(&self, interval: Interval, attribute: RichTextAttribute) -> Result<(), FlowyError> { - let (ret, rx) = oneshot::channel::>(); + let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::Format { interval, attribute, ret, }; let _ = self.edit_cmd_tx.send(msg); - let delta = rx.await.map_err(internal_error)??; - let _ = self.save_local_delta(delta).await?; + let (delta, md5) = rx.await.map_err(internal_error)??; + let _ = self.save_local_delta(delta, md5).await?; Ok(()) } pub async fn replace(&self, interval: Interval, data: T) -> Result<(), FlowyError> { - let (ret, rx) = oneshot::channel::>(); + let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::Replace { interval, data: data.to_string(), ret, }; let _ = self.edit_cmd_tx.send(msg); - let delta = rx.await.map_err(internal_error)??; - let _ = self.save_local_delta(delta).await?; + let (delta, md5) = rx.await.map_err(internal_error)??; + let _ = self.save_local_delta(delta, md5).await?; Ok(()) } @@ -148,7 +148,7 @@ impl ClientDocEditor { } pub async fn delta(&self) -> FlowyResult { - let (ret, rx) = oneshot::channel::>(); + let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::ReadDoc { ret }; let _ = self.edit_cmd_tx.send(msg); let data = rx.await.map_err(internal_error)??; @@ -159,12 +159,19 @@ impl ClientDocEditor { }) } - async fn save_local_delta(&self, delta: RichTextDelta) -> Result { + async fn save_local_delta(&self, delta: RichTextDelta, md5: String) -> Result { 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(); let user_id = self.user.user_id()?; - let revision = Revision::new(base_rev_id, rev_id, delta_data, &self.doc_id, RevType::Local, user_id); + let revision = Revision::new( + &self.doc_id, + base_rev_id, + rev_id, + delta_data, + RevType::Local, + &user_id, + md5, + ); let _ = self.rev_manager.add_local_revision(&revision).await?; Ok(rev_id.into()) } @@ -172,15 +179,15 @@ impl ClientDocEditor { #[tracing::instrument(level = "debug", skip(self, data), err)] pub(crate) async fn composing_local_delta(&self, data: Bytes) -> Result<(), FlowyError> { let delta = RichTextDelta::from_bytes(&data)?; - let (ret, rx) = oneshot::channel::>(); + let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::ComposeDelta { delta: delta.clone(), ret, }; let _ = self.edit_cmd_tx.send(msg); - let _ = rx.await.map_err(internal_error)??; + let md5 = rx.await.map_err(internal_error)??; - let _ = self.save_local_delta(delta).await?; + let _ = self.save_local_delta(delta, md5).await?; Ok(()) } @@ -223,40 +230,44 @@ impl ClientDocEditor { } // compose delta - let (ret, rx) = oneshot::channel::>(); + let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::ComposeDelta { delta: client_prime.clone(), ret, }; let _ = self.edit_cmd_tx.send(msg); - let _ = rx.await.map_err(internal_error)??; + let md5 = rx.await.map_err(internal_error)??; // update rev id self.rev_manager .update_rev_id_counter_value(server_rev_id.clone().into()); let (local_base_rev_id, local_rev_id) = self.rev_manager.next_rev_id(); - + let delta_data = client_prime.to_bytes(); // save the revision let user_id = self.user.user_id()?; let revision = Revision::new( + &self.doc_id, local_base_rev_id, local_rev_id, - client_prime.to_bytes().to_vec(), - &self.doc_id, + delta_data, RevType::Remote, - user_id, + &user_id, + md5.clone(), ); + let _ = self.rev_manager.add_remote_revision(&revision).await?; // send the server_prime delta let user_id = self.user.user_id()?; + let delta_data = server_prime.to_bytes(); let revision = Revision::new( + &self.doc_id, local_base_rev_id, local_rev_id, - server_prime.to_bytes().to_vec(), - &self.doc_id, + delta_data, RevType::Remote, - user_id, + &user_id, + md5, ); let _ = self.ws_sender.send(revision.into()); Ok(()) @@ -324,7 +335,7 @@ fn start_sync( #[cfg(feature = "flowy_unit_test")] impl ClientDocEditor { pub async fn doc_json(&self) -> FlowyResult { - let (ret, rx) = oneshot::channel::>(); + let (ret, rx) = oneshot::channel::>(); let msg = EditCommand::ReadDoc { ret }; let _ = self.edit_cmd_tx.send(msg); let s = rx.await.map_err(internal_error)??; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs index df240e8543..faa239dd3f 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs @@ -4,6 +4,7 @@ use flowy_collaboration::{ core::document::{history::UndoResult, Document}, errors::CollaborateError, }; +use flowy_error::FlowyError; use futures::stream::StreamExt; use lib_ot::{ core::{Interval, OperationTransformable}, @@ -41,12 +42,15 @@ impl EditCommandQueue { }; stream .for_each(|msg| async { - self.handle_message(msg).await; + match self.handle_message(msg).await { + Ok(_) => {}, + Err(e) => tracing::debug!("[EditCommandQueue]: {}", e), + } }) .await; } - async fn handle_message(&self, msg: EditCommand) { + async fn handle_message(&self, msg: EditCommand) -> Result<(), FlowyError> { match msg { EditCommand::ComposeDelta { delta, ret } => { let result = self.composed_delta(delta).await; @@ -56,36 +60,48 @@ impl EditCommandQueue { let f = || async { let revision = Revision::try_from(bytes)?; let delta = RichTextDelta::from_bytes(&revision.delta_data)?; - let rev_id: RevId = revision.rev_id.into(); - let (server_prime, client_prime) = self.document.read().await.delta().transform(&delta)?; + let server_rev_id: RevId = revision.rev_id.into(); + let read_guard = self.document.read().await; + let (server_prime, client_prime) = read_guard.delta().transform(&delta)?; + drop(read_guard); + let transform_delta = TransformDeltas { client_prime, server_prime, - server_rev_id: rev_id, + server_rev_id, }; + Ok::(transform_delta) }; let _ = ret.send(f().await); }, EditCommand::Insert { index, data, ret } => { - let delta = self.document.write().await.insert(index, data); - let _ = ret.send(delta); + let mut write_guard = self.document.write().await; + let delta = write_guard.insert(index, data)?; + let md5 = write_guard.md5(); + let _ = ret.send(Ok((delta, md5))); }, EditCommand::Delete { interval, ret } => { - let result = self.document.write().await.delete(interval); - let _ = ret.send(result); + let mut write_guard = self.document.write().await; + let delta = write_guard.delete(interval)?; + let md5 = write_guard.md5(); + let _ = ret.send(Ok((delta, md5))); }, EditCommand::Format { interval, attribute, ret, } => { - let result = self.document.write().await.format(interval, attribute); - let _ = ret.send(result); + let mut write_guard = self.document.write().await; + let delta = write_guard.format(interval, attribute)?; + let md5 = write_guard.md5(); + let _ = ret.send(Ok((delta, md5))); }, EditCommand::Replace { interval, data, ret } => { - let result = self.document.write().await.replace(interval, data); - let _ = ret.send(result); + let mut write_guard = self.document.write().await; + let delta = write_guard.replace(interval, data)?; + let md5 = write_guard.md5(); + let _ = ret.send(Ok((delta, md5))); }, EditCommand::CanUndo { ret } => { let _ = ret.send(self.document.read().await.can_undo()); @@ -110,10 +126,11 @@ impl EditCommandQueue { let _ = ret.send(Ok(delta)); }, } + Ok(()) } #[tracing::instrument(level = "debug", skip(self, delta), fields(compose_result), err)] - async fn composed_delta(&self, delta: RichTextDelta) -> Result<(), CollaborateError> { + async fn composed_delta(&self, delta: RichTextDelta) -> Result { // tracing::debug!("{:?} thread handle_message", thread::current(),); let mut document = self.document.write().await; tracing::Span::current().record( @@ -121,19 +138,23 @@ impl EditCommandQueue { &format!("doc_id:{} - {}", &self.doc_id, delta.to_json()).as_str(), ); - let result = document.compose_delta(delta); + let _ = document.compose_delta(delta)?; + let md5 = document.md5(); drop(document); - result + Ok(md5) } } pub(crate) type Ret = oneshot::Sender>; +pub(crate) type NewDelta = (RichTextDelta, String); +pub(crate) type DocumentMD5 = String; + #[allow(dead_code)] pub(crate) enum EditCommand { ComposeDelta { delta: RichTextDelta, - ret: Ret<()>, + ret: Ret, }, ProcessRemoteRevision { bytes: Bytes, @@ -142,22 +163,22 @@ pub(crate) enum EditCommand { Insert { index: usize, data: String, - ret: Ret, + ret: Ret, }, Delete { interval: Interval, - ret: Ret, + ret: Ret, }, Format { interval: Interval, attribute: RichTextAttribute, - ret: Ret, + ret: Ret, }, Replace { interval: Interval, data: String, - ret: Ret, + ret: Ret, }, CanUndo { ret: oneshot::Sender, diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs index c76f300d24..7e1f787577 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs @@ -7,7 +7,8 @@ use crate::{ }, sql_tables::RevTableSql, }; -use flowy_collaboration::entities::doc::Doc; +use bytes::Bytes; +use flowy_collaboration::{entities::doc::Doc, util::md5}; use flowy_database::ConnectionPool; use flowy_error::{internal_error, FlowyResult}; use lib_infra::future::FutureResult; @@ -155,14 +156,16 @@ impl RevisionCache { // The document doesn't exist in local. Try load from server let doc = self.server.fetch_document(&self.doc_id).await?; - let delta_data = doc.data.as_bytes(); + let delta_data = Bytes::from(doc.data.clone()); + let doc_md5 = md5(&delta_data); let revision = Revision::new( + &doc.id, doc.base_rev_id, doc.rev_id, - delta_data.to_owned(), - &doc.id, + delta_data, RevType::Remote, - self.user_id.clone(), + &self.user_id, + doc_md5, ); self.add_remote_revision(revision).await?; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs index cd1852c544..ebb61687d9 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs @@ -5,7 +5,10 @@ use crate::{ DocumentWebSocket, }, }; -use flowy_collaboration::{entities::doc::Doc, util::RevIdCounter}; +use flowy_collaboration::{ + entities::doc::Doc, + util::{md5, RevIdCounter}, +}; use flowy_error::FlowyResult; use lib_infra::future::FutureResult; use lib_ot::{ @@ -84,13 +87,15 @@ impl RevisionManager { } let delta_data = new_delta.to_bytes(); + let md5 = md5(&delta_data); let revision = Revision::new( + &self.doc_id, range.start, range.end, - delta_data.to_vec(), - &self.doc_id, + delta_data, RevType::Remote, - self.user_id.clone(), + &self.user_id, + md5, ); Ok(revision) diff --git a/frontend/rust-lib/flowy-document/tests/editor/mod.rs b/frontend/rust-lib/flowy-document/tests/editor/mod.rs index 4fe37a1919..a8fa399f9e 100644 --- a/frontend/rust-lib/flowy-document/tests/editor/mod.rs +++ b/frontend/rust-lib/flowy-document/tests/editor/mod.rs @@ -1,7 +1,6 @@ #![allow(clippy::module_inception)] mod attribute_test; mod op_test; -mod revision_test; mod serde_test; mod undo_redo_test; diff --git a/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs b/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs deleted file mode 100644 index c4e453c78e..0000000000 --- a/frontend/rust-lib/flowy-document/tests/editor/revision_test.rs +++ /dev/null @@ -1,91 +0,0 @@ -use flowy_test::editor::{EditorScript::*, *}; -use lib_ot::revision::RevState; - -#[tokio::test] -async fn doc_rev_state_test1() { - let scripts = vec![ - InsertText("123", 0), - AssertCurrentRevId(1), - AssertRevisionState(1, RevState::StateLocal), - SimulateAckedMessage(1), - AssertRevisionState(1, RevState::Acked), - AssertNextRevId(None), - AssertJson(r#"[{"insert":"123\n"}]"#), - ]; - EditorTest::new().await.run_scripts(scripts).await; -} - -#[tokio::test] -async fn doc_rev_state_test2() { - let scripts = vec![ - InsertText("1", 0), - InsertText("2", 1), - InsertText("3", 2), - AssertCurrentRevId(3), - AssertRevisionState(1, RevState::StateLocal), - AssertRevisionState(2, RevState::StateLocal), - AssertRevisionState(3, RevState::StateLocal), - SimulateAckedMessage(1), - AssertRevisionState(1, RevState::Acked), - AssertNextRevId(Some(2)), - SimulateAckedMessage(2), - AssertRevisionState(2, RevState::Acked), - // - AssertNextRevId(Some(3)), - AssertRevisionState(3, RevState::StateLocal), - AssertJson(r#"[{"insert":"123\n"}]"#), - ]; - EditorTest::new().await.run_scripts(scripts).await; -} - -#[tokio::test] -async fn doc_push_test() { - // let delta = RichTextDeltaBuilder::new().insert("abc\n").build(); - let scripts = vec![ - InsertText("1", 0), - InsertText("2", 1), - InsertText("3", 2), - AssertJson(r#"[{"insert":"123\nabc\n"}]"#), - ]; - EditorTest::new().await.run_scripts(scripts).await; -} - -#[tokio::test] -async fn doc_sync_test() { - let scripts = vec![ - InsertText("1", 0), - InsertText("2", 1), - InsertText("3", 2), - AssertJson(r#"[{"insert":"123\n"}]"#), - AssertNextRevId(None), - ]; - EditorTest::new().await.run_scripts(scripts).await; -} - -#[tokio::test] -async fn doc_sync_lost_ws_conn() { - let scripts = vec![ - InsertText("1", 0), - StopWs, - InsertText("2", 1), - AssertNextRevId(Some(2)), - InsertText("3", 2), - AssertJson(r#"[{"insert":"123\n"}]"#), - ]; - EditorTest::new().await.run_scripts(scripts).await; -} - -#[tokio::test] -async fn doc_sync_retry_ws_conn() { - let scripts = vec![ - InsertText("1", 0), - StopWs, - InsertText("2", 1), - InsertText("3", 2), - StartWs, - WaitSyncFinished, - AssertNextRevId(None), - AssertJson(r#"[{"insert":"123\n"}]"#), - ]; - EditorTest::new().await.run_scripts(scripts).await; -} diff --git a/frontend/rust-lib/flowy-test/Cargo.toml b/frontend/rust-lib/flowy-test/Cargo.toml index 6f384264ef..de27fc3f66 100644 --- a/frontend/rust-lib/flowy-test/Cargo.toml +++ b/frontend/rust-lib/flowy-test/Cargo.toml @@ -10,7 +10,7 @@ flowy-sdk = { path = "../flowy-sdk"} flowy-user = { path = "../flowy-user"} flowy-net = { path = "../flowy-net"} flowy-core = { path = "../flowy-core", default-features = false} -flowy-document = { path = "../flowy-document"} +flowy-document = { path = "../flowy-document", features = ["flowy_unit_test"]} lib-dispatch = { path = "../lib-dispatch" } flowy-collaboration = { path = "../../../shared-lib/flowy-collaboration" } @@ -35,4 +35,5 @@ quickcheck_macros = "0.9.1" fake = "~2.3.0" claim = "0.4.0" futures = "0.3.15" -serial_test = "0.5.1" \ No newline at end of file +serial_test = "0.5.1" +flowy-net = { path = "../flowy-net", features = ["ws_mock"] } \ No newline at end of file diff --git a/frontend/rust-lib/flowy-test/src/editor.rs b/frontend/rust-lib/flowy-test/src/doc_script.rs similarity index 63% rename from frontend/rust-lib/flowy-test/src/editor.rs rename to frontend/rust-lib/flowy-test/src/doc_script.rs index 66b8c894c9..f7828f9836 100644 --- a/frontend/rust-lib/flowy-test/src/editor.rs +++ b/frontend/rust-lib/flowy-test/src/doc_script.rs @@ -1,15 +1,7 @@ use crate::{helper::ViewTest, FlowySDKTest}; -use flowy_collaboration::entities::{ - doc::DocIdentifier, - ws::{WsDocumentData, WsDocumentDataBuilder}, -}; +use flowy_collaboration::entities::{doc::DocIdentifier, ws::WsDocumentData}; use flowy_document::services::doc::{edit::ClientDocEditor, revision::RevisionIterator, SYNC_INTERVAL_IN_MILLIS}; - -use lib_ot::{ - core::Interval, - revision::{RevState, RevType, Revision, RevisionRange}, - rich_text::RichTextDelta, -}; +use lib_ot::{core::Interval, revision::RevState, rich_text::RichTextDelta}; use std::sync::Arc; use tokio::time::{sleep, Duration}; @@ -19,16 +11,13 @@ pub enum EditorScript { InsertText(&'static str, usize), Delete(Interval), Replace(Interval, &'static str), - Undo(), - Redo(), - WaitSyncFinished, - SimulatePushRevisionMessageWithDelta(RichTextDelta), - SimulatePullRevisionMessage(RevisionRange), - SimulateAckedMessage(i64), + AssertRevisionState(i64, RevState), AssertNextRevId(Option), AssertCurrentRevId(i64), AssertJson(&'static str), + + WaitSyncFinished, } pub struct EditorTest { @@ -51,7 +40,7 @@ impl EditorTest { self.run_script(script).await; } - sleep(Duration::from_secs(5)).await; + sleep(Duration::from_secs(3)).await; } async fn run_script(&mut self, script: EditorScript) { @@ -60,21 +49,20 @@ impl EditorTest { let _memory_cache = cache.memory_cache(); let _disk_cache = cache.dish_cache(); let doc_id = self.editor.doc_id.clone(); - let user_id = self.sdk.user_session.user_id().unwrap(); + let _user_id = self.sdk.user_session.user_id().unwrap(); let ws_manager = self.sdk.ws_manager.clone(); let token = self.sdk.user_session.token().unwrap(); + let wait_millis = 2 * SYNC_INTERVAL_IN_MILLIS; match script { EditorScript::StartWs => { ws_manager.start(token.clone()).await.unwrap(); }, EditorScript::StopWs => { - sleep(Duration::from_millis(SYNC_INTERVAL_IN_MILLIS)).await; ws_manager.stop().await; }, EditorScript::InsertText(s, offset) => { self.editor.insert(offset, s).await.unwrap(); - sleep(Duration::from_millis(SYNC_INTERVAL_IN_MILLIS)).await; }, EditorScript::Delete(interval) => { self.editor.delete(interval).await.unwrap(); @@ -82,15 +70,6 @@ impl EditorTest { EditorScript::Replace(interval, s) => { self.editor.replace(interval, s).await.unwrap(); }, - EditorScript::Undo() => { - self.editor.undo().await.unwrap(); - }, - EditorScript::Redo() => { - self.editor.redo().await.unwrap(); - }, - EditorScript::WaitSyncFinished => { - sleep(Duration::from_millis(1000)).await; - }, EditorScript::AssertRevisionState(rev_id, state) => { let record = cache.query_revision(&doc_id, rev_id).await.unwrap(); assert_eq!(record.state, state); @@ -108,40 +87,20 @@ impl EditorTest { let next_revision = next_revision.unwrap(); assert_eq!(next_revision.revision.rev_id, rev_id.unwrap()); }, - EditorScript::SimulatePushRevisionMessageWithDelta(delta) => { - let local_base_rev_id = rev_manager.rev_id(); - let local_rev_id = local_base_rev_id + 1; - let revision = Revision::new( - local_base_rev_id, - local_rev_id, - delta.to_bytes().to_vec(), - &doc_id, - RevType::Remote, - user_id, - ); - let data = WsDocumentDataBuilder::build_push_rev_message(&doc_id, revision); - self.send_ws_message(data).await; - }, - EditorScript::SimulatePullRevisionMessage(_range) => {}, - EditorScript::SimulateAckedMessage(i64) => { - let data = WsDocumentDataBuilder::build_acked_message(&doc_id, i64); - self.send_ws_message(data).await; - }, EditorScript::AssertJson(expected) => { let expected_delta: RichTextDelta = serde_json::from_str(expected).unwrap(); let delta = self.editor.doc_delta().await.unwrap(); - if expected_delta != delta { eprintln!("✅ expect: {}", expected,); eprintln!("❌ receive: {}", delta.to_json()); } assert_eq!(expected_delta, delta); }, + EditorScript::WaitSyncFinished => { + // Workaround: just wait two seconds + sleep(Duration::from_millis(2000)).await; + }, } - } - - async fn send_ws_message(&self, data: WsDocumentData) { - self.editor.handle_ws_message(data).await.unwrap(); - sleep(Duration::from_millis(200)).await; + sleep(Duration::from_millis(wait_millis)).await; } } diff --git a/frontend/rust-lib/flowy-test/src/lib.rs b/frontend/rust-lib/flowy-test/src/lib.rs index 5fda18cff1..40e96d8519 100644 --- a/frontend/rust-lib/flowy-test/src/lib.rs +++ b/frontend/rust-lib/flowy-test/src/lib.rs @@ -1,4 +1,4 @@ -pub mod editor; +pub mod doc_script; pub mod event_builder; pub mod helper; diff --git a/frontend/rust-lib/flowy-test/tests/main.rs b/frontend/rust-lib/flowy-test/tests/main.rs new file mode 100644 index 0000000000..3eb8b414b2 --- /dev/null +++ b/frontend/rust-lib/flowy-test/tests/main.rs @@ -0,0 +1 @@ +mod revision_test; diff --git a/frontend/rust-lib/flowy-test/tests/revision_test.rs b/frontend/rust-lib/flowy-test/tests/revision_test.rs new file mode 100644 index 0000000000..fec5203aab --- /dev/null +++ b/frontend/rust-lib/flowy-test/tests/revision_test.rs @@ -0,0 +1,44 @@ +use flowy_test::doc_script::{EditorScript::*, *}; +use lib_ot::revision::RevState; + +#[tokio::test] +async fn doc_sync_test() { + let scripts = vec![ + InsertText("1", 0), + InsertText("2", 1), + InsertText("3", 2), + AssertJson(r#"[{"insert":"123\n"}]"#), + AssertNextRevId(None), + ]; + EditorTest::new().await.run_scripts(scripts).await; +} + +#[tokio::test] +async fn doc_sync_lost_ws_conn() { + let scripts = vec![ + InsertText("1", 0), + StopWs, + InsertText("2", 1), + InsertText("3", 2), + AssertNextRevId(Some(2)), + AssertJson(r#"[{"insert":"123\n"}]"#), + ]; + EditorTest::new().await.run_scripts(scripts).await; +} + +#[tokio::test] +async fn doc_sync_retry_ws_conn() { + let scripts = vec![ + InsertText("1", 0), + StopWs, + InsertText("2", 1), + InsertText("3", 2), + StartWs, + WaitSyncFinished, + AssertRevisionState(2, RevState::Acked), + AssertRevisionState(3, RevState::Acked), + AssertNextRevId(None), + AssertJson(r#"[{"insert":"123\n"}]"#), + ]; + EditorTest::new().await.run_scripts(scripts).await; +} diff --git a/shared-lib/flowy-collaboration/src/core/document/document.rs b/shared-lib/flowy-collaboration/src/core/document/document.rs index 861f9bed24..67a62952d2 100644 --- a/shared-lib/flowy-collaboration/src/core/document/document.rs +++ b/shared-lib/flowy-collaboration/src/core/document/document.rs @@ -62,6 +62,12 @@ impl Document { pub fn delta(&self) -> &RichTextDelta { &self.delta } + pub fn md5(&self) -> String { + // Opti: calculate the md5 of delta would cause performance issues + let bytes = self.to_bytes(); + format!("{:x}", md5::compute(bytes)) + } + pub fn set_notify(&mut self, notify: mpsc::UnboundedSender<()>) { self.notify = Some(notify); } pub fn set_delta(&mut self, data: RichTextDelta) { diff --git a/shared-lib/flowy-collaboration/src/core/document/extensions/format/mod.rs b/shared-lib/flowy-collaboration/src/core/document/extensions/format/mod.rs index 513320c335..52df2dd8b9 100644 --- a/shared-lib/flowy-collaboration/src/core/document/extensions/format/mod.rs +++ b/shared-lib/flowy-collaboration/src/core/document/extensions/format/mod.rs @@ -5,4 +5,3 @@ pub use resolve_inline_format::*; mod format_at_position; mod resolve_block_format; mod resolve_inline_format; - diff --git a/shared-lib/flowy-collaboration/src/core/document/extensions/format/resolve_block_format.rs b/shared-lib/flowy-collaboration/src/core/document/extensions/format/resolve_block_format.rs index 30c4bbb481..4649e9fd41 100644 --- a/shared-lib/flowy-collaboration/src/core/document/extensions/format/resolve_block_format.rs +++ b/shared-lib/flowy-collaboration/src/core/document/extensions/format/resolve_block_format.rs @@ -1,13 +1,12 @@ use lib_ot::{ core::{DeltaBuilder, DeltaIter, Interval}, - rich_text::{AttributeScope, plain_attributes, RichTextAttribute, RichTextDelta}, + rich_text::{plain_attributes, AttributeScope, RichTextAttribute, RichTextDelta}, }; use crate::{ - core::document::FormatExt, + core::document::{extensions::helper::line_break, FormatExt}, util::find_newline, }; -use crate::core::document::extensions::helper::line_break; pub struct ResolveBlockFormat {} impl FormatExt for ResolveBlockFormat { diff --git a/shared-lib/flowy-collaboration/src/core/document/extensions/format/resolve_inline_format.rs b/shared-lib/flowy-collaboration/src/core/document/extensions/format/resolve_inline_format.rs index 827b3753d1..c953c0ee75 100644 --- a/shared-lib/flowy-collaboration/src/core/document/extensions/format/resolve_inline_format.rs +++ b/shared-lib/flowy-collaboration/src/core/document/extensions/format/resolve_inline_format.rs @@ -4,10 +4,9 @@ use lib_ot::{ }; use crate::{ - core::document::FormatExt, + core::document::{extensions::helper::line_break, FormatExt}, util::find_newline, }; -use crate::core::document::extensions::helper::line_break; pub struct ResolveInlineFormat {} impl FormatExt for ResolveInlineFormat { diff --git a/shared-lib/flowy-collaboration/src/core/document/extensions/mod.rs b/shared-lib/flowy-collaboration/src/core/document/extensions/mod.rs index 82360ebb53..d24e78fab1 100644 --- a/shared-lib/flowy-collaboration/src/core/document/extensions/mod.rs +++ b/shared-lib/flowy-collaboration/src/core/document/extensions/mod.rs @@ -8,8 +8,8 @@ use lib_ot::{ mod delete; mod format; -mod insert; mod helper; +mod insert; pub type InsertExtension = Box; pub type FormatExtension = Box; diff --git a/shared-lib/flowy-derive/src/proto_buf/deserialize.rs b/shared-lib/flowy-derive/src/proto_buf/deserialize.rs index 775670b6bc..15c53c149d 100644 --- a/shared-lib/flowy-derive/src/proto_buf/deserialize.rs +++ b/shared-lib/flowy-derive/src/proto_buf/deserialize.rs @@ -52,7 +52,7 @@ fn token_stream_for_one_of(ctxt: &Ctxt, field: &ASTField) -> Option Err(e) => { eprintln!("token_stream_for_one_of failed: {:?} with error: {}", member, e); panic!(); - } + }, }?; let bracketed_ty_info = ty_info.bracket_ty_info.as_ref().as_ref(); diff --git a/shared-lib/lib-ot/src/revision/model.rs b/shared-lib/lib-ot/src/revision/model.rs index d4d1ea9ee7..2b7b55cc58 100644 --- a/shared-lib/lib-ot/src/revision/model.rs +++ b/shared-lib/lib-ot/src/revision/model.rs @@ -1,4 +1,5 @@ use crate::rich_text::RichTextDelta; +use bytes::Bytes; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use std::{fmt::Formatter, ops::RangeInclusive}; @@ -52,17 +53,20 @@ impl std::fmt::Debug for Revision { } impl Revision { - pub fn new(base_rev_id: T1, rev_id: T2, delta: D, doc_id: &str, ty: RevType, user_id: String) -> Revision - where - T1: Into, - T2: Into, - D: AsRef<[u8]>, - { - let md5 = md5(&delta); + pub fn new( + doc_id: &str, + base_rev_id: i64, + rev_id: i64, + delta_data: Bytes, + ty: RevType, + user_id: &str, + md5: String, + ) -> Revision { let doc_id = doc_id.to_owned(); - let delta_data = delta.as_ref().to_vec(); - let base_rev_id = base_rev_id.into(); - let rev_id = rev_id.into(); + let delta_data = delta_data.to_vec(); + let base_rev_id = base_rev_id; + let rev_id = rev_id; + let user_id = user_id.to_owned(); if base_rev_id != 0 { debug_assert!(base_rev_id != rev_id); diff --git a/shared-lib/lib-ot/tests/main.rs b/shared-lib/lib-ot/tests/main.rs index e69de29bb2..8b13789179 100644 --- a/shared-lib/lib-ot/tests/main.rs +++ b/shared-lib/lib-ot/tests/main.rs @@ -0,0 +1 @@ + From 4a46bf3fa30fa4caed54b2d748ea7c15d1d797e7 Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 16 Dec 2021 21:31:36 +0800 Subject: [PATCH 31/39] refcator web socket message sent logic --- backend/src/services/doc/ws_actor.rs | 10 +- .../protobuf/flowy-collaboration/ws.pb.dart | 84 ++++- .../flowy-collaboration/ws.pbenum.dart | 20 +- .../flowy-collaboration/ws.pbjson.dart | 28 +- frontend/rust-lib/flowy-document/Cargo.toml | 2 +- .../rust-lib/flowy-document/src/module.rs | 4 +- .../src/services/doc/controller.rs | 43 +-- .../src/services/doc/edit/editor.rs | 289 +++++++-------- .../src/services/doc/edit/mod.rs | 7 +- .../src/services/doc/edit/model.rs | 1 + .../src/services/doc/edit/queue.rs | 207 ----------- .../flowy-document/src/services/doc/mod.rs | 6 +- .../src/services/doc/revision/cache/cache.rs | 12 +- .../src/services/doc/revision/manager.rs | 22 +- .../src/services/doc/revision/mod.rs | 2 - .../src/services/doc/revision/sync.rs | 200 ---------- .../src/services/doc/ws_manager.rs | 67 ---- frontend/rust-lib/flowy-net/Cargo.toml | 2 +- .../flowy-net/src/services/mock/ws_mock.rs | 16 +- .../rust-lib/flowy-net/src/services/mod.rs | 2 +- .../flowy-net/src/services/ws/conn.rs | 4 +- .../flowy-net/src/services/ws/manager.rs | 10 +- .../rust-lib/flowy-net/src/services/ws/mod.rs | 4 +- .../flowy-net/src/services/ws/ws_local.rs | 4 +- .../src/deps_resolve/document_deps.rs | 26 +- frontend/rust-lib/flowy-test/Cargo.toml | 2 +- .../rust-lib/flowy-test/src/doc_script.rs | 9 +- .../src/core/sync/synchronizer.rs | 8 +- .../flowy-collaboration/src/entities/ws/ws.rs | 44 ++- .../src/protobuf/model/ws.rs | 350 +++++++++++++++--- .../src/protobuf/proto/ws.proto | 11 +- .../src/derive_cache/derive_cache.rs | 3 +- shared-lib/lib-ot/src/revision/model.rs | 9 +- shared-lib/lib-ws/src/ws.rs | 6 +- 34 files changed, 676 insertions(+), 838 deletions(-) delete mode 100644 frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs delete mode 100644 frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs delete mode 100644 frontend/rust-lib/flowy-document/src/services/doc/ws_manager.rs diff --git a/backend/src/services/doc/ws_actor.rs b/backend/src/services/doc/ws_actor.rs index df93edaba5..10d5c3984f 100644 --- a/backend/src/services/doc/ws_actor.rs +++ b/backend/src/services/doc/ws_actor.rs @@ -11,7 +11,7 @@ use async_stream::stream; use backend_service::errors::{internal_error, Result, ServerError}; use flowy_collaboration::{ core::sync::ServerDocManager, - protobuf::{WsDataType, WsDocumentData}, + protobuf::{WsDocumentData, WsDocumentDataType}, }; use futures::stream::StreamExt; use lib_ot::protobuf::Revision; @@ -78,10 +78,10 @@ impl DocWsActor { let data = document_data.data; match document_data.ty { - WsDataType::Acked => Ok(()), - WsDataType::PushRev => self.apply_pushed_rev(user, socket, data, pool).await, - WsDataType::PullRev => Ok(()), - WsDataType::Conflict => Ok(()), + WsDocumentDataType::Acked => Ok(()), + WsDocumentDataType::PushRev => self.apply_pushed_rev(user, socket, data, pool).await, + WsDocumentDataType::PullRev => Ok(()), + WsDocumentDataType::UserConnect => Ok(()), } } diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pb.dart index e3192816ff..df1ef65a13 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pb.dart @@ -7,6 +7,7 @@ import 'dart:core' as $core; +import 'package:fixnum/fixnum.dart' as $fixnum; import 'package:protobuf/protobuf.dart' as $pb; import 'ws.pbenum.dart'; @@ -16,7 +17,7 @@ export 'ws.pbenum.dart'; class WsDocumentData extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'WsDocumentData', createEmptyInstance: create) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'docId') - ..e(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'ty', $pb.PbFieldType.OE, defaultOrMaker: WsDataType.Acked, valueOf: WsDataType.valueOf, enumValues: WsDataType.values) + ..e(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'ty', $pb.PbFieldType.OE, defaultOrMaker: WsDocumentDataType.Acked, valueOf: WsDocumentDataType.valueOf, enumValues: WsDocumentDataType.values) ..a<$core.List<$core.int>>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data', $pb.PbFieldType.OY) ..hasRequiredFields = false ; @@ -24,7 +25,7 @@ class WsDocumentData extends $pb.GeneratedMessage { WsDocumentData._() : super(); factory WsDocumentData({ $core.String? docId, - WsDataType? ty, + WsDocumentDataType? ty, $core.List<$core.int>? data, }) { final _result = create(); @@ -70,9 +71,9 @@ class WsDocumentData extends $pb.GeneratedMessage { void clearDocId() => clearField(1); @$pb.TagNumber(2) - WsDataType get ty => $_getN(1); + WsDocumentDataType get ty => $_getN(1); @$pb.TagNumber(2) - set ty(WsDataType v) { setField(2, v); } + set ty(WsDocumentDataType v) { setField(2, v); } @$pb.TagNumber(2) $core.bool hasTy() => $_has(1); @$pb.TagNumber(2) @@ -88,3 +89,78 @@ class WsDocumentData extends $pb.GeneratedMessage { void clearData() => clearField(3); } +class DocumentConnected extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DocumentConnected', createEmptyInstance: create) + ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'userId') + ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'docId') + ..aInt64(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'revId') + ..hasRequiredFields = false + ; + + DocumentConnected._() : super(); + factory DocumentConnected({ + $core.String? userId, + $core.String? docId, + $fixnum.Int64? revId, + }) { + final _result = create(); + if (userId != null) { + _result.userId = userId; + } + if (docId != null) { + _result.docId = docId; + } + if (revId != null) { + _result.revId = revId; + } + return _result; + } + factory DocumentConnected.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory DocumentConnected.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + DocumentConnected clone() => DocumentConnected()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + DocumentConnected copyWith(void Function(DocumentConnected) updates) => super.copyWith((message) => updates(message as DocumentConnected)) as DocumentConnected; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static DocumentConnected create() => DocumentConnected._(); + DocumentConnected createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static DocumentConnected getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static DocumentConnected? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get userId => $_getSZ(0); + @$pb.TagNumber(1) + set userId($core.String v) { $_setString(0, v); } + @$pb.TagNumber(1) + $core.bool hasUserId() => $_has(0); + @$pb.TagNumber(1) + void clearUserId() => clearField(1); + + @$pb.TagNumber(2) + $core.String get docId => $_getSZ(1); + @$pb.TagNumber(2) + set docId($core.String v) { $_setString(1, v); } + @$pb.TagNumber(2) + $core.bool hasDocId() => $_has(1); + @$pb.TagNumber(2) + void clearDocId() => clearField(2); + + @$pb.TagNumber(3) + $fixnum.Int64 get revId => $_getI64(2); + @$pb.TagNumber(3) + set revId($fixnum.Int64 v) { $_setInt64(2, v); } + @$pb.TagNumber(3) + $core.bool hasRevId() => $_has(2); + @$pb.TagNumber(3) + void clearRevId() => clearField(3); +} + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbenum.dart index 31f54d22ea..b11c8b7fa1 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbenum.dart @@ -9,22 +9,22 @@ import 'dart:core' as $core; import 'package:protobuf/protobuf.dart' as $pb; -class WsDataType extends $pb.ProtobufEnum { - static const WsDataType Acked = WsDataType._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Acked'); - static const WsDataType PushRev = WsDataType._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PushRev'); - static const WsDataType PullRev = WsDataType._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PullRev'); - static const WsDataType Conflict = WsDataType._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Conflict'); +class WsDocumentDataType extends $pb.ProtobufEnum { + static const WsDocumentDataType Acked = WsDocumentDataType._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Acked'); + static const WsDocumentDataType PushRev = WsDocumentDataType._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PushRev'); + static const WsDocumentDataType PullRev = WsDocumentDataType._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PullRev'); + static const WsDocumentDataType UserConnect = WsDocumentDataType._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserConnect'); - static const $core.List values = [ + static const $core.List values = [ Acked, PushRev, PullRev, - Conflict, + UserConnect, ]; - static final $core.Map<$core.int, WsDataType> _byValue = $pb.ProtobufEnum.initByValue(values); - static WsDataType? valueOf($core.int value) => _byValue[value]; + static final $core.Map<$core.int, WsDocumentDataType> _byValue = $pb.ProtobufEnum.initByValue(values); + static WsDocumentDataType? valueOf($core.int value) => _byValue[value]; - const WsDataType._($core.int v, $core.String n) : super(v, n); + const WsDocumentDataType._($core.int v, $core.String n) : super(v, n); } diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbjson.dart index 50bc4f4d5b..9917157067 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbjson.dart @@ -8,28 +8,40 @@ import 'dart:core' as $core; import 'dart:convert' as $convert; import 'dart:typed_data' as $typed_data; -@$core.Deprecated('Use wsDataTypeDescriptor instead') -const WsDataType$json = const { - '1': 'WsDataType', +@$core.Deprecated('Use wsDocumentDataTypeDescriptor instead') +const WsDocumentDataType$json = const { + '1': 'WsDocumentDataType', '2': const [ const {'1': 'Acked', '2': 0}, const {'1': 'PushRev', '2': 1}, const {'1': 'PullRev', '2': 2}, - const {'1': 'Conflict', '2': 3}, + const {'1': 'UserConnect', '2': 3}, ], }; -/// Descriptor for `WsDataType`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List wsDataTypeDescriptor = $convert.base64Decode('CgpXc0RhdGFUeXBlEgkKBUFja2VkEAASCwoHUHVzaFJldhABEgsKB1B1bGxSZXYQAhIMCghDb25mbGljdBAD'); +/// Descriptor for `WsDocumentDataType`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List wsDocumentDataTypeDescriptor = $convert.base64Decode('ChJXc0RvY3VtZW50RGF0YVR5cGUSCQoFQWNrZWQQABILCgdQdXNoUmV2EAESCwoHUHVsbFJldhACEg8KC1VzZXJDb25uZWN0EAM='); @$core.Deprecated('Use wsDocumentDataDescriptor instead') const WsDocumentData$json = const { '1': 'WsDocumentData', '2': const [ const {'1': 'doc_id', '3': 1, '4': 1, '5': 9, '10': 'docId'}, - const {'1': 'ty', '3': 2, '4': 1, '5': 14, '6': '.WsDataType', '10': 'ty'}, + const {'1': 'ty', '3': 2, '4': 1, '5': 14, '6': '.WsDocumentDataType', '10': 'ty'}, const {'1': 'data', '3': 3, '4': 1, '5': 12, '10': 'data'}, ], }; /// Descriptor for `WsDocumentData`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List wsDocumentDataDescriptor = $convert.base64Decode('Cg5Xc0RvY3VtZW50RGF0YRIVCgZkb2NfaWQYASABKAlSBWRvY0lkEhsKAnR5GAIgASgOMgsuV3NEYXRhVHlwZVICdHkSEgoEZGF0YRgDIAEoDFIEZGF0YQ=='); +final $typed_data.Uint8List wsDocumentDataDescriptor = $convert.base64Decode('Cg5Xc0RvY3VtZW50RGF0YRIVCgZkb2NfaWQYASABKAlSBWRvY0lkEiMKAnR5GAIgASgOMhMuV3NEb2N1bWVudERhdGFUeXBlUgJ0eRISCgRkYXRhGAMgASgMUgRkYXRh'); +@$core.Deprecated('Use documentConnectedDescriptor instead') +const DocumentConnected$json = const { + '1': 'DocumentConnected', + '2': const [ + const {'1': 'user_id', '3': 1, '4': 1, '5': 9, '10': 'userId'}, + const {'1': 'doc_id', '3': 2, '4': 1, '5': 9, '10': 'docId'}, + const {'1': 'rev_id', '3': 3, '4': 1, '5': 3, '10': 'revId'}, + ], +}; + +/// Descriptor for `DocumentConnected`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List documentConnectedDescriptor = $convert.base64Decode('ChFEb2N1bWVudENvbm5lY3RlZBIXCgd1c2VyX2lkGAEgASgJUgZ1c2VySWQSFQoGZG9jX2lkGAIgASgJUgVkb2NJZBIVCgZyZXZfaWQYAyABKANSBXJldklk'); diff --git a/frontend/rust-lib/flowy-document/Cargo.toml b/frontend/rust-lib/flowy-document/Cargo.toml index bd5c8763d4..4760e93343 100644 --- a/frontend/rust-lib/flowy-document/Cargo.toml +++ b/frontend/rust-lib/flowy-document/Cargo.toml @@ -48,7 +48,7 @@ pin-project = "1.0.0" [dev-dependencies] flowy-test = { path = "../flowy-test" } flowy-document = { path = "../flowy-document", features = ["flowy_unit_test"]} -flowy-net = { path = "../flowy-net", features = ["ws_mock"] } +flowy-net = { path = "../flowy-net", features = ["flowy_unit_test"] } color-eyre = { version = "0.5", default-features = false } criterion = "0.3" rand = "0.7.3" diff --git a/frontend/rust-lib/flowy-document/src/module.rs b/frontend/rust-lib/flowy-document/src/module.rs index 4144f3dcb0..865f09111a 100644 --- a/frontend/rust-lib/flowy-document/src/module.rs +++ b/frontend/rust-lib/flowy-document/src/module.rs @@ -1,7 +1,7 @@ use crate::{ errors::FlowyError, services::{ - doc::{controller::DocController, edit::ClientDocEditor, WsDocumentManager}, + doc::{controller::DocController, edit::ClientDocEditor, DocumentWsHandlers}, server::construct_doc_server, }, }; @@ -25,7 +25,7 @@ pub struct FlowyDocument { impl FlowyDocument { pub fn new( user: Arc, - ws_manager: Arc, + ws_manager: Arc, server_config: &ClientServerConfiguration, ) -> FlowyDocument { let server = construct_doc_server(server_config); diff --git a/frontend/rust-lib/flowy-document/src/services/doc/controller.rs b/frontend/rust-lib/flowy-document/src/services/doc/controller.rs index 5f2886778c..12813a1daf 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/controller.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/controller.rs @@ -3,9 +3,9 @@ use crate::{ module::DocumentUser, services::{ doc::{ - edit::{ClientDocEditor, EditDocWsHandler}, + edit::ClientDocEditor, revision::{RevisionCache, RevisionManager, RevisionServer}, - WsDocumentManager, + DocumentWsHandlers, }, server::Server, }, @@ -20,24 +20,19 @@ use std::sync::Arc; pub(crate) struct DocController { server: Server, - ws_manager: Arc, + ws_handlers: Arc, open_cache: Arc, user: Arc, } impl DocController { - pub(crate) fn new(server: Server, user: Arc, ws: Arc) -> Self { + pub(crate) fn new(server: Server, user: Arc, ws_handlers: Arc) -> Self { let open_cache = Arc::new(OpenDocCache::new()); - Self { - server, - user, - ws_manager: ws, - open_cache, - } + Self { server, ws_handlers, open_cache, user } } pub(crate) fn init(&self) -> FlowyResult<()> { - self.ws_manager.init(); + self.ws_handlers.init(); Ok(()) } @@ -58,7 +53,7 @@ impl DocController { 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); + self.ws_handlers.remove_handler(doc_id); Ok(()) } @@ -66,7 +61,7 @@ impl DocController { 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); + self.ws_handlers.remove_handler(doc_id); Ok(()) } @@ -99,18 +94,17 @@ impl DocController { ) -> Result, 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?; - let ws_handler = Arc::new(EditDocWsHandler(edit_ctx.clone())); - self.ws_manager.register_handler(doc_id, ws_handler); - self.open_cache.set(edit_ctx.clone()); - Ok(edit_ctx) + let doc_editor = ClientDocEditor::new(doc_id, user, pool, rev_manager, self.ws_handlers.ws()).await?; + let ws_handler = doc_editor.ws_handler(); + self.ws_handlers.register_handler(doc_id, ws_handler); + self.open_cache.insert(&doc_id, &doc_editor); + Ok(doc_editor) } fn make_rev_manager(&self, doc_id: &str, pool: Arc) -> Result { // 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?; - let ws_sender = self.ws_manager.ws(); let token = self.user.token()?; let user_id = self.user.user_id()?; let server = Arc::new(RevisionServerImpl { @@ -118,7 +112,7 @@ impl DocController { server: self.server.clone(), }); let cache = Arc::new(RevisionCache::new(&user_id, doc_id, pool, server)); - Ok(RevisionManager::new(&user_id, doc_id, cache, ws_sender)) + Ok(RevisionManager::new(&user_id, doc_id, cache)) } } @@ -152,12 +146,11 @@ pub struct OpenDocCache { impl OpenDocCache { fn new() -> Self { Self { inner: DashMap::new() } } - pub(crate) fn set(&self, doc: Arc) { - let doc_id = doc.doc_id.clone(); - if self.inner.contains_key(&doc_id) { - log::warn!("Doc:{} already exists in cache", &doc_id); + pub(crate) fn insert(&self, doc_id: &str, doc: &Arc) { + if self.inner.contains_key(doc_id) { + log::warn!("Doc:{} already exists in cache", doc_id); } - self.inner.insert(doc_id, doc); + self.inner.insert(doc_id.to_string(), doc.clone()); } pub(crate) fn contains(&self, doc_id: &str) -> bool { self.inner.get(doc_id).is_some() } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs index 00162f1d0a..7b23582b99 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs @@ -1,13 +1,4 @@ -use crate::{ - errors::FlowyError, - module::DocumentUser, - services::doc::{ - edit::{DocumentMD5, EditCommand, EditCommandQueue, NewDelta, OpenDocAction, TransformDeltas}, - revision::{RevisionDownStream, RevisionManager, SteamStopTx}, - DocumentWebSocket, - WsDocumentHandler, - }, -}; +use crate::{errors::FlowyError, module::DocumentUser, services::doc::*}; use bytes::Bytes; use flowy_collaboration::{ core::document::history::UndoResult, @@ -16,13 +7,12 @@ use flowy_collaboration::{ }; use flowy_database::ConnectionPool; use flowy_error::{internal_error, FlowyResult}; -use lib_infra::retry::{ExponentialBackoff, Retry}; +use lib_infra::future::FutureResult; use lib_ot::{ core::Interval, - revision::{RevId, RevType, Revision}, + revision::{RevId, RevType, Revision, RevisionRange}, rich_text::{RichTextAttribute, RichTextDelta}, }; -use lib_ws::WsConnectState; use std::sync::Arc; use tokio::sync::{mpsc, mpsc::UnboundedSender, oneshot}; @@ -31,11 +21,9 @@ pub type DocId = String; pub struct ClientDocEditor { pub doc_id: DocId, rev_manager: Arc, + ws_manager: Arc, edit_cmd_tx: UnboundedSender, - ws_sender: Arc, user: Arc, - ws_msg_tx: UnboundedSender, - stop_sync_tx: tokio::sync::broadcast::Sender<()>, } impl ClientDocEditor { @@ -44,29 +32,31 @@ impl ClientDocEditor { user: Arc, pool: Arc, mut rev_manager: RevisionManager, - ws_sender: Arc, + ws: Arc, ) -> FlowyResult> { 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(); let rev_manager = Arc::new(rev_manager); - let (ws_msg_tx, ws_msg_rx) = mpsc::unbounded_channel(); - let (stop_sync_tx, _) = tokio::sync::broadcast::channel(2); - let cloned_stop_sync_tx = stop_sync_tx.clone(); - let edit_doc = Arc::new(Self { + + let data_provider = Arc::new(DocumentSinkDataProviderAdapter { + rev_manager: rev_manager.clone(), + }); + let stream_consumer = Arc::new(DocumentWebSocketSteamConsumerAdapter { + doc_id: doc_id.clone(), + edit_cmd_tx: edit_cmd_tx.clone(), + rev_manager: rev_manager.clone(), + user: user.clone(), + }); + let ws_manager = Arc::new(WebSocketManager::new(&doc_id, ws, data_provider, stream_consumer)); + let editor = Arc::new(Self { doc_id, rev_manager, + ws_manager, edit_cmd_tx, - ws_sender, user, - ws_msg_tx, - stop_sync_tx, }); - - edit_doc.connect_to_doc(); - - start_sync(edit_doc.clone(), ws_msg_rx, cloned_stop_sync_tx); - Ok(edit_doc) + Ok(editor) } pub async fn insert(&self, index: usize, data: T) -> Result<(), FlowyError> { @@ -192,122 +182,9 @@ impl ClientDocEditor { } #[tracing::instrument(level = "debug", skip(self))] - pub fn stop_sync(&self) { - tracing::debug!("{} stop sync", self.doc_id); - let _ = self.stop_sync_tx.send(()); - } + pub fn stop_sync(&self) { self.ws_manager.stop(); } - #[tracing::instrument(level = "debug", skip(self))] - fn connect_to_doc(&self) { - let rev_id: RevId = self.rev_manager.rev_id().into(); - if let Ok(user_id) = self.user.user_id() { - let action = OpenDocAction::new(&user_id, &self.doc_id, &rev_id, &self.ws_sender); - let strategy = ExponentialBackoff::from_millis(50).take(3); - let retry = Retry::spawn(strategy, action); - tokio::spawn(async move { - match retry.await { - Ok(_) => log::debug!("Notify open doc success"), - Err(e) => log::error!("Notify open doc failed: {}", e), - } - }); - } - } - - #[tracing::instrument(level = "debug", skip(self))] - pub(crate) async fn handle_push_rev(&self, bytes: Bytes) -> FlowyResult<()> { - // Transform the revision - let (ret, rx) = oneshot::channel::>(); - let _ = self.edit_cmd_tx.send(EditCommand::ProcessRemoteRevision { bytes, ret }); - let TransformDeltas { - client_prime, - server_prime, - server_rev_id, - } = rx.await.map_err(internal_error)??; - - if self.rev_manager.rev_id() >= server_rev_id.value { - // Ignore this push revision if local_rev_id >= server_rev_id - return Ok(()); - } - - // compose delta - let (ret, rx) = oneshot::channel::>(); - let msg = EditCommand::ComposeDelta { - delta: client_prime.clone(), - ret, - }; - let _ = self.edit_cmd_tx.send(msg); - let md5 = rx.await.map_err(internal_error)??; - - // update rev id - self.rev_manager - .update_rev_id_counter_value(server_rev_id.clone().into()); - let (local_base_rev_id, local_rev_id) = self.rev_manager.next_rev_id(); - let delta_data = client_prime.to_bytes(); - // save the revision - let user_id = self.user.user_id()?; - let revision = Revision::new( - &self.doc_id, - local_base_rev_id, - local_rev_id, - delta_data, - RevType::Remote, - &user_id, - md5.clone(), - ); - - let _ = self.rev_manager.add_remote_revision(&revision).await?; - - // send the server_prime delta - let user_id = self.user.user_id()?; - let delta_data = server_prime.to_bytes(); - let revision = Revision::new( - &self.doc_id, - local_base_rev_id, - local_rev_id, - delta_data, - RevType::Remote, - &user_id, - md5, - ); - let _ = self.ws_sender.send(revision.into()); - Ok(()) - } - - 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), - } - Ok(()) - } -} - -pub struct EditDocWsHandler(pub Arc); - -impl std::ops::Deref for EditDocWsHandler { - type Target = Arc; - - fn deref(&self) -> &Self::Target { &self.0 } -} - -impl WsDocumentHandler for EditDocWsHandler { - fn receive(&self, doc_data: WsDocumentData) { - let edit_doc = self.0.clone(); - tokio::spawn(async move { - if let Err(e) = edit_doc.handle_ws_message(doc_data).await { - tracing::error!("❌{:?}", e); - } - }); - } - - fn state_changed(&self, state: &WsConnectState) { - match state { - WsConnectState::Init => {}, - WsConnectState::Connecting => {}, - WsConnectState::Connected => self.connect_to_doc(), - WsConnectState::Disconnected => {}, - } - } + pub(crate) fn ws_handler(&self) -> Arc { self.ws_manager.clone() } } fn spawn_edit_queue(doc_id: &str, delta: RichTextDelta, _pool: Arc) -> UnboundedSender { @@ -317,19 +194,121 @@ fn spawn_edit_queue(doc_id: &str, delta: RichTextDelta, _pool: Arc, - ws_msg_rx: mpsc::UnboundedReceiver, - stop_sync_tx: SteamStopTx, -) { - let rev_manager = editor.rev_manager.clone(); - let ws_sender = editor.ws_sender.clone(); +struct DocumentWebSocketSteamConsumerAdapter { + doc_id: String, + edit_cmd_tx: UnboundedSender, + rev_manager: Arc, + user: Arc, +} - let up_stream = editor.rev_manager.make_up_stream(stop_sync_tx.subscribe()); - let down_stream = RevisionDownStream::new(editor, rev_manager, ws_msg_rx, ws_sender, stop_sync_tx.subscribe()); +impl DocumentWebSocketSteamConsumer for DocumentWebSocketSteamConsumerAdapter { + fn receive_push_revision(&self, bytes: Bytes) -> FutureResult<(), FlowyError> { + let user = self.user.clone(); + let rev_manager = self.rev_manager.clone(); + let edit_cmd_tx = self.edit_cmd_tx.clone(); + let doc_id = self.doc_id.clone(); + FutureResult::new(async move { + let user_id = user.user_id()?; + let _revision = handle_push_rev(&doc_id, &user_id, edit_cmd_tx, rev_manager, bytes).await?; + Ok(()) + }) + } - tokio::spawn(up_stream.run()); - tokio::spawn(down_stream.run()); + fn make_revision_from_range(&self, range: RevisionRange) -> FutureResult { + let rev_manager = self.rev_manager.clone(); + FutureResult::new(async move { + let revision = rev_manager.mk_revisions(range).await?; + Ok(revision) + }) + } + + fn ack_revision(&self, rev_id: i64) -> FutureResult<(), FlowyError> { + let rev_manager = self.rev_manager.clone(); + FutureResult::new(async move { + let _ = rev_manager.ack_revision(rev_id).await?; + Ok(()) + }) + } +} + +struct DocumentSinkDataProviderAdapter { + rev_manager: Arc, +} + +impl DocumentSinkDataProvider for DocumentSinkDataProviderAdapter { + fn next(&self) -> FutureResult, FlowyError> { + let rev_manager = self.rev_manager.clone(); + FutureResult::new(async move { + match rev_manager.next_sync_revision().await? { + Some(rev) => { + tracing::debug!("[DocumentSinkDataProvider]: revision: {}:{:?}", rev.doc_id, rev.rev_id); + Ok(Some(rev.into())) + }, + None => Ok(None), + } + }) + } +} + +#[tracing::instrument(level = "debug", skip(edit_cmd_tx, rev_manager, bytes))] +pub(crate) async fn handle_push_rev( + doc_id: &str, + user_id: &str, + edit_cmd_tx: UnboundedSender, + rev_manager: Arc, + bytes: Bytes, +) -> FlowyResult> { + // Transform the revision + let (ret, rx) = oneshot::channel::>(); + let _ = edit_cmd_tx.send(EditCommand::ProcessRemoteRevision { bytes, ret }); + let TransformDeltas { + client_prime, + server_prime, + server_rev_id, + } = rx.await.map_err(internal_error)??; + + if rev_manager.rev_id() >= server_rev_id.value { + // Ignore this push revision if local_rev_id >= server_rev_id + return Ok(None); + } + + // compose delta + let (ret, rx) = oneshot::channel::>(); + let msg = EditCommand::ComposeDelta { + delta: client_prime.clone(), + ret, + }; + let _ = edit_cmd_tx.send(msg); + let md5 = rx.await.map_err(internal_error)??; + + // update rev id + rev_manager.update_rev_id_counter_value(server_rev_id.clone().into()); + let (local_base_rev_id, local_rev_id) = rev_manager.next_rev_id(); + let delta_data = client_prime.to_bytes(); + // save the revision + let revision = Revision::new( + &doc_id, + local_base_rev_id, + local_rev_id, + delta_data, + RevType::Remote, + &user_id, + md5.clone(), + ); + + let _ = rev_manager.add_remote_revision(&revision).await?; + + // send the server_prime delta + let delta_data = server_prime.to_bytes(); + Ok(Some(Revision::new( + &doc_id, + local_base_rev_id, + local_rev_id, + delta_data, + RevType::Remote, + &user_id, + md5, + ))) } #[cfg(feature = "flowy_unit_test")] diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/mod.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/mod.rs index 6d4fb5fa62..794da84e62 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/mod.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/mod.rs @@ -1,7 +1,8 @@ +mod edit_queue; +mod edit_ws; mod editor; mod model; -mod queue; +pub(crate) use edit_queue::*; +pub use edit_ws::*; pub use editor::*; -pub(crate) use model::*; -pub(crate) use queue::*; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/model.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/model.rs index 12e1d2fc28..bd78e32c15 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/model.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/model.rs @@ -15,6 +15,7 @@ pub(crate) struct OpenDocAction { ws: Arc, } +#[allow(dead_code)] impl OpenDocAction { pub(crate) fn new(user_id: &str, doc_id: &str, rev_id: &RevId, ws: &Arc) -> Self { Self { diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs deleted file mode 100644 index faa239dd3f..0000000000 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/queue.rs +++ /dev/null @@ -1,207 +0,0 @@ -use async_stream::stream; -use bytes::Bytes; -use flowy_collaboration::{ - core::document::{history::UndoResult, Document}, - errors::CollaborateError, -}; -use flowy_error::FlowyError; -use futures::stream::StreamExt; -use lib_ot::{ - core::{Interval, OperationTransformable}, - revision::{RevId, Revision}, - rich_text::{RichTextAttribute, RichTextDelta}, -}; -use std::{convert::TryFrom, sync::Arc}; -use tokio::sync::{mpsc, oneshot, RwLock}; - -pub(crate) struct EditCommandQueue { - doc_id: String, - document: Arc>, - receiver: Option>, -} - -impl EditCommandQueue { - pub(crate) fn new(doc_id: &str, delta: RichTextDelta, receiver: mpsc::UnboundedReceiver) -> Self { - let document = Arc::new(RwLock::new(Document::from_delta(delta))); - Self { - doc_id: doc_id.to_owned(), - document, - receiver: Some(receiver), - } - } - - pub(crate) async fn run(mut self) { - let mut receiver = self.receiver.take().expect("Should only call once"); - let stream = stream! { - loop { - match receiver.recv().await { - Some(msg) => yield msg, - None => break, - } - } - }; - stream - .for_each(|msg| async { - match self.handle_message(msg).await { - Ok(_) => {}, - Err(e) => tracing::debug!("[EditCommandQueue]: {}", e), - } - }) - .await; - } - - async fn handle_message(&self, msg: EditCommand) -> Result<(), FlowyError> { - match msg { - EditCommand::ComposeDelta { delta, ret } => { - let result = self.composed_delta(delta).await; - let _ = ret.send(result); - }, - EditCommand::ProcessRemoteRevision { bytes, ret } => { - let f = || async { - let revision = Revision::try_from(bytes)?; - let delta = RichTextDelta::from_bytes(&revision.delta_data)?; - let server_rev_id: RevId = revision.rev_id.into(); - let read_guard = self.document.read().await; - let (server_prime, client_prime) = read_guard.delta().transform(&delta)?; - drop(read_guard); - - let transform_delta = TransformDeltas { - client_prime, - server_prime, - server_rev_id, - }; - - Ok::(transform_delta) - }; - let _ = ret.send(f().await); - }, - EditCommand::Insert { index, data, ret } => { - let mut write_guard = self.document.write().await; - let delta = write_guard.insert(index, data)?; - let md5 = write_guard.md5(); - let _ = ret.send(Ok((delta, md5))); - }, - EditCommand::Delete { interval, ret } => { - let mut write_guard = self.document.write().await; - let delta = write_guard.delete(interval)?; - let md5 = write_guard.md5(); - let _ = ret.send(Ok((delta, md5))); - }, - EditCommand::Format { - interval, - attribute, - ret, - } => { - let mut write_guard = self.document.write().await; - let delta = write_guard.format(interval, attribute)?; - let md5 = write_guard.md5(); - let _ = ret.send(Ok((delta, md5))); - }, - EditCommand::Replace { interval, data, ret } => { - let mut write_guard = self.document.write().await; - let delta = write_guard.replace(interval, data)?; - let md5 = write_guard.md5(); - let _ = ret.send(Ok((delta, md5))); - }, - EditCommand::CanUndo { ret } => { - let _ = ret.send(self.document.read().await.can_undo()); - }, - EditCommand::CanRedo { ret } => { - let _ = ret.send(self.document.read().await.can_redo()); - }, - EditCommand::Undo { ret } => { - let result = self.document.write().await.undo(); - let _ = ret.send(result); - }, - EditCommand::Redo { ret } => { - let result = self.document.write().await.redo(); - let _ = ret.send(result); - }, - EditCommand::ReadDoc { ret } => { - let data = self.document.read().await.to_json(); - let _ = ret.send(Ok(data)); - }, - EditCommand::ReadDocDelta { ret } => { - let delta = self.document.read().await.delta().clone(); - let _ = ret.send(Ok(delta)); - }, - } - Ok(()) - } - - #[tracing::instrument(level = "debug", skip(self, delta), fields(compose_result), err)] - async fn composed_delta(&self, delta: RichTextDelta) -> Result { - // tracing::debug!("{:?} thread handle_message", thread::current(),); - let mut document = self.document.write().await; - tracing::Span::current().record( - "composed_delta", - &format!("doc_id:{} - {}", &self.doc_id, delta.to_json()).as_str(), - ); - - let _ = document.compose_delta(delta)?; - let md5 = document.md5(); - drop(document); - - Ok(md5) - } -} - -pub(crate) type Ret = oneshot::Sender>; -pub(crate) type NewDelta = (RichTextDelta, String); -pub(crate) type DocumentMD5 = String; - -#[allow(dead_code)] -pub(crate) enum EditCommand { - ComposeDelta { - delta: RichTextDelta, - ret: Ret, - }, - ProcessRemoteRevision { - bytes: Bytes, - ret: Ret, - }, - Insert { - index: usize, - data: String, - ret: Ret, - }, - Delete { - interval: Interval, - ret: Ret, - }, - Format { - interval: Interval, - attribute: RichTextAttribute, - ret: Ret, - }, - - Replace { - interval: Interval, - data: String, - ret: Ret, - }, - CanUndo { - ret: oneshot::Sender, - }, - CanRedo { - ret: oneshot::Sender, - }, - Undo { - ret: Ret, - }, - Redo { - ret: Ret, - }, - ReadDoc { - ret: Ret, - }, - ReadDocDelta { - ret: Ret, - }, -} - -pub(crate) struct TransformDeltas { - pub client_prime: RichTextDelta, - pub server_prime: RichTextDelta, - pub server_rev_id: RevId, -} diff --git a/frontend/rust-lib/flowy-document/src/services/doc/mod.rs b/frontend/rust-lib/flowy-document/src/services/doc/mod.rs index 9188a3f339..c276f674d3 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/mod.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/mod.rs @@ -3,7 +3,9 @@ pub mod revision; pub(crate) mod controller; -mod ws_manager; -pub use ws_manager::*; +mod ws_handlers; +pub use edit::*; +pub use revision::*; +pub use ws_handlers::*; pub const SYNC_INTERVAL_IN_MILLIS: u64 = 500; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs index 7e1f787577..6858108afa 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs @@ -23,10 +23,6 @@ use tokio::{ task::{spawn_blocking, JoinHandle}, }; -pub trait RevisionIterator: Send + Sync { - fn next(&self) -> FutureResult, FlowyError>; -} - type DocRevisionDeskCache = dyn RevisionDiskCache; pub struct RevisionCache { @@ -171,10 +167,8 @@ impl RevisionCache { self.add_remote_revision(revision).await?; Ok(doc) } -} -impl RevisionIterator for RevisionCache { - fn next(&self) -> FutureResult, FlowyError> { + pub(crate) fn next_revision(&self) -> FutureResult, FlowyError> { let memory_cache = self.memory_cache.clone(); let disk_cache = self.dish_cache.clone(); let doc_id = self.doc_id.clone(); @@ -184,10 +178,10 @@ impl RevisionIterator for RevisionCache { None => Ok(None), Some(rev_id) => match disk_cache.read_revision(&doc_id, rev_id)? { None => Ok(None), - Some(record) => Ok(Some(record)), + Some(record) => Ok(Some(record.revision)), }, }, - Some((_, record)) => Ok(Some(record)), + Some((_, record)) => Ok(Some(record.revision)), } }) } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs index ebb61687d9..9cc4c6d4ed 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs @@ -1,10 +1,4 @@ -use crate::{ - errors::FlowyError, - services::doc::{ - revision::{RevisionCache, RevisionUpStream, SteamStopRx}, - DocumentWebSocket, - }, -}; +use crate::{errors::FlowyError, services::doc::revision::RevisionCache}; use flowy_collaboration::{ entities::doc::Doc, util::{md5, RevIdCounter}, @@ -13,7 +7,7 @@ use flowy_error::FlowyResult; use lib_infra::future::FutureResult; use lib_ot::{ core::OperationTransformable, - revision::{RevId, RevType, Revision, RevisionRange}, + revision::{RevType, Revision, RevisionRange}, rich_text::RichTextDelta, }; use std::sync::Arc; @@ -27,18 +21,16 @@ pub struct RevisionManager { user_id: String, rev_id_counter: RevIdCounter, cache: Arc, - ws_sender: Arc, } impl RevisionManager { - pub fn new(user_id: &str, doc_id: &str, cache: Arc, ws_sender: Arc) -> Self { + pub fn new(user_id: &str, doc_id: &str, cache: Arc) -> Self { let rev_id_counter = RevIdCounter::new(0); Self { doc_id: doc_id.to_string(), user_id: user_id.to_owned(), rev_id_counter, cache, - ws_sender, } } @@ -58,8 +50,8 @@ impl RevisionManager { Ok(()) } - pub async fn ack_revision(&self, rev_id: RevId) -> Result<(), FlowyError> { - self.cache.ack_revision(rev_id.into()).await; + pub async fn ack_revision(&self, rev_id: i64) -> Result<(), FlowyError> { + self.cache.ack_revision(rev_id).await; Ok(()) } @@ -101,9 +93,7 @@ impl RevisionManager { Ok(revision) } - pub(crate) fn make_up_stream(&self, stop_rx: SteamStopRx) -> RevisionUpStream { - RevisionUpStream::new(&self.doc_id, self.cache.clone(), self.ws_sender.clone(), stop_rx) - } + pub fn next_sync_revision(&self) -> FutureResult, FlowyError> { self.cache.next_revision() } } #[cfg(feature = "flowy_unit_test")] diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/mod.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/mod.rs index 867c30173c..e101635339 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/mod.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/mod.rs @@ -1,7 +1,5 @@ mod cache; mod manager; -mod sync; pub use cache::*; pub use manager::*; -pub(crate) use sync::*; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs deleted file mode 100644 index fd839ff98a..0000000000 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/sync.rs +++ /dev/null @@ -1,200 +0,0 @@ -use crate::services::doc::{ - edit::ClientDocEditor, - revision::{RevisionIterator, RevisionManager}, - DocumentWebSocket, - SYNC_INTERVAL_IN_MILLIS, -}; -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}; -use tokio::{ - sync::{broadcast, mpsc}, - task::spawn_blocking, - time::{interval, Duration}, -}; - -pub(crate) struct RevisionDownStream { - editor: Arc, - rev_manager: Arc, - ws_msg_rx: Option>, - ws_sender: Arc, - stop_rx: Option, -} - -impl RevisionDownStream { - pub(crate) fn new( - editor: Arc, - rev_manager: Arc, - ws_msg_rx: mpsc::UnboundedReceiver, - ws_sender: Arc, - stop_rx: SteamStopRx, - ) -> Self { - RevisionDownStream { - editor, - rev_manager, - ws_msg_rx: Some(ws_msg_rx), - ws_sender, - stop_rx: Some(stop_rx), - } - } - - pub async fn run(mut self) { - let mut receiver = self.ws_msg_rx.take().expect("Only take once"); - let mut stop_rx = self.stop_rx.take().expect("Only take once"); - let doc_id = self.editor.doc_id.clone(); - let stream = stream! { - loop { - tokio::select! { - result = receiver.recv() => { - match result { - Some(msg) => { - yield msg - }, - None => { - tracing::debug!("[RevisionDownStream:{}] loop exit", doc_id); - break; - }, - } - }, - _ = stop_rx.recv() => { - tracing::debug!("[RevisionDownStream:{}] loop exit", doc_id); - break - }, - }; - } - }; - - stream - .for_each(|msg| async { - match self.handle_message(msg).await { - Ok(_) => {}, - Err(e) => log::error!("[RevisionDownStream:{}] error: {}", self.editor.doc_id, e), - } - }) - .await; - } - - async fn handle_message(&self, msg: WsDocumentData) -> FlowyResult<()> { - let WsDocumentData { doc_id: _, ty, data } = msg; - let bytes = spawn_blocking(move || Bytes::from(data)) - .await - .map_err(internal_error)?; - - tracing::debug!("[RevisionDownStream]: receives new message: {:?}", ty); - match ty { - WsDataType::PushRev => { - let _ = self.editor.handle_push_rev(bytes).await?; - }, - WsDataType::PullRev => { - let range = RevisionRange::try_from(bytes)?; - let revision = self.rev_manager.mk_revisions(range).await?; - let _ = self.ws_sender.send(revision.into()); - }, - WsDataType::Acked => { - let rev_id = RevId::try_from(bytes)?; - let _ = self.rev_manager.ack_revision(rev_id).await?; - }, - WsDataType::Conflict => {}, - } - - Ok(()) - } -} - -// RevisionUpStream -pub(crate) enum UpStreamMsg { - Tick, -} - -pub type SteamStopRx = broadcast::Receiver<()>; -pub type SteamStopTx = broadcast::Sender<()>; - -pub(crate) struct RevisionUpStream { - revisions: Arc, - ws_sender: Arc, - stop_rx: Option, - doc_id: String, -} - -impl RevisionUpStream { - pub(crate) fn new( - doc_id: &str, - revisions: Arc, - ws_sender: Arc, - stop_rx: SteamStopRx, - ) -> Self { - Self { - revisions, - ws_sender, - stop_rx: Some(stop_rx), - doc_id: doc_id.to_owned(), - } - } - - pub async fn run(mut self) { - let (tx, mut rx) = mpsc::unbounded_channel(); - let mut stop_rx = self.stop_rx.take().expect("Only take once"); - let doc_id = self.doc_id.clone(); - tokio::spawn(tick(tx)); - let stream = stream! { - loop { - tokio::select! { - result = rx.recv() => { - match result { - Some(msg) => yield msg, - None => break, - } - }, - _ = stop_rx.recv() => { - tracing::debug!("[RevisionUpStream:{}] loop exit", doc_id); - break - }, - }; - } - }; - stream - .for_each(|msg| async { - match self.handle_msg(msg).await { - Ok(_) => {}, - Err(e) => log::error!("[RevisionUpStream]: send msg failed, {:?}", e), - } - }) - .await; - } - - async fn handle_msg(&self, msg: UpStreamMsg) -> FlowyResult<()> { - match msg { - UpStreamMsg::Tick => self.send_next_revision().await, - } - } - - async fn send_next_revision(&self) -> FlowyResult<()> { - match self.revisions.next().await? { - None => { - tracing::debug!("Finish synchronizing revisions"); - Ok(()) - }, - Some(record) => { - tracing::debug!( - "[RevisionUpStream]: processes revision: {}:{:?}", - record.revision.doc_id, - record.revision.rev_id - ); - self.ws_sender.send(record.revision.into()).map_err(internal_error) - // let _ = tokio::time::timeout(Duration::from_millis(2000), - // ret.recv()).await; - }, - } - } -} - -async fn tick(sender: mpsc::UnboundedSender) { - let mut i = interval(Duration::from_millis(SYNC_INTERVAL_IN_MILLIS)); - while sender.send(UpStreamMsg::Tick).is_ok() { - i.tick().await; - } -} diff --git a/frontend/rust-lib/flowy-document/src/services/doc/ws_manager.rs b/frontend/rust-lib/flowy-document/src/services/doc/ws_manager.rs deleted file mode 100644 index efccc18ece..0000000000 --- a/frontend/rust-lib/flowy-document/src/services/doc/ws_manager.rs +++ /dev/null @@ -1,67 +0,0 @@ -use crate::errors::FlowyError; -use bytes::Bytes; -use dashmap::DashMap; -use flowy_collaboration::entities::ws::WsDocumentData; -use lib_ws::WsConnectState; -use std::{convert::TryInto, sync::Arc}; - -pub(crate) trait WsDocumentHandler: Send + Sync { - fn receive(&self, data: WsDocumentData); - fn state_changed(&self, state: &WsConnectState); -} - -pub type WsStateReceiver = tokio::sync::broadcast::Receiver; -pub trait DocumentWebSocket: Send + Sync { - fn send(&self, data: WsDocumentData) -> Result<(), FlowyError>; - fn subscribe_state_changed(&self) -> WsStateReceiver; -} - -pub struct WsDocumentManager { - ws: Arc, - // key: the document id - handlers: Arc>>, -} - -impl WsDocumentManager { - pub fn new(ws: Arc) -> Self { - let handlers: Arc>> = Arc::new(DashMap::new()); - Self { ws, handlers } - } - - pub(crate) fn init(&self) { listen_ws_state_changed(self.ws.clone(), self.handlers.clone()); } - - pub(crate) fn register_handler(&self, id: &str, handler: Arc) { - if self.handlers.contains_key(id) { - log::error!("Duplicate handler registered for {:?}", id); - } - self.handlers.insert(id.to_string(), handler); - } - - pub(crate) fn remove_handler(&self, id: &str) { self.handlers.remove(id); } - - pub fn did_receive_ws_data(&self, data: Bytes) { - let data: WsDocumentData = data.try_into().unwrap(); - match self.handlers.get(&data.doc_id) { - None => { - log::error!("Can't find any source handler for {:?}", data.doc_id); - }, - Some(handler) => { - handler.receive(data); - }, - } - } - - pub fn ws(&self) -> Arc { self.ws.clone() } -} - -#[tracing::instrument(level = "debug", skip(ws, handlers))] -fn listen_ws_state_changed(ws: Arc, handlers: Arc>>) { - let mut notify = ws.subscribe_state_changed(); - tokio::spawn(async move { - while let Ok(state) = notify.recv().await { - handlers.iter().for_each(|handle| { - handle.value().state_changed(&state); - }); - } - }); -} diff --git a/frontend/rust-lib/flowy-net/Cargo.toml b/frontend/rust-lib/flowy-net/Cargo.toml index 24268edc08..500fd74d90 100644 --- a/frontend/rust-lib/flowy-net/Cargo.toml +++ b/frontend/rust-lib/flowy-net/Cargo.toml @@ -25,5 +25,5 @@ lazy_static = {version = "1.4.0", optional = true} dashmap = {version = "4.0", optional = true} [features] -ws_mock = ["flowy-collaboration", "lazy_static", "dashmap"] +flowy_unit_test = ["flowy-collaboration", "lazy_static", "dashmap"] http_server = [] \ No newline at end of file diff --git a/frontend/rust-lib/flowy-net/src/services/mock/ws_mock.rs b/frontend/rust-lib/flowy-net/src/services/mock/ws_mock.rs index 419aaf3454..b22e4fac48 100644 --- a/frontend/rust-lib/flowy-net/src/services/mock/ws_mock.rs +++ b/frontend/rust-lib/flowy-net/src/services/mock/ws_mock.rs @@ -1,11 +1,11 @@ -use crate::services::ws::{FlowyError, FlowyWebSocket, FlowyWsSender, WsConnectState, WsMessage, WsMessageHandler}; +use crate::services::ws::{FlowyError, FlowyWebSocket, FlowyWsSender, WsConnectState, WsMessage, WsMessageReceiver}; use bytes::Bytes; use dashmap::DashMap; use flowy_collaboration::{ core::sync::{RevisionUser, ServerDocManager, ServerDocPersistence, SyncResponse}, entities::{ doc::Doc, - ws::{WsDataType, WsDocumentData}, + ws::{WsDocumentData, WsDocumentDataType}, }, errors::CollaborateError, Revision, @@ -22,7 +22,7 @@ use std::{ use tokio::sync::{broadcast, broadcast::Receiver, mpsc}; pub struct MockWebSocket { - handlers: DashMap>, + handlers: DashMap>, state_sender: broadcast::Sender, ws_sender: broadcast::Sender, is_stop: RwLock, @@ -79,7 +79,7 @@ impl FlowyWebSocket for Arc { fn reconnect(&self, _count: usize) -> FutureResult<(), FlowyError> { FutureResult::new(async { Ok(()) }) } - fn add_ws_message_handler(&self, handler: Arc) -> Result<(), FlowyError> { + fn add_message_receiver(&self, handler: Arc) -> Result<(), FlowyError> { let source = handler.source(); if self.handlers.contains_key(&source) { tracing::error!("WsSource's {:?} is already registered", source); @@ -111,10 +111,10 @@ impl MockDocServer { async fn handle_ws_data(&self, ws_data: WsDocumentData) -> mpsc::Receiver { let bytes = Bytes::from(ws_data.data); match ws_data.ty { - WsDataType::Acked => { + WsDocumentDataType::Acked => { unimplemented!() }, - WsDataType::PushRev => { + WsDocumentDataType::PushRev => { let revision = Revision::try_from(bytes).unwrap(); let handler = match self.manager.get(&revision.doc_id).await { None => self.manager.create_doc(revision.clone()).await.unwrap(), @@ -129,10 +129,10 @@ impl MockDocServer { handler.apply_revision(Arc::new(user), revision).await.unwrap(); rx }, - WsDataType::PullRev => { + WsDocumentDataType::PullRev => { unimplemented!() }, - WsDataType::Conflict => { + WsDocumentDataType::UserConnect => { unimplemented!() }, } diff --git a/frontend/rust-lib/flowy-net/src/services/mod.rs b/frontend/rust-lib/flowy-net/src/services/mod.rs index bd8f542936..1d5e1d784f 100644 --- a/frontend/rust-lib/flowy-net/src/services/mod.rs +++ b/frontend/rust-lib/flowy-net/src/services/mod.rs @@ -1,4 +1,4 @@ pub mod ws; -#[cfg(feature = "ws_mock")] +#[cfg(feature = "flowy_unit_test")] mod mock; diff --git a/frontend/rust-lib/flowy-net/src/services/ws/conn.rs b/frontend/rust-lib/flowy-net/src/services/ws/conn.rs index 0013ea8cbd..fa3d5b9185 100644 --- a/frontend/rust-lib/flowy-net/src/services/ws/conn.rs +++ b/frontend/rust-lib/flowy-net/src/services/ws/conn.rs @@ -3,14 +3,14 @@ use std::sync::Arc; use tokio::sync::broadcast; pub use flowy_error::FlowyError; -pub use lib_ws::{WsConnectState, WsMessage, WsMessageHandler}; +pub use lib_ws::{WsConnectState, WsMessage, WsMessageReceiver}; pub trait FlowyWebSocket: Send + Sync { fn start_connect(&self, addr: String) -> FutureResult<(), FlowyError>; fn stop_connect(&self) -> FutureResult<(), FlowyError>; fn subscribe_connect_state(&self) -> broadcast::Receiver; fn reconnect(&self, count: usize) -> FutureResult<(), FlowyError>; - fn add_ws_message_handler(&self, handler: Arc) -> Result<(), FlowyError>; + fn add_message_receiver(&self, handler: Arc) -> Result<(), FlowyError>; fn ws_sender(&self) -> Result, FlowyError>; } diff --git a/frontend/rust-lib/flowy-net/src/services/ws/manager.rs b/frontend/rust-lib/flowy-net/src/services/ws/manager.rs index 138e281a95..fac7835b6f 100644 --- a/frontend/rust-lib/flowy-net/src/services/ws/manager.rs +++ b/frontend/rust-lib/flowy-net/src/services/ws/manager.rs @@ -4,7 +4,7 @@ use crate::{ }; use flowy_error::{internal_error, FlowyError}; use lib_infra::future::FutureResult; -use lib_ws::{WsConnectState, WsController, WsMessage, WsMessageHandler, WsSender}; +use lib_ws::{WsConnectState, WsController, WsMessage, WsMessageReceiver, WsSender}; use parking_lot::RwLock; use std::sync::Arc; use tokio::sync::{broadcast, broadcast::Receiver}; @@ -71,8 +71,8 @@ impl WsManager { pub fn subscribe_network_ty(&self) -> broadcast::Receiver { self.status_notifier.subscribe() } - pub fn add_handler(&self, handler: Arc) -> Result<(), FlowyError> { - let _ = self.inner.add_ws_message_handler(handler)?; + pub fn add_receiver(&self, handler: Arc) -> Result<(), FlowyError> { + let _ = self.inner.add_message_receiver(handler)?; Ok(()) } @@ -139,8 +139,8 @@ impl FlowyWebSocket for Arc { }) } - fn add_ws_message_handler(&self, handler: Arc) -> Result<(), FlowyError> { - let _ = self.add_handler(handler).map_err(internal_error)?; + fn add_message_receiver(&self, handler: Arc) -> Result<(), FlowyError> { + let _ = self.add_receiver(handler).map_err(internal_error)?; Ok(()) } diff --git a/frontend/rust-lib/flowy-net/src/services/ws/mod.rs b/frontend/rust-lib/flowy-net/src/services/ws/mod.rs index aae5ecffdc..56738af71b 100644 --- a/frontend/rust-lib/flowy-net/src/services/ws/mod.rs +++ b/frontend/rust-lib/flowy-net/src/services/ws/mod.rs @@ -6,10 +6,10 @@ mod conn; mod manager; mod ws_local; -#[cfg(not(feature = "ws_mock"))] +#[cfg(not(feature = "flowy_unit_test"))] pub(crate) fn local_web_socket() -> Arc { Arc::new(Arc::new(ws_local::LocalWebSocket::default())) } -#[cfg(feature = "ws_mock")] +#[cfg(feature = "flowy_unit_test")] pub(crate) fn local_web_socket() -> Arc { Arc::new(Arc::new(crate::services::mock::MockWebSocket::default())) } diff --git a/frontend/rust-lib/flowy-net/src/services/ws/ws_local.rs b/frontend/rust-lib/flowy-net/src/services/ws/ws_local.rs index 20d73eb0ef..692b9244fe 100644 --- a/frontend/rust-lib/flowy-net/src/services/ws/ws_local.rs +++ b/frontend/rust-lib/flowy-net/src/services/ws/ws_local.rs @@ -1,4 +1,4 @@ -use crate::services::ws::{FlowyError, FlowyWebSocket, FlowyWsSender, WsConnectState, WsMessage, WsMessageHandler}; +use crate::services::ws::{FlowyError, FlowyWebSocket, FlowyWsSender, WsConnectState, WsMessage, WsMessageReceiver}; use lib_infra::future::FutureResult; use std::sync::Arc; use tokio::sync::{broadcast, broadcast::Receiver}; @@ -28,7 +28,7 @@ impl FlowyWebSocket for Arc { fn reconnect(&self, _count: usize) -> FutureResult<(), FlowyError> { FutureResult::new(async { Ok(()) }) } - fn add_ws_message_handler(&self, _handler: Arc) -> Result<(), FlowyError> { Ok(()) } + fn add_message_receiver(&self, _handler: Arc) -> Result<(), FlowyError> { Ok(()) } fn ws_sender(&self) -> Result, FlowyError> { Ok(Arc::new(self.ws_sender.clone())) } } diff --git a/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs b/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs index 4cf1606b40..6ad1d7c0f4 100644 --- a/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs +++ b/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs @@ -4,11 +4,11 @@ use flowy_database::ConnectionPool; use flowy_document::{ errors::{internal_error, FlowyError}, module::DocumentUser, - services::doc::{DocumentWebSocket, WsDocumentManager, WsStateReceiver}, + services::doc::{DocumentWebSocket, DocumentWsHandlers, WsStateReceiver}, }; use flowy_net::services::ws::WsManager; use flowy_user::services::user::UserSession; -use lib_ws::{WsMessage, WsMessageHandler, WsModule}; +use lib_ws::{WsMessage, WsMessageReceiver, WsModule}; use std::{convert::TryInto, path::Path, sync::Arc}; pub struct DocumentDepsResolver(); @@ -16,16 +16,16 @@ impl DocumentDepsResolver { pub fn resolve( ws_manager: Arc, user_session: Arc, - ) -> (Arc, Arc) { + ) -> (Arc, Arc) { 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).unwrap(); - (user, ws_doc) + let document_ws_handlers = Arc::new(DocumentWsHandlers::new(sender)); + let receiver = Arc::new(WsMessageReceiverAdaptor(document_ws_handlers.clone())); + ws_manager.add_receiver(receiver).unwrap(); + (user, document_ws_handlers) } } @@ -76,15 +76,9 @@ impl DocumentWebSocket for WsSenderImpl { fn subscribe_state_changed(&self) -> WsStateReceiver { self.ws_manager.subscribe_websocket_state() } } -struct DocumentWsMessageReceiver { - inner: Arc, -} +struct WsMessageReceiverAdaptor(Arc); -impl WsMessageHandler for DocumentWsMessageReceiver { +impl WsMessageReceiver for WsMessageReceiverAdaptor { fn source(&self) -> WsModule { WsModule::Doc } - - fn receive_message(&self, msg: WsMessage) { - let data = Bytes::from(msg.data); - self.inner.did_receive_ws_data(data); - } + fn receive_message(&self, msg: WsMessage) { self.0.did_receive_data(Bytes::from(msg.data)); } } diff --git a/frontend/rust-lib/flowy-test/Cargo.toml b/frontend/rust-lib/flowy-test/Cargo.toml index de27fc3f66..56fd34ef46 100644 --- a/frontend/rust-lib/flowy-test/Cargo.toml +++ b/frontend/rust-lib/flowy-test/Cargo.toml @@ -36,4 +36,4 @@ fake = "~2.3.0" claim = "0.4.0" futures = "0.3.15" serial_test = "0.5.1" -flowy-net = { path = "../flowy-net", features = ["ws_mock"] } \ No newline at end of file +flowy-net = { path = "../flowy-net", features = ["flowy_unit_test"] } \ No newline at end of file diff --git a/frontend/rust-lib/flowy-test/src/doc_script.rs b/frontend/rust-lib/flowy-test/src/doc_script.rs index f7828f9836..6c699033e2 100644 --- a/frontend/rust-lib/flowy-test/src/doc_script.rs +++ b/frontend/rust-lib/flowy-test/src/doc_script.rs @@ -1,6 +1,6 @@ use crate::{helper::ViewTest, FlowySDKTest}; -use flowy_collaboration::entities::{doc::DocIdentifier, ws::WsDocumentData}; -use flowy_document::services::doc::{edit::ClientDocEditor, revision::RevisionIterator, SYNC_INTERVAL_IN_MILLIS}; +use flowy_collaboration::entities::doc::DocIdentifier; +use flowy_document::services::doc::{edit::ClientDocEditor, SYNC_INTERVAL_IN_MILLIS}; use lib_ot::{core::Interval, revision::RevState, rich_text::RichTextDelta}; use std::sync::Arc; use tokio::time::{sleep, Duration}; @@ -78,14 +78,13 @@ impl EditorTest { assert_eq!(self.editor.rev_manager().rev_id(), rev_id); }, EditorScript::AssertNextRevId(rev_id) => { - let next_revision = cache.next().await.unwrap(); + let next_revision = rev_manager.next_sync_revision().await.unwrap(); if rev_id.is_none() { assert_eq!(next_revision.is_none(), true); return; } - let next_revision = next_revision.unwrap(); - assert_eq!(next_revision.revision.rev_id, rev_id.unwrap()); + assert_eq!(next_revision.rev_id, rev_id.unwrap()); }, EditorScript::AssertJson(expected) => { let expected_delta: RichTextDelta = serde_json::from_str(expected).unwrap(); diff --git a/shared-lib/flowy-collaboration/src/core/sync/synchronizer.rs b/shared-lib/flowy-collaboration/src/core/sync/synchronizer.rs index 2d62071407..6d799c1dde 100644 --- a/shared-lib/flowy-collaboration/src/core/sync/synchronizer.rs +++ b/shared-lib/flowy-collaboration/src/core/sync/synchronizer.rs @@ -1,6 +1,6 @@ use crate::{ core::document::Document, - entities::ws::{WsDataType, WsDocumentData}, + entities::ws::{WsDocumentData, WsDocumentDataType}, }; use bytes::Bytes; use lib_ot::{ @@ -147,7 +147,7 @@ fn mk_push_message(doc_id: &str, revision: Revision) -> WsDocumentData { let bytes: Bytes = revision.try_into().unwrap(); WsDocumentData { doc_id: doc_id.to_string(), - ty: WsDataType::PushRev, + ty: WsDocumentDataType::PushRev, data: bytes.to_vec(), } } @@ -162,7 +162,7 @@ fn mk_pull_message(doc_id: &str, from_rev_id: i64, to_rev_id: i64) -> WsDocument let bytes: Bytes = range.try_into().unwrap(); WsDocumentData { doc_id: doc_id.to_string(), - ty: WsDataType::PullRev, + ty: WsDocumentDataType::PullRev, data: bytes.to_vec(), } } @@ -176,7 +176,7 @@ fn mk_acked_message(revision: &Revision) -> WsDocumentData { WsDocumentData { doc_id: revision.doc_id.clone(), - ty: WsDataType::Acked, + ty: WsDocumentDataType::Acked, data, } } diff --git a/shared-lib/flowy-collaboration/src/entities/ws/ws.rs b/shared-lib/flowy-collaboration/src/entities/ws/ws.rs index 3e41268aef..a2e1e31d2f 100644 --- a/shared-lib/flowy-collaboration/src/entities/ws/ws.rs +++ b/shared-lib/flowy-collaboration/src/entities/ws/ws.rs @@ -5,17 +5,17 @@ use lib_ot::revision::{RevId, Revision, RevisionRange}; use std::convert::{TryFrom, TryInto}; #[derive(Debug, Clone, ProtoBuf_Enum, Eq, PartialEq, Hash)] -pub enum WsDataType { +pub enum WsDocumentDataType { // The frontend receives the Acked means the backend has accepted the revision - Acked = 0, + Acked = 0, // The frontend receives the PushRev event means the backend is pushing the new revision to frontend - PushRev = 1, + PushRev = 1, // The fronted receives the PullRev event means the backend try to pull the revision from frontend - PullRev = 2, - Conflict = 3, + PullRev = 2, + UserConnect = 3, } -impl WsDataType { +impl WsDocumentDataType { pub fn data(&self, bytes: Bytes) -> Result where T: TryFrom, @@ -24,8 +24,8 @@ impl WsDataType { } } -impl std::default::Default for WsDataType { - fn default() -> Self { WsDataType::Acked } +impl std::default::Default for WsDocumentDataType { + fn default() -> Self { WsDocumentDataType::Acked } } #[derive(ProtoBuf, Default, Debug, Clone)] @@ -34,7 +34,7 @@ pub struct WsDocumentData { pub doc_id: String, #[pb(index = 2)] - pub ty: WsDataType, + pub ty: WsDocumentDataType, #[pb(index = 3)] pub data: Vec, @@ -46,7 +46,7 @@ impl std::convert::From for WsDocumentData { let bytes: Bytes = revision.try_into().unwrap(); Self { doc_id, - ty: WsDataType::PushRev, + ty: WsDocumentDataType::PushRev, data: bytes.to_vec(), } } @@ -54,34 +54,46 @@ impl std::convert::From for WsDocumentData { pub struct WsDocumentDataBuilder(); impl WsDocumentDataBuilder { - // WsDataType::PushRev -> Revision + // WsDocumentDataType::PushRev -> Revision pub fn build_push_rev_message(doc_id: &str, revision: Revision) -> WsDocumentData { let bytes: Bytes = revision.try_into().unwrap(); WsDocumentData { doc_id: doc_id.to_string(), - ty: WsDataType::PushRev, + ty: WsDocumentDataType::PushRev, data: bytes.to_vec(), } } - // WsDataType::PullRev -> RevisionRange + // WsDocumentDataType::PullRev -> RevisionRange pub fn build_push_pull_message(doc_id: &str, range: RevisionRange) -> WsDocumentData { let bytes: Bytes = range.try_into().unwrap(); WsDocumentData { doc_id: doc_id.to_string(), - ty: WsDataType::PullRev, + ty: WsDocumentDataType::PullRev, data: bytes.to_vec(), } } - // WsDataType::Acked -> RevId + // WsDocumentDataType::Acked -> RevId pub fn build_acked_message(doc_id: &str, rev_id: i64) -> WsDocumentData { let rev_id: RevId = rev_id.into(); let bytes: Bytes = rev_id.try_into().unwrap(); WsDocumentData { doc_id: doc_id.to_string(), - ty: WsDataType::Acked, + ty: WsDocumentDataType::Acked, data: bytes.to_vec(), } } } + +#[derive(ProtoBuf, Default, Debug, Clone)] +pub struct DocumentConnected { + #[pb(index = 1)] + pub user_id: String, + + #[pb(index = 2)] + pub doc_id: String, + + #[pb(index = 3)] + pub rev_id: i64, +} diff --git a/shared-lib/flowy-collaboration/src/protobuf/model/ws.rs b/shared-lib/flowy-collaboration/src/protobuf/model/ws.rs index dbdcbe6569..394459aaff 100644 --- a/shared-lib/flowy-collaboration/src/protobuf/model/ws.rs +++ b/shared-lib/flowy-collaboration/src/protobuf/model/ws.rs @@ -27,7 +27,7 @@ pub struct WsDocumentData { // message fields pub doc_id: ::std::string::String, - pub ty: WsDataType, + pub ty: WsDocumentDataType, pub data: ::std::vec::Vec, // special fields pub unknown_fields: ::protobuf::UnknownFields, @@ -71,18 +71,18 @@ impl WsDocumentData { ::std::mem::replace(&mut self.doc_id, ::std::string::String::new()) } - // .WsDataType ty = 2; + // .WsDocumentDataType ty = 2; - pub fn get_ty(&self) -> WsDataType { + pub fn get_ty(&self) -> WsDocumentDataType { self.ty } pub fn clear_ty(&mut self) { - self.ty = WsDataType::Acked; + self.ty = WsDocumentDataType::Acked; } // Param is passed by value, moved - pub fn set_ty(&mut self, v: WsDataType) { + pub fn set_ty(&mut self, v: WsDocumentDataType) { self.ty = v; } @@ -146,7 +146,7 @@ impl ::protobuf::Message for WsDocumentData { if !self.doc_id.is_empty() { my_size += ::protobuf::rt::string_size(1, &self.doc_id); } - if self.ty != WsDataType::Acked { + if self.ty != WsDocumentDataType::Acked { my_size += ::protobuf::rt::enum_size(2, self.ty); } if !self.data.is_empty() { @@ -161,7 +161,7 @@ impl ::protobuf::Message for WsDocumentData { if !self.doc_id.is_empty() { os.write_string(1, &self.doc_id)?; } - if self.ty != WsDataType::Acked { + if self.ty != WsDocumentDataType::Acked { os.write_enum(2, ::protobuf::ProtobufEnum::value(&self.ty))?; } if !self.data.is_empty() { @@ -210,7 +210,7 @@ impl ::protobuf::Message for WsDocumentData { |m: &WsDocumentData| { &m.doc_id }, |m: &mut WsDocumentData| { &mut m.doc_id }, )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( "ty", |m: &WsDocumentData| { &m.ty }, |m: &mut WsDocumentData| { &mut m.ty }, @@ -237,7 +237,7 @@ impl ::protobuf::Message for WsDocumentData { impl ::protobuf::Clear for WsDocumentData { fn clear(&mut self) { self.doc_id.clear(); - self.ty = WsDataType::Acked; + self.ty = WsDocumentDataType::Acked; self.data.clear(); self.unknown_fields.clear(); } @@ -255,35 +255,271 @@ impl ::protobuf::reflect::ProtobufValue for WsDocumentData { } } +#[derive(PartialEq,Clone,Default)] +pub struct DocumentConnected { + // message fields + pub user_id: ::std::string::String, + pub doc_id: ::std::string::String, + pub rev_id: i64, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a DocumentConnected { + fn default() -> &'a DocumentConnected { + ::default_instance() + } +} + +impl DocumentConnected { + pub fn new() -> DocumentConnected { + ::std::default::Default::default() + } + + // string user_id = 1; + + + pub fn get_user_id(&self) -> &str { + &self.user_id + } + pub fn clear_user_id(&mut self) { + self.user_id.clear(); + } + + // Param is passed by value, moved + pub fn set_user_id(&mut self, v: ::std::string::String) { + self.user_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_user_id(&mut self) -> &mut ::std::string::String { + &mut self.user_id + } + + // Take field + pub fn take_user_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.user_id, ::std::string::String::new()) + } + + // string doc_id = 2; + + + pub fn get_doc_id(&self) -> &str { + &self.doc_id + } + pub fn clear_doc_id(&mut self) { + self.doc_id.clear(); + } + + // Param is passed by value, moved + pub fn set_doc_id(&mut self, v: ::std::string::String) { + self.doc_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_doc_id(&mut self) -> &mut ::std::string::String { + &mut self.doc_id + } + + // Take field + pub fn take_doc_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.doc_id, ::std::string::String::new()) + } + + // int64 rev_id = 3; + + + pub fn get_rev_id(&self) -> i64 { + self.rev_id + } + pub fn clear_rev_id(&mut self) { + self.rev_id = 0; + } + + // Param is passed by value, moved + pub fn set_rev_id(&mut self, v: i64) { + self.rev_id = v; + } +} + +impl ::protobuf::Message for DocumentConnected { + 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_singular_proto3_string_into(wire_type, is, &mut self.user_id)?; + }, + 2 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.doc_id)?; + }, + 3 => { + if wire_type != ::protobuf::wire_format::WireTypeVarint { + return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); + } + let tmp = is.read_int64()?; + self.rev_id = tmp; + }, + _ => { + ::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.user_id.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.user_id); + } + if !self.doc_id.is_empty() { + my_size += ::protobuf::rt::string_size(2, &self.doc_id); + } + if self.rev_id != 0 { + my_size += ::protobuf::rt::value_size(3, self.rev_id, ::protobuf::wire_format::WireTypeVarint); + } + 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.user_id.is_empty() { + os.write_string(1, &self.user_id)?; + } + if !self.doc_id.is_empty() { + os.write_string(2, &self.doc_id)?; + } + if self.rev_id != 0 { + os.write_int64(3, self.rev_id)?; + } + 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) -> ::std::boxed::Box { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + Self::descriptor_static() + } + + fn new() -> DocumentConnected { + DocumentConnected::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::ProtobufTypeString>( + "user_id", + |m: &DocumentConnected| { &m.user_id }, + |m: &mut DocumentConnected| { &mut m.user_id }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "doc_id", + |m: &DocumentConnected| { &m.doc_id }, + |m: &mut DocumentConnected| { &mut m.doc_id }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeInt64>( + "rev_id", + |m: &DocumentConnected| { &m.rev_id }, + |m: &mut DocumentConnected| { &mut m.rev_id }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "DocumentConnected", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static DocumentConnected { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(DocumentConnected::new) + } +} + +impl ::protobuf::Clear for DocumentConnected { + fn clear(&mut self) { + self.user_id.clear(); + self.doc_id.clear(); + self.rev_id = 0; + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for DocumentConnected { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for DocumentConnected { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + #[derive(Clone,PartialEq,Eq,Debug,Hash)] -pub enum WsDataType { +pub enum WsDocumentDataType { Acked = 0, PushRev = 1, PullRev = 2, - Conflict = 3, + UserConnect = 3, } -impl ::protobuf::ProtobufEnum for WsDataType { +impl ::protobuf::ProtobufEnum for WsDocumentDataType { fn value(&self) -> i32 { *self as i32 } - fn from_i32(value: i32) -> ::std::option::Option { + fn from_i32(value: i32) -> ::std::option::Option { match value { - 0 => ::std::option::Option::Some(WsDataType::Acked), - 1 => ::std::option::Option::Some(WsDataType::PushRev), - 2 => ::std::option::Option::Some(WsDataType::PullRev), - 3 => ::std::option::Option::Some(WsDataType::Conflict), + 0 => ::std::option::Option::Some(WsDocumentDataType::Acked), + 1 => ::std::option::Option::Some(WsDocumentDataType::PushRev), + 2 => ::std::option::Option::Some(WsDocumentDataType::PullRev), + 3 => ::std::option::Option::Some(WsDocumentDataType::UserConnect), _ => ::std::option::Option::None } } fn values() -> &'static [Self] { - static values: &'static [WsDataType] = &[ - WsDataType::Acked, - WsDataType::PushRev, - WsDataType::PullRev, - WsDataType::Conflict, + static values: &'static [WsDocumentDataType] = &[ + WsDocumentDataType::Acked, + WsDocumentDataType::PushRev, + WsDocumentDataType::PullRev, + WsDocumentDataType::UserConnect, ]; values } @@ -291,51 +527,63 @@ impl ::protobuf::ProtobufEnum for WsDataType { 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::("WsDataType", file_descriptor_proto()) + ::protobuf::reflect::EnumDescriptor::new_pb_name::("WsDocumentDataType", file_descriptor_proto()) }) } } -impl ::std::marker::Copy for WsDataType { +impl ::std::marker::Copy for WsDocumentDataType { } -impl ::std::default::Default for WsDataType { +impl ::std::default::Default for WsDocumentDataType { fn default() -> Self { - WsDataType::Acked + WsDocumentDataType::Acked } } -impl ::protobuf::reflect::ProtobufValue for WsDataType { +impl ::protobuf::reflect::ProtobufValue for WsDocumentDataType { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { ::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self)) } } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x08ws.proto\"X\n\x0eWsDocumentData\x12\x15\n\x06doc_id\x18\x01\x20\ - \x01(\tR\x05docId\x12\x1b\n\x02ty\x18\x02\x20\x01(\x0e2\x0b.WsDataTypeR\ - \x02ty\x12\x12\n\x04data\x18\x03\x20\x01(\x0cR\x04data*?\n\nWsDataType\ - \x12\t\n\x05Acked\x10\0\x12\x0b\n\x07PushRev\x10\x01\x12\x0b\n\x07PullRe\ - v\x10\x02\x12\x0c\n\x08Conflict\x10\x03J\x8b\x03\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\x06\ - \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\x16\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\ - \x05\x04\0\x02\0\x01\x12\x03\x03\x0b\x11\n\x0c\n\x05\x04\0\x02\0\x03\x12\ - \x03\x03\x14\x15\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x04\x04\x16\n\x0c\n\ - \x05\x04\0\x02\x01\x06\x12\x03\x04\x04\x0e\n\x0c\n\x05\x04\0\x02\x01\x01\ - \x12\x03\x04\x0f\x11\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x04\x14\x15\n\ - \x0b\n\x04\x04\0\x02\x02\x12\x03\x05\x04\x13\n\x0c\n\x05\x04\0\x02\x02\ - \x05\x12\x03\x05\x04\t\n\x0c\n\x05\x04\0\x02\x02\x01\x12\x03\x05\n\x0e\n\ - \x0c\n\x05\x04\0\x02\x02\x03\x12\x03\x05\x11\x12\n\n\n\x02\x05\0\x12\x04\ - \x07\0\x0c\x01\n\n\n\x03\x05\0\x01\x12\x03\x07\x05\x0f\n\x0b\n\x04\x05\0\ - \x02\0\x12\x03\x08\x04\x0e\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\x08\x04\t\ - \n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x08\x0c\r\n\x0b\n\x04\x05\0\x02\x01\ - \x12\x03\t\x04\x10\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\t\x04\x0b\n\x0c\ - \n\x05\x05\0\x02\x01\x02\x12\x03\t\x0e\x0f\n\x0b\n\x04\x05\0\x02\x02\x12\ - \x03\n\x04\x10\n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\n\x04\x0b\n\x0c\n\ - \x05\x05\0\x02\x02\x02\x12\x03\n\x0e\x0f\n\x0b\n\x04\x05\0\x02\x03\x12\ - \x03\x0b\x04\x11\n\x0c\n\x05\x05\0\x02\x03\x01\x12\x03\x0b\x04\x0c\n\x0c\ - \n\x05\x05\0\x02\x03\x02\x12\x03\x0b\x0f\x10b\x06proto3\ + \n\x08ws.proto\"`\n\x0eWsDocumentData\x12\x15\n\x06doc_id\x18\x01\x20\ + \x01(\tR\x05docId\x12#\n\x02ty\x18\x02\x20\x01(\x0e2\x13.WsDocumentDataT\ + ypeR\x02ty\x12\x12\n\x04data\x18\x03\x20\x01(\x0cR\x04data\"Z\n\x11Docum\ + entConnected\x12\x17\n\x07user_id\x18\x01\x20\x01(\tR\x06userId\x12\x15\ + \n\x06doc_id\x18\x02\x20\x01(\tR\x05docId\x12\x15\n\x06rev_id\x18\x03\ + \x20\x01(\x03R\x05revId*J\n\x12WsDocumentDataType\x12\t\n\x05Acked\x10\0\ + \x12\x0b\n\x07PushRev\x10\x01\x12\x0b\n\x07PullRev\x10\x02\x12\x0f\n\x0b\ + UserConnect\x10\x03J\xc8\x04\n\x06\x12\x04\0\0\x11\x01\n\x08\n\x01\x0c\ + \x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x06\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\x16\n\ + \x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\ + \x12\x03\x03\x0b\x11\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x14\x15\n\ + \x0b\n\x04\x04\0\x02\x01\x12\x03\x04\x04\x1e\n\x0c\n\x05\x04\0\x02\x01\ + \x06\x12\x03\x04\x04\x16\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\x17\ + \x19\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x04\x1c\x1d\n\x0b\n\x04\x04\0\ + \x02\x02\x12\x03\x05\x04\x13\n\x0c\n\x05\x04\0\x02\x02\x05\x12\x03\x05\ + \x04\t\n\x0c\n\x05\x04\0\x02\x02\x01\x12\x03\x05\n\x0e\n\x0c\n\x05\x04\0\ + \x02\x02\x03\x12\x03\x05\x11\x12\n\n\n\x02\x04\x01\x12\x04\x07\0\x0b\x01\ + \n\n\n\x03\x04\x01\x01\x12\x03\x07\x08\x19\n\x0b\n\x04\x04\x01\x02\0\x12\ + \x03\x08\x04\x17\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03\x08\x04\n\n\x0c\n\ + \x05\x04\x01\x02\0\x01\x12\x03\x08\x0b\x12\n\x0c\n\x05\x04\x01\x02\0\x03\ + \x12\x03\x08\x15\x16\n\x0b\n\x04\x04\x01\x02\x01\x12\x03\t\x04\x16\n\x0c\ + \n\x05\x04\x01\x02\x01\x05\x12\x03\t\x04\n\n\x0c\n\x05\x04\x01\x02\x01\ + \x01\x12\x03\t\x0b\x11\n\x0c\n\x05\x04\x01\x02\x01\x03\x12\x03\t\x14\x15\ + \n\x0b\n\x04\x04\x01\x02\x02\x12\x03\n\x04\x15\n\x0c\n\x05\x04\x01\x02\ + \x02\x05\x12\x03\n\x04\t\n\x0c\n\x05\x04\x01\x02\x02\x01\x12\x03\n\n\x10\ + \n\x0c\n\x05\x04\x01\x02\x02\x03\x12\x03\n\x13\x14\n\n\n\x02\x05\0\x12\ + \x04\x0c\0\x11\x01\n\n\n\x03\x05\0\x01\x12\x03\x0c\x05\x17\n\x0b\n\x04\ + \x05\0\x02\0\x12\x03\r\x04\x0e\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\r\x04\ + \t\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\r\x0c\r\n\x0b\n\x04\x05\0\x02\x01\ + \x12\x03\x0e\x04\x10\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x0e\x04\x0b\n\ + \x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x0e\x0e\x0f\n\x0b\n\x04\x05\0\x02\ + \x02\x12\x03\x0f\x04\x10\n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\x0f\x04\ + \x0b\n\x0c\n\x05\x05\0\x02\x02\x02\x12\x03\x0f\x0e\x0f\n\x0b\n\x04\x05\0\ + \x02\x03\x12\x03\x10\x04\x14\n\x0c\n\x05\x05\0\x02\x03\x01\x12\x03\x10\ + \x04\x0f\n\x0c\n\x05\x05\0\x02\x03\x02\x12\x03\x10\x12\x13b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/shared-lib/flowy-collaboration/src/protobuf/proto/ws.proto b/shared-lib/flowy-collaboration/src/protobuf/proto/ws.proto index 423a3e3869..35a10bbbcf 100644 --- a/shared-lib/flowy-collaboration/src/protobuf/proto/ws.proto +++ b/shared-lib/flowy-collaboration/src/protobuf/proto/ws.proto @@ -2,12 +2,17 @@ syntax = "proto3"; message WsDocumentData { string doc_id = 1; - WsDataType ty = 2; + WsDocumentDataType ty = 2; bytes data = 3; } -enum WsDataType { +message DocumentConnected { + string user_id = 1; + string doc_id = 2; + int64 rev_id = 3; +} +enum WsDocumentDataType { Acked = 0; PushRev = 1; PullRev = 2; - Conflict = 3; + UserConnect = 3; } diff --git a/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs b/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs index 3e314e6a7f..4c178596a8 100644 --- a/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs +++ b/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs @@ -61,6 +61,7 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { | "NewDocUser" | "DocIdentifier" | "WsDocumentData" + | "DocumentConnected" | "WsError" | "WsMessage" | "Revision" @@ -88,7 +89,7 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { | "TrashType" | "ViewType" | "ExportType" - | "WsDataType" + | "WsDocumentDataType" | "ErrorCode" | "WsModule" | "RevType" diff --git a/shared-lib/lib-ot/src/revision/model.rs b/shared-lib/lib-ot/src/revision/model.rs index 2b7b55cc58..f9ba9aa837 100644 --- a/shared-lib/lib-ot/src/revision/model.rs +++ b/shared-lib/lib-ot/src/revision/model.rs @@ -1,7 +1,7 @@ use crate::rich_text::RichTextDelta; use bytes::Bytes; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; -use std::{fmt::Formatter, ops::RangeInclusive}; +use std::{convert::TryFrom, fmt::Formatter, ops::RangeInclusive}; #[derive(PartialEq, Eq, Clone, Default, ProtoBuf)] pub struct Revision { @@ -27,6 +27,13 @@ pub struct Revision { pub user_id: String, } +impl std::convert::From> for Revision { + fn from(data: Vec) -> Self { + let bytes = Bytes::from(data); + Revision::try_from(bytes).unwrap() + } +} + impl Revision { pub fn is_empty(&self) -> bool { self.base_rev_id == self.rev_id } diff --git a/shared-lib/lib-ws/src/ws.rs b/shared-lib/lib-ws/src/ws.rs index b33870dca9..ba62f4a454 100644 --- a/shared-lib/lib-ws/src/ws.rs +++ b/shared-lib/lib-ws/src/ws.rs @@ -30,9 +30,9 @@ use tokio_tungstenite::tungstenite::{ pub type MsgReceiver = UnboundedReceiver; pub type MsgSender = UnboundedSender; -type Handlers = DashMap>; +type Handlers = DashMap>; -pub trait WsMessageHandler: Sync + Send + 'static { +pub trait WsMessageReceiver: Sync + Send + 'static { fn source(&self) -> WsModule; fn receive_message(&self, msg: WsMessage); } @@ -59,7 +59,7 @@ impl std::default::Default for WsController { impl WsController { pub fn new() -> Self { WsController::default() } - pub fn add_handler(&self, handler: Arc) -> Result<(), WsError> { + pub fn add_receiver(&self, handler: Arc) -> Result<(), WsError> { let source = handler.source(); if self.handlers.contains_key(&source) { log::error!("WsSource's {:?} is already registered", source); From 405c618d27d776deb1f76523a52c848faded56b9 Mon Sep 17 00:00:00 2001 From: appflowy Date: Thu, 16 Dec 2021 22:24:05 +0800 Subject: [PATCH 32/39] rename some struct --- backend/src/context.rs | 4 +- backend/src/services/doc/ws_actor.rs | 12 +- backend/src/web_socket/biz_handler.rs | 8 +- backend/src/web_socket/entities/message.rs | 12 +- backend/src/web_socket/ws_client.rs | 4 +- .../protobuf/flowy-collaboration/ws.pb.dart | 61 +++- .../flowy-collaboration/ws.pbenum.dart | 18 +- .../flowy-collaboration/ws.pbjson.dart | 26 +- .../lib/protobuf/lib-ws/errors.pb.dart | 26 +- .../lib/protobuf/lib-ws/errors.pbjson.dart | 10 +- .../flowy_sdk/lib/protobuf/lib-ws/msg.pb.dart | 34 +- .../lib/protobuf/lib-ws/msg.pbenum.dart | 12 +- .../lib/protobuf/lib-ws/msg.pbjson.dart | 22 +- .../src/services/doc/edit/edit_queue.rs | 207 ++++++++++++ .../src/services/doc/edit/edit_ws.rs | 297 ++++++++++++++++++ .../src/services/doc/edit/editor.rs | 42 ++- .../flowy-document/src/services/doc/ws/mod.rs | 0 .../src/services/doc/ws_handlers.rs | 67 ++++ .../flowy-net/src/services/mock/ws_mock.rs | 42 +-- .../flowy-net/src/services/ws/conn.rs | 8 +- .../flowy-net/src/services/ws/manager.rs | 26 +- .../flowy-net/src/services/ws/ws_local.rs | 14 +- .../src/deps_resolve/document_deps.rs | 16 +- frontend/scripts/flowy-tool/src/proto/ast.rs | 2 +- .../src/core/sync/synchronizer.rs | 63 +--- .../flowy-collaboration/src/entities/ws/ws.rs | 51 +-- .../src/protobuf/model/ws.rs | 233 +++++++++----- .../src/protobuf/proto/ws.proto | 7 +- .../src/derive_cache/derive_cache.rs | 10 +- shared-lib/lib-ws/src/connect.rs | 32 +- shared-lib/lib-ws/src/errors.rs | 44 +-- shared-lib/lib-ws/src/msg.rs | 18 +- .../lib-ws/src/protobuf/model/errors.rs | 44 +-- shared-lib/lib-ws/src/protobuf/model/msg.rs | 88 +++--- .../lib-ws/src/protobuf/proto/errors.proto | 2 +- .../lib-ws/src/protobuf/proto/msg.proto | 6 +- shared-lib/lib-ws/src/ws.rs | 168 +++++----- 37 files changed, 1199 insertions(+), 537 deletions(-) create mode 100644 frontend/rust-lib/flowy-document/src/services/doc/edit/edit_queue.rs create mode 100644 frontend/rust-lib/flowy-document/src/services/doc/edit/edit_ws.rs create mode 100644 frontend/rust-lib/flowy-document/src/services/doc/ws/mod.rs create mode 100644 frontend/rust-lib/flowy-document/src/services/doc/ws_handlers.rs diff --git a/backend/src/context.rs b/backend/src/context.rs index cfe56c68dd..082e2e5240 100644 --- a/backend/src/context.rs +++ b/backend/src/context.rs @@ -4,7 +4,7 @@ use crate::{ }; use actix::Addr; use actix_web::web::Data; -use lib_ws::WsModule; +use lib_ws::WSModule; use sqlx::PgPool; use std::sync::Arc; @@ -23,7 +23,7 @@ impl AppContext { let mut ws_bizs = WsBizHandlers::new(); let document_core = Arc::new(DocumentCore::new(pg_pool.clone())); - ws_bizs.register(WsModule::Doc, document_core.clone()); + ws_bizs.register(WSModule::Doc, document_core.clone()); AppContext { ws_server, diff --git a/backend/src/services/doc/ws_actor.rs b/backend/src/services/doc/ws_actor.rs index 10d5c3984f..edf24ac920 100644 --- a/backend/src/services/doc/ws_actor.rs +++ b/backend/src/services/doc/ws_actor.rs @@ -11,7 +11,7 @@ use async_stream::stream; use backend_service::errors::{internal_error, Result, ServerError}; use flowy_collaboration::{ core::sync::ServerDocManager, - protobuf::{WsDocumentData, WsDocumentDataType}, + protobuf::{DocumentWSData, DocumentWSDataType}, }; use futures::stream::StreamExt; use lib_ot::protobuf::Revision; @@ -69,7 +69,7 @@ impl DocWsActor { async fn handle_client_data(&self, client_data: WsClientData, pool: Data) -> Result<()> { let WsClientData { user, socket, data } = client_data; let document_data = spawn_blocking(move || { - let document_data: WsDocumentData = parse_from_bytes(&data)?; + let document_data: DocumentWSData = parse_from_bytes(&data)?; Result::Ok(document_data) }) .await @@ -78,10 +78,10 @@ impl DocWsActor { let data = document_data.data; match document_data.ty { - WsDocumentDataType::Acked => Ok(()), - WsDocumentDataType::PushRev => self.apply_pushed_rev(user, socket, data, pool).await, - WsDocumentDataType::PullRev => Ok(()), - WsDocumentDataType::UserConnect => Ok(()), + DocumentWSDataType::Acked => Ok(()), + DocumentWSDataType::PushRev => self.apply_pushed_rev(user, socket, data, pool).await, + DocumentWSDataType::PullRev => Ok(()), + DocumentWSDataType::UserConnect => Ok(()), } } diff --git a/backend/src/web_socket/biz_handler.rs b/backend/src/web_socket/biz_handler.rs index 144ee0ac79..e4c62b8981 100644 --- a/backend/src/web_socket/biz_handler.rs +++ b/backend/src/web_socket/biz_handler.rs @@ -1,5 +1,5 @@ use crate::web_socket::WsClientData; -use lib_ws::WsModule; +use lib_ws::WSModule; use std::{collections::HashMap, sync::Arc}; pub trait WsBizHandler: Send + Sync { @@ -8,7 +8,7 @@ pub trait WsBizHandler: Send + Sync { pub type BizHandler = Arc; pub struct WsBizHandlers { - inner: HashMap, + inner: HashMap, } impl std::default::Default for WsBizHandlers { @@ -18,7 +18,7 @@ impl std::default::Default for WsBizHandlers { impl WsBizHandlers { pub fn new() -> Self { WsBizHandlers::default() } - pub fn register(&mut self, source: WsModule, handler: BizHandler) { self.inner.insert(source, handler); } + pub fn register(&mut self, source: WSModule, handler: BizHandler) { self.inner.insert(source, handler); } - pub fn get(&self, source: &WsModule) -> Option { self.inner.get(source).cloned() } + pub fn get(&self, source: &WSModule) -> Option { self.inner.get(source).cloned() } } diff --git a/backend/src/web_socket/entities/message.rs b/backend/src/web_socket/entities/message.rs index 9438d9587e..c65ca69ea4 100644 --- a/backend/src/web_socket/entities/message.rs +++ b/backend/src/web_socket/entities/message.rs @@ -1,7 +1,7 @@ use actix::Message; use bytes::Bytes; -use flowy_collaboration::entities::ws::WsDocumentData; -use lib_ws::{WsMessage, WsModule}; +use flowy_collaboration::entities::ws::DocumentWSData; +use lib_ws::{WSMessage, WSModule}; use std::convert::TryInto; #[derive(Debug, Message, Clone)] @@ -14,11 +14,11 @@ impl std::ops::Deref for WsMessageAdaptor { fn deref(&self) -> &Self::Target { &self.0 } } -impl std::convert::From for WsMessageAdaptor { - fn from(data: WsDocumentData) -> Self { +impl std::convert::From for WsMessageAdaptor { + fn from(data: DocumentWSData) -> Self { let bytes: Bytes = data.try_into().unwrap(); - let msg = WsMessage { - module: WsModule::Doc, + let msg = WSMessage { + module: WSModule::Doc, data: bytes.to_vec(), }; diff --git a/backend/src/web_socket/ws_client.rs b/backend/src/web_socket/ws_client.rs index f2365958fd..c048f7e0b9 100644 --- a/backend/src/web_socket/ws_client.rs +++ b/backend/src/web_socket/ws_client.rs @@ -12,7 +12,7 @@ use actix::*; use actix_web::web::Data; use actix_web_actors::{ws, ws::Message::Text}; use bytes::Bytes; -use lib_ws::WsMessage; +use lib_ws::WSMessage; use std::{convert::TryFrom, sync::Arc, time::Instant}; #[derive(Debug)] @@ -64,7 +64,7 @@ impl WsClient { fn handle_binary_message(&self, bytes: Bytes, socket: Socket) { // TODO: ok to unwrap? - let message: WsMessage = WsMessage::try_from(bytes).unwrap(); + let message: WSMessage = WSMessage::try_from(bytes).unwrap(); match self.biz_handlers.get(&message.module) { None => { log::error!("Can't find the handler for {:?}", message.module); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pb.dart index df1ef65a13..53eff22b3b 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pb.dart @@ -14,19 +14,31 @@ import 'ws.pbenum.dart'; export 'ws.pbenum.dart'; -class WsDocumentData extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'WsDocumentData', createEmptyInstance: create) +enum DocumentWSData_OneOfId { + id, + notSet +} + +class DocumentWSData extends $pb.GeneratedMessage { + static const $core.Map<$core.int, DocumentWSData_OneOfId> _DocumentWSData_OneOfIdByTag = { + 4 : DocumentWSData_OneOfId.id, + 0 : DocumentWSData_OneOfId.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DocumentWSData', createEmptyInstance: create) + ..oo(0, [4]) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'docId') - ..e(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'ty', $pb.PbFieldType.OE, defaultOrMaker: WsDocumentDataType.Acked, valueOf: WsDocumentDataType.valueOf, enumValues: WsDocumentDataType.values) + ..e(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'ty', $pb.PbFieldType.OE, defaultOrMaker: DocumentWSDataType.Acked, valueOf: DocumentWSDataType.valueOf, enumValues: DocumentWSDataType.values) ..a<$core.List<$core.int>>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data', $pb.PbFieldType.OY) + ..aInt64(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id') ..hasRequiredFields = false ; - WsDocumentData._() : super(); - factory WsDocumentData({ + DocumentWSData._() : super(); + factory DocumentWSData({ $core.String? docId, - WsDocumentDataType? ty, + DocumentWSDataType? ty, $core.List<$core.int>? data, + $fixnum.Int64? id, }) { final _result = create(); if (docId != null) { @@ -38,28 +50,34 @@ class WsDocumentData extends $pb.GeneratedMessage { if (data != null) { _result.data = data; } + if (id != null) { + _result.id = id; + } return _result; } - factory WsDocumentData.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory WsDocumentData.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + factory DocumentWSData.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory DocumentWSData.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' 'Will be removed in next major version') - WsDocumentData clone() => WsDocumentData()..mergeFromMessage(this); + DocumentWSData clone() => DocumentWSData()..mergeFromMessage(this); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - WsDocumentData copyWith(void Function(WsDocumentData) updates) => super.copyWith((message) => updates(message as WsDocumentData)) as WsDocumentData; // ignore: deprecated_member_use + DocumentWSData copyWith(void Function(DocumentWSData) updates) => super.copyWith((message) => updates(message as DocumentWSData)) as DocumentWSData; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; @$core.pragma('dart2js:noInline') - static WsDocumentData create() => WsDocumentData._(); - WsDocumentData createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); + static DocumentWSData create() => DocumentWSData._(); + DocumentWSData createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); @$core.pragma('dart2js:noInline') - static WsDocumentData getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static WsDocumentData? _defaultInstance; + static DocumentWSData getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static DocumentWSData? _defaultInstance; + + DocumentWSData_OneOfId whichOneOfId() => _DocumentWSData_OneOfIdByTag[$_whichOneof(0)]!; + void clearOneOfId() => clearField($_whichOneof(0)); @$pb.TagNumber(1) $core.String get docId => $_getSZ(0); @@ -71,9 +89,9 @@ class WsDocumentData extends $pb.GeneratedMessage { void clearDocId() => clearField(1); @$pb.TagNumber(2) - WsDocumentDataType get ty => $_getN(1); + DocumentWSDataType get ty => $_getN(1); @$pb.TagNumber(2) - set ty(WsDocumentDataType v) { setField(2, v); } + set ty(DocumentWSDataType v) { setField(2, v); } @$pb.TagNumber(2) $core.bool hasTy() => $_has(1); @$pb.TagNumber(2) @@ -87,6 +105,15 @@ class WsDocumentData extends $pb.GeneratedMessage { $core.bool hasData() => $_has(2); @$pb.TagNumber(3) void clearData() => clearField(3); + + @$pb.TagNumber(4) + $fixnum.Int64 get id => $_getI64(3); + @$pb.TagNumber(4) + set id($fixnum.Int64 v) { $_setInt64(3, v); } + @$pb.TagNumber(4) + $core.bool hasId() => $_has(3); + @$pb.TagNumber(4) + void clearId() => clearField(4); } class DocumentConnected extends $pb.GeneratedMessage { diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbenum.dart index b11c8b7fa1..83be5c1784 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbenum.dart @@ -9,22 +9,22 @@ import 'dart:core' as $core; import 'package:protobuf/protobuf.dart' as $pb; -class WsDocumentDataType extends $pb.ProtobufEnum { - static const WsDocumentDataType Acked = WsDocumentDataType._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Acked'); - static const WsDocumentDataType PushRev = WsDocumentDataType._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PushRev'); - static const WsDocumentDataType PullRev = WsDocumentDataType._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PullRev'); - static const WsDocumentDataType UserConnect = WsDocumentDataType._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserConnect'); +class DocumentWSDataType extends $pb.ProtobufEnum { + static const DocumentWSDataType Acked = DocumentWSDataType._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Acked'); + static const DocumentWSDataType PushRev = DocumentWSDataType._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PushRev'); + static const DocumentWSDataType PullRev = DocumentWSDataType._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PullRev'); + static const DocumentWSDataType UserConnect = DocumentWSDataType._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserConnect'); - static const $core.List values = [ + static const $core.List values = [ Acked, PushRev, PullRev, UserConnect, ]; - static final $core.Map<$core.int, WsDocumentDataType> _byValue = $pb.ProtobufEnum.initByValue(values); - static WsDocumentDataType? valueOf($core.int value) => _byValue[value]; + static final $core.Map<$core.int, DocumentWSDataType> _byValue = $pb.ProtobufEnum.initByValue(values); + static DocumentWSDataType? valueOf($core.int value) => _byValue[value]; - const WsDocumentDataType._($core.int v, $core.String n) : super(v, n); + const DocumentWSDataType._($core.int v, $core.String n) : super(v, n); } diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbjson.dart index 9917157067..2bcc352adf 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbjson.dart @@ -8,9 +8,9 @@ import 'dart:core' as $core; import 'dart:convert' as $convert; import 'dart:typed_data' as $typed_data; -@$core.Deprecated('Use wsDocumentDataTypeDescriptor instead') -const WsDocumentDataType$json = const { - '1': 'WsDocumentDataType', +@$core.Deprecated('Use documentWSDataTypeDescriptor instead') +const DocumentWSDataType$json = const { + '1': 'DocumentWSDataType', '2': const [ const {'1': 'Acked', '2': 0}, const {'1': 'PushRev', '2': 1}, @@ -19,20 +19,24 @@ const WsDocumentDataType$json = const { ], }; -/// Descriptor for `WsDocumentDataType`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List wsDocumentDataTypeDescriptor = $convert.base64Decode('ChJXc0RvY3VtZW50RGF0YVR5cGUSCQoFQWNrZWQQABILCgdQdXNoUmV2EAESCwoHUHVsbFJldhACEg8KC1VzZXJDb25uZWN0EAM='); -@$core.Deprecated('Use wsDocumentDataDescriptor instead') -const WsDocumentData$json = const { - '1': 'WsDocumentData', +/// Descriptor for `DocumentWSDataType`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List documentWSDataTypeDescriptor = $convert.base64Decode('ChJEb2N1bWVudFdTRGF0YVR5cGUSCQoFQWNrZWQQABILCgdQdXNoUmV2EAESCwoHUHVsbFJldhACEg8KC1VzZXJDb25uZWN0EAM='); +@$core.Deprecated('Use documentWSDataDescriptor instead') +const DocumentWSData$json = const { + '1': 'DocumentWSData', '2': const [ const {'1': 'doc_id', '3': 1, '4': 1, '5': 9, '10': 'docId'}, - const {'1': 'ty', '3': 2, '4': 1, '5': 14, '6': '.WsDocumentDataType', '10': 'ty'}, + const {'1': 'ty', '3': 2, '4': 1, '5': 14, '6': '.DocumentWSDataType', '10': 'ty'}, const {'1': 'data', '3': 3, '4': 1, '5': 12, '10': 'data'}, + const {'1': 'id', '3': 4, '4': 1, '5': 3, '9': 0, '10': 'id'}, + ], + '8': const [ + const {'1': 'one_of_id'}, ], }; -/// Descriptor for `WsDocumentData`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List wsDocumentDataDescriptor = $convert.base64Decode('Cg5Xc0RvY3VtZW50RGF0YRIVCgZkb2NfaWQYASABKAlSBWRvY0lkEiMKAnR5GAIgASgOMhMuV3NEb2N1bWVudERhdGFUeXBlUgJ0eRISCgRkYXRhGAMgASgMUgRkYXRh'); +/// Descriptor for `DocumentWSData`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List documentWSDataDescriptor = $convert.base64Decode('Cg5Eb2N1bWVudFdTRGF0YRIVCgZkb2NfaWQYASABKAlSBWRvY0lkEiMKAnR5GAIgASgOMhMuRG9jdW1lbnRXU0RhdGFUeXBlUgJ0eRISCgRkYXRhGAMgASgMUgRkYXRhEhAKAmlkGAQgASgDSABSAmlkQgsKCW9uZV9vZl9pZA=='); @$core.Deprecated('Use documentConnectedDescriptor instead') const DocumentConnected$json = const { '1': 'DocumentConnected', diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ws/errors.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ws/errors.pb.dart index 63c73c28f3..f85e4e8280 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ws/errors.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ws/errors.pb.dart @@ -13,15 +13,15 @@ import 'errors.pbenum.dart'; export 'errors.pbenum.dart'; -class WsError extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'WsError', createEmptyInstance: create) +class WSError extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'WSError', createEmptyInstance: create) ..e(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'code', $pb.PbFieldType.OE, defaultOrMaker: ErrorCode.InternalError, valueOf: ErrorCode.valueOf, enumValues: ErrorCode.values) ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'msg') ..hasRequiredFields = false ; - WsError._() : super(); - factory WsError({ + WSError._() : super(); + factory WSError({ ErrorCode? code, $core.String? msg, }) { @@ -34,26 +34,26 @@ class WsError extends $pb.GeneratedMessage { } return _result; } - factory WsError.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory WsError.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + factory WSError.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory WSError.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' 'Will be removed in next major version') - WsError clone() => WsError()..mergeFromMessage(this); + WSError clone() => WSError()..mergeFromMessage(this); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - WsError copyWith(void Function(WsError) updates) => super.copyWith((message) => updates(message as WsError)) as WsError; // ignore: deprecated_member_use + WSError copyWith(void Function(WSError) updates) => super.copyWith((message) => updates(message as WSError)) as WSError; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; @$core.pragma('dart2js:noInline') - static WsError create() => WsError._(); - WsError createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); + static WSError create() => WSError._(); + WSError createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); @$core.pragma('dart2js:noInline') - static WsError getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static WsError? _defaultInstance; + static WSError getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static WSError? _defaultInstance; @$pb.TagNumber(1) ErrorCode get code => $_getN(0); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ws/errors.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ws/errors.pbjson.dart index c1039debcf..69eff54ee8 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ws/errors.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ws/errors.pbjson.dart @@ -20,14 +20,14 @@ const ErrorCode$json = const { /// Descriptor for `ErrorCode`. Decode as a `google.protobuf.EnumDescriptorProto`. final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSEQoNSW50ZXJuYWxFcnJvchAAEhYKElVuc3VwcG9ydGVkTWVzc2FnZRABEhAKDFVuYXV0aG9yaXplZBAC'); -@$core.Deprecated('Use wsErrorDescriptor instead') -const WsError$json = const { - '1': 'WsError', +@$core.Deprecated('Use wSErrorDescriptor instead') +const WSError$json = const { + '1': 'WSError', '2': const [ const {'1': 'code', '3': 1, '4': 1, '5': 14, '6': '.ErrorCode', '10': 'code'}, const {'1': 'msg', '3': 2, '4': 1, '5': 9, '10': 'msg'}, ], }; -/// Descriptor for `WsError`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List wsErrorDescriptor = $convert.base64Decode('CgdXc0Vycm9yEh4KBGNvZGUYASABKA4yCi5FcnJvckNvZGVSBGNvZGUSEAoDbXNnGAIgASgJUgNtc2c='); +/// Descriptor for `WSError`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List wSErrorDescriptor = $convert.base64Decode('CgdXU0Vycm9yEh4KBGNvZGUYASABKA4yCi5FcnJvckNvZGVSBGNvZGUSEAoDbXNnGAIgASgJUgNtc2c='); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ws/msg.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ws/msg.pb.dart index 0c07e01026..d71cbad363 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ws/msg.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ws/msg.pb.dart @@ -13,16 +13,16 @@ import 'msg.pbenum.dart'; export 'msg.pbenum.dart'; -class WsMessage extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'WsMessage', createEmptyInstance: create) - ..e(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'module', $pb.PbFieldType.OE, defaultOrMaker: WsModule.Doc, valueOf: WsModule.valueOf, enumValues: WsModule.values) +class WSMessage extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'WSMessage', createEmptyInstance: create) + ..e(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'module', $pb.PbFieldType.OE, defaultOrMaker: WSModule.Doc, valueOf: WSModule.valueOf, enumValues: WSModule.values) ..a<$core.List<$core.int>>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data', $pb.PbFieldType.OY) ..hasRequiredFields = false ; - WsMessage._() : super(); - factory WsMessage({ - WsModule? module, + WSMessage._() : super(); + factory WSMessage({ + WSModule? module, $core.List<$core.int>? data, }) { final _result = create(); @@ -34,31 +34,31 @@ class WsMessage extends $pb.GeneratedMessage { } return _result; } - factory WsMessage.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory WsMessage.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + factory WSMessage.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory WSMessage.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' 'Will be removed in next major version') - WsMessage clone() => WsMessage()..mergeFromMessage(this); + WSMessage clone() => WSMessage()..mergeFromMessage(this); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - WsMessage copyWith(void Function(WsMessage) updates) => super.copyWith((message) => updates(message as WsMessage)) as WsMessage; // ignore: deprecated_member_use + WSMessage copyWith(void Function(WSMessage) updates) => super.copyWith((message) => updates(message as WSMessage)) as WSMessage; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; @$core.pragma('dart2js:noInline') - static WsMessage create() => WsMessage._(); - WsMessage createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); + static WSMessage create() => WSMessage._(); + WSMessage createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); @$core.pragma('dart2js:noInline') - static WsMessage getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static WsMessage? _defaultInstance; + static WSMessage getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static WSMessage? _defaultInstance; @$pb.TagNumber(1) - WsModule get module => $_getN(0); + WSModule get module => $_getN(0); @$pb.TagNumber(1) - set module(WsModule v) { setField(1, v); } + set module(WSModule v) { setField(1, v); } @$pb.TagNumber(1) $core.bool hasModule() => $_has(0); @$pb.TagNumber(1) diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ws/msg.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ws/msg.pbenum.dart index dddbfe6eaa..9b4fbd51b0 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ws/msg.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ws/msg.pbenum.dart @@ -9,16 +9,16 @@ import 'dart:core' as $core; import 'package:protobuf/protobuf.dart' as $pb; -class WsModule extends $pb.ProtobufEnum { - static const WsModule Doc = WsModule._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Doc'); +class WSModule extends $pb.ProtobufEnum { + static const WSModule Doc = WSModule._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Doc'); - static const $core.List values = [ + static const $core.List values = [ Doc, ]; - static final $core.Map<$core.int, WsModule> _byValue = $pb.ProtobufEnum.initByValue(values); - static WsModule? valueOf($core.int value) => _byValue[value]; + static final $core.Map<$core.int, WSModule> _byValue = $pb.ProtobufEnum.initByValue(values); + static WSModule? valueOf($core.int value) => _byValue[value]; - const WsModule._($core.int v, $core.String n) : super(v, n); + const WSModule._($core.int v, $core.String n) : super(v, n); } diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ws/msg.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ws/msg.pbjson.dart index 13899cc203..ca42294573 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ws/msg.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/lib-ws/msg.pbjson.dart @@ -8,24 +8,24 @@ import 'dart:core' as $core; import 'dart:convert' as $convert; import 'dart:typed_data' as $typed_data; -@$core.Deprecated('Use wsModuleDescriptor instead') -const WsModule$json = const { - '1': 'WsModule', +@$core.Deprecated('Use wSModuleDescriptor instead') +const WSModule$json = const { + '1': 'WSModule', '2': const [ const {'1': 'Doc', '2': 0}, ], }; -/// Descriptor for `WsModule`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List wsModuleDescriptor = $convert.base64Decode('CghXc01vZHVsZRIHCgNEb2MQAA=='); -@$core.Deprecated('Use wsMessageDescriptor instead') -const WsMessage$json = const { - '1': 'WsMessage', +/// Descriptor for `WSModule`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List wSModuleDescriptor = $convert.base64Decode('CghXU01vZHVsZRIHCgNEb2MQAA=='); +@$core.Deprecated('Use wSMessageDescriptor instead') +const WSMessage$json = const { + '1': 'WSMessage', '2': const [ - const {'1': 'module', '3': 1, '4': 1, '5': 14, '6': '.WsModule', '10': 'module'}, + const {'1': 'module', '3': 1, '4': 1, '5': 14, '6': '.WSModule', '10': 'module'}, const {'1': 'data', '3': 2, '4': 1, '5': 12, '10': 'data'}, ], }; -/// Descriptor for `WsMessage`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List wsMessageDescriptor = $convert.base64Decode('CglXc01lc3NhZ2USIQoGbW9kdWxlGAEgASgOMgkuV3NNb2R1bGVSBm1vZHVsZRISCgRkYXRhGAIgASgMUgRkYXRh'); +/// Descriptor for `WSMessage`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List wSMessageDescriptor = $convert.base64Decode('CglXU01lc3NhZ2USIQoGbW9kdWxlGAEgASgOMgkuV1NNb2R1bGVSBm1vZHVsZRISCgRkYXRhGAIgASgMUgRkYXRh'); diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/edit_queue.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/edit_queue.rs new file mode 100644 index 0000000000..faa239dd3f --- /dev/null +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/edit_queue.rs @@ -0,0 +1,207 @@ +use async_stream::stream; +use bytes::Bytes; +use flowy_collaboration::{ + core::document::{history::UndoResult, Document}, + errors::CollaborateError, +}; +use flowy_error::FlowyError; +use futures::stream::StreamExt; +use lib_ot::{ + core::{Interval, OperationTransformable}, + revision::{RevId, Revision}, + rich_text::{RichTextAttribute, RichTextDelta}, +}; +use std::{convert::TryFrom, sync::Arc}; +use tokio::sync::{mpsc, oneshot, RwLock}; + +pub(crate) struct EditCommandQueue { + doc_id: String, + document: Arc>, + receiver: Option>, +} + +impl EditCommandQueue { + pub(crate) fn new(doc_id: &str, delta: RichTextDelta, receiver: mpsc::UnboundedReceiver) -> Self { + let document = Arc::new(RwLock::new(Document::from_delta(delta))); + Self { + doc_id: doc_id.to_owned(), + document, + receiver: Some(receiver), + } + } + + pub(crate) async fn run(mut self) { + let mut receiver = self.receiver.take().expect("Should only call once"); + let stream = stream! { + loop { + match receiver.recv().await { + Some(msg) => yield msg, + None => break, + } + } + }; + stream + .for_each(|msg| async { + match self.handle_message(msg).await { + Ok(_) => {}, + Err(e) => tracing::debug!("[EditCommandQueue]: {}", e), + } + }) + .await; + } + + async fn handle_message(&self, msg: EditCommand) -> Result<(), FlowyError> { + match msg { + EditCommand::ComposeDelta { delta, ret } => { + let result = self.composed_delta(delta).await; + let _ = ret.send(result); + }, + EditCommand::ProcessRemoteRevision { bytes, ret } => { + let f = || async { + let revision = Revision::try_from(bytes)?; + let delta = RichTextDelta::from_bytes(&revision.delta_data)?; + let server_rev_id: RevId = revision.rev_id.into(); + let read_guard = self.document.read().await; + let (server_prime, client_prime) = read_guard.delta().transform(&delta)?; + drop(read_guard); + + let transform_delta = TransformDeltas { + client_prime, + server_prime, + server_rev_id, + }; + + Ok::(transform_delta) + }; + let _ = ret.send(f().await); + }, + EditCommand::Insert { index, data, ret } => { + let mut write_guard = self.document.write().await; + let delta = write_guard.insert(index, data)?; + let md5 = write_guard.md5(); + let _ = ret.send(Ok((delta, md5))); + }, + EditCommand::Delete { interval, ret } => { + let mut write_guard = self.document.write().await; + let delta = write_guard.delete(interval)?; + let md5 = write_guard.md5(); + let _ = ret.send(Ok((delta, md5))); + }, + EditCommand::Format { + interval, + attribute, + ret, + } => { + let mut write_guard = self.document.write().await; + let delta = write_guard.format(interval, attribute)?; + let md5 = write_guard.md5(); + let _ = ret.send(Ok((delta, md5))); + }, + EditCommand::Replace { interval, data, ret } => { + let mut write_guard = self.document.write().await; + let delta = write_guard.replace(interval, data)?; + let md5 = write_guard.md5(); + let _ = ret.send(Ok((delta, md5))); + }, + EditCommand::CanUndo { ret } => { + let _ = ret.send(self.document.read().await.can_undo()); + }, + EditCommand::CanRedo { ret } => { + let _ = ret.send(self.document.read().await.can_redo()); + }, + EditCommand::Undo { ret } => { + let result = self.document.write().await.undo(); + let _ = ret.send(result); + }, + EditCommand::Redo { ret } => { + let result = self.document.write().await.redo(); + let _ = ret.send(result); + }, + EditCommand::ReadDoc { ret } => { + let data = self.document.read().await.to_json(); + let _ = ret.send(Ok(data)); + }, + EditCommand::ReadDocDelta { ret } => { + let delta = self.document.read().await.delta().clone(); + let _ = ret.send(Ok(delta)); + }, + } + Ok(()) + } + + #[tracing::instrument(level = "debug", skip(self, delta), fields(compose_result), err)] + async fn composed_delta(&self, delta: RichTextDelta) -> Result { + // tracing::debug!("{:?} thread handle_message", thread::current(),); + let mut document = self.document.write().await; + tracing::Span::current().record( + "composed_delta", + &format!("doc_id:{} - {}", &self.doc_id, delta.to_json()).as_str(), + ); + + let _ = document.compose_delta(delta)?; + let md5 = document.md5(); + drop(document); + + Ok(md5) + } +} + +pub(crate) type Ret = oneshot::Sender>; +pub(crate) type NewDelta = (RichTextDelta, String); +pub(crate) type DocumentMD5 = String; + +#[allow(dead_code)] +pub(crate) enum EditCommand { + ComposeDelta { + delta: RichTextDelta, + ret: Ret, + }, + ProcessRemoteRevision { + bytes: Bytes, + ret: Ret, + }, + Insert { + index: usize, + data: String, + ret: Ret, + }, + Delete { + interval: Interval, + ret: Ret, + }, + Format { + interval: Interval, + attribute: RichTextAttribute, + ret: Ret, + }, + + Replace { + interval: Interval, + data: String, + ret: Ret, + }, + CanUndo { + ret: oneshot::Sender, + }, + CanRedo { + ret: oneshot::Sender, + }, + Undo { + ret: Ret, + }, + Redo { + ret: Ret, + }, + ReadDoc { + ret: Ret, + }, + ReadDocDelta { + ret: Ret, + }, +} + +pub(crate) struct TransformDeltas { + pub client_prime: RichTextDelta, + pub server_prime: RichTextDelta, + pub server_rev_id: RevId, +} diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/edit_ws.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/edit_ws.rs new file mode 100644 index 0000000000..59d548eaa8 --- /dev/null +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/edit_ws.rs @@ -0,0 +1,297 @@ +use crate::services::doc::{DocumentWebSocket, DocumentWsHandler, SYNC_INTERVAL_IN_MILLIS}; +use async_stream::stream; +use bytes::Bytes; +use flowy_collaboration::{ + entities::ws::{DocumentWSData, DocumentWSDataType}, + Revision, +}; +use flowy_error::{internal_error, FlowyError, FlowyResult}; +use futures::stream::StreamExt; +use lib_infra::future::FutureResult; +use lib_ot::revision::{RevId, RevisionRange}; +use lib_ws::WSConnectState; +use std::{convert::TryFrom, sync::Arc}; +use tokio::{ + sync::{ + broadcast, + mpsc, + mpsc::{UnboundedReceiver, UnboundedSender}, + }, + task::spawn_blocking, + time::{interval, Duration}, +}; + +pub(crate) struct WebSocketManager { + doc_id: String, + data_provider: Arc, + stream_consumer: Arc, + ws: Arc, + ws_msg_tx: UnboundedSender, + ws_msg_rx: Option>, + stop_sync_tx: SinkStopTx, +} + +impl WebSocketManager { + pub(crate) fn new( + doc_id: &str, + ws: Arc, + data_provider: Arc, + stream_consumer: Arc, + ) -> Self { + let (ws_msg_tx, ws_msg_rx) = mpsc::unbounded_channel(); + let (stop_sync_tx, _) = tokio::sync::broadcast::channel(2); + let doc_id = doc_id.to_string(); + let mut manager = WebSocketManager { + doc_id, + data_provider, + stream_consumer, + ws, + ws_msg_tx, + ws_msg_rx: Some(ws_msg_rx), + stop_sync_tx, + }; + manager.start_sync(); + manager + } + + fn start_sync(&mut self) { + let ws_msg_rx = self.ws_msg_rx.take().expect("Only take once"); + let sink = DocumentWebSocketSink::new( + &self.doc_id, + self.data_provider.clone(), + self.ws.clone(), + self.stop_sync_tx.subscribe(), + ); + let stream = DocumentWebSocketStream::new( + &self.doc_id, + self.stream_consumer.clone(), + ws_msg_rx, + self.ws.clone(), + self.stop_sync_tx.subscribe(), + ); + tokio::spawn(sink.run()); + tokio::spawn(stream.run()); + self.notify_user_conn(); + } + + pub(crate) fn stop(&self) { + if self.stop_sync_tx.send(()).is_ok() { + tracing::debug!("{} stop sync", self.doc_id) + } + } + + #[tracing::instrument(level = "debug", skip(self))] + fn notify_user_conn(&self) { + // let rev_id: RevId = self.rev_manager.rev_id().into(); + // if let Ok(user_id) = self.user.user_id() { + // let action = OpenDocAction::new(&user_id, &self.doc_id, &rev_id, + // &self.ws_sender); let strategy = + // ExponentialBackoff::from_millis(50).take(3); let retry = + // Retry::spawn(strategy, action); tokio::spawn(async move { + // match retry.await { + // Ok(_) => log::debug!("Notify open doc success"), + // Err(e) => log::error!("Notify open doc failed: {}", e), + // } + // }); + // } + } +} + +impl DocumentWsHandler for WebSocketManager { + fn receive(&self, doc_data: DocumentWSData) { + match self.ws_msg_tx.send(doc_data) { + Ok(_) => {}, + Err(e) => tracing::error!("❌Propagate ws message failed. {}", e), + } + } + + fn connect_state_changed(&self, state: &WSConnectState) { + match state { + WSConnectState::Init => {}, + WSConnectState::Connecting => {}, + WSConnectState::Connected => self.notify_user_conn(), + WSConnectState::Disconnected => {}, + } + } +} + +pub trait DocumentWebSocketSteamConsumer: Send + Sync { + fn receive_push_revision(&self, bytes: Bytes) -> FutureResult<(), FlowyError>; + fn make_revision_from_range(&self, range: RevisionRange) -> FutureResult; + fn ack_revision(&self, rev_id: i64) -> FutureResult<(), FlowyError>; +} + +pub(crate) struct DocumentWebSocketStream { + doc_id: String, + consumer: Arc, + ws_msg_rx: Option>, + ws_sender: Arc, + stop_rx: Option, +} + +impl DocumentWebSocketStream { + pub(crate) fn new( + doc_id: &str, + consumer: Arc, + ws_msg_rx: mpsc::UnboundedReceiver, + ws_sender: Arc, + stop_rx: SinkStopRx, + ) -> Self { + DocumentWebSocketStream { + doc_id: doc_id.to_owned(), + consumer, + ws_msg_rx: Some(ws_msg_rx), + ws_sender, + stop_rx: Some(stop_rx), + } + } + + pub async fn run(mut self) { + let mut receiver = self.ws_msg_rx.take().expect("Only take once"); + let mut stop_rx = self.stop_rx.take().expect("Only take once"); + let doc_id = self.doc_id.clone(); + let stream = stream! { + loop { + tokio::select! { + result = receiver.recv() => { + match result { + Some(msg) => { + yield msg + }, + None => { + tracing::debug!("[DocumentStream:{}] loop exit", doc_id); + break; + }, + } + }, + _ = stop_rx.recv() => { + tracing::debug!("[DocumentStream:{}] loop exit", doc_id); + break + }, + }; + } + }; + + stream + .for_each(|msg| async { + match self.handle_message(msg).await { + Ok(_) => {}, + Err(e) => log::error!("[DocumentStream:{}] error: {}", self.doc_id, e), + } + }) + .await; + } + + async fn handle_message(&self, msg: DocumentWSData) -> FlowyResult<()> { + let DocumentWSData { + doc_id: _, + ty, + data, + id: _, + } = msg; + let bytes = spawn_blocking(move || Bytes::from(data)) + .await + .map_err(internal_error)?; + + tracing::debug!("[DocumentStream]: receives new message: {:?}", ty); + match ty { + DocumentWSDataType::PushRev => { + let _ = self.consumer.receive_push_revision(bytes).await?; + }, + DocumentWSDataType::PullRev => { + let range = RevisionRange::try_from(bytes)?; + let revision = self.consumer.make_revision_from_range(range).await?; + let _ = self.ws_sender.send(revision.into()); + }, + DocumentWSDataType::Acked => { + let rev_id = RevId::try_from(bytes)?; + let _ = self.consumer.ack_revision(rev_id.into()).await; + }, + DocumentWSDataType::UserConnect => {}, + } + + Ok(()) + } +} + +pub(crate) type Tick = (); +pub(crate) type SinkStopRx = broadcast::Receiver<()>; +pub(crate) type SinkStopTx = broadcast::Sender<()>; + +pub trait DocumentSinkDataProvider: Send + Sync { + fn next(&self) -> FutureResult, FlowyError>; +} + +pub(crate) struct DocumentWebSocketSink { + provider: Arc, + ws_sender: Arc, + stop_rx: Option, + doc_id: String, +} + +impl DocumentWebSocketSink { + pub(crate) fn new( + doc_id: &str, + provider: Arc, + ws_sender: Arc, + stop_rx: SinkStopRx, + ) -> Self { + Self { + provider, + ws_sender, + stop_rx: Some(stop_rx), + doc_id: doc_id.to_owned(), + } + } + + pub async fn run(mut self) { + let (tx, mut rx) = mpsc::unbounded_channel(); + let mut stop_rx = self.stop_rx.take().expect("Only take once"); + let doc_id = self.doc_id.clone(); + tokio::spawn(tick(tx)); + let stream = stream! { + loop { + tokio::select! { + result = rx.recv() => { + match result { + Some(msg) => yield msg, + None => break, + } + }, + _ = stop_rx.recv() => { + tracing::debug!("[DocumentSink:{}] loop exit", doc_id); + break + }, + }; + } + }; + stream + .for_each(|_| async { + match self.send_next_revision().await { + Ok(_) => {}, + Err(e) => log::error!("[DocumentSink]: send msg failed, {:?}", e), + } + }) + .await; + } + + async fn send_next_revision(&self) -> FlowyResult<()> { + match self.provider.next().await? { + None => { + tracing::debug!("Finish synchronizing revisions"); + Ok(()) + }, + Some(data) => { + self.ws_sender.send(data).map_err(internal_error) + // let _ = tokio::time::timeout(Duration::from_millis(2000), + }, + } + } +} + +async fn tick(sender: mpsc::UnboundedSender) { + let mut interval = interval(Duration::from_millis(SYNC_INTERVAL_IN_MILLIS)); + while sender.send(()).is_ok() { + interval.tick().await; + } +} diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs index 7b23582b99..c5fc1ae140 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs @@ -2,7 +2,7 @@ use crate::{errors::FlowyError, module::DocumentUser, services::doc::*}; use bytes::Bytes; use flowy_collaboration::{ core::document::history::UndoResult, - entities::{doc::DocDelta, ws::WsDocumentData}, + entities::{doc::DocDelta, ws::DocumentWSData}, errors::CollaborateResult, }; use flowy_database::ConnectionPool; @@ -13,16 +13,16 @@ use lib_ot::{ revision::{RevId, RevType, Revision, RevisionRange}, rich_text::{RichTextAttribute, RichTextDelta}, }; -use std::sync::Arc; +use parking_lot::RwLock; +use std::{collections::VecDeque, sync::Arc}; use tokio::sync::{mpsc, mpsc::UnboundedSender, oneshot}; - -pub type DocId = String; - +type SinkVec = Arc>>; pub struct ClientDocEditor { - pub doc_id: DocId, + pub doc_id: String, rev_manager: Arc, ws_manager: Arc, edit_cmd_tx: UnboundedSender, + sink_vec: SinkVec, user: Arc, } @@ -38,15 +38,17 @@ impl ClientDocEditor { let edit_cmd_tx = spawn_edit_queue(doc_id, delta, pool.clone()); let doc_id = doc_id.to_string(); let rev_manager = Arc::new(rev_manager); - + let sink_vec = Arc::new(RwLock::new(VecDeque::new())); let data_provider = Arc::new(DocumentSinkDataProviderAdapter { rev_manager: rev_manager.clone(), + sink_vec: sink_vec.clone(), }); let stream_consumer = Arc::new(DocumentWebSocketSteamConsumerAdapter { doc_id: doc_id.clone(), edit_cmd_tx: edit_cmd_tx.clone(), rev_manager: rev_manager.clone(), user: user.clone(), + sink_vec: sink_vec.clone(), }); let ws_manager = Arc::new(WebSocketManager::new(&doc_id, ws, data_provider, stream_consumer)); let editor = Arc::new(Self { @@ -54,6 +56,7 @@ impl ClientDocEditor { rev_manager, ws_manager, edit_cmd_tx, + sink_vec, user, }); Ok(editor) @@ -199,6 +202,7 @@ struct DocumentWebSocketSteamConsumerAdapter { edit_cmd_tx: UnboundedSender, rev_manager: Arc, user: Arc, + sink_vec: SinkVec, } impl DocumentWebSocketSteamConsumer for DocumentWebSocketSteamConsumerAdapter { @@ -233,18 +237,28 @@ impl DocumentWebSocketSteamConsumer for DocumentWebSocketSteamConsumerAdapter { struct DocumentSinkDataProviderAdapter { rev_manager: Arc, + sink_vec: SinkVec, } impl DocumentSinkDataProvider for DocumentSinkDataProviderAdapter { - fn next(&self) -> FutureResult, FlowyError> { + fn next(&self) -> FutureResult, FlowyError> { let rev_manager = self.rev_manager.clone(); + let sink_vec = self.sink_vec.clone(); + FutureResult::new(async move { - match rev_manager.next_sync_revision().await? { - Some(rev) => { - tracing::debug!("[DocumentSinkDataProvider]: revision: {}:{:?}", rev.doc_id, rev.rev_id); - Ok(Some(rev.into())) - }, - None => Ok(None), + if sink_vec.read().is_empty() { + match rev_manager.next_sync_revision().await? { + Some(rev) => { + tracing::debug!("[DocumentSinkDataProvider]: revision: {}:{:?}", rev.doc_id, rev.rev_id); + Ok(Some(rev.into())) + }, + None => Ok(None), + } + } else { + match sink_vec.read().front() { + None => Ok(None), + Some(data) => Ok(Some(data.clone())), + } } }) } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/ws/mod.rs b/frontend/rust-lib/flowy-document/src/services/doc/ws/mod.rs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/frontend/rust-lib/flowy-document/src/services/doc/ws_handlers.rs b/frontend/rust-lib/flowy-document/src/services/doc/ws_handlers.rs new file mode 100644 index 0000000000..1c36ffdd51 --- /dev/null +++ b/frontend/rust-lib/flowy-document/src/services/doc/ws_handlers.rs @@ -0,0 +1,67 @@ +use crate::errors::FlowyError; +use bytes::Bytes; +use dashmap::DashMap; +use flowy_collaboration::entities::ws::DocumentWSData; +use lib_ws::WSConnectState; +use std::{convert::TryInto, sync::Arc}; + +pub(crate) trait DocumentWsHandler: Send + Sync { + fn receive(&self, data: DocumentWSData); + fn connect_state_changed(&self, state: &WSConnectState); +} + +pub type WsStateReceiver = tokio::sync::broadcast::Receiver; +pub trait DocumentWebSocket: Send + Sync { + fn send(&self, data: DocumentWSData) -> Result<(), FlowyError>; + fn subscribe_state_changed(&self) -> WsStateReceiver; +} + +pub struct DocumentWsHandlers { + ws: Arc, + // key: the document id + handlers: Arc>>, +} + +impl DocumentWsHandlers { + pub fn new(ws: Arc) -> Self { + let handlers: Arc>> = Arc::new(DashMap::new()); + Self { ws, handlers } + } + + pub(crate) fn init(&self) { listen_ws_state_changed(self.ws.clone(), self.handlers.clone()); } + + pub(crate) fn register_handler(&self, id: &str, handler: Arc) { + if self.handlers.contains_key(id) { + log::error!("Duplicate handler registered for {:?}", id); + } + self.handlers.insert(id.to_string(), handler); + } + + pub(crate) fn remove_handler(&self, id: &str) { self.handlers.remove(id); } + + pub fn did_receive_data(&self, data: Bytes) { + let data: DocumentWSData = data.try_into().unwrap(); + match self.handlers.get(&data.doc_id) { + None => { + log::error!("Can't find any source handler for {:?}", data.doc_id); + }, + Some(handler) => { + handler.receive(data); + }, + } + } + + pub fn ws(&self) -> Arc { self.ws.clone() } +} + +#[tracing::instrument(level = "debug", skip(ws, handlers))] +fn listen_ws_state_changed(ws: Arc, handlers: Arc>>) { + let mut notify = ws.subscribe_state_changed(); + tokio::spawn(async move { + while let Ok(state) = notify.recv().await { + handlers.iter().for_each(|handle| { + handle.value().connect_state_changed(&state); + }); + } + }); +} diff --git a/frontend/rust-lib/flowy-net/src/services/mock/ws_mock.rs b/frontend/rust-lib/flowy-net/src/services/mock/ws_mock.rs index b22e4fac48..ea06008889 100644 --- a/frontend/rust-lib/flowy-net/src/services/mock/ws_mock.rs +++ b/frontend/rust-lib/flowy-net/src/services/mock/ws_mock.rs @@ -1,11 +1,11 @@ -use crate::services::ws::{FlowyError, FlowyWebSocket, FlowyWsSender, WsConnectState, WsMessage, WsMessageReceiver}; +use crate::services::ws::{FlowyError, FlowyWebSocket, FlowyWsSender, WSConnectState, WSMessage, WSMessageReceiver}; use bytes::Bytes; use dashmap::DashMap; use flowy_collaboration::{ core::sync::{RevisionUser, ServerDocManager, ServerDocPersistence, SyncResponse}, entities::{ doc::Doc, - ws::{WsDocumentData, WsDocumentDataType}, + ws::{DocumentWSData, DocumentWSDataType}, }, errors::CollaborateError, Revision, @@ -13,7 +13,7 @@ use flowy_collaboration::{ }; use lazy_static::lazy_static; use lib_infra::future::{FutureResult, FutureResultSend}; -use lib_ws::WsModule; +use lib_ws::WSModule; use parking_lot::RwLock; use std::{ convert::{TryFrom, TryInto}, @@ -22,9 +22,9 @@ use std::{ use tokio::sync::{broadcast, broadcast::Receiver, mpsc}; pub struct MockWebSocket { - handlers: DashMap>, - state_sender: broadcast::Sender, - ws_sender: broadcast::Sender, + handlers: DashMap>, + state_sender: broadcast::Sender, + ws_sender: broadcast::Sender, is_stop: RwLock, } @@ -56,7 +56,7 @@ impl FlowyWebSocket for Arc { if *cloned_ws.is_stop.read() { // do nothing } else { - let ws_data = WsDocumentData::try_from(Bytes::from(message.data.clone())).unwrap(); + let ws_data = DocumentWSData::try_from(Bytes::from(message.data.clone())).unwrap(); let mut rx = DOC_SERVER.handle_ws_data(ws_data).await; let new_ws_message = rx.recv().await.unwrap(); match cloned_ws.handlers.get(&new_ws_message.module) { @@ -75,11 +75,11 @@ impl FlowyWebSocket for Arc { FutureResult::new(async { Ok(()) }) } - fn subscribe_connect_state(&self) -> Receiver { self.state_sender.subscribe() } + fn subscribe_connect_state(&self) -> Receiver { self.state_sender.subscribe() } fn reconnect(&self, _count: usize) -> FutureResult<(), FlowyError> { FutureResult::new(async { Ok(()) }) } - fn add_message_receiver(&self, handler: Arc) -> Result<(), FlowyError> { + fn add_message_receiver(&self, handler: Arc) -> Result<(), FlowyError> { let source = handler.source(); if self.handlers.contains_key(&source) { tracing::error!("WsSource's {:?} is already registered", source); @@ -108,13 +108,13 @@ impl std::default::Default for MockDocServer { } impl MockDocServer { - async fn handle_ws_data(&self, ws_data: WsDocumentData) -> mpsc::Receiver { + async fn handle_ws_data(&self, ws_data: DocumentWSData) -> mpsc::Receiver { let bytes = Bytes::from(ws_data.data); match ws_data.ty { - WsDocumentDataType::Acked => { + DocumentWSDataType::Acked => { unimplemented!() }, - WsDocumentDataType::PushRev => { + DocumentWSDataType::PushRev => { let revision = Revision::try_from(bytes).unwrap(); let handler = match self.manager.get(&revision.doc_id).await { None => self.manager.create_doc(revision.clone()).await.unwrap(), @@ -129,10 +129,10 @@ impl MockDocServer { handler.apply_revision(Arc::new(user), revision).await.unwrap(); rx }, - WsDocumentDataType::PullRev => { + DocumentWSDataType::PullRev => { unimplemented!() }, - WsDocumentDataType::UserConnect => { + DocumentWSDataType::UserConnect => { unimplemented!() }, } @@ -184,7 +184,7 @@ impl ServerDocPersistence for MockDocServerPersistence { #[derive(Debug)] struct MockDocUser { user_id: String, - tx: mpsc::Sender, + tx: mpsc::Sender, } impl RevisionUser for MockDocUser { @@ -196,24 +196,24 @@ impl RevisionUser for MockDocUser { match resp { SyncResponse::Pull(data) => { let bytes: Bytes = data.try_into().unwrap(); - let msg = WsMessage { - module: WsModule::Doc, + let msg = WSMessage { + module: WSModule::Doc, data: bytes.to_vec(), }; sender.send(msg).await.unwrap(); }, SyncResponse::Push(data) => { let bytes: Bytes = data.try_into().unwrap(); - let msg = WsMessage { - module: WsModule::Doc, + let msg = WSMessage { + module: WSModule::Doc, data: bytes.to_vec(), }; sender.send(msg).await.unwrap(); }, SyncResponse::Ack(data) => { let bytes: Bytes = data.try_into().unwrap(); - let msg = WsMessage { - module: WsModule::Doc, + let msg = WSMessage { + module: WSModule::Doc, data: bytes.to_vec(), }; sender.send(msg).await.unwrap(); diff --git a/frontend/rust-lib/flowy-net/src/services/ws/conn.rs b/frontend/rust-lib/flowy-net/src/services/ws/conn.rs index fa3d5b9185..4f2f6e2f4c 100644 --- a/frontend/rust-lib/flowy-net/src/services/ws/conn.rs +++ b/frontend/rust-lib/flowy-net/src/services/ws/conn.rs @@ -3,17 +3,17 @@ use std::sync::Arc; use tokio::sync::broadcast; pub use flowy_error::FlowyError; -pub use lib_ws::{WsConnectState, WsMessage, WsMessageReceiver}; +pub use lib_ws::{WSConnectState, WSMessage, WSMessageReceiver}; pub trait FlowyWebSocket: Send + Sync { fn start_connect(&self, addr: String) -> FutureResult<(), FlowyError>; fn stop_connect(&self) -> FutureResult<(), FlowyError>; - fn subscribe_connect_state(&self) -> broadcast::Receiver; + fn subscribe_connect_state(&self) -> broadcast::Receiver; fn reconnect(&self, count: usize) -> FutureResult<(), FlowyError>; - fn add_message_receiver(&self, handler: Arc) -> Result<(), FlowyError>; + fn add_message_receiver(&self, handler: Arc) -> Result<(), FlowyError>; fn ws_sender(&self) -> Result, FlowyError>; } pub trait FlowyWsSender: Send + Sync { - fn send(&self, msg: WsMessage) -> Result<(), FlowyError>; + fn send(&self, msg: WSMessage) -> Result<(), FlowyError>; } diff --git a/frontend/rust-lib/flowy-net/src/services/ws/manager.rs b/frontend/rust-lib/flowy-net/src/services/ws/manager.rs index fac7835b6f..53a94f6b1c 100644 --- a/frontend/rust-lib/flowy-net/src/services/ws/manager.rs +++ b/frontend/rust-lib/flowy-net/src/services/ws/manager.rs @@ -4,7 +4,7 @@ use crate::{ }; use flowy_error::{internal_error, FlowyError}; use lib_infra::future::FutureResult; -use lib_ws::{WsConnectState, WsController, WsMessage, WsMessageReceiver, WsSender}; +use lib_ws::{WSConnectState, WSController, WSMessage, WSMessageReceiver, WSSender}; use parking_lot::RwLock; use std::sync::Arc; use tokio::sync::{broadcast, broadcast::Receiver}; @@ -19,7 +19,7 @@ pub struct WsManager { impl WsManager { pub fn new(addr: String) -> Self { let ws: Arc = if cfg!(feature = "http_server") { - Arc::new(Arc::new(WsController::new())) + Arc::new(Arc::new(WSController::new())) } else { local_web_socket() }; @@ -65,13 +65,13 @@ impl WsManager { } } - pub fn subscribe_websocket_state(&self) -> broadcast::Receiver { + pub fn subscribe_websocket_state(&self) -> broadcast::Receiver { self.inner.subscribe_connect_state() } pub fn subscribe_network_ty(&self) -> broadcast::Receiver { self.status_notifier.subscribe() } - pub fn add_receiver(&self, handler: Arc) -> Result<(), FlowyError> { + pub fn add_receiver(&self, handler: Arc) -> Result<(), FlowyError> { let _ = self.inner.add_message_receiver(handler)?; Ok(()) } @@ -88,10 +88,10 @@ fn listen_on_websocket(ws: Arc) { Ok(state) => { tracing::info!("Websocket state changed: {}", state); match state { - WsConnectState::Init => {}, - WsConnectState::Connected => {}, - WsConnectState::Connecting => {}, - WsConnectState::Disconnected => retry_connect(ws.clone(), 100).await, + WSConnectState::Init => {}, + WSConnectState::Connected => {}, + WSConnectState::Connecting => {}, + WSConnectState::Disconnected => retry_connect(ws.clone(), 100).await, } }, Err(e) => { @@ -112,7 +112,7 @@ async fn retry_connect(ws: Arc, count: usize) { } } -impl FlowyWebSocket for Arc { +impl FlowyWebSocket for Arc { fn start_connect(&self, addr: String) -> FutureResult<(), FlowyError> { let cloned_ws = self.clone(); FutureResult::new(async move { @@ -129,7 +129,7 @@ impl FlowyWebSocket for Arc { }) } - fn subscribe_connect_state(&self) -> Receiver { self.subscribe_state() } + fn subscribe_connect_state(&self) -> Receiver { self.subscribe_state() } fn reconnect(&self, count: usize) -> FutureResult<(), FlowyError> { let cloned_ws = self.clone(); @@ -139,7 +139,7 @@ impl FlowyWebSocket for Arc { }) } - fn add_message_receiver(&self, handler: Arc) -> Result<(), FlowyError> { + fn add_message_receiver(&self, handler: Arc) -> Result<(), FlowyError> { let _ = self.add_receiver(handler).map_err(internal_error)?; Ok(()) } @@ -150,8 +150,8 @@ impl FlowyWebSocket for Arc { } } -impl FlowyWsSender for WsSender { - fn send(&self, msg: WsMessage) -> Result<(), FlowyError> { +impl FlowyWsSender for WSSender { + fn send(&self, msg: WSMessage) -> Result<(), FlowyError> { let _ = self.send_msg(msg).map_err(internal_error)?; Ok(()) } diff --git a/frontend/rust-lib/flowy-net/src/services/ws/ws_local.rs b/frontend/rust-lib/flowy-net/src/services/ws/ws_local.rs index 692b9244fe..2450505d9d 100644 --- a/frontend/rust-lib/flowy-net/src/services/ws/ws_local.rs +++ b/frontend/rust-lib/flowy-net/src/services/ws/ws_local.rs @@ -1,11 +1,11 @@ -use crate::services::ws::{FlowyError, FlowyWebSocket, FlowyWsSender, WsConnectState, WsMessage, WsMessageReceiver}; +use crate::services::ws::{FlowyError, FlowyWebSocket, FlowyWsSender, WSConnectState, WSMessage, WSMessageReceiver}; use lib_infra::future::FutureResult; use std::sync::Arc; use tokio::sync::{broadcast, broadcast::Receiver}; pub(crate) struct LocalWebSocket { - state_sender: broadcast::Sender, - ws_sender: broadcast::Sender, + state_sender: broadcast::Sender, + ws_sender: broadcast::Sender, } impl std::default::Default for LocalWebSocket { @@ -24,17 +24,17 @@ impl FlowyWebSocket for Arc { fn stop_connect(&self) -> FutureResult<(), FlowyError> { FutureResult::new(async { Ok(()) }) } - fn subscribe_connect_state(&self) -> Receiver { self.state_sender.subscribe() } + fn subscribe_connect_state(&self) -> Receiver { self.state_sender.subscribe() } fn reconnect(&self, _count: usize) -> FutureResult<(), FlowyError> { FutureResult::new(async { Ok(()) }) } - fn add_message_receiver(&self, _handler: Arc) -> Result<(), FlowyError> { Ok(()) } + fn add_message_receiver(&self, _handler: Arc) -> Result<(), FlowyError> { Ok(()) } fn ws_sender(&self) -> Result, FlowyError> { Ok(Arc::new(self.ws_sender.clone())) } } -impl FlowyWsSender for broadcast::Sender { - fn send(&self, msg: WsMessage) -> Result<(), FlowyError> { +impl FlowyWsSender for broadcast::Sender { + fn send(&self, msg: WSMessage) -> Result<(), FlowyError> { let _ = self.send(msg); Ok(()) } diff --git a/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs b/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs index 6ad1d7c0f4..036b082f7d 100644 --- a/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs +++ b/frontend/rust-lib/flowy-sdk/src/deps_resolve/document_deps.rs @@ -1,5 +1,5 @@ use bytes::Bytes; -use flowy_collaboration::entities::ws::WsDocumentData; +use flowy_collaboration::entities::ws::DocumentWSData; use flowy_database::ConnectionPool; use flowy_document::{ errors::{internal_error, FlowyError}, @@ -8,7 +8,7 @@ use flowy_document::{ }; use flowy_net::services::ws::WsManager; use flowy_user::services::user::UserSession; -use lib_ws::{WsMessage, WsMessageReceiver, WsModule}; +use lib_ws::{WSMessage, WSMessageReceiver, WSModule}; use std::{convert::TryInto, path::Path, sync::Arc}; pub struct DocumentDepsResolver(); @@ -61,10 +61,10 @@ struct WsSenderImpl { } impl DocumentWebSocket for WsSenderImpl { - fn send(&self, data: WsDocumentData) -> Result<(), FlowyError> { + fn send(&self, data: DocumentWSData) -> Result<(), FlowyError> { let bytes: Bytes = data.try_into().unwrap(); - let msg = WsMessage { - module: WsModule::Doc, + let msg = WSMessage { + module: WSModule::Doc, data: bytes.to_vec(), }; let sender = self.ws_manager.ws_sender().map_err(internal_error)?; @@ -78,7 +78,7 @@ impl DocumentWebSocket for WsSenderImpl { struct WsMessageReceiverAdaptor(Arc); -impl WsMessageReceiver for WsMessageReceiverAdaptor { - fn source(&self) -> WsModule { WsModule::Doc } - fn receive_message(&self, msg: WsMessage) { self.0.did_receive_data(Bytes::from(msg.data)); } +impl WSMessageReceiver for WsMessageReceiverAdaptor { + fn source(&self) -> WSModule { WSModule::Doc } + fn receive_message(&self, msg: WSMessage) { self.0.did_receive_data(Bytes::from(msg.data)); } } diff --git a/frontend/scripts/flowy-tool/src/proto/ast.rs b/frontend/scripts/flowy-tool/src/proto/ast.rs index 59e7619312..92d94d6f43 100644 --- a/frontend/scripts/flowy-tool/src/proto/ast.rs +++ b/frontend/scripts/flowy-tool/src/proto/ast.rs @@ -46,7 +46,7 @@ fn parse_files_protobuf(proto_crate_path: &str, proto_output_dir: &str) -> Vec

{ // Do nothing log::warn!("Applied revision rev_id is the same as cur_rev_id"); - user.recv(SyncResponse::Ack(mk_acked_message(&revision))); + let data = WsDocumentDataBuilder::build_acked_message(&revision.doc_id, revision.rev_id); + user.recv(SyncResponse::Ack(data)); }, Ordering::Greater => { // The client document is outdated. Transform the client revision delta and then // send the prime delta to the client. Client should compose the this prime // delta. let cli_revision = self.transform_revision(&revision)?; - let data = mk_push_message(&self.doc_id, cli_revision); + let data = WsDocumentDataBuilder::build_push_rev_message(&self.doc_id, cli_revision); user.recv(SyncResponse::Push(data)); }, } @@ -143,44 +152,6 @@ impl RevisionSynchronizer { } } -fn mk_push_message(doc_id: &str, revision: Revision) -> WsDocumentData { - let bytes: Bytes = revision.try_into().unwrap(); - WsDocumentData { - doc_id: doc_id.to_string(), - ty: WsDocumentDataType::PushRev, - data: bytes.to_vec(), - } -} - -fn mk_pull_message(doc_id: &str, from_rev_id: i64, to_rev_id: i64) -> WsDocumentData { - let range = RevisionRange { - doc_id: doc_id.to_string(), - start: from_rev_id, - end: to_rev_id, - }; - - let bytes: Bytes = range.try_into().unwrap(); - WsDocumentData { - doc_id: doc_id.to_string(), - ty: WsDocumentDataType::PullRev, - data: bytes.to_vec(), - } -} - -fn mk_acked_message(revision: &Revision) -> WsDocumentData { - // let mut wtr = vec![]; - // let _ = wtr.write_i64::(revision.rev_id); - let mut rev_id = RevId::new(); - rev_id.set_value(revision.rev_id); - let data = rev_id.write_to_bytes().unwrap(); - - WsDocumentData { - doc_id: revision.doc_id.clone(), - ty: WsDocumentDataType::Acked, - data, - } -} - #[inline] fn next(rev_id: i64) -> i64 { rev_id + 1 } diff --git a/shared-lib/flowy-collaboration/src/entities/ws/ws.rs b/shared-lib/flowy-collaboration/src/entities/ws/ws.rs index a2e1e31d2f..a13ac2fa79 100644 --- a/shared-lib/flowy-collaboration/src/entities/ws/ws.rs +++ b/shared-lib/flowy-collaboration/src/entities/ws/ws.rs @@ -5,7 +5,7 @@ use lib_ot::revision::{RevId, Revision, RevisionRange}; use std::convert::{TryFrom, TryInto}; #[derive(Debug, Clone, ProtoBuf_Enum, Eq, PartialEq, Hash)] -pub enum WsDocumentDataType { +pub enum DocumentWSDataType { // The frontend receives the Acked means the backend has accepted the revision Acked = 0, // The frontend receives the PushRev event means the backend is pushing the new revision to frontend @@ -15,7 +15,7 @@ pub enum WsDocumentDataType { UserConnect = 3, } -impl WsDocumentDataType { +impl DocumentWSDataType { pub fn data(&self, bytes: Bytes) -> Result where T: TryFrom, @@ -24,64 +24,75 @@ impl WsDocumentDataType { } } -impl std::default::Default for WsDocumentDataType { - fn default() -> Self { WsDocumentDataType::Acked } +impl std::default::Default for DocumentWSDataType { + fn default() -> Self { DocumentWSDataType::Acked } } #[derive(ProtoBuf, Default, Debug, Clone)] -pub struct WsDocumentData { +pub struct DocumentWSData { #[pb(index = 1)] pub doc_id: String, #[pb(index = 2)] - pub ty: WsDocumentDataType, + pub ty: DocumentWSDataType, #[pb(index = 3)] pub data: Vec, + + #[pb(index = 4, one_of)] + pub id: Option, } -impl std::convert::From for WsDocumentData { +impl std::convert::From for DocumentWSData { fn from(revision: Revision) -> Self { let doc_id = revision.doc_id.clone(); + let rev_id = revision.rev_id; let bytes: Bytes = revision.try_into().unwrap(); Self { doc_id, - ty: WsDocumentDataType::PushRev, + ty: DocumentWSDataType::PushRev, data: bytes.to_vec(), + id: Some(rev_id), } } } pub struct WsDocumentDataBuilder(); impl WsDocumentDataBuilder { - // WsDocumentDataType::PushRev -> Revision - pub fn build_push_rev_message(doc_id: &str, revision: Revision) -> WsDocumentData { + // DocumentWSDataType::PushRev -> Revision + pub fn build_push_rev_message(doc_id: &str, revision: Revision) -> DocumentWSData { + let rev_id = revision.rev_id; let bytes: Bytes = revision.try_into().unwrap(); - WsDocumentData { + DocumentWSData { doc_id: doc_id.to_string(), - ty: WsDocumentDataType::PushRev, + ty: DocumentWSDataType::PushRev, data: bytes.to_vec(), + id: Some(rev_id), } } - // WsDocumentDataType::PullRev -> RevisionRange - pub fn build_push_pull_message(doc_id: &str, range: RevisionRange) -> WsDocumentData { + // DocumentWSDataType::PullRev -> RevisionRange + pub fn build_push_pull_message(doc_id: &str, range: RevisionRange) -> DocumentWSData { let bytes: Bytes = range.try_into().unwrap(); - WsDocumentData { + DocumentWSData { doc_id: doc_id.to_string(), - ty: WsDocumentDataType::PullRev, + ty: DocumentWSDataType::PullRev, data: bytes.to_vec(), + id: None, } } - // WsDocumentDataType::Acked -> RevId - pub fn build_acked_message(doc_id: &str, rev_id: i64) -> WsDocumentData { + // DocumentWSDataType::Acked -> RevId + pub fn build_acked_message(doc_id: &str, rev_id: i64) -> DocumentWSData { + let cloned_rev_id = rev_id.clone(); let rev_id: RevId = rev_id.into(); let bytes: Bytes = rev_id.try_into().unwrap(); - WsDocumentData { + + DocumentWSData { doc_id: doc_id.to_string(), - ty: WsDocumentDataType::Acked, + ty: DocumentWSDataType::Acked, data: bytes.to_vec(), + id: Some(cloned_rev_id), } } } diff --git a/shared-lib/flowy-collaboration/src/protobuf/model/ws.rs b/shared-lib/flowy-collaboration/src/protobuf/model/ws.rs index 394459aaff..703c6b305f 100644 --- a/shared-lib/flowy-collaboration/src/protobuf/model/ws.rs +++ b/shared-lib/flowy-collaboration/src/protobuf/model/ws.rs @@ -24,24 +24,31 @@ // const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_22_1; #[derive(PartialEq,Clone,Default)] -pub struct WsDocumentData { +pub struct DocumentWSData { // message fields pub doc_id: ::std::string::String, - pub ty: WsDocumentDataType, + pub ty: DocumentWSDataType, pub data: ::std::vec::Vec, + // message oneof groups + pub one_of_id: ::std::option::Option, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, } -impl<'a> ::std::default::Default for &'a WsDocumentData { - fn default() -> &'a WsDocumentData { - ::default_instance() +impl<'a> ::std::default::Default for &'a DocumentWSData { + fn default() -> &'a DocumentWSData { + ::default_instance() } } -impl WsDocumentData { - pub fn new() -> WsDocumentData { +#[derive(Clone,PartialEq,Debug)] +pub enum DocumentWSData_oneof_one_of_id { + id(i64), +} + +impl DocumentWSData { + pub fn new() -> DocumentWSData { ::std::default::Default::default() } @@ -71,18 +78,18 @@ impl WsDocumentData { ::std::mem::replace(&mut self.doc_id, ::std::string::String::new()) } - // .WsDocumentDataType ty = 2; + // .DocumentWSDataType ty = 2; - pub fn get_ty(&self) -> WsDocumentDataType { + pub fn get_ty(&self) -> DocumentWSDataType { self.ty } pub fn clear_ty(&mut self) { - self.ty = WsDocumentDataType::Acked; + self.ty = DocumentWSDataType::Acked; } // Param is passed by value, moved - pub fn set_ty(&mut self, v: WsDocumentDataType) { + pub fn set_ty(&mut self, v: DocumentWSDataType) { self.ty = v; } @@ -111,9 +118,34 @@ impl WsDocumentData { pub fn take_data(&mut self) -> ::std::vec::Vec { ::std::mem::replace(&mut self.data, ::std::vec::Vec::new()) } + + // int64 id = 4; + + + pub fn get_id(&self) -> i64 { + match self.one_of_id { + ::std::option::Option::Some(DocumentWSData_oneof_one_of_id::id(v)) => v, + _ => 0, + } + } + pub fn clear_id(&mut self) { + self.one_of_id = ::std::option::Option::None; + } + + pub fn has_id(&self) -> bool { + match self.one_of_id { + ::std::option::Option::Some(DocumentWSData_oneof_one_of_id::id(..)) => true, + _ => false, + } + } + + // Param is passed by value, moved + pub fn set_id(&mut self, v: i64) { + self.one_of_id = ::std::option::Option::Some(DocumentWSData_oneof_one_of_id::id(v)) + } } -impl ::protobuf::Message for WsDocumentData { +impl ::protobuf::Message for DocumentWSData { fn is_initialized(&self) -> bool { true } @@ -131,6 +163,12 @@ impl ::protobuf::Message for WsDocumentData { 3 => { ::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.data)?; }, + 4 => { + if wire_type != ::protobuf::wire_format::WireTypeVarint { + return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); + } + self.one_of_id = ::std::option::Option::Some(DocumentWSData_oneof_one_of_id::id(is.read_int64()?)); + }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; }, @@ -146,12 +184,19 @@ impl ::protobuf::Message for WsDocumentData { if !self.doc_id.is_empty() { my_size += ::protobuf::rt::string_size(1, &self.doc_id); } - if self.ty != WsDocumentDataType::Acked { + if self.ty != DocumentWSDataType::Acked { my_size += ::protobuf::rt::enum_size(2, self.ty); } if !self.data.is_empty() { my_size += ::protobuf::rt::bytes_size(3, &self.data); } + if let ::std::option::Option::Some(ref v) = self.one_of_id { + match v { + &DocumentWSData_oneof_one_of_id::id(v) => { + my_size += ::protobuf::rt::value_size(4, v, ::protobuf::wire_format::WireTypeVarint); + }, + }; + } my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); self.cached_size.set(my_size); my_size @@ -161,12 +206,19 @@ impl ::protobuf::Message for WsDocumentData { if !self.doc_id.is_empty() { os.write_string(1, &self.doc_id)?; } - if self.ty != WsDocumentDataType::Acked { + if self.ty != DocumentWSDataType::Acked { os.write_enum(2, ::protobuf::ProtobufEnum::value(&self.ty))?; } if !self.data.is_empty() { os.write_bytes(3, &self.data)?; } + if let ::std::option::Option::Some(ref v) = self.one_of_id { + match v { + &DocumentWSData_oneof_one_of_id::id(v) => { + os.write_int64(4, v)?; + }, + }; + } os.write_unknown_fields(self.get_unknown_fields())?; ::std::result::Result::Ok(()) } @@ -197,8 +249,8 @@ impl ::protobuf::Message for WsDocumentData { Self::descriptor_static() } - fn new() -> WsDocumentData { - WsDocumentData::new() + fn new() -> DocumentWSData { + DocumentWSData::new() } fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { @@ -207,49 +259,55 @@ impl ::protobuf::Message for WsDocumentData { let mut fields = ::std::vec::Vec::new(); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "doc_id", - |m: &WsDocumentData| { &m.doc_id }, - |m: &mut WsDocumentData| { &mut m.doc_id }, + |m: &DocumentWSData| { &m.doc_id }, + |m: &mut DocumentWSData| { &mut m.doc_id }, )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( "ty", - |m: &WsDocumentData| { &m.ty }, - |m: &mut WsDocumentData| { &mut m.ty }, + |m: &DocumentWSData| { &m.ty }, + |m: &mut DocumentWSData| { &mut m.ty }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>( "data", - |m: &WsDocumentData| { &m.data }, - |m: &mut WsDocumentData| { &mut m.data }, + |m: &DocumentWSData| { &m.data }, + |m: &mut DocumentWSData| { &mut m.data }, )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "WsDocumentData", + fields.push(::protobuf::reflect::accessor::make_singular_i64_accessor::<_>( + "id", + DocumentWSData::has_id, + DocumentWSData::get_id, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "DocumentWSData", fields, file_descriptor_proto() ) }) } - fn default_instance() -> &'static WsDocumentData { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(WsDocumentData::new) + fn default_instance() -> &'static DocumentWSData { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(DocumentWSData::new) } } -impl ::protobuf::Clear for WsDocumentData { +impl ::protobuf::Clear for DocumentWSData { fn clear(&mut self) { self.doc_id.clear(); - self.ty = WsDocumentDataType::Acked; + self.ty = DocumentWSDataType::Acked; self.data.clear(); + self.one_of_id = ::std::option::Option::None; self.unknown_fields.clear(); } } -impl ::std::fmt::Debug for WsDocumentData { +impl ::std::fmt::Debug for DocumentWSData { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { ::protobuf::text_format::fmt(self, f) } } -impl ::protobuf::reflect::ProtobufValue for WsDocumentData { +impl ::protobuf::reflect::ProtobufValue for DocumentWSData { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { ::protobuf::reflect::ReflectValueRef::Message(self) } @@ -492,34 +550,34 @@ impl ::protobuf::reflect::ProtobufValue for DocumentConnected { } #[derive(Clone,PartialEq,Eq,Debug,Hash)] -pub enum WsDocumentDataType { +pub enum DocumentWSDataType { Acked = 0, PushRev = 1, PullRev = 2, UserConnect = 3, } -impl ::protobuf::ProtobufEnum for WsDocumentDataType { +impl ::protobuf::ProtobufEnum for DocumentWSDataType { fn value(&self) -> i32 { *self as i32 } - fn from_i32(value: i32) -> ::std::option::Option { + fn from_i32(value: i32) -> ::std::option::Option { match value { - 0 => ::std::option::Option::Some(WsDocumentDataType::Acked), - 1 => ::std::option::Option::Some(WsDocumentDataType::PushRev), - 2 => ::std::option::Option::Some(WsDocumentDataType::PullRev), - 3 => ::std::option::Option::Some(WsDocumentDataType::UserConnect), + 0 => ::std::option::Option::Some(DocumentWSDataType::Acked), + 1 => ::std::option::Option::Some(DocumentWSDataType::PushRev), + 2 => ::std::option::Option::Some(DocumentWSDataType::PullRev), + 3 => ::std::option::Option::Some(DocumentWSDataType::UserConnect), _ => ::std::option::Option::None } } fn values() -> &'static [Self] { - static values: &'static [WsDocumentDataType] = &[ - WsDocumentDataType::Acked, - WsDocumentDataType::PushRev, - WsDocumentDataType::PullRev, - WsDocumentDataType::UserConnect, + static values: &'static [DocumentWSDataType] = &[ + DocumentWSDataType::Acked, + DocumentWSDataType::PushRev, + DocumentWSDataType::PullRev, + DocumentWSDataType::UserConnect, ]; values } @@ -527,63 +585,68 @@ impl ::protobuf::ProtobufEnum for WsDocumentDataType { 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::("WsDocumentDataType", file_descriptor_proto()) + ::protobuf::reflect::EnumDescriptor::new_pb_name::("DocumentWSDataType", file_descriptor_proto()) }) } } -impl ::std::marker::Copy for WsDocumentDataType { +impl ::std::marker::Copy for DocumentWSDataType { } -impl ::std::default::Default for WsDocumentDataType { +impl ::std::default::Default for DocumentWSDataType { fn default() -> Self { - WsDocumentDataType::Acked + DocumentWSDataType::Acked } } -impl ::protobuf::reflect::ProtobufValue for WsDocumentDataType { +impl ::protobuf::reflect::ProtobufValue for DocumentWSDataType { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { ::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self)) } } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x08ws.proto\"`\n\x0eWsDocumentData\x12\x15\n\x06doc_id\x18\x01\x20\ - \x01(\tR\x05docId\x12#\n\x02ty\x18\x02\x20\x01(\x0e2\x13.WsDocumentDataT\ - ypeR\x02ty\x12\x12\n\x04data\x18\x03\x20\x01(\x0cR\x04data\"Z\n\x11Docum\ - entConnected\x12\x17\n\x07user_id\x18\x01\x20\x01(\tR\x06userId\x12\x15\ - \n\x06doc_id\x18\x02\x20\x01(\tR\x05docId\x12\x15\n\x06rev_id\x18\x03\ - \x20\x01(\x03R\x05revId*J\n\x12WsDocumentDataType\x12\t\n\x05Acked\x10\0\ - \x12\x0b\n\x07PushRev\x10\x01\x12\x0b\n\x07PullRev\x10\x02\x12\x0f\n\x0b\ - UserConnect\x10\x03J\xc8\x04\n\x06\x12\x04\0\0\x11\x01\n\x08\n\x01\x0c\ - \x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x06\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\x16\n\ - \x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\ - \x12\x03\x03\x0b\x11\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x14\x15\n\ - \x0b\n\x04\x04\0\x02\x01\x12\x03\x04\x04\x1e\n\x0c\n\x05\x04\0\x02\x01\ - \x06\x12\x03\x04\x04\x16\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\x17\ - \x19\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x04\x1c\x1d\n\x0b\n\x04\x04\0\ - \x02\x02\x12\x03\x05\x04\x13\n\x0c\n\x05\x04\0\x02\x02\x05\x12\x03\x05\ - \x04\t\n\x0c\n\x05\x04\0\x02\x02\x01\x12\x03\x05\n\x0e\n\x0c\n\x05\x04\0\ - \x02\x02\x03\x12\x03\x05\x11\x12\n\n\n\x02\x04\x01\x12\x04\x07\0\x0b\x01\ - \n\n\n\x03\x04\x01\x01\x12\x03\x07\x08\x19\n\x0b\n\x04\x04\x01\x02\0\x12\ - \x03\x08\x04\x17\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03\x08\x04\n\n\x0c\n\ - \x05\x04\x01\x02\0\x01\x12\x03\x08\x0b\x12\n\x0c\n\x05\x04\x01\x02\0\x03\ - \x12\x03\x08\x15\x16\n\x0b\n\x04\x04\x01\x02\x01\x12\x03\t\x04\x16\n\x0c\ - \n\x05\x04\x01\x02\x01\x05\x12\x03\t\x04\n\n\x0c\n\x05\x04\x01\x02\x01\ - \x01\x12\x03\t\x0b\x11\n\x0c\n\x05\x04\x01\x02\x01\x03\x12\x03\t\x14\x15\ - \n\x0b\n\x04\x04\x01\x02\x02\x12\x03\n\x04\x15\n\x0c\n\x05\x04\x01\x02\ - \x02\x05\x12\x03\n\x04\t\n\x0c\n\x05\x04\x01\x02\x02\x01\x12\x03\n\n\x10\ - \n\x0c\n\x05\x04\x01\x02\x02\x03\x12\x03\n\x13\x14\n\n\n\x02\x05\0\x12\ - \x04\x0c\0\x11\x01\n\n\n\x03\x05\0\x01\x12\x03\x0c\x05\x17\n\x0b\n\x04\ - \x05\0\x02\0\x12\x03\r\x04\x0e\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\r\x04\ - \t\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\r\x0c\r\n\x0b\n\x04\x05\0\x02\x01\ - \x12\x03\x0e\x04\x10\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x0e\x04\x0b\n\ - \x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x0e\x0e\x0f\n\x0b\n\x04\x05\0\x02\ - \x02\x12\x03\x0f\x04\x10\n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\x0f\x04\ - \x0b\n\x0c\n\x05\x05\0\x02\x02\x02\x12\x03\x0f\x0e\x0f\n\x0b\n\x04\x05\0\ - \x02\x03\x12\x03\x10\x04\x14\n\x0c\n\x05\x05\0\x02\x03\x01\x12\x03\x10\ - \x04\x0f\n\x0c\n\x05\x05\0\x02\x03\x02\x12\x03\x10\x12\x13b\x06proto3\ + \n\x08ws.proto\"\x7f\n\x0eDocumentWSData\x12\x15\n\x06doc_id\x18\x01\x20\ + \x01(\tR\x05docId\x12#\n\x02ty\x18\x02\x20\x01(\x0e2\x13.DocumentWSDataT\ + ypeR\x02ty\x12\x12\n\x04data\x18\x03\x20\x01(\x0cR\x04data\x12\x10\n\x02\ + id\x18\x04\x20\x01(\x03H\0R\x02idB\x0b\n\tone_of_id\"Z\n\x11DocumentConn\ + ected\x12\x17\n\x07user_id\x18\x01\x20\x01(\tR\x06userId\x12\x15\n\x06do\ + c_id\x18\x02\x20\x01(\tR\x05docId\x12\x15\n\x06rev_id\x18\x03\x20\x01(\ + \x03R\x05revId*J\n\x12DocumentWSDataType\x12\t\n\x05Acked\x10\0\x12\x0b\ + \n\x07PushRev\x10\x01\x12\x0b\n\x07PullRev\x10\x02\x12\x0f\n\x0bUserConn\ + ect\x10\x03J\x9a\x05\n\x06\x12\x04\0\0\x12\x01\n\x08\n\x01\x0c\x12\x03\0\ + \0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x07\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\x16\n\x0c\n\x05\x04\ + \0\x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\ + \x0b\x11\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x14\x15\n\x0b\n\x04\x04\ + \0\x02\x01\x12\x03\x04\x04\x1e\n\x0c\n\x05\x04\0\x02\x01\x06\x12\x03\x04\ + \x04\x16\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\x17\x19\n\x0c\n\x05\ + \x04\0\x02\x01\x03\x12\x03\x04\x1c\x1d\n\x0b\n\x04\x04\0\x02\x02\x12\x03\ + \x05\x04\x13\n\x0c\n\x05\x04\0\x02\x02\x05\x12\x03\x05\x04\t\n\x0c\n\x05\ + \x04\0\x02\x02\x01\x12\x03\x05\n\x0e\n\x0c\n\x05\x04\0\x02\x02\x03\x12\ + \x03\x05\x11\x12\n\x0b\n\x04\x04\0\x08\0\x12\x03\x06\x04%\n\x0c\n\x05\ + \x04\0\x08\0\x01\x12\x03\x06\n\x13\n\x0b\n\x04\x04\0\x02\x03\x12\x03\x06\ + \x16#\n\x0c\n\x05\x04\0\x02\x03\x05\x12\x03\x06\x16\x1b\n\x0c\n\x05\x04\ + \0\x02\x03\x01\x12\x03\x06\x1c\x1e\n\x0c\n\x05\x04\0\x02\x03\x03\x12\x03\ + \x06!\"\n\n\n\x02\x04\x01\x12\x04\x08\0\x0c\x01\n\n\n\x03\x04\x01\x01\ + \x12\x03\x08\x08\x19\n\x0b\n\x04\x04\x01\x02\0\x12\x03\t\x04\x17\n\x0c\n\ + \x05\x04\x01\x02\0\x05\x12\x03\t\x04\n\n\x0c\n\x05\x04\x01\x02\0\x01\x12\ + \x03\t\x0b\x12\n\x0c\n\x05\x04\x01\x02\0\x03\x12\x03\t\x15\x16\n\x0b\n\ + \x04\x04\x01\x02\x01\x12\x03\n\x04\x16\n\x0c\n\x05\x04\x01\x02\x01\x05\ + \x12\x03\n\x04\n\n\x0c\n\x05\x04\x01\x02\x01\x01\x12\x03\n\x0b\x11\n\x0c\ + \n\x05\x04\x01\x02\x01\x03\x12\x03\n\x14\x15\n\x0b\n\x04\x04\x01\x02\x02\ + \x12\x03\x0b\x04\x15\n\x0c\n\x05\x04\x01\x02\x02\x05\x12\x03\x0b\x04\t\n\ + \x0c\n\x05\x04\x01\x02\x02\x01\x12\x03\x0b\n\x10\n\x0c\n\x05\x04\x01\x02\ + \x02\x03\x12\x03\x0b\x13\x14\n\n\n\x02\x05\0\x12\x04\r\0\x12\x01\n\n\n\ + \x03\x05\0\x01\x12\x03\r\x05\x17\n\x0b\n\x04\x05\0\x02\0\x12\x03\x0e\x04\ + \x0e\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\x0e\x04\t\n\x0c\n\x05\x05\0\x02\ + \0\x02\x12\x03\x0e\x0c\r\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x0f\x04\x10\n\ + \x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x0f\x04\x0b\n\x0c\n\x05\x05\0\x02\ + \x01\x02\x12\x03\x0f\x0e\x0f\n\x0b\n\x04\x05\0\x02\x02\x12\x03\x10\x04\ + \x10\n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\x10\x04\x0b\n\x0c\n\x05\x05\0\ + \x02\x02\x02\x12\x03\x10\x0e\x0f\n\x0b\n\x04\x05\0\x02\x03\x12\x03\x11\ + \x04\x14\n\x0c\n\x05\x05\0\x02\x03\x01\x12\x03\x11\x04\x0f\n\x0c\n\x05\ + \x05\0\x02\x03\x02\x12\x03\x11\x12\x13b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/shared-lib/flowy-collaboration/src/protobuf/proto/ws.proto b/shared-lib/flowy-collaboration/src/protobuf/proto/ws.proto index 35a10bbbcf..9d0517d576 100644 --- a/shared-lib/flowy-collaboration/src/protobuf/proto/ws.proto +++ b/shared-lib/flowy-collaboration/src/protobuf/proto/ws.proto @@ -1,16 +1,17 @@ syntax = "proto3"; -message WsDocumentData { +message DocumentWSData { string doc_id = 1; - WsDocumentDataType ty = 2; + DocumentWSDataType ty = 2; bytes data = 3; + oneof one_of_id { int64 id = 4; }; } message DocumentConnected { string user_id = 1; string doc_id = 2; int64 rev_id = 3; } -enum WsDocumentDataType { +enum DocumentWSDataType { Acked = 0; PushRev = 1; PullRev = 2; diff --git a/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs b/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs index 4c178596a8..21677dfc6d 100644 --- a/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs +++ b/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs @@ -60,10 +60,10 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { | "DocDelta" | "NewDocUser" | "DocIdentifier" - | "WsDocumentData" + | "DocumentWSData" | "DocumentConnected" - | "WsError" - | "WsMessage" + | "WSError" + | "WSMessage" | "Revision" | "RevId" | "RevisionRange" @@ -89,9 +89,9 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { | "TrashType" | "ViewType" | "ExportType" - | "WsDocumentDataType" + | "DocumentWSDataType" | "ErrorCode" - | "WsModule" + | "WSModule" | "RevType" | "RevState" => TypeCategory::Enum, diff --git a/shared-lib/lib-ws/src/connect.rs b/shared-lib/lib-ws/src/connect.rs index e1848b46ed..b3fb181d37 100644 --- a/shared-lib/lib-ws/src/connect.rs +++ b/shared-lib/lib-ws/src/connect.rs @@ -1,6 +1,6 @@ #![allow(clippy::all)] use crate::{ - errors::{internal_error, WsError}, + errors::{internal_error, WSError}, MsgReceiver, MsgSender, }; @@ -24,16 +24,16 @@ use tokio_tungstenite::{ type WsConnectResult = Result<(WebSocketStream>, Response), Error>; #[pin_project] -pub struct WsConnectionFuture { +pub struct WSConnectionFuture { msg_tx: Option, ws_rx: Option, #[pin] fut: Pin + Send + Sync>>, } -impl WsConnectionFuture { +impl WSConnectionFuture { pub fn new(msg_tx: MsgSender, ws_rx: MsgReceiver, addr: String) -> Self { - WsConnectionFuture { + WSConnectionFuture { msg_tx: Some(msg_tx), ws_rx: Some(ws_rx), fut: Box::pin(async move { connect_async(&addr).await }), @@ -41,8 +41,8 @@ impl WsConnectionFuture { } } -impl Future for WsConnectionFuture { - type Output = Result; +impl Future for WSConnectionFuture { + type Output = Result; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { // [[pin]] // poll async function. The following methods not work. @@ -66,7 +66,7 @@ impl Future for WsConnectionFuture { self.msg_tx.take().expect("WsConnection should be call once "), self.ws_rx.take().expect("WsConnection should be call once "), ); - Poll::Ready(Ok(WsStream::new(msg_tx, ws_rx, stream))) + Poll::Ready(Ok(WSStream::new(msg_tx, ws_rx, stream))) }, Err(error) => { tracing::debug!("🐴 ws connect failed: {:?}", error); @@ -77,16 +77,16 @@ impl Future for WsConnectionFuture { } } -type Fut = BoxFuture<'static, Result<(), WsError>>; +type Fut = BoxFuture<'static, Result<(), WSError>>; #[pin_project] -pub struct WsStream { +pub struct WSStream { #[allow(dead_code)] msg_tx: MsgSender, #[pin] inner: Option<(Fut, Fut)>, } -impl WsStream { +impl WSStream { pub fn new(msg_tx: MsgSender, ws_rx: MsgReceiver, stream: WebSocketStream>) -> Self { let (ws_write, ws_read) = stream.split(); Self { @@ -110,7 +110,7 @@ impl WsStream { loop { match rx.recv().await { None => { - return Err(WsError::internal().context("WsStream rx closed unexpectedly")); + return Err(WSError::internal().context("WsStream rx closed unexpectedly")); }, Some(result) => { if result.is_err() { @@ -136,12 +136,12 @@ impl WsStream { } } -impl fmt::Debug for WsStream { +impl fmt::Debug for WSStream { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("WsStream").finish() } } -impl Future for WsStream { - type Output = Result<(), WsError>; +impl Future for WSStream { + type Output = Result<(), WSError>; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let (mut ws_read, mut ws_write) = self.inner.take().unwrap(); @@ -161,11 +161,11 @@ impl Future for WsStream { } } -fn send_message(msg_tx: MsgSender, message: Result) -> Result<(), WsError> { +fn send_message(msg_tx: MsgSender, message: Result) -> Result<(), WSError> { match message { Ok(Message::Binary(bytes)) => msg_tx.unbounded_send(Message::Binary(bytes)).map_err(internal_error), Ok(_) => Ok(()), - Err(e) => Err(WsError::internal().context(e)), + Err(e) => Err(WSError::internal().context(e)), } } #[allow(dead_code)] diff --git a/shared-lib/lib-ws/src/errors.rs b/shared-lib/lib-ws/src/errors.rs index 44f59d61ae..9003f9ebf9 100644 --- a/shared-lib/lib-ws/src/errors.rs +++ b/shared-lib/lib-ws/src/errors.rs @@ -6,7 +6,7 @@ use tokio_tungstenite::tungstenite::{http::StatusCode, Message}; use url::ParseError; #[derive(Debug, Default, Clone, ProtoBuf)] -pub struct WsError { +pub struct WSError { #[pb(index = 1)] pub code: ErrorCode, @@ -14,11 +14,11 @@ pub struct WsError { pub msg: String, } -macro_rules! static_user_error { +macro_rules! static_ws_error { ($name:ident, $status:expr) => { #[allow(non_snake_case, missing_docs)] - pub fn $name() -> WsError { - WsError { + pub fn $name() -> WSError { + WSError { code: $status, msg: format!("{}", $status), } @@ -26,10 +26,10 @@ macro_rules! static_user_error { }; } -impl WsError { +impl WSError { #[allow(dead_code)] - pub(crate) fn new(code: ErrorCode) -> WsError { - WsError { + pub(crate) fn new(code: ErrorCode) -> WSError { + WSError { code, msg: "".to_string(), } @@ -40,16 +40,16 @@ impl WsError { self } - static_user_error!(internal, ErrorCode::InternalError); - static_user_error!(unsupported_message, ErrorCode::UnsupportedMessage); - static_user_error!(unauthorized, ErrorCode::Unauthorized); + static_ws_error!(internal, ErrorCode::InternalError); + static_ws_error!(unsupported_message, ErrorCode::UnsupportedMessage); + static_ws_error!(unauthorized, ErrorCode::Unauthorized); } -pub fn internal_error(e: T) -> WsError +pub fn internal_error(e: T) -> WSError where T: std::fmt::Debug, { - WsError::internal().context(e) + WSError::internal().context(e) } #[derive(Debug, Clone, ProtoBuf_Enum, Display, PartialEq, Eq)] @@ -63,29 +63,29 @@ impl std::default::Default for ErrorCode { fn default() -> Self { ErrorCode::InternalError } } -impl std::convert::From for WsError { - fn from(error: ParseError) -> Self { WsError::internal().context(error) } +impl std::convert::From for WSError { + fn from(error: ParseError) -> Self { WSError::internal().context(error) } } -impl std::convert::From for WsError { - fn from(error: protobuf::ProtobufError) -> Self { WsError::internal().context(error) } +impl std::convert::From for WSError { + fn from(error: protobuf::ProtobufError) -> Self { WSError::internal().context(error) } } -impl std::convert::From> for WsError { - fn from(error: TrySendError) -> Self { WsError::internal().context(error) } +impl std::convert::From> for WSError { + fn from(error: TrySendError) -> Self { WSError::internal().context(error) } } -impl std::convert::From for WsError { +impl std::convert::From for WSError { fn from(error: tokio_tungstenite::tungstenite::Error) -> Self { match error { tokio_tungstenite::tungstenite::Error::Http(response) => { if response.status() == StatusCode::UNAUTHORIZED { - WsError::unauthorized() + WSError::unauthorized() } else { - WsError::internal().context(response) + WSError::internal().context(response) } }, - _ => WsError::internal().context(error), + _ => WSError::internal().context(error), } } } diff --git a/shared-lib/lib-ws/src/msg.rs b/shared-lib/lib-ws/src/msg.rs index f7dcaa23b0..dc61309e26 100644 --- a/shared-lib/lib-ws/src/msg.rs +++ b/shared-lib/lib-ws/src/msg.rs @@ -5,33 +5,33 @@ use tokio_tungstenite::tungstenite::Message as TokioMessage; // Opti: using four bytes of the data to represent the source #[derive(ProtoBuf, Debug, Clone, Default)] -pub struct WsMessage { +pub struct WSMessage { #[pb(index = 1)] - pub module: WsModule, + pub module: WSModule, #[pb(index = 2)] pub data: Vec, } #[derive(ProtoBuf_Enum, Debug, Clone, Eq, PartialEq, Hash)] -pub enum WsModule { +pub enum WSModule { Doc = 0, } -impl std::default::Default for WsModule { - fn default() -> Self { WsModule::Doc } +impl std::default::Default for WSModule { + fn default() -> Self { WSModule::Doc } } -impl ToString for WsModule { +impl ToString for WSModule { fn to_string(&self) -> String { match self { - WsModule::Doc => "0".to_string(), + WSModule::Doc => "0".to_string(), } } } -impl std::convert::From for TokioMessage { - fn from(msg: WsMessage) -> Self { +impl std::convert::From for TokioMessage { + fn from(msg: WSMessage) -> Self { let result: Result = msg.try_into(); match result { Ok(bytes) => TokioMessage::Binary(bytes.to_vec()), diff --git a/shared-lib/lib-ws/src/protobuf/model/errors.rs b/shared-lib/lib-ws/src/protobuf/model/errors.rs index 7db7f53940..1f4e8a0bec 100644 --- a/shared-lib/lib-ws/src/protobuf/model/errors.rs +++ b/shared-lib/lib-ws/src/protobuf/model/errors.rs @@ -24,7 +24,7 @@ // const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_22_1; #[derive(PartialEq,Clone,Default)] -pub struct WsError { +pub struct WSError { // message fields pub code: ErrorCode, pub msg: ::std::string::String, @@ -33,14 +33,14 @@ pub struct WsError { pub cached_size: ::protobuf::CachedSize, } -impl<'a> ::std::default::Default for &'a WsError { - fn default() -> &'a WsError { - ::default_instance() +impl<'a> ::std::default::Default for &'a WSError { + fn default() -> &'a WSError { + ::default_instance() } } -impl WsError { - pub fn new() -> WsError { +impl WSError { + pub fn new() -> WSError { ::std::default::Default::default() } @@ -86,7 +86,7 @@ impl WsError { } } -impl ::protobuf::Message for WsError { +impl ::protobuf::Message for WSError { fn is_initialized(&self) -> bool { true } @@ -161,8 +161,8 @@ impl ::protobuf::Message for WsError { Self::descriptor_static() } - fn new() -> WsError { - WsError::new() + fn new() -> WSError { + WSError::new() } fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { @@ -171,29 +171,29 @@ impl ::protobuf::Message for WsError { let mut fields = ::std::vec::Vec::new(); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( "code", - |m: &WsError| { &m.code }, - |m: &mut WsError| { &mut m.code }, + |m: &WSError| { &m.code }, + |m: &mut WSError| { &mut m.code }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "msg", - |m: &WsError| { &m.msg }, - |m: &mut WsError| { &mut m.msg }, + |m: &WSError| { &m.msg }, + |m: &mut WSError| { &mut m.msg }, )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "WsError", + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "WSError", fields, file_descriptor_proto() ) }) } - fn default_instance() -> &'static WsError { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(WsError::new) + fn default_instance() -> &'static WSError { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(WSError::new) } } -impl ::protobuf::Clear for WsError { +impl ::protobuf::Clear for WSError { fn clear(&mut self) { self.code = ErrorCode::InternalError; self.msg.clear(); @@ -201,13 +201,13 @@ impl ::protobuf::Clear for WsError { } } -impl ::std::fmt::Debug for WsError { +impl ::std::fmt::Debug for WSError { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { ::protobuf::text_format::fmt(self, f) } } -impl ::protobuf::reflect::ProtobufValue for WsError { +impl ::protobuf::reflect::ProtobufValue for WSError { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { ::protobuf::reflect::ReflectValueRef::Message(self) } @@ -267,7 +267,7 @@ impl ::protobuf::reflect::ProtobufValue for ErrorCode { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x0cerrors.proto\";\n\x07WsError\x12\x1e\n\x04code\x18\x01\x20\x01(\ + \n\x0cerrors.proto\";\n\x07WSError\x12\x1e\n\x04code\x18\x01\x20\x01(\ \x0e2\n.ErrorCodeR\x04code\x12\x10\n\x03msg\x18\x02\x20\x01(\tR\x03msg*H\ \n\tErrorCode\x12\x11\n\rInternalError\x10\0\x12\x16\n\x12UnsupportedMes\ sage\x10\x01\x12\x10\n\x0cUnauthorized\x10\x02J\xab\x02\n\x06\x12\x04\0\ diff --git a/shared-lib/lib-ws/src/protobuf/model/msg.rs b/shared-lib/lib-ws/src/protobuf/model/msg.rs index 35c80e3a65..9484576264 100644 --- a/shared-lib/lib-ws/src/protobuf/model/msg.rs +++ b/shared-lib/lib-ws/src/protobuf/model/msg.rs @@ -24,38 +24,38 @@ // const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_22_1; #[derive(PartialEq,Clone,Default)] -pub struct WsMessage { +pub struct WSMessage { // message fields - pub module: WsModule, + pub module: WSModule, pub data: ::std::vec::Vec, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, } -impl<'a> ::std::default::Default for &'a WsMessage { - fn default() -> &'a WsMessage { - ::default_instance() +impl<'a> ::std::default::Default for &'a WSMessage { + fn default() -> &'a WSMessage { + ::default_instance() } } -impl WsMessage { - pub fn new() -> WsMessage { +impl WSMessage { + pub fn new() -> WSMessage { ::std::default::Default::default() } - // .WsModule module = 1; + // .WSModule module = 1; - pub fn get_module(&self) -> WsModule { + pub fn get_module(&self) -> WSModule { self.module } pub fn clear_module(&mut self) { - self.module = WsModule::Doc; + self.module = WSModule::Doc; } // Param is passed by value, moved - pub fn set_module(&mut self, v: WsModule) { + pub fn set_module(&mut self, v: WSModule) { self.module = v; } @@ -86,7 +86,7 @@ impl WsMessage { } } -impl ::protobuf::Message for WsMessage { +impl ::protobuf::Message for WSMessage { fn is_initialized(&self) -> bool { true } @@ -113,7 +113,7 @@ impl ::protobuf::Message for WsMessage { #[allow(unused_variables)] fn compute_size(&self) -> u32 { let mut my_size = 0; - if self.module != WsModule::Doc { + if self.module != WSModule::Doc { my_size += ::protobuf::rt::enum_size(1, self.module); } if !self.data.is_empty() { @@ -125,7 +125,7 @@ impl ::protobuf::Message for WsMessage { } fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { - if self.module != WsModule::Doc { + if self.module != WSModule::Doc { os.write_enum(1, ::protobuf::ProtobufEnum::value(&self.module))?; } if !self.data.is_empty() { @@ -161,78 +161,78 @@ impl ::protobuf::Message for WsMessage { Self::descriptor_static() } - fn new() -> WsMessage { - WsMessage::new() + fn new() -> WSMessage { + WSMessage::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>( + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( "module", - |m: &WsMessage| { &m.module }, - |m: &mut WsMessage| { &mut m.module }, + |m: &WSMessage| { &m.module }, + |m: &mut WSMessage| { &mut m.module }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>( "data", - |m: &WsMessage| { &m.data }, - |m: &mut WsMessage| { &mut m.data }, + |m: &WSMessage| { &m.data }, + |m: &mut WSMessage| { &mut m.data }, )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "WsMessage", + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "WSMessage", fields, file_descriptor_proto() ) }) } - fn default_instance() -> &'static WsMessage { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(WsMessage::new) + fn default_instance() -> &'static WSMessage { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(WSMessage::new) } } -impl ::protobuf::Clear for WsMessage { +impl ::protobuf::Clear for WSMessage { fn clear(&mut self) { - self.module = WsModule::Doc; + self.module = WSModule::Doc; self.data.clear(); self.unknown_fields.clear(); } } -impl ::std::fmt::Debug for WsMessage { +impl ::std::fmt::Debug for WSMessage { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { ::protobuf::text_format::fmt(self, f) } } -impl ::protobuf::reflect::ProtobufValue for WsMessage { +impl ::protobuf::reflect::ProtobufValue for WSMessage { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { ::protobuf::reflect::ReflectValueRef::Message(self) } } #[derive(Clone,PartialEq,Eq,Debug,Hash)] -pub enum WsModule { +pub enum WSModule { Doc = 0, } -impl ::protobuf::ProtobufEnum for WsModule { +impl ::protobuf::ProtobufEnum for WSModule { fn value(&self) -> i32 { *self as i32 } - fn from_i32(value: i32) -> ::std::option::Option { + fn from_i32(value: i32) -> ::std::option::Option { match value { - 0 => ::std::option::Option::Some(WsModule::Doc), + 0 => ::std::option::Option::Some(WSModule::Doc), _ => ::std::option::Option::None } } fn values() -> &'static [Self] { - static values: &'static [WsModule] = &[ - WsModule::Doc, + static values: &'static [WSModule] = &[ + WSModule::Doc, ]; values } @@ -240,30 +240,30 @@ impl ::protobuf::ProtobufEnum for WsModule { 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::("WsModule", file_descriptor_proto()) + ::protobuf::reflect::EnumDescriptor::new_pb_name::("WSModule", file_descriptor_proto()) }) } } -impl ::std::marker::Copy for WsModule { +impl ::std::marker::Copy for WSModule { } -impl ::std::default::Default for WsModule { +impl ::std::default::Default for WSModule { fn default() -> Self { - WsModule::Doc + WSModule::Doc } } -impl ::protobuf::reflect::ProtobufValue for WsModule { +impl ::protobuf::reflect::ProtobufValue for WSModule { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { ::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self)) } } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\tmsg.proto\"B\n\tWsMessage\x12!\n\x06module\x18\x01\x20\x01(\x0e2\t.W\ - sModuleR\x06module\x12\x12\n\x04data\x18\x02\x20\x01(\x0cR\x04data*\x13\ - \n\x08WsModule\x12\x07\n\x03Doc\x10\0J\xd9\x01\n\x06\x12\x04\0\0\x08\x01\ + \n\tmsg.proto\"B\n\tWSMessage\x12!\n\x06module\x18\x01\x20\x01(\x0e2\t.W\ + SModuleR\x06module\x12\x12\n\x04data\x18\x02\x20\x01(\x0cR\x04data*\x13\ + \n\x08WSModule\x12\x07\n\x03Doc\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\x11\n\x0b\n\x04\x04\0\x02\0\x12\x03\ \x03\x04\x18\n\x0c\n\x05\x04\0\x02\0\x06\x12\x03\x03\x04\x0c\n\x0c\n\x05\ diff --git a/shared-lib/lib-ws/src/protobuf/proto/errors.proto b/shared-lib/lib-ws/src/protobuf/proto/errors.proto index cbb330a6e8..a2e3ccc45a 100644 --- a/shared-lib/lib-ws/src/protobuf/proto/errors.proto +++ b/shared-lib/lib-ws/src/protobuf/proto/errors.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -message WsError { +message WSError { ErrorCode code = 1; string msg = 2; } diff --git a/shared-lib/lib-ws/src/protobuf/proto/msg.proto b/shared-lib/lib-ws/src/protobuf/proto/msg.proto index 4b71578340..551a813596 100644 --- a/shared-lib/lib-ws/src/protobuf/proto/msg.proto +++ b/shared-lib/lib-ws/src/protobuf/proto/msg.proto @@ -1,9 +1,9 @@ syntax = "proto3"; -message WsMessage { - WsModule module = 1; +message WSMessage { + WSModule module = 1; bytes data = 2; } -enum WsModule { +enum WSModule { Doc = 0; } diff --git a/shared-lib/lib-ws/src/ws.rs b/shared-lib/lib-ws/src/ws.rs index ba62f4a454..02bc58279f 100644 --- a/shared-lib/lib-ws/src/ws.rs +++ b/shared-lib/lib-ws/src/ws.rs @@ -1,9 +1,9 @@ #![allow(clippy::type_complexity)] use crate::{ - connect::{WsConnectionFuture, WsStream}, - errors::WsError, - WsMessage, - WsModule, + connect::{WSConnectionFuture, WSStream}, + errors::WSError, + WSMessage, + WSModule, }; use backend_service::errors::ServerError; use bytes::Bytes; @@ -30,36 +30,36 @@ use tokio_tungstenite::tungstenite::{ pub type MsgReceiver = UnboundedReceiver; pub type MsgSender = UnboundedSender; -type Handlers = DashMap>; +type Handlers = DashMap>; -pub trait WsMessageReceiver: Sync + Send + 'static { - fn source(&self) -> WsModule; - fn receive_message(&self, msg: WsMessage); +pub trait WSMessageReceiver: Sync + Send + 'static { + fn source(&self) -> WSModule; + fn receive_message(&self, msg: WSMessage); } -pub struct WsController { +pub struct WSController { handlers: Handlers, - state_notify: Arc>, - sender_ctrl: Arc>, + state_notify: Arc>, + sender_ctrl: Arc>, addr: Arc>>, } -impl std::default::Default for WsController { +impl std::default::Default for WSController { fn default() -> Self { let (state_notify, _) = broadcast::channel(16); Self { handlers: DashMap::new(), - sender_ctrl: Arc::new(RwLock::new(WsSenderController::default())), + sender_ctrl: Arc::new(RwLock::new(WSSenderController::default())), state_notify: Arc::new(state_notify), addr: Arc::new(RwLock::new(None)), } } } -impl WsController { - pub fn new() -> Self { WsController::default() } +impl WSController { + pub fn new() -> Self { WSController::default() } - pub fn add_receiver(&self, handler: Arc) -> Result<(), WsError> { + pub fn add_receiver(&self, handler: Arc) -> Result<(), WSError> { let source = handler.source(); if self.handlers.contains_key(&source) { log::error!("WsSource's {:?} is already registered", source); @@ -74,7 +74,7 @@ impl WsController { self.connect(addr, strategy).await } - pub async fn stop(&self) { self.sender_ctrl.write().set_state(WsConnectState::Disconnected); } + pub async fn stop(&self) { self.sender_ctrl.write().set_state(WSConnectState::Disconnected); } async fn connect(&self, addr: String, strategy: T) -> Result<(), ServerError> where @@ -83,25 +83,25 @@ impl WsController { { let (ret, rx) = oneshot::channel::>(); *self.addr.write() = Some(addr.clone()); - let action = WsConnectAction { + let action = WSConnectAction { addr, handlers: self.handlers.clone(), }; let retry = Retry::spawn(strategy, action); let sender_ctrl = self.sender_ctrl.clone(); - sender_ctrl.write().set_state(WsConnectState::Connecting); + sender_ctrl.write().set_state(WSConnectState::Connecting); tokio::spawn(async move { match retry.await { Ok(result) => { - let WsConnectResult { + let WSConnectResult { stream, handlers_fut, sender, } = result; sender_ctrl.write().set_sender(sender); - sender_ctrl.write().set_state(WsConnectState::Connected); + sender_ctrl.write().set_state(WSConnectState::Connected); let _ = ret.send(Ok(())); spawn_stream_and_handlers(stream, handlers_fut, sender_ctrl.clone()).await; }, @@ -131,20 +131,20 @@ impl WsController { self.connect(addr, strategy).await } - pub fn subscribe_state(&self) -> broadcast::Receiver { self.state_notify.subscribe() } + pub fn subscribe_state(&self) -> broadcast::Receiver { self.state_notify.subscribe() } - pub fn sender(&self) -> Result, WsError> { + pub fn sender(&self) -> Result, WSError> { match self.sender_ctrl.read().sender() { - None => Err(WsError::internal().context("WsSender is not initialized, should call connect first")), + None => Err(WSError::internal().context("WsSender is not initialized, should call connect first")), Some(sender) => Ok(sender), } } } async fn spawn_stream_and_handlers( - stream: WsStream, - handlers: WsHandlerFuture, - sender_ctrl: Arc>, + stream: WSStream, + handlers: WSHandlerFuture, + sender_ctrl: Arc>, ) { tokio::select! { result = stream => { @@ -157,14 +157,14 @@ async fn spawn_stream_and_handlers( } #[pin_project] -pub struct WsHandlerFuture { +pub struct WSHandlerFuture { #[pin] msg_rx: MsgReceiver, // Opti: Hashmap would be better handlers: Handlers, } -impl WsHandlerFuture { +impl WSHandlerFuture { fn new(handlers: Handlers, msg_rx: MsgReceiver) -> Self { Self { msg_rx, handlers } } fn handler_ws_message(&self, message: Message) { @@ -175,7 +175,7 @@ impl WsHandlerFuture { fn handle_binary_message(&self, bytes: Vec) { let bytes = Bytes::from(bytes); - match WsMessage::try_from(bytes) { + match WSMessage::try_from(bytes) { Ok(message) => match self.handlers.get(&message.module) { None => log::error!("Can't find any handler for message: {:?}", message), Some(handler) => handler.receive_message(message.clone()), @@ -187,7 +187,7 @@ impl WsHandlerFuture { } } -impl Future for WsHandlerFuture { +impl Future for WSHandlerFuture { type Output = (); fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { loop { @@ -202,37 +202,37 @@ impl Future for WsHandlerFuture { } #[derive(Debug, Clone)] -pub struct WsSender { +pub struct WSSender { ws_tx: MsgSender, } -impl WsSender { - pub fn send_msg>(&self, msg: T) -> Result<(), WsError> { +impl WSSender { + pub fn send_msg>(&self, msg: T) -> Result<(), WSError> { let msg = msg.into(); let _ = self .ws_tx .unbounded_send(msg.into()) - .map_err(|e| WsError::internal().context(e))?; + .map_err(|e| WSError::internal().context(e))?; Ok(()) } - pub fn send_text(&self, source: &WsModule, text: &str) -> Result<(), WsError> { - let msg = WsMessage { + pub fn send_text(&self, source: &WSModule, text: &str) -> Result<(), WSError> { + let msg = WSMessage { module: source.clone(), data: text.as_bytes().to_vec(), }; self.send_msg(msg) } - pub fn send_binary(&self, source: &WsModule, bytes: Vec) -> Result<(), WsError> { - let msg = WsMessage { + pub fn send_binary(&self, source: &WSModule, bytes: Vec) -> Result<(), WSError> { + let msg = WSMessage { module: source.clone(), data: bytes, }; self.send_msg(msg) } - pub fn send_disconnect(&self, reason: &str) -> Result<(), WsError> { + pub fn send_disconnect(&self, reason: &str) -> Result<(), WSError> { let frame = CloseFrame { code: CloseCode::Normal, reason: reason.to_owned().into(), @@ -241,44 +241,44 @@ impl WsSender { let _ = self .ws_tx .unbounded_send(msg) - .map_err(|e| WsError::internal().context(e))?; + .map_err(|e| WSError::internal().context(e))?; Ok(()) } } -struct WsConnectAction { +struct WSConnectAction { addr: String, handlers: Handlers, } -impl Action for WsConnectAction { +impl Action for WSConnectAction { type Future = Pin> + Send + Sync>>; - type Item = WsConnectResult; - type Error = WsError; + type Item = WSConnectResult; + type Error = WSError; fn run(&mut self) -> Self::Future { let addr = self.addr.clone(); let handlers = self.handlers.clone(); - Box::pin(WsConnectActionFut::new(addr, handlers)) + Box::pin(WSConnectActionFut::new(addr, handlers)) } } -struct WsConnectResult { - stream: WsStream, - handlers_fut: WsHandlerFuture, - sender: WsSender, +struct WSConnectResult { + stream: WSStream, + handlers_fut: WSHandlerFuture, + sender: WSSender, } #[pin_project] -struct WsConnectActionFut { +struct WSConnectActionFut { addr: String, #[pin] - conn: WsConnectionFuture, - handlers_fut: Option, - sender: Option, + conn: WSConnectionFuture, + handlers_fut: Option, + sender: Option, } -impl WsConnectActionFut { +impl WSConnectActionFut { fn new(addr: String, handlers: Handlers) -> Self { // Stream User // ┌───────────────┐ ┌──────────────┐ @@ -292,9 +292,9 @@ impl WsConnectActionFut { // └───────────────┘ └──────────────┘ let (msg_tx, msg_rx) = futures_channel::mpsc::unbounded(); let (ws_tx, ws_rx) = futures_channel::mpsc::unbounded(); - let sender = WsSender { ws_tx }; - let handlers_fut = WsHandlerFuture::new(handlers, msg_rx); - let conn = WsConnectionFuture::new(msg_tx, ws_rx, addr.clone()); + let sender = WSSender { ws_tx }; + let handlers_fut = WSHandlerFuture::new(handlers, msg_rx); + let conn = WSConnectionFuture::new(msg_tx, ws_rx, addr.clone()); Self { addr, conn, @@ -304,15 +304,15 @@ impl WsConnectActionFut { } } -impl Future for WsConnectActionFut { - type Output = Result; +impl Future for WSConnectActionFut { + type Output = Result; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let mut this = self.project(); match ready!(this.conn.as_mut().poll(cx)) { Ok(stream) => { let handlers_fut = this.handlers_fut.take().expect("Only take once"); let sender = this.sender.take().expect("Only take once"); - Poll::Ready(Ok(WsConnectResult { + Poll::Ready(Ok(WSConnectResult { stream, handlers_fut, sender, @@ -324,39 +324,39 @@ impl Future for WsConnectActionFut { } #[derive(Clone, Eq, PartialEq)] -pub enum WsConnectState { +pub enum WSConnectState { Init, Connecting, Connected, Disconnected, } -impl std::fmt::Display for WsConnectState { +impl std::fmt::Display for WSConnectState { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { - WsConnectState::Init => f.write_str("Init"), - WsConnectState::Connected => f.write_str("Connecting"), - WsConnectState::Connecting => f.write_str("Connected"), - WsConnectState::Disconnected => f.write_str("Disconnected"), + WSConnectState::Init => f.write_str("Init"), + WSConnectState::Connected => f.write_str("Connecting"), + WSConnectState::Connecting => f.write_str("Connected"), + WSConnectState::Disconnected => f.write_str("Disconnected"), } } } -impl std::fmt::Debug for WsConnectState { +impl std::fmt::Debug for WSConnectState { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.write_str(&format!("{}", self)) } } -struct WsSenderController { - state: WsConnectState, - state_notify: Arc>, - sender: Option>, +struct WSSenderController { + state: WSConnectState, + state_notify: Arc>, + sender: Option>, } -impl WsSenderController { - fn set_sender(&mut self, sender: WsSender) { self.sender = Some(Arc::new(sender)); } +impl WSSenderController { + fn set_sender(&mut self, sender: WSSender) { self.sender = Some(Arc::new(sender)); } - fn set_state(&mut self, state: WsConnectState) { - if state != WsConnectState::Connected { + fn set_state(&mut self, state: WSConnectState) { + if state != WSConnectState::Connected { self.sender = None; } @@ -364,24 +364,24 @@ impl WsSenderController { let _ = self.state_notify.send(self.state.clone()); } - fn set_error(&mut self, error: WsError) { + fn set_error(&mut self, error: WSError) { log::error!("{:?}", error); - self.set_state(WsConnectState::Disconnected); + self.set_state(WSConnectState::Disconnected); } - fn sender(&self) -> Option> { self.sender.clone() } + fn sender(&self) -> Option> { self.sender.clone() } - fn is_connecting(&self) -> bool { self.state == WsConnectState::Connecting } + fn is_connecting(&self) -> bool { self.state == WSConnectState::Connecting } #[allow(dead_code)] - fn is_connected(&self) -> bool { self.state == WsConnectState::Connected } + fn is_connected(&self) -> bool { self.state == WSConnectState::Connected } } -impl std::default::Default for WsSenderController { +impl std::default::Default for WSSenderController { fn default() -> Self { let (state_notify, _) = broadcast::channel(16); - WsSenderController { - state: WsConnectState::Init, + WSSenderController { + state: WSConnectState::Init, state_notify: Arc::new(state_notify), sender: None, } From 1744938a515872d446e28807d278327fe01448fb Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 18 Dec 2021 00:23:26 +0800 Subject: [PATCH 33/39] fix bugs --- frontend/rust-lib/flowy-core/Flowy.toml | 2 +- frontend/rust-lib/flowy-document/Flowy.toml | 2 +- .../src/services/doc/controller.rs | 21 +- .../src/services/doc/edit/editor.rs | 60 ++-- .../src/services/doc/edit/mod.rs | 4 +- .../doc/edit/{edit_ws.rs => web_socket.rs} | 18 +- .../src/services/doc/revision/cache/cache.rs | 273 +++++------------- .../src/services/doc/revision/cache/disk.rs | 49 +++- .../src/services/doc/revision/cache/memory.rs | 167 ++++------- .../src/services/doc/revision/cache/mod.rs | 1 + .../src/services/doc/revision/cache/sync.rs | 71 +++++ .../src/services/doc/revision/manager.rs | 94 +++++- .../flowy-document/src/services/doc/ws/mod.rs | 0 .../rust-lib/flowy-test/src/doc_script.rs | 4 +- frontend/rust-lib/flowy-user/Flowy.toml | 2 +- .../src/core/sync/synchronizer.rs | 6 +- .../flowy-collaboration/src/entities/ws/ws.rs | 2 +- 17 files changed, 409 insertions(+), 367 deletions(-) rename frontend/rust-lib/flowy-document/src/services/doc/edit/{edit_ws.rs => web_socket.rs} (93%) create mode 100644 frontend/rust-lib/flowy-document/src/services/doc/revision/cache/sync.rs delete mode 100644 frontend/rust-lib/flowy-document/src/services/doc/ws/mod.rs diff --git a/frontend/rust-lib/flowy-core/Flowy.toml b/frontend/rust-lib/flowy-core/Flowy.toml index 152585acd5..667c9f7ae4 100644 --- a/frontend/rust-lib/flowy-core/Flowy.toml +++ b/frontend/rust-lib/flowy-core/Flowy.toml @@ -1,3 +1,3 @@ -proto_crates = ["src/entities", "src/event.rs", "src/errors.rs", "src/notify"] +proto_crates = ["src/entities", "src/event.rs", "src/notify"] event_files = ["src/event.rs"] \ No newline at end of file diff --git a/frontend/rust-lib/flowy-document/Flowy.toml b/frontend/rust-lib/flowy-document/Flowy.toml index d55cb31ce9..f9ff7f7438 100644 --- a/frontend/rust-lib/flowy-document/Flowy.toml +++ b/frontend/rust-lib/flowy-document/Flowy.toml @@ -1,3 +1,3 @@ -proto_crates = ["src/event.rs", "src/errors.rs", "src/notify"] +proto_crates = ["src/notify"] event_files = [] \ No newline at end of file diff --git a/frontend/rust-lib/flowy-document/src/services/doc/controller.rs b/frontend/rust-lib/flowy-document/src/services/doc/controller.rs index 12813a1daf..7ea9a59fe1 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/controller.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/controller.rs @@ -28,7 +28,12 @@ pub(crate) struct DocController { impl DocController { pub(crate) fn new(server: Server, user: Arc, ws_handlers: Arc) -> Self { let open_cache = Arc::new(OpenDocCache::new()); - Self { server, ws_handlers, open_cache, user } + Self { + server, + ws_handlers, + open_cache, + user, + } } pub(crate) fn init(&self) -> FlowyResult<()> { @@ -93,8 +98,13 @@ impl DocController { pool: Arc, ) -> Result, FlowyError> { let user = self.user.clone(); + let token = self.user.token()?; let rev_manager = self.make_rev_manager(doc_id, pool.clone())?; - let doc_editor = ClientDocEditor::new(doc_id, user, pool, rev_manager, self.ws_handlers.ws()).await?; + let server = Arc::new(RevisionServerImpl { + token, + server: self.server.clone(), + }); + let doc_editor = ClientDocEditor::new(doc_id, user, pool, rev_manager, self.ws_handlers.ws(), server).await?; let ws_handler = doc_editor.ws_handler(); self.ws_handlers.register_handler(doc_id, ws_handler); self.open_cache.insert(&doc_id, &doc_editor); @@ -105,13 +115,8 @@ impl DocController { // 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?; - let token = self.user.token()?; let user_id = self.user.user_id()?; - let server = Arc::new(RevisionServerImpl { - token, - server: self.server.clone(), - }); - let cache = Arc::new(RevisionCache::new(&user_id, doc_id, pool, server)); + let cache = Arc::new(RevisionCache::new(&user_id, doc_id, pool)); Ok(RevisionManager::new(&user_id, doc_id, cache)) } } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs index c5fc1ae140..8f5a697c93 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs @@ -13,16 +13,15 @@ use lib_ot::{ revision::{RevId, RevType, Revision, RevisionRange}, rich_text::{RichTextAttribute, RichTextDelta}, }; -use parking_lot::RwLock; use std::{collections::VecDeque, sync::Arc}; -use tokio::sync::{mpsc, mpsc::UnboundedSender, oneshot}; -type SinkVec = Arc>>; +use tokio::sync::{mpsc, mpsc::UnboundedSender, oneshot, RwLock}; + pub struct ClientDocEditor { pub doc_id: String, rev_manager: Arc, ws_manager: Arc, edit_cmd_tx: UnboundedSender, - sink_vec: SinkVec, + sink_data_provider: SinkDataProvider, user: Arc, } @@ -33,22 +32,23 @@ impl ClientDocEditor { pool: Arc, mut rev_manager: RevisionManager, ws: Arc, + server: Arc, ) -> FlowyResult> { - let delta = rev_manager.load_document().await?; + let delta = rev_manager.load_document(server).await?; let edit_cmd_tx = spawn_edit_queue(doc_id, delta, pool.clone()); let doc_id = doc_id.to_string(); let rev_manager = Arc::new(rev_manager); - let sink_vec = Arc::new(RwLock::new(VecDeque::new())); + let sink_data_provider = Arc::new(RwLock::new(VecDeque::new())); let data_provider = Arc::new(DocumentSinkDataProviderAdapter { rev_manager: rev_manager.clone(), - sink_vec: sink_vec.clone(), + data_provider: sink_data_provider.clone(), }); let stream_consumer = Arc::new(DocumentWebSocketSteamConsumerAdapter { doc_id: doc_id.clone(), edit_cmd_tx: edit_cmd_tx.clone(), rev_manager: rev_manager.clone(), user: user.clone(), - sink_vec: sink_vec.clone(), + sink_data_provider: sink_data_provider.clone(), }); let ws_manager = Arc::new(WebSocketManager::new(&doc_id, ws, data_provider, stream_consumer)); let editor = Arc::new(Self { @@ -56,7 +56,7 @@ impl ClientDocEditor { rev_manager, ws_manager, edit_cmd_tx, - sink_vec, + sink_data_provider, user, }); Ok(editor) @@ -202,7 +202,7 @@ struct DocumentWebSocketSteamConsumerAdapter { edit_cmd_tx: UnboundedSender, rev_manager: Arc, user: Arc, - sink_vec: SinkVec, + sink_data_provider: SinkDataProvider, } impl DocumentWebSocketSteamConsumer for DocumentWebSocketSteamConsumerAdapter { @@ -210,43 +210,50 @@ impl DocumentWebSocketSteamConsumer for DocumentWebSocketSteamConsumerAdapter { let user = self.user.clone(); let rev_manager = self.rev_manager.clone(); let edit_cmd_tx = self.edit_cmd_tx.clone(); + let sink_data_provider = self.sink_data_provider.clone(); let doc_id = self.doc_id.clone(); FutureResult::new(async move { let user_id = user.user_id()?; - let _revision = handle_push_rev(&doc_id, &user_id, edit_cmd_tx, rev_manager, bytes).await?; + if let Some(revision) = handle_push_rev(&doc_id, &user_id, edit_cmd_tx, rev_manager, bytes).await? { + sink_data_provider.write().await.push_back(revision.into()); + } Ok(()) }) } - fn make_revision_from_range(&self, range: RevisionRange) -> FutureResult { - let rev_manager = self.rev_manager.clone(); - FutureResult::new(async move { - let revision = rev_manager.mk_revisions(range).await?; - Ok(revision) - }) - } - - fn ack_revision(&self, rev_id: i64) -> FutureResult<(), FlowyError> { + fn receive_ack_revision(&self, rev_id: i64) -> FutureResult<(), FlowyError> { let rev_manager = self.rev_manager.clone(); FutureResult::new(async move { let _ = rev_manager.ack_revision(rev_id).await?; Ok(()) }) } + + fn send_revision_in_range(&self, range: RevisionRange) -> FutureResult<(), FlowyError> { + let rev_manager = self.rev_manager.clone(); + let sink_data_provider = self.sink_data_provider.clone(); + FutureResult::new(async move { + let revision = rev_manager.mk_revisions(range).await?; + sink_data_provider.write().await.push_back(revision.into()); + Ok(()) + }) + } } +type SinkDataProvider = Arc>>; + struct DocumentSinkDataProviderAdapter { rev_manager: Arc, - sink_vec: SinkVec, + data_provider: SinkDataProvider, } impl DocumentSinkDataProvider for DocumentSinkDataProviderAdapter { fn next(&self) -> FutureResult, FlowyError> { let rev_manager = self.rev_manager.clone(); - let sink_vec = self.sink_vec.clone(); + let data_provider = self.data_provider.clone(); FutureResult::new(async move { - if sink_vec.read().is_empty() { + if data_provider.read().await.is_empty() { match rev_manager.next_sync_revision().await? { Some(rev) => { tracing::debug!("[DocumentSinkDataProvider]: revision: {}:{:?}", rev.doc_id, rev.rev_id); @@ -255,9 +262,12 @@ impl DocumentSinkDataProvider for DocumentSinkDataProviderAdapter { None => Ok(None), } } else { - match sink_vec.read().front() { + match data_provider.read().await.front() { None => Ok(None), - Some(data) => Ok(Some(data.clone())), + Some(data) => { + tracing::debug!("[DocumentSinkDataProvider]: {}:{:?}", data.doc_id, data.ty); + Ok(Some(data.clone())) + }, } } }) diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/mod.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/mod.rs index 794da84e62..de21adfac6 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/mod.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/mod.rs @@ -1,8 +1,8 @@ mod edit_queue; -mod edit_ws; mod editor; mod model; +mod web_socket; pub(crate) use edit_queue::*; -pub use edit_ws::*; pub use editor::*; +pub use web_socket::*; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/edit_ws.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/web_socket.rs similarity index 93% rename from frontend/rust-lib/flowy-document/src/services/doc/edit/edit_ws.rs rename to frontend/rust-lib/flowy-document/src/services/doc/edit/web_socket.rs index 59d548eaa8..adcdf39a42 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/edit_ws.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/web_socket.rs @@ -1,10 +1,7 @@ use crate::services::doc::{DocumentWebSocket, DocumentWsHandler, SYNC_INTERVAL_IN_MILLIS}; use async_stream::stream; use bytes::Bytes; -use flowy_collaboration::{ - entities::ws::{DocumentWSData, DocumentWSDataType}, - Revision, -}; +use flowy_collaboration::entities::ws::{DocumentWSData, DocumentWSDataType}; use flowy_error::{internal_error, FlowyError, FlowyResult}; use futures::stream::StreamExt; use lib_infra::future::FutureResult; @@ -66,7 +63,6 @@ impl WebSocketManager { &self.doc_id, self.stream_consumer.clone(), ws_msg_rx, - self.ws.clone(), self.stop_sync_tx.subscribe(), ); tokio::spawn(sink.run()); @@ -117,15 +113,14 @@ impl DocumentWsHandler for WebSocketManager { pub trait DocumentWebSocketSteamConsumer: Send + Sync { fn receive_push_revision(&self, bytes: Bytes) -> FutureResult<(), FlowyError>; - fn make_revision_from_range(&self, range: RevisionRange) -> FutureResult; - fn ack_revision(&self, rev_id: i64) -> FutureResult<(), FlowyError>; + fn receive_ack_revision(&self, rev_id: i64) -> FutureResult<(), FlowyError>; + fn send_revision_in_range(&self, range: RevisionRange) -> FutureResult<(), FlowyError>; } pub(crate) struct DocumentWebSocketStream { doc_id: String, consumer: Arc, ws_msg_rx: Option>, - ws_sender: Arc, stop_rx: Option, } @@ -134,14 +129,12 @@ impl DocumentWebSocketStream { doc_id: &str, consumer: Arc, ws_msg_rx: mpsc::UnboundedReceiver, - ws_sender: Arc, stop_rx: SinkStopRx, ) -> Self { DocumentWebSocketStream { doc_id: doc_id.to_owned(), consumer, ws_msg_rx: Some(ws_msg_rx), - ws_sender, stop_rx: Some(stop_rx), } } @@ -200,12 +193,11 @@ impl DocumentWebSocketStream { }, DocumentWSDataType::PullRev => { let range = RevisionRange::try_from(bytes)?; - let revision = self.consumer.make_revision_from_range(range).await?; - let _ = self.ws_sender.send(revision.into()); + let _ = self.consumer.send_revision_in_range(range).await?; }, DocumentWSDataType::Acked => { let rev_id = RevId::try_from(bytes)?; - let _ = self.consumer.ack_revision(rev_id.into()).await; + let _ = self.consumer.receive_ack_revision(rev_id.into()).await; }, DocumentWSDataType::UserConnect => {}, } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs index 6858108afa..ce85c8c4dd 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs @@ -1,56 +1,51 @@ use crate::{ errors::FlowyError, services::doc::revision::{ - cache::{disk::RevisionDiskCache, memory::RevisionMemoryCache}, + cache::{ + disk::{Persistence, RevisionDiskCache}, + memory::{RevisionMemoryCache, RevisionMemoryCacheMissing}, + sync::RevisionSyncSeq, + }, RevisionRecord, - RevisionServer, }, - sql_tables::RevTableSql, }; -use bytes::Bytes; -use flowy_collaboration::{entities::doc::Doc, util::md5}; + use flowy_database::ConnectionPool; use flowy_error::{internal_error, FlowyResult}; use lib_infra::future::FutureResult; use lib_ot::{ - core::{Operation, OperationTransformable}, - revision::{RevState, RevType, Revision, RevisionRange}, + core::Operation, + revision::{RevState, Revision, RevisionRange}, rich_text::RichTextDelta, }; -use std::{sync::Arc, time::Duration}; +use std::sync::Arc; use tokio::{ - sync::{mpsc, RwLock}, + sync::RwLock, task::{spawn_blocking, JoinHandle}, }; -type DocRevisionDeskCache = dyn RevisionDiskCache; +type DocRevisionDiskCache = dyn RevisionDiskCache; pub struct RevisionCache { - user_id: String, doc_id: String, - dish_cache: Arc, + pub disk_cache: Arc, memory_cache: Arc, + sync_seq: Arc, defer_save: RwLock>>, - server: Arc, } impl RevisionCache { - pub fn new( - user_id: &str, - doc_id: &str, - pool: Arc, - server: Arc, - ) -> RevisionCache { + pub fn new(user_id: &str, doc_id: &str, pool: Arc) -> RevisionCache { + let disk_cache = Arc::new(Persistence::new(user_id, pool)); + let memory_cache = Arc::new(RevisionMemoryCache::new(doc_id, Arc::new(disk_cache.clone()))); + let sync_seq = Arc::new(RevisionSyncSeq::new()); let doc_id = doc_id.to_owned(); - let dish_cache = Arc::new(Persistence::new(user_id, pool)); - let memory_cache = Arc::new(RevisionMemoryCache::new()); Self { - user_id: user_id.to_owned(), doc_id, - dish_cache, + disk_cache, memory_cache, + sync_seq, defer_save: RwLock::new(None), - server, } } @@ -63,7 +58,8 @@ impl RevisionCache { revision, state: RevState::StateLocal, }; - self.memory_cache.add_revision(record).await?; + let _ = self.memory_cache.add_revision(&record).await; + self.sync_seq.add_revision(record).await?; self.save_revisions().await; Ok(()) } @@ -77,104 +73,60 @@ impl RevisionCache { revision, state: RevState::StateLocal, }; - self.memory_cache.add_revision(record).await?; + self.memory_cache.add_revision(&record).await; self.save_revisions().await; Ok(()) } #[tracing::instrument(level = "debug", skip(self, rev_id), fields(rev_id = %rev_id))] pub async fn ack_revision(&self, rev_id: i64) { - self.memory_cache.ack_revision(&rev_id).await; + self.sync_seq.ack_revision(&rev_id).await; self.save_revisions().await; } - pub async fn query_revision(&self, doc_id: &str, rev_id: i64) -> Option { - match self.memory_cache.query_revision(&rev_id).await { - None => match self.dish_cache.read_revision(doc_id, rev_id) { - Ok(revision) => revision, - Err(e) => { - log::error!("query_revision error: {:?}", e); - None - }, - }, - Some(record) => Some(record), - } + pub async fn get_revision(&self, _doc_id: &str, rev_id: i64) -> Option { + self.memory_cache.get_revision(&rev_id).await } async fn save_revisions(&self) { + // https://github.com/async-graphql/async-graphql/blob/ed8449beec3d9c54b94da39bab33cec809903953/src/dataloader/mod.rs#L362 if let Some(handler) = self.defer_save.write().await.take() { handler.abort(); } - if self.memory_cache.is_empty() { - return; - } + // if self.sync_seq.is_empty() { + // return; + // } - let memory_cache = self.memory_cache.clone(); - let disk_cache = self.dish_cache.clone(); - *self.defer_save.write().await = Some(tokio::spawn(async move { - tokio::time::sleep(Duration::from_millis(300)).await; - let (ids, records) = memory_cache.revisions(); - match disk_cache.create_revisions(records) { - Ok(_) => { - memory_cache.remove_revisions(ids); - }, - Err(e) => log::error!("Save revision failed: {:?}", e), - } - })); + // let memory_cache = self.sync_seq.clone(); + // let disk_cache = self.disk_cache.clone(); + // *self.defer_save.write().await = Some(tokio::spawn(async move { + // tokio::time::sleep(Duration::from_millis(300)).await; + // let (ids, records) = memory_cache.revisions(); + // match disk_cache.create_revisions(records) { + // Ok(_) => { + // memory_cache.remove_revisions(ids); + // }, + // Err(e) => log::error!("Save revision failed: {:?}", e), + // } + // })); } pub async fn revisions_in_range(&self, range: RevisionRange) -> FlowyResult> { - let revs = self.memory_cache.revisions_in_range(&range).await?; - if revs.len() == range.len() as usize { - Ok(revs) - } else { - let doc_id = self.doc_id.clone(); - let disk_cache = self.dish_cache.clone(); - let records = spawn_blocking(move || disk_cache.revisions_in_range(&doc_id, &range)) - .await - .map_err(internal_error)??; - - let revisions = records - .into_iter() - .map(|record| record.revision) - .collect::>(); - Ok(revisions) - } - } - - pub async fn load_document(&self) -> FlowyResult { - // 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() { - return result; - } - - // The document doesn't exist in local. Try load from server - let doc = self.server.fetch_document(&self.doc_id).await?; - let delta_data = Bytes::from(doc.data.clone()); - let doc_md5 = md5(&delta_data); - let revision = Revision::new( - &doc.id, - doc.base_rev_id, - doc.rev_id, - delta_data, - RevType::Remote, - &self.user_id, - doc_md5, - ); - - self.add_remote_revision(revision).await?; - Ok(doc) + let records = self.memory_cache.get_revisions_in_range(&range).await?; + Ok(records + .into_iter() + .map(|record| record.revision) + .collect::>()) } pub(crate) fn next_revision(&self) -> FutureResult, FlowyError> { - let memory_cache = self.memory_cache.clone(); - let disk_cache = self.dish_cache.clone(); + let sync_seq = self.sync_seq.clone(); + let disk_cache = self.disk_cache.clone(); let doc_id = self.doc_id.clone(); FutureResult::new(async move { - match memory_cache.front_local_revision().await { - None => match memory_cache.front_local_rev_id().await { + match sync_seq.next_sync_revision().await { + None => match sync_seq.next_sync_rev_id().await { None => Ok(None), Some(rev_id) => match disk_cache.read_revision(&doc_id, rev_id)? { None => Ok(None), @@ -187,116 +139,37 @@ impl RevisionCache { } } -async fn load_from_disk( - doc_id: &str, - memory_cache: Arc, - disk_cache: Arc, -) -> FlowyResult { - 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(FlowyError::record_not_found().context("Local doesn't have this document")); +impl RevisionMemoryCacheMissing for Arc { + fn get_revision_record(&self, doc_id: &str, rev_id: i64) -> Result, FlowyError> { + match self.read_revision(&doc_id, rev_id)? { + None => { + tracing::warn!("Can't find revision in {} with rev_id: {}", doc_id, rev_id); + Ok(None) + }, + Some(record) => Ok(Some(record)), } + } - let (base_rev_id, rev_id) = records.last().unwrap().revision.pair_rev_id(); - let mut delta = RichTextDelta::new(); - for (_, record) in records.into_iter().enumerate() { - // Opti: revision's clone may cause memory issues - match RichTextDelta::from_bytes(record.revision.clone().delta_data) { - Ok(local_delta) => { - delta = delta.compose(&local_delta)?; - match tx.blocking_send(record) { - Ok(_) => {}, - Err(e) => tracing::error!("❌Load document from disk error: {}", e), - } - }, - Err(e) => { - tracing::error!("Deserialize delta from revision failed: {}", e); - }, - } - } + fn get_revision_records_with_range( + &self, + doc_id: &str, + range: RevisionRange, + ) -> FutureResult, FlowyError> { + let disk_cache = self.clone(); + let doc_id = doc_id.to_owned(); + FutureResult::new(async move { + let records = spawn_blocking(move || disk_cache.revisions_in_range(&doc_id, &range)) + .await + .map_err(internal_error)??; - correct_delta_if_need(&mut delta); - Result::::Ok(Doc { - id: doc_id, - data: delta.to_json(), - rev_id, - base_rev_id, + Ok::, FlowyError>(records) }) - }) - .await - .map_err(internal_error)?; - - while let Some(record) = rx.recv().await { - match memory_cache.add_revision(record).await { - Ok(_) => {}, - Err(e) => log::error!("{:?}", e), - } - } - doc -} - -fn correct_delta_if_need(delta: &mut RichTextDelta) { - if delta.ops.last().is_none() { - return; - } - - let data = delta.ops.last().as_ref().unwrap().get_data(); - if !data.ends_with('\n') { - log::error!("❌The op must end with newline. Correcting it by inserting newline op"); - delta.ops.push(Operation::Insert("\n".into())); - } -} - -pub(crate) struct Persistence { - user_id: String, - pub(crate) pool: Arc, -} - -impl RevisionDiskCache for Persistence { - type Error = FlowyError; - - fn create_revisions(&self, revisions: Vec) -> Result<(), Self::Error> { - let conn = &*self.pool.get().map_err(internal_error)?; - conn.immediate_transaction::<_, FlowyError, _>(|| { - let _ = RevTableSql::create_rev_table(revisions, conn)?; - Ok(()) - }) - } - - fn revisions_in_range(&self, doc_id: &str, range: &RevisionRange) -> Result, Self::Error> { - let conn = &*self.pool.get().map_err(internal_error).unwrap(); - let revisions = RevTableSql::read_rev_tables_with_range(&self.user_id, doc_id, range.clone(), conn)?; - Ok(revisions) - } - - fn read_revision(&self, doc_id: &str, rev_id: i64) -> Result, Self::Error> { - let conn = self.pool.get().map_err(internal_error)?; - let some = RevTableSql::read_rev_table(&self.user_id, doc_id, &rev_id, &*conn)?; - Ok(some) - } - - fn read_revisions(&self, doc_id: &str) -> Result, Self::Error> { - let conn = self.pool.get().map_err(internal_error)?; - let some = RevTableSql::read_rev_tables(&self.user_id, doc_id, &*conn)?; - Ok(some) - } -} - -impl Persistence { - pub(crate) fn new(user_id: &str, pool: Arc) -> Self { - Self { - user_id: user_id.to_owned(), - pool, - } } } #[cfg(feature = "flowy_unit_test")] impl RevisionCache { - pub fn dish_cache(&self) -> Arc { self.dish_cache.clone() } + pub fn disk_cache(&self) -> Arc { self.disk_cache.clone() } - pub fn memory_cache(&self) -> Arc { self.memory_cache.clone() } + pub fn memory_cache(&self) -> Arc { self.sync_seq.clone() } } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/disk.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/disk.rs index a72a6ede8b..1cbde7dd91 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/disk.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/disk.rs @@ -1,7 +1,10 @@ use crate::services::doc::revision::RevisionRecord; +use crate::sql_tables::RevTableSql; +use flowy_database::ConnectionPool; +use flowy_error::{internal_error, FlowyError}; use lib_ot::revision::RevisionRange; -use std::fmt::Debug; +use std::{fmt::Debug, sync::Arc}; pub trait RevisionDiskCache: Sync + Send { type Error: Debug; @@ -10,3 +13,47 @@ pub trait RevisionDiskCache: Sync + Send { fn read_revision(&self, doc_id: &str, rev_id: i64) -> Result, Self::Error>; fn read_revisions(&self, doc_id: &str) -> Result, Self::Error>; } + +pub(crate) struct Persistence { + user_id: String, + pub(crate) pool: Arc, +} + +impl RevisionDiskCache for Persistence { + type Error = FlowyError; + + fn create_revisions(&self, revisions: Vec) -> Result<(), Self::Error> { + let conn = &*self.pool.get().map_err(internal_error)?; + conn.immediate_transaction::<_, FlowyError, _>(|| { + let _ = RevTableSql::create_rev_table(revisions, conn)?; + Ok(()) + }) + } + + fn revisions_in_range(&self, doc_id: &str, range: &RevisionRange) -> Result, Self::Error> { + let conn = &*self.pool.get().map_err(internal_error).unwrap(); + let revisions = RevTableSql::read_rev_tables_with_range(&self.user_id, doc_id, range.clone(), conn)?; + Ok(revisions) + } + + fn read_revision(&self, doc_id: &str, rev_id: i64) -> Result, Self::Error> { + let conn = self.pool.get().map_err(internal_error)?; + let some = RevTableSql::read_rev_table(&self.user_id, doc_id, &rev_id, &*conn)?; + Ok(some) + } + + fn read_revisions(&self, doc_id: &str) -> Result, Self::Error> { + let conn = self.pool.get().map_err(internal_error)?; + let some = RevTableSql::read_rev_tables(&self.user_id, doc_id, &*conn)?; + Ok(some) + } +} + +impl Persistence { + pub(crate) fn new(user_id: &str, pool: Arc) -> Self { + Self { + user_id: user_id.to_owned(), + pool, + } + } +} diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/memory.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/memory.rs index 618a20db90..a468dffc9e 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/memory.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/memory.rs @@ -1,126 +1,87 @@ -use crate::services::doc::revision::RevisionRecord; +use crate::services::doc::RevisionRecord; use dashmap::DashMap; -use lib_ot::{ - errors::OTError, - revision::{RevState, Revision, RevisionRange}, -}; -use std::{collections::VecDeque, sync::Arc}; +use flowy_error::FlowyError; +use lib_infra::future::FutureResult; +use lib_ot::revision::RevisionRange; +use std::sync::Arc; use tokio::sync::RwLock; -pub struct RevisionMemoryCache { +pub(crate) trait RevisionMemoryCacheMissing: Send + Sync { + fn get_revision_record(&self, doc_id: &str, rev_id: i64) -> Result, FlowyError>; + fn get_revision_records_with_range( + &self, + doc_id: &str, + range: RevisionRange, + ) -> FutureResult, FlowyError>; +} + +pub(crate) struct RevisionMemoryCache { + doc_id: String, revs_map: Arc>, - local_revs: Arc>>, -} - -impl std::default::Default for RevisionMemoryCache { - fn default() -> Self { - let local_revs = Arc::new(RwLock::new(VecDeque::new())); - RevisionMemoryCache { - revs_map: Arc::new(DashMap::new()), - local_revs, - } - } + rev_loader: Arc, + revs_order: Arc>>, } +// TODO: remove outdated revisions to reduce memory usage impl RevisionMemoryCache { - pub fn new() -> Self { RevisionMemoryCache::default() } - - pub async fn add_revision(&self, record: RevisionRecord) -> Result<(), OTError> { - // The last revision's rev_id must be greater than the new one. - if let Some(rev_id) = self.local_revs.read().await.back() { - if *rev_id >= record.revision.rev_id { - return Err(OTError::revision_id_conflict() - .context(format!("The new revision's id must be greater than {}", rev_id))); - } + pub(crate) fn new(doc_id: &str, rev_loader: Arc) -> Self { + RevisionMemoryCache { + doc_id: doc_id.to_owned(), + revs_map: Arc::new(DashMap::new()), + rev_loader, + revs_order: Arc::new(RwLock::new(vec![])), } - - match record.state { - RevState::StateLocal => { - tracing::debug!("{}:add revision {}", record.revision.doc_id, record.revision.rev_id); - self.local_revs.write().await.push_back(record.revision.rev_id); - }, - RevState::Acked => {}, - } - - self.revs_map.insert(record.revision.rev_id, record); - Ok(()) } - pub fn remove_revisions(&self, ids: Vec) { self.revs_map.retain(|k, _| !ids.contains(k)); } + pub(crate) async fn is_empty(&self) -> bool { self.revs_order.read().await.is_empty() } - pub async fn ack_revision(&self, rev_id: &i64) { - if let Some(pop_rev_id) = self.front_local_rev_id().await { - if &pop_rev_id != rev_id { + pub(crate) fn contains(&self, rev_id: &i64) -> bool { self.revs_map.contains_key(rev_id) } + + pub(crate) async fn add_revision(&self, record: &RevisionRecord) { + if let Some(rev_id) = self.revs_order.read().await.last() { + if *rev_id >= record.revision.rev_id { + tracing::error!("Duplicated revision added to memory_cache"); return; } } - - match self.local_revs.write().await.pop_front() { - None => {}, - Some(pop_rev_id) => { - if &pop_rev_id != rev_id { - tracing::error!("The front rev_id:{} not equal to ack rev_id: {}", pop_rev_id, rev_id); - assert_eq!(&pop_rev_id, rev_id); - } else { - tracing::debug!("pop revision {}", pop_rev_id); - } - }, - } + self.revs_map.insert(record.revision.rev_id, record.clone()); + self.revs_order.write().await.push(record.revision.rev_id); } - pub async fn revisions_in_range(&self, range: &RevisionRange) -> Result, OTError> { - let revs = range - .iter() - .flat_map(|rev_id| match self.revs_map.get(&rev_id) { - None => None, - Some(record) => Some(record.revision.clone()), - }) - .collect::>(); - - if revs.len() == range.len() as usize { - Ok(revs) - } else { - Ok(vec![]) - } - } - - pub fn contains(&self, rev_id: &i64) -> bool { self.revs_map.contains_key(rev_id) } - - pub fn is_empty(&self) -> bool { self.revs_map.is_empty() } - - pub fn revisions(&self) -> (Vec, Vec) { - let mut records: Vec = vec![]; - let mut ids: Vec = vec![]; - - self.revs_map.iter().for_each(|kv| { - records.push(kv.value().clone()); - ids.push(*kv.key()); - }); - (ids, records) - } - - pub async fn query_revision(&self, rev_id: &i64) -> Option { - self.revs_map.get(&rev_id).map(|r| r.value().clone()) - } - - pub async fn front_local_revision(&self) -> Option<(i64, RevisionRecord)> { - match self.local_revs.read().await.front() { - None => None, - Some(rev_id) => match self.revs_map.get(rev_id).map(|r| (*r.key(), r.value().clone())) { - None => None, - Some(val) => { - tracing::debug!("{}:try send revision {}", val.1.revision.doc_id, val.1.revision.rev_id); - Some(val) + pub(crate) async fn get_revision(&self, rev_id: &i64) -> Option { + match self.revs_map.get(&rev_id).map(|r| r.value().clone()) { + None => match self.rev_loader.get_revision_record(&self.doc_id, *rev_id) { + Ok(revision) => revision, + Err(e) => { + tracing::error!("{}", e); + None }, }, + Some(revision) => Some(revision), } } - pub async fn front_local_rev_id(&self) -> Option { self.local_revs.read().await.front().copied() } -} + pub(crate) async fn get_revisions_in_range( + &self, + range: &RevisionRange, + ) -> Result, FlowyError> { + let range_len = range.len() as usize; + let revs = range + .iter() + .flat_map(|rev_id| self.revs_map.get(&rev_id).map(|record| record.clone())) + .collect::>(); -#[cfg(feature = "flowy_unit_test")] -impl RevisionMemoryCache { - pub fn revs_map(&self) -> Arc> { self.revs_map.clone() } - pub fn pending_revs(&self) -> Arc>> { self.local_revs.clone() } + if revs.len() == range_len { + Ok(revs) + } else { + let revs = self + .rev_loader + .get_revision_records_with_range(&self.doc_id, range.clone()) + .await?; + if revs.len() != range_len { + log::error!("Revisions len is not equal to range required"); + } + Ok(revs) + } + } } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/mod.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/mod.rs index 2886d90fe0..916b334e4c 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/mod.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/mod.rs @@ -3,6 +3,7 @@ mod cache; mod disk; mod memory; mod model; +mod sync; pub use cache::*; pub use model::*; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/sync.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/sync.rs new file mode 100644 index 0000000000..449d3101e0 --- /dev/null +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/sync.rs @@ -0,0 +1,71 @@ +use crate::services::doc::revision::RevisionRecord; +use dashmap::DashMap; +use lib_ot::errors::OTError; +use std::{collections::VecDeque, sync::Arc}; +use tokio::sync::RwLock; + +pub struct RevisionSyncSeq { + revs_map: Arc>, + local_revs: Arc>>, +} + +impl std::default::Default for RevisionSyncSeq { + fn default() -> Self { + let local_revs = Arc::new(RwLock::new(VecDeque::new())); + RevisionSyncSeq { + revs_map: Arc::new(DashMap::new()), + local_revs, + } + } +} + +impl RevisionSyncSeq { + pub fn new() -> Self { RevisionSyncSeq::default() } + + pub async fn add_revision(&self, record: RevisionRecord) -> Result<(), OTError> { + // The last revision's rev_id must be greater than the new one. + if let Some(rev_id) = self.local_revs.read().await.back() { + if *rev_id >= record.revision.rev_id { + return Err(OTError::revision_id_conflict() + .context(format!("The new revision's id must be greater than {}", rev_id))); + } + } + self.revs_map.insert(record.revision.rev_id, record); + Ok(()) + } + + pub async fn ack_revision(&self, rev_id: &i64) { + if let Some(pop_rev_id) = self.next_sync_rev_id().await { + if &pop_rev_id != rev_id { + tracing::error!("The next ack rev_id must be equal to the next rev_id"); + assert_eq!(&pop_rev_id, rev_id); + return; + } + + tracing::debug!("pop revision {}", pop_rev_id); + self.revs_map.remove(&pop_rev_id); + let _ = self.local_revs.write().await.pop_front(); + } + } + + pub async fn next_sync_revision(&self) -> Option<(i64, RevisionRecord)> { + match self.local_revs.read().await.front() { + None => None, + Some(rev_id) => match self.revs_map.get(rev_id).map(|r| (*r.key(), r.value().clone())) { + None => None, + Some(val) => { + tracing::debug!("{}:try send revision {}", val.1.revision.doc_id, val.1.revision.rev_id); + Some(val) + }, + }, + } + } + + pub async fn next_sync_rev_id(&self) -> Option { self.local_revs.read().await.front().copied() } +} + +#[cfg(feature = "flowy_unit_test")] +impl RevisionSyncSeq { + pub fn revs_map(&self) -> Arc> { self.revs_map.clone() } + pub fn pending_revs(&self) -> Arc>> { self.local_revs.clone() } +} diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs index 9cc4c6d4ed..a1c5f99cdb 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs @@ -1,4 +1,5 @@ use crate::{errors::FlowyError, services::doc::revision::RevisionCache}; +use bytes::Bytes; use flowy_collaboration::{ entities::doc::Doc, util::{md5, RevIdCounter}, @@ -6,8 +7,8 @@ use flowy_collaboration::{ use flowy_error::FlowyResult; use lib_infra::future::FutureResult; use lib_ot::{ - core::OperationTransformable, - revision::{RevType, Revision, RevisionRange}, + core::{Operation, OperationTransformable}, + revision::{RevState, RevType, Revision, RevisionRange}, rich_text::RichTextDelta, }; use std::sync::Arc; @@ -34,8 +35,16 @@ impl RevisionManager { } } - pub async fn load_document(&mut self) -> FlowyResult { - let doc = self.cache.load_document().await?; + pub async fn load_document(&mut self, server: Arc) -> FlowyResult { + let revisions = RevisionLoader { + doc_id: self.doc_id.clone(), + user_id: self.user_id.clone(), + server, + cache: self.cache.clone(), + } + .load() + .await?; + let doc = mk_doc_from_revisions(&self.doc_id, revisions)?; self.update_rev_id_counter_value(doc.rev_id); Ok(doc.delta()?) } @@ -100,3 +109,80 @@ impl RevisionManager { impl RevisionManager { pub fn revision_cache(&self) -> Arc { self.cache.clone() } } + +struct RevisionLoader { + doc_id: String, + user_id: String, + server: Arc, + cache: Arc, +} + +impl RevisionLoader { + async fn load(&self) -> Result, FlowyError> { + let records = self.cache.disk_cache.read_revisions(&self.doc_id)?; + let revisions: Vec; + if records.is_empty() { + let doc = self.server.fetch_document(&self.doc_id).await?; + let delta_data = Bytes::from(doc.data.clone()); + let doc_md5 = md5(&delta_data); + let revision = Revision::new( + &doc.id, + doc.base_rev_id, + doc.rev_id, + delta_data, + RevType::Remote, + &self.user_id, + doc_md5, + ); + let _ = self.cache.add_remote_revision(revision.clone()).await?; + revisions = vec![revision]; + } else { + for record in &records { + match record.state { + RevState::StateLocal => match self.cache.add_local_revision(record.revision.clone()).await { + Ok(_) => {}, + Err(e) => tracing::error!("{}", e), + }, + RevState::Acked => {}, + } + } + revisions = records.into_iter().map(|record| record.revision).collect::<_>(); + } + + Ok(revisions) + } +} + +fn mk_doc_from_revisions(doc_id: &str, revisions: Vec) -> FlowyResult { + let (base_rev_id, rev_id) = revisions.last().unwrap().pair_rev_id(); + let mut delta = RichTextDelta::new(); + for (_, revision) in revisions.into_iter().enumerate() { + match RichTextDelta::from_bytes(revision.delta_data) { + Ok(local_delta) => { + delta = delta.compose(&local_delta)?; + }, + Err(e) => { + tracing::error!("Deserialize delta from revision failed: {}", e); + }, + } + } + correct_delta_if_need(&mut delta); + + Result::::Ok(Doc { + id: doc_id.to_owned(), + data: delta.to_json(), + rev_id, + base_rev_id, + }) +} +fn correct_delta_if_need(delta: &mut RichTextDelta) { + if delta.ops.last().is_none() { + return; + } + + let data = delta.ops.last().as_ref().unwrap().get_data(); + if !data.ends_with('\n') { + log::error!("❌The op must end with newline. Correcting it by inserting newline op"); + delta.ops.push(Operation::Insert("\n".into())); + } +} diff --git a/frontend/rust-lib/flowy-document/src/services/doc/ws/mod.rs b/frontend/rust-lib/flowy-document/src/services/doc/ws/mod.rs deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frontend/rust-lib/flowy-test/src/doc_script.rs b/frontend/rust-lib/flowy-test/src/doc_script.rs index 6c699033e2..d5cb59825a 100644 --- a/frontend/rust-lib/flowy-test/src/doc_script.rs +++ b/frontend/rust-lib/flowy-test/src/doc_script.rs @@ -47,7 +47,7 @@ impl EditorTest { let rev_manager = self.editor.rev_manager(); let cache = rev_manager.revision_cache(); let _memory_cache = cache.memory_cache(); - let _disk_cache = cache.dish_cache(); + let _disk_cache = cache.disk_cache(); let doc_id = self.editor.doc_id.clone(); let _user_id = self.sdk.user_session.user_id().unwrap(); let ws_manager = self.sdk.ws_manager.clone(); @@ -71,7 +71,7 @@ impl EditorTest { self.editor.replace(interval, s).await.unwrap(); }, EditorScript::AssertRevisionState(rev_id, state) => { - let record = cache.query_revision(&doc_id, rev_id).await.unwrap(); + let record = cache.get_revision(&doc_id, rev_id).await.unwrap(); assert_eq!(record.state, state); }, EditorScript::AssertCurrentRevId(rev_id) => { diff --git a/frontend/rust-lib/flowy-user/Flowy.toml b/frontend/rust-lib/flowy-user/Flowy.toml index 6560862303..2056e35fa5 100644 --- a/frontend/rust-lib/flowy-user/Flowy.toml +++ b/frontend/rust-lib/flowy-user/Flowy.toml @@ -1,3 +1,3 @@ -proto_crates = ["src/event.rs", "src/errors.rs", "src/notify"] +proto_crates = ["src/event.rs", "src/notify"] event_files = ["src/event.rs"] \ No newline at end of file diff --git a/shared-lib/flowy-collaboration/src/core/sync/synchronizer.rs b/shared-lib/flowy-collaboration/src/core/sync/synchronizer.rs index ec93db482e..3c01cb3a22 100644 --- a/shared-lib/flowy-collaboration/src/core/sync/synchronizer.rs +++ b/shared-lib/flowy-collaboration/src/core/sync/synchronizer.rs @@ -1,20 +1,16 @@ use crate::{ core::document::Document, - entities::ws::{DocumentWSData, DocumentWSDataType, WsDocumentDataBuilder}, + entities::ws::{DocumentWSData, WsDocumentDataBuilder}, }; -use bytes::Bytes; use lib_ot::{ core::OperationTransformable, errors::OTError, - protobuf::RevId, revision::{RevType, Revision, RevisionRange}, rich_text::RichTextDelta, }; use parking_lot::RwLock; -use protobuf::Message; use std::{ cmp::Ordering, - convert::TryInto, fmt::Debug, sync::{ atomic::{AtomicI64, Ordering::SeqCst}, diff --git a/shared-lib/flowy-collaboration/src/entities/ws/ws.rs b/shared-lib/flowy-collaboration/src/entities/ws/ws.rs index a13ac2fa79..53fb551f16 100644 --- a/shared-lib/flowy-collaboration/src/entities/ws/ws.rs +++ b/shared-lib/flowy-collaboration/src/entities/ws/ws.rs @@ -84,7 +84,7 @@ impl WsDocumentDataBuilder { // DocumentWSDataType::Acked -> RevId pub fn build_acked_message(doc_id: &str, rev_id: i64) -> DocumentWSData { - let cloned_rev_id = rev_id.clone(); + let cloned_rev_id = rev_id; let rev_id: RevId = rev_id.into(); let bytes: Bytes = rev_id.try_into().unwrap(); From 987a246c80aeacd4e296ebbe41873ad4320bd84d Mon Sep 17 00:00:00 2001 From: appflowy Date: Sat, 18 Dec 2021 18:35:45 +0800 Subject: [PATCH 34/39] send user connect message --- .../rust-lib/flowy-document/src/module.rs | 3 +- .../src/services/{doc => }/controller.rs | 0 .../src/services/doc/edit/editor.rs | 153 ++++++++++++------ ...edit_queue.rs => editor_edit_cmd_queue.rs} | 36 ++--- .../{web_socket.rs => editor_web_socket.rs} | 42 ++--- .../src/services/doc/edit/mod.rs | 9 +- .../src/services/doc/edit/model.rs | 48 ------ .../flowy-document/src/services/doc/mod.rs | 7 +- .../src/services/doc/revision/cache/cache.rs | 128 +++++++-------- .../src/services/doc/revision/cache/disk.rs | 16 +- .../src/services/doc/revision/cache/memory.rs | 117 +++++++++----- .../src/services/doc/revision/cache/sync.rs | 22 +-- .../src/services/doc/revision/manager.rs | 6 +- .../flowy-document/src/services/mod.rs | 2 + .../src/services/{doc => }/ws_handlers.rs | 0 .../src/sql_tables/doc/rev_sql.rs | 1 - .../src/sql_tables/doc/rev_table.rs | 3 +- .../src/core/sync/server_editor.rs | 6 - .../flowy-collaboration/src/entities/ws/ws.rs | 12 ++ shared-lib/lib-ot/src/revision/model.rs | 1 + 20 files changed, 325 insertions(+), 287 deletions(-) rename frontend/rust-lib/flowy-document/src/services/{doc => }/controller.rs (100%) rename frontend/rust-lib/flowy-document/src/services/doc/edit/{edit_queue.rs => editor_edit_cmd_queue.rs} (86%) rename frontend/rust-lib/flowy-document/src/services/doc/edit/{web_socket.rs => editor_web_socket.rs} (86%) delete mode 100644 frontend/rust-lib/flowy-document/src/services/doc/edit/model.rs rename frontend/rust-lib/flowy-document/src/services/{doc => }/ws_handlers.rs (100%) diff --git a/frontend/rust-lib/flowy-document/src/module.rs b/frontend/rust-lib/flowy-document/src/module.rs index 865f09111a..c8b8372db7 100644 --- a/frontend/rust-lib/flowy-document/src/module.rs +++ b/frontend/rust-lib/flowy-document/src/module.rs @@ -1,7 +1,8 @@ use crate::{ errors::FlowyError, services::{ - doc::{controller::DocController, edit::ClientDocEditor, DocumentWsHandlers}, + controller::DocController, + doc::{edit::ClientDocEditor, DocumentWsHandlers}, server::construct_doc_server, }, }; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/controller.rs b/frontend/rust-lib/flowy-document/src/services/controller.rs similarity index 100% rename from frontend/rust-lib/flowy-document/src/services/doc/controller.rs rename to frontend/rust-lib/flowy-document/src/services/controller.rs diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs index 8f5a697c93..5aa7698eb9 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs @@ -2,7 +2,10 @@ use crate::{errors::FlowyError, module::DocumentUser, services::doc::*}; use bytes::Bytes; use flowy_collaboration::{ core::document::history::UndoResult, - entities::{doc::DocDelta, ws::DocumentWSData}, + entities::{ + doc::DocDelta, + ws::{DocumentConnected, DocumentWSData, DocumentWSDataType, WsDocumentDataBuilder}, + }, errors::CollaborateResult, }; use flowy_database::ConnectionPool; @@ -13,15 +16,15 @@ use lib_ot::{ revision::{RevId, RevType, Revision, RevisionRange}, rich_text::{RichTextAttribute, RichTextDelta}, }; +use lib_ws::WSConnectState; use std::{collections::VecDeque, sync::Arc}; -use tokio::sync::{mpsc, mpsc::UnboundedSender, oneshot, RwLock}; +use tokio::sync::{broadcast, mpsc, mpsc::UnboundedSender, oneshot, RwLock}; pub struct ClientDocEditor { pub doc_id: String, rev_manager: Arc, - ws_manager: Arc, - edit_cmd_tx: UnboundedSender, - sink_data_provider: SinkDataProvider, + editor_ws: Arc, + editor_cmd_sender: UnboundedSender, user: Arc, } @@ -35,8 +38,9 @@ impl ClientDocEditor { server: Arc, ) -> FlowyResult> { let delta = rev_manager.load_document(server).await?; - let edit_cmd_tx = spawn_edit_queue(doc_id, delta, pool.clone()); + let editor_cmd_sender = spawn_edit_queue(doc_id, delta, pool.clone()); let doc_id = doc_id.to_string(); + let user_id = user.user_id()?; let rev_manager = Arc::new(rev_manager); let sink_data_provider = Arc::new(RwLock::new(VecDeque::new())); let data_provider = Arc::new(DocumentSinkDataProviderAdapter { @@ -45,18 +49,27 @@ impl ClientDocEditor { }); let stream_consumer = Arc::new(DocumentWebSocketSteamConsumerAdapter { doc_id: doc_id.clone(), - edit_cmd_tx: edit_cmd_tx.clone(), + editor_cmd_sender: editor_cmd_sender.clone(), rev_manager: rev_manager.clone(), user: user.clone(), sink_data_provider: sink_data_provider.clone(), }); - let ws_manager = Arc::new(WebSocketManager::new(&doc_id, ws, data_provider, stream_consumer)); + let editor_ws = Arc::new(EditorWebSocket::new(&doc_id, ws, data_provider, stream_consumer)); + notify_user_conn(&user_id, &doc_id, rev_manager.clone(), sink_data_provider.clone()).await; + + listen_document_ws_state( + &user_id, + &doc_id, + editor_ws.scribe_state(), + rev_manager.clone(), + sink_data_provider, + ); + let editor = Arc::new(Self { doc_id, rev_manager, - ws_manager, - edit_cmd_tx, - sink_data_provider, + editor_ws, + editor_cmd_sender, user, }); Ok(editor) @@ -64,12 +77,12 @@ impl ClientDocEditor { pub async fn insert(&self, index: usize, data: T) -> Result<(), FlowyError> { let (ret, rx) = oneshot::channel::>(); - let msg = EditCommand::Insert { + let msg = EditorCommand::Insert { index, data: data.to_string(), ret, }; - let _ = self.edit_cmd_tx.send(msg); + let _ = self.editor_cmd_sender.send(msg); let (delta, md5) = rx.await.map_err(internal_error)??; let _ = self.save_local_delta(delta, md5).await?; Ok(()) @@ -77,8 +90,8 @@ impl ClientDocEditor { pub async fn delete(&self, interval: Interval) -> Result<(), FlowyError> { let (ret, rx) = oneshot::channel::>(); - let msg = EditCommand::Delete { interval, ret }; - let _ = self.edit_cmd_tx.send(msg); + let msg = EditorCommand::Delete { interval, ret }; + let _ = self.editor_cmd_sender.send(msg); let (delta, md5) = rx.await.map_err(internal_error)??; let _ = self.save_local_delta(delta, md5).await?; Ok(()) @@ -86,12 +99,12 @@ impl ClientDocEditor { pub async fn format(&self, interval: Interval, attribute: RichTextAttribute) -> Result<(), FlowyError> { let (ret, rx) = oneshot::channel::>(); - let msg = EditCommand::Format { + let msg = EditorCommand::Format { interval, attribute, ret, }; - let _ = self.edit_cmd_tx.send(msg); + let _ = self.editor_cmd_sender.send(msg); let (delta, md5) = rx.await.map_err(internal_error)??; let _ = self.save_local_delta(delta, md5).await?; Ok(()) @@ -99,12 +112,12 @@ impl ClientDocEditor { pub async fn replace(&self, interval: Interval, data: T) -> Result<(), FlowyError> { let (ret, rx) = oneshot::channel::>(); - let msg = EditCommand::Replace { + let msg = EditorCommand::Replace { interval, data: data.to_string(), ret, }; - let _ = self.edit_cmd_tx.send(msg); + let _ = self.editor_cmd_sender.send(msg); let (delta, md5) = rx.await.map_err(internal_error)??; let _ = self.save_local_delta(delta, md5).await?; Ok(()) @@ -112,38 +125,38 @@ impl ClientDocEditor { pub async fn can_undo(&self) -> bool { let (ret, rx) = oneshot::channel::(); - let msg = EditCommand::CanUndo { ret }; - let _ = self.edit_cmd_tx.send(msg); + let msg = EditorCommand::CanUndo { ret }; + let _ = self.editor_cmd_sender.send(msg); rx.await.unwrap_or(false) } pub async fn can_redo(&self) -> bool { let (ret, rx) = oneshot::channel::(); - let msg = EditCommand::CanRedo { ret }; - let _ = self.edit_cmd_tx.send(msg); + let msg = EditorCommand::CanRedo { ret }; + let _ = self.editor_cmd_sender.send(msg); rx.await.unwrap_or(false) } pub async fn undo(&self) -> Result { let (ret, rx) = oneshot::channel::>(); - let msg = EditCommand::Undo { ret }; - let _ = self.edit_cmd_tx.send(msg); + let msg = EditorCommand::Undo { ret }; + let _ = self.editor_cmd_sender.send(msg); let r = rx.await.map_err(internal_error)??; Ok(r) } pub async fn redo(&self) -> Result { let (ret, rx) = oneshot::channel::>(); - let msg = EditCommand::Redo { ret }; - let _ = self.edit_cmd_tx.send(msg); + let msg = EditorCommand::Redo { ret }; + let _ = self.editor_cmd_sender.send(msg); let r = rx.await.map_err(internal_error)??; Ok(r) } pub async fn delta(&self) -> FlowyResult { let (ret, rx) = oneshot::channel::>(); - let msg = EditCommand::ReadDoc { ret }; - let _ = self.edit_cmd_tx.send(msg); + let msg = EditorCommand::ReadDoc { ret }; + let _ = self.editor_cmd_sender.send(msg); let data = rx.await.map_err(internal_error)??; Ok(DocDelta { @@ -173,11 +186,11 @@ impl ClientDocEditor { pub(crate) async fn composing_local_delta(&self, data: Bytes) -> Result<(), FlowyError> { let delta = RichTextDelta::from_bytes(&data)?; let (ret, rx) = oneshot::channel::>(); - let msg = EditCommand::ComposeDelta { + let msg = EditorCommand::ComposeDelta { delta: delta.clone(), ret, }; - let _ = self.edit_cmd_tx.send(msg); + let _ = self.editor_cmd_sender.send(msg); let md5 = rx.await.map_err(internal_error)??; let _ = self.save_local_delta(delta, md5).await?; @@ -185,21 +198,21 @@ impl ClientDocEditor { } #[tracing::instrument(level = "debug", skip(self))] - pub fn stop_sync(&self) { self.ws_manager.stop(); } + pub fn stop_sync(&self) { self.editor_ws.stop(); } - pub(crate) fn ws_handler(&self) -> Arc { self.ws_manager.clone() } + pub(crate) fn ws_handler(&self) -> Arc { self.editor_ws.clone() } } -fn spawn_edit_queue(doc_id: &str, delta: RichTextDelta, _pool: Arc) -> UnboundedSender { - let (sender, receiver) = mpsc::unbounded_channel::(); - let actor = EditCommandQueue::new(doc_id, delta, receiver); +fn spawn_edit_queue(doc_id: &str, delta: RichTextDelta, _pool: Arc) -> UnboundedSender { + let (sender, receiver) = mpsc::unbounded_channel::(); + let actor = EditorCommandQueue::new(doc_id, delta, receiver); tokio::spawn(actor.run()); sender } struct DocumentWebSocketSteamConsumerAdapter { doc_id: String, - edit_cmd_tx: UnboundedSender, + editor_cmd_sender: UnboundedSender, rev_manager: Arc, user: Arc, sink_data_provider: SinkDataProvider, @@ -209,7 +222,7 @@ impl DocumentWebSocketSteamConsumer for DocumentWebSocketSteamConsumerAdapter { fn receive_push_revision(&self, bytes: Bytes) -> FutureResult<(), FlowyError> { let user = self.user.clone(); let rev_manager = self.rev_manager.clone(); - let edit_cmd_tx = self.edit_cmd_tx.clone(); + let edit_cmd_tx = self.editor_cmd_sender.clone(); let sink_data_provider = self.sink_data_provider.clone(); let doc_id = self.doc_id.clone(); FutureResult::new(async move { @@ -240,6 +253,54 @@ impl DocumentWebSocketSteamConsumer for DocumentWebSocketSteamConsumerAdapter { } } +async fn notify_user_conn( + user_id: &str, + doc_id: &str, + rev_manager: Arc, + sink_data_provider: SinkDataProvider, +) { + let need_notify = match sink_data_provider.read().await.front() { + None => true, + Some(data) => data.ty != DocumentWSDataType::UserConnect, + }; + + if need_notify { + let document_conn = DocumentConnected { + user_id: user_id.to_owned(), + doc_id: doc_id.to_owned(), + rev_id: rev_manager.latest_rev_id(), + }; + + let data = WsDocumentDataBuilder::build_document_conn_message(doc_id, document_conn); + sink_data_provider.write().await.push_front(data); + } +} + +fn listen_document_ws_state( + user_id: &str, + doc_id: &str, + mut subscriber: broadcast::Receiver, + rev_manager: Arc, + sink_data_provider: SinkDataProvider, +) { + let user_id = user_id.to_owned(); + let doc_id = doc_id.to_owned(); + + tokio::spawn(async move { + while let Ok(state) = subscriber.recv().await { + match state { + WSConnectState::Init => {}, + WSConnectState::Connecting => {}, + WSConnectState::Connected => { + // self.notify_user_conn() + notify_user_conn(&user_id, &doc_id, rev_manager.clone(), sink_data_provider.clone()).await; + }, + WSConnectState::Disconnected => {}, + } + } + }); +} + type SinkDataProvider = Arc>>; struct DocumentSinkDataProviderAdapter { @@ -256,7 +317,7 @@ impl DocumentSinkDataProvider for DocumentSinkDataProviderAdapter { if data_provider.read().await.is_empty() { match rev_manager.next_sync_revision().await? { Some(rev) => { - tracing::debug!("[DocumentSinkDataProvider]: revision: {}:{:?}", rev.doc_id, rev.rev_id); + tracing::debug!("[DocumentSinkDataProvider]: {}:{:?}", rev.doc_id, rev.rev_id); Ok(Some(rev.into())) }, None => Ok(None), @@ -278,13 +339,13 @@ impl DocumentSinkDataProvider for DocumentSinkDataProviderAdapter { pub(crate) async fn handle_push_rev( doc_id: &str, user_id: &str, - edit_cmd_tx: UnboundedSender, + edit_cmd_tx: UnboundedSender, rev_manager: Arc, bytes: Bytes, ) -> FlowyResult> { // Transform the revision let (ret, rx) = oneshot::channel::>(); - let _ = edit_cmd_tx.send(EditCommand::ProcessRemoteRevision { bytes, ret }); + let _ = edit_cmd_tx.send(EditorCommand::ProcessRemoteRevision { bytes, ret }); let TransformDeltas { client_prime, server_prime, @@ -298,7 +359,7 @@ pub(crate) async fn handle_push_rev( // compose delta let (ret, rx) = oneshot::channel::>(); - let msg = EditCommand::ComposeDelta { + let msg = EditorCommand::ComposeDelta { delta: client_prime.clone(), ret, }; @@ -339,16 +400,16 @@ pub(crate) async fn handle_push_rev( impl ClientDocEditor { pub async fn doc_json(&self) -> FlowyResult { let (ret, rx) = oneshot::channel::>(); - let msg = EditCommand::ReadDoc { ret }; - let _ = self.edit_cmd_tx.send(msg); + let msg = EditorCommand::ReadDoc { ret }; + let _ = self.editor_cmd_sender.send(msg); let s = rx.await.map_err(internal_error)??; Ok(s) } pub async fn doc_delta(&self) -> FlowyResult { let (ret, rx) = oneshot::channel::>(); - let msg = EditCommand::ReadDocDelta { ret }; - let _ = self.edit_cmd_tx.send(msg); + let msg = EditorCommand::ReadDocDelta { ret }; + let _ = self.editor_cmd_sender.send(msg); let delta = rx.await.map_err(internal_error)??; Ok(delta) } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/edit_queue.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor_edit_cmd_queue.rs similarity index 86% rename from frontend/rust-lib/flowy-document/src/services/doc/edit/edit_queue.rs rename to frontend/rust-lib/flowy-document/src/services/doc/edit/editor_edit_cmd_queue.rs index faa239dd3f..3cf6d25034 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/edit_queue.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor_edit_cmd_queue.rs @@ -14,14 +14,14 @@ use lib_ot::{ use std::{convert::TryFrom, sync::Arc}; use tokio::sync::{mpsc, oneshot, RwLock}; -pub(crate) struct EditCommandQueue { +pub(crate) struct EditorCommandQueue { doc_id: String, document: Arc>, - receiver: Option>, + receiver: Option>, } -impl EditCommandQueue { - pub(crate) fn new(doc_id: &str, delta: RichTextDelta, receiver: mpsc::UnboundedReceiver) -> Self { +impl EditorCommandQueue { + pub(crate) fn new(doc_id: &str, delta: RichTextDelta, receiver: mpsc::UnboundedReceiver) -> Self { let document = Arc::new(RwLock::new(Document::from_delta(delta))); Self { doc_id: doc_id.to_owned(), @@ -50,13 +50,13 @@ impl EditCommandQueue { .await; } - async fn handle_message(&self, msg: EditCommand) -> Result<(), FlowyError> { + async fn handle_message(&self, msg: EditorCommand) -> Result<(), FlowyError> { match msg { - EditCommand::ComposeDelta { delta, ret } => { + EditorCommand::ComposeDelta { delta, ret } => { let result = self.composed_delta(delta).await; let _ = ret.send(result); }, - EditCommand::ProcessRemoteRevision { bytes, ret } => { + EditorCommand::ProcessRemoteRevision { bytes, ret } => { let f = || async { let revision = Revision::try_from(bytes)?; let delta = RichTextDelta::from_bytes(&revision.delta_data)?; @@ -75,19 +75,19 @@ impl EditCommandQueue { }; let _ = ret.send(f().await); }, - EditCommand::Insert { index, data, ret } => { + EditorCommand::Insert { index, data, ret } => { let mut write_guard = self.document.write().await; let delta = write_guard.insert(index, data)?; let md5 = write_guard.md5(); let _ = ret.send(Ok((delta, md5))); }, - EditCommand::Delete { interval, ret } => { + EditorCommand::Delete { interval, ret } => { let mut write_guard = self.document.write().await; let delta = write_guard.delete(interval)?; let md5 = write_guard.md5(); let _ = ret.send(Ok((delta, md5))); }, - EditCommand::Format { + EditorCommand::Format { interval, attribute, ret, @@ -97,31 +97,31 @@ impl EditCommandQueue { let md5 = write_guard.md5(); let _ = ret.send(Ok((delta, md5))); }, - EditCommand::Replace { interval, data, ret } => { + EditorCommand::Replace { interval, data, ret } => { let mut write_guard = self.document.write().await; let delta = write_guard.replace(interval, data)?; let md5 = write_guard.md5(); let _ = ret.send(Ok((delta, md5))); }, - EditCommand::CanUndo { ret } => { + EditorCommand::CanUndo { ret } => { let _ = ret.send(self.document.read().await.can_undo()); }, - EditCommand::CanRedo { ret } => { + EditorCommand::CanRedo { ret } => { let _ = ret.send(self.document.read().await.can_redo()); }, - EditCommand::Undo { ret } => { + EditorCommand::Undo { ret } => { let result = self.document.write().await.undo(); let _ = ret.send(result); }, - EditCommand::Redo { ret } => { + EditorCommand::Redo { ret } => { let result = self.document.write().await.redo(); let _ = ret.send(result); }, - EditCommand::ReadDoc { ret } => { + EditorCommand::ReadDoc { ret } => { let data = self.document.read().await.to_json(); let _ = ret.send(Ok(data)); }, - EditCommand::ReadDocDelta { ret } => { + EditorCommand::ReadDocDelta { ret } => { let delta = self.document.read().await.delta().clone(); let _ = ret.send(Ok(delta)); }, @@ -151,7 +151,7 @@ pub(crate) type NewDelta = (RichTextDelta, String); pub(crate) type DocumentMD5 = String; #[allow(dead_code)] -pub(crate) enum EditCommand { +pub(crate) enum EditorCommand { ComposeDelta { delta: RichTextDelta, ret: Ret, diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/web_socket.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor_web_socket.rs similarity index 86% rename from frontend/rust-lib/flowy-document/src/services/doc/edit/web_socket.rs rename to frontend/rust-lib/flowy-document/src/services/doc/edit/editor_web_socket.rs index adcdf39a42..1f8ba327f1 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/web_socket.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor_web_socket.rs @@ -18,7 +18,7 @@ use tokio::{ time::{interval, Duration}, }; -pub(crate) struct WebSocketManager { +pub(crate) struct EditorWebSocket { doc_id: String, data_provider: Arc, stream_consumer: Arc, @@ -26,9 +26,10 @@ pub(crate) struct WebSocketManager { ws_msg_tx: UnboundedSender, ws_msg_rx: Option>, stop_sync_tx: SinkStopTx, + state: broadcast::Sender, } -impl WebSocketManager { +impl EditorWebSocket { pub(crate) fn new( doc_id: &str, ws: Arc, @@ -38,7 +39,8 @@ impl WebSocketManager { let (ws_msg_tx, ws_msg_rx) = mpsc::unbounded_channel(); let (stop_sync_tx, _) = tokio::sync::broadcast::channel(2); let doc_id = doc_id.to_string(); - let mut manager = WebSocketManager { + let (state, _) = broadcast::channel(2); + let mut manager = EditorWebSocket { doc_id, data_provider, stream_consumer, @@ -46,6 +48,7 @@ impl WebSocketManager { ws_msg_tx, ws_msg_rx: Some(ws_msg_rx), stop_sync_tx, + state, }; manager.start_sync(); manager @@ -67,7 +70,6 @@ impl WebSocketManager { ); tokio::spawn(sink.run()); tokio::spawn(stream.run()); - self.notify_user_conn(); } pub(crate) fn stop(&self) { @@ -76,24 +78,10 @@ impl WebSocketManager { } } - #[tracing::instrument(level = "debug", skip(self))] - fn notify_user_conn(&self) { - // let rev_id: RevId = self.rev_manager.rev_id().into(); - // if let Ok(user_id) = self.user.user_id() { - // let action = OpenDocAction::new(&user_id, &self.doc_id, &rev_id, - // &self.ws_sender); let strategy = - // ExponentialBackoff::from_millis(50).take(3); let retry = - // Retry::spawn(strategy, action); tokio::spawn(async move { - // match retry.await { - // Ok(_) => log::debug!("Notify open doc success"), - // Err(e) => log::error!("Notify open doc failed: {}", e), - // } - // }); - // } - } + pub(crate) fn scribe_state(&self) -> broadcast::Receiver { self.state.subscribe() } } -impl DocumentWsHandler for WebSocketManager { +impl DocumentWsHandler for EditorWebSocket { fn receive(&self, doc_data: DocumentWSData) { match self.ws_msg_tx.send(doc_data) { Ok(_) => {}, @@ -102,11 +90,9 @@ impl DocumentWsHandler for WebSocketManager { } fn connect_state_changed(&self, state: &WSConnectState) { - match state { - WSConnectState::Init => {}, - WSConnectState::Connecting => {}, - WSConnectState::Connected => self.notify_user_conn(), - WSConnectState::Disconnected => {}, + match self.state.send(state.clone()) { + Ok(_) => {}, + Err(e) => tracing::error!("{}", e), } } } @@ -199,7 +185,9 @@ impl DocumentWebSocketStream { let rev_id = RevId::try_from(bytes)?; let _ = self.consumer.receive_ack_revision(rev_id.into()).await; }, - DocumentWSDataType::UserConnect => {}, + DocumentWSDataType::UserConnect => { + // Notify the user that someone has connected to this document + }, } Ok(()) @@ -270,7 +258,7 @@ impl DocumentWebSocketSink { async fn send_next_revision(&self) -> FlowyResult<()> { match self.provider.next().await? { None => { - tracing::debug!("Finish synchronizing revisions"); + tracing::trace!("Finish synchronizing revisions"); Ok(()) }, Some(data) => { diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/mod.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/mod.rs index de21adfac6..cfbe4f27f1 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/mod.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/mod.rs @@ -1,8 +1,7 @@ -mod edit_queue; mod editor; -mod model; -mod web_socket; +mod editor_edit_cmd_queue; +mod editor_web_socket; -pub(crate) use edit_queue::*; pub use editor::*; -pub use web_socket::*; +pub(crate) use editor_edit_cmd_queue::*; +pub use editor_web_socket::*; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/model.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/model.rs deleted file mode 100644 index bd78e32c15..0000000000 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/model.rs +++ /dev/null @@ -1,48 +0,0 @@ -#![allow(clippy::all)] -#![cfg_attr(rustfmt, rustfmt::skip)] -use crate::{errors::FlowyError}; -use futures::future::BoxFuture; -use lib_infra::retry::Action; -use lib_ot::revision::RevId; -use std::{future, sync::Arc}; -use crate::services::doc::DocumentWebSocket; - -#[allow(dead_code)] -pub(crate) struct OpenDocAction { - user_id: String, - rev_id: RevId, - doc_id: String, - ws: Arc, -} - -#[allow(dead_code)] -impl OpenDocAction { - pub(crate) fn new(user_id: &str, doc_id: &str, rev_id: &RevId, ws: &Arc) -> Self { - Self { - user_id: user_id.to_owned(), - rev_id: rev_id.clone(), - doc_id: doc_id.to_owned(), - ws: ws.clone(), - } - } -} - -impl Action for OpenDocAction { - type Future = BoxFuture<'static, Result>; - type Item = (); - type Error = FlowyError; - - fn run(&mut self) -> Self::Future { - // let new_doc_user = NewDocUser { - // user_id: self.user_id.clone(), - // rev_id: self.rev_id.clone().into(), - // doc_id: self.doc_id.clone(), - // }; - // - // match self.ws.send(new_doc_user.into()) { - // Ok(_) => Box::pin(future::ready(Ok::<(), DocError>(()))), - // Err(e) => Box::pin(future::ready(Err::<(), DocError>(e))), - // } - Box::pin(future::ready(Ok::<(), FlowyError>(()))) - } -} diff --git a/frontend/rust-lib/flowy-document/src/services/doc/mod.rs b/frontend/rust-lib/flowy-document/src/services/doc/mod.rs index c276f674d3..6b9355e13a 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/mod.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/mod.rs @@ -1,11 +1,8 @@ pub mod edit; pub mod revision; -pub(crate) mod controller; - -mod ws_handlers; +pub use crate::services::ws_handlers::*; pub use edit::*; pub use revision::*; -pub use ws_handlers::*; -pub const SYNC_INTERVAL_IN_MILLIS: u64 = 500; +pub const SYNC_INTERVAL_IN_MILLIS: u64 = 1000; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs index ce85c8c4dd..b3d12b56ae 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs @@ -3,26 +3,22 @@ use crate::{ services::doc::revision::{ cache::{ disk::{Persistence, RevisionDiskCache}, - memory::{RevisionMemoryCache, RevisionMemoryCacheMissing}, + memory::{RevisionMemoryCache, RevisionMemoryCacheDelegate}, sync::RevisionSyncSeq, }, RevisionRecord, }, + sql_tables::{RevChangeset, RevTableState}, }; - use flowy_database::ConnectionPool; use flowy_error::{internal_error, FlowyResult}; use lib_infra::future::FutureResult; -use lib_ot::{ - core::Operation, - revision::{RevState, Revision, RevisionRange}, - rich_text::RichTextDelta, -}; -use std::sync::Arc; -use tokio::{ - sync::RwLock, - task::{spawn_blocking, JoinHandle}, +use lib_ot::revision::{RevState, Revision, RevisionRange}; +use std::sync::{ + atomic::{AtomicI64, Ordering::SeqCst}, + Arc, }; +use tokio::task::spawn_blocking; type DocRevisionDiskCache = dyn RevisionDiskCache; @@ -31,7 +27,7 @@ pub struct RevisionCache { pub disk_cache: Arc, memory_cache: Arc, sync_seq: Arc, - defer_save: RwLock>>, + latest_rev_id: AtomicI64, } impl RevisionCache { @@ -45,7 +41,7 @@ impl RevisionCache { disk_cache, memory_cache, sync_seq, - defer_save: RwLock::new(None), + latest_rev_id: AtomicI64::new(0), } } @@ -54,13 +50,14 @@ impl RevisionCache { if self.memory_cache.contains(&revision.rev_id) { return Err(FlowyError::internal().context(format!("Duplicate revision id: {}", revision.rev_id))); } + let rev_id = revision.rev_id; let record = RevisionRecord { revision, state: RevState::StateLocal, }; let _ = self.memory_cache.add_revision(&record).await; self.sync_seq.add_revision(record).await?; - self.save_revisions().await; + let _ = self.latest_rev_id.fetch_update(SeqCst, SeqCst, |_e| Some(rev_id)); Ok(()) } @@ -69,58 +66,63 @@ impl RevisionCache { if self.memory_cache.contains(&revision.rev_id) { return Err(FlowyError::internal().context(format!("Duplicate revision id: {}", revision.rev_id))); } + let rev_id = revision.rev_id; let record = RevisionRecord { revision, - state: RevState::StateLocal, + state: RevState::Acked, }; self.memory_cache.add_revision(&record).await; - self.save_revisions().await; + let _ = self.latest_rev_id.fetch_update(SeqCst, SeqCst, |_e| Some(rev_id)); Ok(()) } #[tracing::instrument(level = "debug", skip(self, rev_id), fields(rev_id = %rev_id))] pub async fn ack_revision(&self, rev_id: i64) { - self.sync_seq.ack_revision(&rev_id).await; - self.save_revisions().await; - } - - pub async fn get_revision(&self, _doc_id: &str, rev_id: i64) -> Option { - self.memory_cache.get_revision(&rev_id).await - } - - async fn save_revisions(&self) { - // https://github.com/async-graphql/async-graphql/blob/ed8449beec3d9c54b94da39bab33cec809903953/src/dataloader/mod.rs#L362 - if let Some(handler) = self.defer_save.write().await.take() { - handler.abort(); + if self.sync_seq.ack_revision(&rev_id).await.is_ok() { + self.memory_cache.ack_revision(&rev_id).await; } + } - // if self.sync_seq.is_empty() { - // return; - // } + pub fn latest_rev_id(&self) -> i64 { self.latest_rev_id.load(SeqCst) } - // let memory_cache = self.sync_seq.clone(); - // let disk_cache = self.disk_cache.clone(); - // *self.defer_save.write().await = Some(tokio::spawn(async move { - // tokio::time::sleep(Duration::from_millis(300)).await; - // let (ids, records) = memory_cache.revisions(); - // match disk_cache.create_revisions(records) { - // Ok(_) => { - // memory_cache.remove_revisions(ids); - // }, - // Err(e) => log::error!("Save revision failed: {:?}", e), - // } - // })); + pub async fn get_revision(&self, doc_id: &str, rev_id: i64) -> Option { + match self.memory_cache.get_revision(&rev_id).await { + None => match self.disk_cache.read_revision(&self.doc_id, rev_id) { + Ok(Some(revision)) => Some(revision), + Ok(None) => { + tracing::warn!("Can't find revision in {} with rev_id: {}", doc_id, rev_id); + None + }, + Err(e) => { + tracing::error!("{}", e); + None + }, + }, + Some(revision) => Some(revision), + } } pub async fn revisions_in_range(&self, range: RevisionRange) -> FlowyResult> { - let records = self.memory_cache.get_revisions_in_range(&range).await?; + let mut records = self.memory_cache.get_revisions_in_range(&range).await?; + let range_len = range.len() as usize; + if records.len() != range_len { + let disk_cache = self.disk_cache.clone(); + let doc_id = self.doc_id.clone(); + records = spawn_blocking(move || disk_cache.revisions_in_range(&doc_id, &range)) + .await + .map_err(internal_error)??; + + if records.len() != range_len { + log::error!("Revisions len is not equal to range required"); + } + } Ok(records .into_iter() .map(|record| record.revision) .collect::>()) } - pub(crate) fn next_revision(&self) -> FutureResult, FlowyError> { + pub(crate) fn next_sync_revision(&self) -> FutureResult, FlowyError> { let sync_seq = self.sync_seq.clone(); let disk_cache = self.disk_cache.clone(); let doc_id = self.doc_id.clone(); @@ -139,32 +141,20 @@ impl RevisionCache { } } -impl RevisionMemoryCacheMissing for Arc { - fn get_revision_record(&self, doc_id: &str, rev_id: i64) -> Result, FlowyError> { - match self.read_revision(&doc_id, rev_id)? { - None => { - tracing::warn!("Can't find revision in {} with rev_id: {}", doc_id, rev_id); - Ok(None) - }, - Some(record) => Ok(Some(record)), +impl RevisionMemoryCacheDelegate for Arc { + fn receive_checkpoint(&self, records: Vec) -> FlowyResult<()> { self.create_revisions(records) } + + fn receive_ack(&self, doc_id: &str, rev_id: i64) { + let changeset = RevChangeset { + doc_id: doc_id.to_string(), + rev_id: rev_id.into(), + state: RevTableState::Acked, + }; + match self.update_revisions(vec![changeset]) { + Ok(_) => {}, + Err(e) => tracing::error!("{}", e), } } - - fn get_revision_records_with_range( - &self, - doc_id: &str, - range: RevisionRange, - ) -> FutureResult, FlowyError> { - let disk_cache = self.clone(); - let doc_id = doc_id.to_owned(); - FutureResult::new(async move { - let records = spawn_blocking(move || disk_cache.revisions_in_range(&doc_id, &range)) - .await - .map_err(internal_error)??; - - Ok::, FlowyError>(records) - }) - } } #[cfg(feature = "flowy_unit_test")] diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/disk.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/disk.rs index 1cbde7dd91..b65d44b5ee 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/disk.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/disk.rs @@ -1,8 +1,8 @@ use crate::services::doc::revision::RevisionRecord; -use crate::sql_tables::RevTableSql; +use crate::sql_tables::{RevChangeset, RevTableSql}; use flowy_database::ConnectionPool; -use flowy_error::{internal_error, FlowyError}; +use flowy_error::{internal_error, FlowyError, FlowyResult}; use lib_ot::revision::RevisionRange; use std::{fmt::Debug, sync::Arc}; @@ -12,6 +12,7 @@ pub trait RevisionDiskCache: Sync + Send { fn revisions_in_range(&self, doc_id: &str, range: &RevisionRange) -> Result, Self::Error>; fn read_revision(&self, doc_id: &str, rev_id: i64) -> Result, Self::Error>; fn read_revisions(&self, doc_id: &str) -> Result, Self::Error>; + fn update_revisions(&self, changesets: Vec) -> FlowyResult<()>; } pub(crate) struct Persistence { @@ -47,6 +48,17 @@ impl RevisionDiskCache for Persistence { let some = RevTableSql::read_rev_tables(&self.user_id, doc_id, &*conn)?; Ok(some) } + + fn update_revisions(&self, changesets: Vec) -> FlowyResult<()> { + let conn = &*self.pool.get().map_err(internal_error)?; + let _ = conn.immediate_transaction::<_, FlowyError, _>(|| { + for changeset in changesets { + let _ = RevTableSql::update_rev_table(changeset, conn)?; + } + Ok(()) + })?; + Ok(()) + } } impl Persistence { diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/memory.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/memory.rs index a468dffc9e..9c8df20824 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/memory.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/memory.rs @@ -1,87 +1,116 @@ use crate::services::doc::RevisionRecord; use dashmap::DashMap; -use flowy_error::FlowyError; -use lib_infra::future::FutureResult; -use lib_ot::revision::RevisionRange; -use std::sync::Arc; -use tokio::sync::RwLock; +use flowy_error::{FlowyError, FlowyResult}; -pub(crate) trait RevisionMemoryCacheMissing: Send + Sync { - fn get_revision_record(&self, doc_id: &str, rev_id: i64) -> Result, FlowyError>; - fn get_revision_records_with_range( - &self, - doc_id: &str, - range: RevisionRange, - ) -> FutureResult, FlowyError>; +use lib_ot::revision::RevisionRange; +use std::{sync::Arc, time::Duration}; +use tokio::{sync::RwLock, task::JoinHandle}; + +pub(crate) trait RevisionMemoryCacheDelegate: Send + Sync { + fn receive_checkpoint(&self, records: Vec) -> FlowyResult<()>; + fn receive_ack(&self, doc_id: &str, rev_id: i64); } pub(crate) struct RevisionMemoryCache { doc_id: String, revs_map: Arc>, - rev_loader: Arc, - revs_order: Arc>>, + delegate: Arc, + pending_write_revs: Arc>>, + defer_save: RwLock>>, } -// TODO: remove outdated revisions to reduce memory usage impl RevisionMemoryCache { - pub(crate) fn new(doc_id: &str, rev_loader: Arc) -> Self { + pub(crate) fn new(doc_id: &str, delegate: Arc) -> Self { RevisionMemoryCache { doc_id: doc_id.to_owned(), revs_map: Arc::new(DashMap::new()), - rev_loader, - revs_order: Arc::new(RwLock::new(vec![])), + delegate, + pending_write_revs: Arc::new(RwLock::new(vec![])), + defer_save: RwLock::new(None), } } - pub(crate) async fn is_empty(&self) -> bool { self.revs_order.read().await.is_empty() } - pub(crate) fn contains(&self, rev_id: &i64) -> bool { self.revs_map.contains_key(rev_id) } pub(crate) async fn add_revision(&self, record: &RevisionRecord) { - if let Some(rev_id) = self.revs_order.read().await.last() { + if let Some(rev_id) = self.pending_write_revs.read().await.last() { if *rev_id >= record.revision.rev_id { tracing::error!("Duplicated revision added to memory_cache"); return; } } + // FIXME: Remove outdated revisions to reduce memory usage self.revs_map.insert(record.revision.rev_id, record.clone()); - self.revs_order.write().await.push(record.revision.rev_id); + self.pending_write_revs.write().await.push(record.revision.rev_id); + self.make_checkpoint().await; + } + + pub(crate) async fn ack_revision(&self, rev_id: &i64) { + match self.revs_map.get_mut(rev_id) { + None => {}, + Some(mut record) => record.ack(), + } + + if !self.pending_write_revs.read().await.contains(rev_id) { + // The revision must be saved on disk if the pending_write_revs + // doesn't contains the rev_id. + self.delegate.receive_ack(&self.doc_id, *rev_id); + } else { + self.make_checkpoint().await; + } } pub(crate) async fn get_revision(&self, rev_id: &i64) -> Option { - match self.revs_map.get(&rev_id).map(|r| r.value().clone()) { - None => match self.rev_loader.get_revision_record(&self.doc_id, *rev_id) { - Ok(revision) => revision, - Err(e) => { - tracing::error!("{}", e); - None - }, - }, - Some(revision) => Some(revision), - } + self.revs_map.get(&rev_id).map(|r| r.value().clone()) } pub(crate) async fn get_revisions_in_range( &self, range: &RevisionRange, ) -> Result, FlowyError> { - let range_len = range.len() as usize; let revs = range .iter() .flat_map(|rev_id| self.revs_map.get(&rev_id).map(|record| record.clone())) .collect::>(); + Ok(revs) + } - if revs.len() == range_len { - Ok(revs) - } else { - let revs = self - .rev_loader - .get_revision_records_with_range(&self.doc_id, range.clone()) - .await?; - if revs.len() != range_len { - log::error!("Revisions len is not equal to range required"); - } - Ok(revs) + async fn make_checkpoint(&self) { + // https://github.com/async-graphql/async-graphql/blob/ed8449beec3d9c54b94da39bab33cec809903953/src/dataloader/mod.rs#L362 + if let Some(handler) = self.defer_save.write().await.take() { + handler.abort(); } + + if self.pending_write_revs.read().await.is_empty() { + return; + } + + let rev_map = self.revs_map.clone(); + let pending_write_revs = self.pending_write_revs.clone(); + let delegate = self.delegate.clone(); + + *self.defer_save.write().await = Some(tokio::spawn(async move { + tokio::time::sleep(Duration::from_millis(300)).await; + let mut revs_write_guard = pending_write_revs.write().await; + // FIXME: + // It may cause performance issues because we hold the write lock of the + // rev_order and the lock will be released after the checkpoint has been written + // to the disk. + // + // Use saturating_sub and split_off ? + // https://stackoverflow.com/questions/28952411/what-is-the-idiomatic-way-to-pop-the-last-n-elements-in-a-mutable-vec + let mut save_records: Vec = vec![]; + revs_write_guard.iter().for_each(|rev_id| match rev_map.get(rev_id) { + None => {}, + Some(value) => { + save_records.push(value.value().clone()); + }, + }); + + if delegate.receive_checkpoint(save_records).is_ok() { + revs_write_guard.clear(); + drop(revs_write_guard); + } + })); } } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/sync.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/sync.rs index 449d3101e0..b9f454e9f5 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/sync.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/sync.rs @@ -1,5 +1,6 @@ use crate::services::doc::revision::RevisionRecord; use dashmap::DashMap; +use flowy_error::{FlowyError, FlowyResult}; use lib_ot::errors::OTError; use std::{collections::VecDeque, sync::Arc}; use tokio::sync::RwLock; @@ -30,34 +31,33 @@ impl RevisionSyncSeq { .context(format!("The new revision's id must be greater than {}", rev_id))); } } + self.local_revs.write().await.push_back(record.revision.rev_id); self.revs_map.insert(record.revision.rev_id, record); Ok(()) } - pub async fn ack_revision(&self, rev_id: &i64) { + pub async fn ack_revision(&self, rev_id: &i64) -> FlowyResult<()> { if let Some(pop_rev_id) = self.next_sync_rev_id().await { if &pop_rev_id != rev_id { - tracing::error!("The next ack rev_id must be equal to the next rev_id"); - assert_eq!(&pop_rev_id, rev_id); - return; + let desc = format!( + "The ack rev_id:{} is not equal to the current rev_id:{}", + rev_id, pop_rev_id + ); + // tracing::error!("{}", desc); + return Err(FlowyError::internal().context(desc)); } tracing::debug!("pop revision {}", pop_rev_id); self.revs_map.remove(&pop_rev_id); let _ = self.local_revs.write().await.pop_front(); } + Ok(()) } pub async fn next_sync_revision(&self) -> Option<(i64, RevisionRecord)> { match self.local_revs.read().await.front() { None => None, - Some(rev_id) => match self.revs_map.get(rev_id).map(|r| (*r.key(), r.value().clone())) { - None => None, - Some(val) => { - tracing::debug!("{}:try send revision {}", val.1.revision.doc_id, val.1.revision.rev_id); - Some(val) - }, - }, + Some(rev_id) => self.revs_map.get(rev_id).map(|r| (*r.key(), r.value().clone())), } } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs index a1c5f99cdb..b6a828ed49 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/manager.rs @@ -102,7 +102,9 @@ impl RevisionManager { Ok(revision) } - pub fn next_sync_revision(&self) -> FutureResult, FlowyError> { self.cache.next_revision() } + pub fn next_sync_revision(&self) -> FutureResult, FlowyError> { self.cache.next_sync_revision() } + + pub fn latest_rev_id(&self) -> i64 { self.cache.latest_rev_id() } } #[cfg(feature = "flowy_unit_test")] @@ -134,7 +136,7 @@ impl RevisionLoader { &self.user_id, doc_md5, ); - let _ = self.cache.add_remote_revision(revision.clone()).await?; + let _ = self.cache.add_local_revision(revision.clone()).await?; revisions = vec![revision]; } else { for record in &records { diff --git a/frontend/rust-lib/flowy-document/src/services/mod.rs b/frontend/rust-lib/flowy-document/src/services/mod.rs index 82dbce10c4..634e507938 100644 --- a/frontend/rust-lib/flowy-document/src/services/mod.rs +++ b/frontend/rust-lib/flowy-document/src/services/mod.rs @@ -1,2 +1,4 @@ +pub(crate) mod controller; pub mod doc; pub mod server; +mod ws_handlers; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/ws_handlers.rs b/frontend/rust-lib/flowy-document/src/services/ws_handlers.rs similarity index 100% rename from frontend/rust-lib/flowy-document/src/services/doc/ws_handlers.rs rename to frontend/rust-lib/flowy-document/src/services/ws_handlers.rs diff --git a/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_sql.rs b/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_sql.rs index 80a9f106bf..84520b57f5 100644 --- a/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_sql.rs +++ b/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_sql.rs @@ -32,7 +32,6 @@ impl RevTableSql { Ok(()) } - #[allow(dead_code)] 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())) diff --git a/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_table.rs b/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_table.rs index d6ef355c5f..732f4ae9a9 100644 --- a/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_table.rs +++ b/frontend/rust-lib/flowy-document/src/sql_tables/doc/rev_table.rs @@ -128,8 +128,7 @@ impl RevTableType { } impl_sql_integer_expression!(RevTableType); -#[allow(dead_code)] -pub(crate) struct RevChangeset { +pub struct RevChangeset { pub(crate) doc_id: String, pub(crate) rev_id: RevId, pub(crate) state: RevTableState, diff --git a/shared-lib/flowy-collaboration/src/core/sync/server_editor.rs b/shared-lib/flowy-collaboration/src/core/sync/server_editor.rs index a15f3201cf..3bd1111375 100644 --- a/shared-lib/flowy-collaboration/src/core/sync/server_editor.rs +++ b/shared-lib/flowy-collaboration/src/core/sync/server_editor.rs @@ -81,12 +81,6 @@ impl ServerDocManager { } pub async fn create_doc(&self, revision: Revision) -> Result, CollaborateError> { - if !revision.is_initial() { - return Err( - CollaborateError::revision_conflict().context("Revision's rev_id should be 0 when creating the doc") - ); - } - let doc = self.persistence.create_doc(revision).await?; let handler = self.cache(doc).await?; Ok(handler) diff --git a/shared-lib/flowy-collaboration/src/entities/ws/ws.rs b/shared-lib/flowy-collaboration/src/entities/ws/ws.rs index 53fb551f16..818a07cbf3 100644 --- a/shared-lib/flowy-collaboration/src/entities/ws/ws.rs +++ b/shared-lib/flowy-collaboration/src/entities/ws/ws.rs @@ -95,6 +95,18 @@ impl WsDocumentDataBuilder { id: Some(cloned_rev_id), } } + + // DocumentWSDataType::UserConnect -> DocumentConnected + pub fn build_document_conn_message(doc_id: &str, document_conn: DocumentConnected) -> DocumentWSData { + let rev_id = document_conn.rev_id; + let bytes: Bytes = document_conn.try_into().unwrap(); + DocumentWSData { + doc_id: doc_id.to_string(), + ty: DocumentWSDataType::UserConnect, + data: bytes.to_vec(), + id: Some(rev_id), + } + } } #[derive(ProtoBuf, Default, Debug, Clone)] diff --git a/shared-lib/lib-ot/src/revision/model.rs b/shared-lib/lib-ot/src/revision/model.rs index f9ba9aa837..5ca284cc63 100644 --- a/shared-lib/lib-ot/src/revision/model.rs +++ b/shared-lib/lib-ot/src/revision/model.rs @@ -39,6 +39,7 @@ impl Revision { pub fn pair_rev_id(&self) -> (i64, i64) { (self.base_rev_id, self.rev_id) } + #[allow(dead_code)] pub fn is_initial(&self) -> bool { self.rev_id == 0 } } From 77be3e9c71dbb7adf7c444be208b7fa9b9dcb927 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 19 Dec 2021 21:10:50 +0800 Subject: [PATCH 35/39] send connect message when open the document --- backend/src/services/doc/ws_actor.rs | 42 +-- .../protobuf/flowy-collaboration/ws.pb.dart | 49 ++- .../flowy-collaboration/ws.pbenum.dart | 4 +- .../flowy-collaboration/ws.pbjson.dart | 21 +- .../src/services/doc/edit/editor.rs | 279 +++++++++++------- .../services/doc/edit/editor_web_socket.rs | 37 +-- .../src/services/doc/revision/cache/cache.rs | 107 +++++-- .../src/services/doc/revision/cache/mod.rs | 3 - .../src/services/doc/revision/cache/model.rs | 15 - .../flowy-net/src/services/mock/ws_mock.rs | 15 +- .../rust-lib/flowy-test/src/doc_script.rs | 2 - .../src/core/sync/synchronizer.rs | 12 +- .../flowy-collaboration/src/entities/ws/ws.rs | 45 ++- .../src/protobuf/model/ws.rs | 211 ++++++------- .../src/protobuf/proto/ws.proto | 6 +- .../src/derive_cache/derive_cache.rs | 2 +- shared-lib/lib-ws/src/msg.rs | 1 - 17 files changed, 481 insertions(+), 370 deletions(-) delete mode 100644 frontend/rust-lib/flowy-document/src/services/doc/revision/cache/model.rs diff --git a/backend/src/services/doc/ws_actor.rs b/backend/src/services/doc/ws_actor.rs index edf24ac920..e8384b58ec 100644 --- a/backend/src/services/doc/ws_actor.rs +++ b/backend/src/services/doc/ws_actor.rs @@ -3,16 +3,19 @@ use crate::{ doc::editor::ServerDocUser, util::{md5, parse_from_bytes}, }, - web_socket::{entities::Socket, WsClientData, WsUser}, + web_socket::WsClientData, }; use actix_rt::task::spawn_blocking; use actix_web::web::Data; use async_stream::stream; use backend_service::errors::{internal_error, Result, ServerError}; use flowy_collaboration::{ - core::sync::ServerDocManager, + core::sync::{RevisionUser, ServerDocManager, SyncResponse}, + entities::ws::DocumentWSDataBuilder, protobuf::{DocumentWSData, DocumentWSDataType}, }; + +use flowy_collaboration::protobuf::NewDocumentUser; use futures::stream::StreamExt; use lib_ot::protobuf::Revision; use sqlx::PgPool; @@ -66,7 +69,7 @@ impl DocWsActor { } } - async fn handle_client_data(&self, client_data: WsClientData, pool: Data) -> Result<()> { + async fn handle_client_data(&self, client_data: WsClientData, pg_pool: Data) -> Result<()> { let WsClientData { user, socket, data } = client_data; let document_data = spawn_blocking(move || { let document_data: DocumentWSData = parse_from_bytes(&data)?; @@ -75,23 +78,29 @@ impl DocWsActor { .await .map_err(internal_error)??; - let data = document_data.data; - - match document_data.ty { - DocumentWSDataType::Acked => Ok(()), - DocumentWSDataType::PushRev => self.apply_pushed_rev(user, socket, data, pool).await, + let user = Arc::new(ServerDocUser { user, socket, pg_pool }); + match &document_data.ty { + DocumentWSDataType::Ack => Ok(()), + DocumentWSDataType::PushRev => self.handle_pushed_rev(user, document_data.data).await, DocumentWSDataType::PullRev => Ok(()), - DocumentWSDataType::UserConnect => Ok(()), + DocumentWSDataType::UserConnect => self.handle_user_connect(user, document_data).await, } } - async fn apply_pushed_rev( - &self, - user: Arc, - socket: Socket, - data: Vec, - pg_pool: Data, - ) -> Result<()> { + async fn handle_user_connect(&self, user: Arc, document_data: DocumentWSData) -> Result<()> { + let id = document_data.id.clone(); + let new_user = spawn_blocking(move || parse_from_bytes::(&document_data.data)) + .await + .map_err(internal_error)??; + + user.recv(SyncResponse::Ack(DocumentWSDataBuilder::build_ack_message( + &new_user.doc_id, + &id, + ))); + Ok(()) + } + + async fn handle_pushed_rev(&self, user: Arc, data: Vec) -> Result<()> { let mut revision_pb = spawn_blocking(move || { let revision: Revision = parse_from_bytes(&data)?; let _ = verify_md5(&revision)?; @@ -110,7 +119,6 @@ impl DocWsActor { Some(handler) => handler, }; - let user = Arc::new(ServerDocUser { user, socket, pg_pool }); handler.apply_revision(user, revision).await.map_err(internal_error)?; Ok(()) } diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pb.dart index 53eff22b3b..b38a10b674 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pb.dart @@ -14,22 +14,12 @@ import 'ws.pbenum.dart'; export 'ws.pbenum.dart'; -enum DocumentWSData_OneOfId { - id, - notSet -} - class DocumentWSData extends $pb.GeneratedMessage { - static const $core.Map<$core.int, DocumentWSData_OneOfId> _DocumentWSData_OneOfIdByTag = { - 4 : DocumentWSData_OneOfId.id, - 0 : DocumentWSData_OneOfId.notSet - }; static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DocumentWSData', createEmptyInstance: create) - ..oo(0, [4]) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'docId') - ..e(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'ty', $pb.PbFieldType.OE, defaultOrMaker: DocumentWSDataType.Acked, valueOf: DocumentWSDataType.valueOf, enumValues: DocumentWSDataType.values) + ..e(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'ty', $pb.PbFieldType.OE, defaultOrMaker: DocumentWSDataType.Ack, valueOf: DocumentWSDataType.valueOf, enumValues: DocumentWSDataType.values) ..a<$core.List<$core.int>>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data', $pb.PbFieldType.OY) - ..aInt64(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id') + ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id') ..hasRequiredFields = false ; @@ -38,7 +28,7 @@ class DocumentWSData extends $pb.GeneratedMessage { $core.String? docId, DocumentWSDataType? ty, $core.List<$core.int>? data, - $fixnum.Int64? id, + $core.String? id, }) { final _result = create(); if (docId != null) { @@ -76,9 +66,6 @@ class DocumentWSData extends $pb.GeneratedMessage { static DocumentWSData getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); static DocumentWSData? _defaultInstance; - DocumentWSData_OneOfId whichOneOfId() => _DocumentWSData_OneOfIdByTag[$_whichOneof(0)]!; - void clearOneOfId() => clearField($_whichOneof(0)); - @$pb.TagNumber(1) $core.String get docId => $_getSZ(0); @$pb.TagNumber(1) @@ -107,25 +94,25 @@ class DocumentWSData extends $pb.GeneratedMessage { void clearData() => clearField(3); @$pb.TagNumber(4) - $fixnum.Int64 get id => $_getI64(3); + $core.String get id => $_getSZ(3); @$pb.TagNumber(4) - set id($fixnum.Int64 v) { $_setInt64(3, v); } + set id($core.String v) { $_setString(3, v); } @$pb.TagNumber(4) $core.bool hasId() => $_has(3); @$pb.TagNumber(4) void clearId() => clearField(4); } -class DocumentConnected extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DocumentConnected', createEmptyInstance: create) +class NewDocumentUser extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'NewDocumentUser', createEmptyInstance: create) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'userId') ..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'docId') ..aInt64(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'revId') ..hasRequiredFields = false ; - DocumentConnected._() : super(); - factory DocumentConnected({ + NewDocumentUser._() : super(); + factory NewDocumentUser({ $core.String? userId, $core.String? docId, $fixnum.Int64? revId, @@ -142,26 +129,26 @@ class DocumentConnected extends $pb.GeneratedMessage { } return _result; } - factory DocumentConnected.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory DocumentConnected.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + factory NewDocumentUser.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory NewDocumentUser.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' 'Will be removed in next major version') - DocumentConnected clone() => DocumentConnected()..mergeFromMessage(this); + NewDocumentUser clone() => NewDocumentUser()..mergeFromMessage(this); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - DocumentConnected copyWith(void Function(DocumentConnected) updates) => super.copyWith((message) => updates(message as DocumentConnected)) as DocumentConnected; // ignore: deprecated_member_use + NewDocumentUser copyWith(void Function(NewDocumentUser) updates) => super.copyWith((message) => updates(message as NewDocumentUser)) as NewDocumentUser; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; @$core.pragma('dart2js:noInline') - static DocumentConnected create() => DocumentConnected._(); - DocumentConnected createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); + static NewDocumentUser create() => NewDocumentUser._(); + NewDocumentUser createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); @$core.pragma('dart2js:noInline') - static DocumentConnected getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static DocumentConnected? _defaultInstance; + static NewDocumentUser getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static NewDocumentUser? _defaultInstance; @$pb.TagNumber(1) $core.String get userId => $_getSZ(0); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbenum.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbenum.dart index 83be5c1784..43dc8c25ba 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbenum.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbenum.dart @@ -10,13 +10,13 @@ import 'dart:core' as $core; import 'package:protobuf/protobuf.dart' as $pb; class DocumentWSDataType extends $pb.ProtobufEnum { - static const DocumentWSDataType Acked = DocumentWSDataType._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Acked'); + static const DocumentWSDataType Ack = DocumentWSDataType._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Ack'); static const DocumentWSDataType PushRev = DocumentWSDataType._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PushRev'); static const DocumentWSDataType PullRev = DocumentWSDataType._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PullRev'); static const DocumentWSDataType UserConnect = DocumentWSDataType._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserConnect'); static const $core.List values = [ - Acked, + Ack, PushRev, PullRev, UserConnect, diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbjson.dart index 2bcc352adf..2ee4eac6a7 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-collaboration/ws.pbjson.dart @@ -12,7 +12,7 @@ import 'dart:typed_data' as $typed_data; const DocumentWSDataType$json = const { '1': 'DocumentWSDataType', '2': const [ - const {'1': 'Acked', '2': 0}, + const {'1': 'Ack', '2': 0}, const {'1': 'PushRev', '2': 1}, const {'1': 'PullRev', '2': 2}, const {'1': 'UserConnect', '2': 3}, @@ -20,7 +20,7 @@ const DocumentWSDataType$json = const { }; /// Descriptor for `DocumentWSDataType`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List documentWSDataTypeDescriptor = $convert.base64Decode('ChJEb2N1bWVudFdTRGF0YVR5cGUSCQoFQWNrZWQQABILCgdQdXNoUmV2EAESCwoHUHVsbFJldhACEg8KC1VzZXJDb25uZWN0EAM='); +final $typed_data.Uint8List documentWSDataTypeDescriptor = $convert.base64Decode('ChJEb2N1bWVudFdTRGF0YVR5cGUSBwoDQWNrEAASCwoHUHVzaFJldhABEgsKB1B1bGxSZXYQAhIPCgtVc2VyQ29ubmVjdBAD'); @$core.Deprecated('Use documentWSDataDescriptor instead') const DocumentWSData$json = const { '1': 'DocumentWSData', @@ -28,18 +28,15 @@ const DocumentWSData$json = const { const {'1': 'doc_id', '3': 1, '4': 1, '5': 9, '10': 'docId'}, const {'1': 'ty', '3': 2, '4': 1, '5': 14, '6': '.DocumentWSDataType', '10': 'ty'}, const {'1': 'data', '3': 3, '4': 1, '5': 12, '10': 'data'}, - const {'1': 'id', '3': 4, '4': 1, '5': 3, '9': 0, '10': 'id'}, - ], - '8': const [ - const {'1': 'one_of_id'}, + const {'1': 'id', '3': 4, '4': 1, '5': 9, '10': 'id'}, ], }; /// Descriptor for `DocumentWSData`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List documentWSDataDescriptor = $convert.base64Decode('Cg5Eb2N1bWVudFdTRGF0YRIVCgZkb2NfaWQYASABKAlSBWRvY0lkEiMKAnR5GAIgASgOMhMuRG9jdW1lbnRXU0RhdGFUeXBlUgJ0eRISCgRkYXRhGAMgASgMUgRkYXRhEhAKAmlkGAQgASgDSABSAmlkQgsKCW9uZV9vZl9pZA=='); -@$core.Deprecated('Use documentConnectedDescriptor instead') -const DocumentConnected$json = const { - '1': 'DocumentConnected', +final $typed_data.Uint8List documentWSDataDescriptor = $convert.base64Decode('Cg5Eb2N1bWVudFdTRGF0YRIVCgZkb2NfaWQYASABKAlSBWRvY0lkEiMKAnR5GAIgASgOMhMuRG9jdW1lbnRXU0RhdGFUeXBlUgJ0eRISCgRkYXRhGAMgASgMUgRkYXRhEg4KAmlkGAQgASgJUgJpZA=='); +@$core.Deprecated('Use newDocumentUserDescriptor instead') +const NewDocumentUser$json = const { + '1': 'NewDocumentUser', '2': const [ const {'1': 'user_id', '3': 1, '4': 1, '5': 9, '10': 'userId'}, const {'1': 'doc_id', '3': 2, '4': 1, '5': 9, '10': 'docId'}, @@ -47,5 +44,5 @@ const DocumentConnected$json = const { ], }; -/// Descriptor for `DocumentConnected`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List documentConnectedDescriptor = $convert.base64Decode('ChFEb2N1bWVudENvbm5lY3RlZBIXCgd1c2VyX2lkGAEgASgJUgZ1c2VySWQSFQoGZG9jX2lkGAIgASgJUgVkb2NJZBIVCgZyZXZfaWQYAyABKANSBXJldklk'); +/// Descriptor for `NewDocumentUser`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List newDocumentUserDescriptor = $convert.base64Decode('Cg9OZXdEb2N1bWVudFVzZXISFwoHdXNlcl9pZBgBIAEoCVIGdXNlcklkEhUKBmRvY19pZBgCIAEoCVIFZG9jSWQSFQoGcmV2X2lkGAMgASgDUgVyZXZJZA=='); diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs index 5aa7698eb9..f179507f58 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs @@ -4,7 +4,7 @@ use flowy_collaboration::{ core::document::history::UndoResult, entities::{ doc::DocDelta, - ws::{DocumentConnected, DocumentWSData, DocumentWSDataType, WsDocumentDataBuilder}, + ws::{DocumentWSData, DocumentWSDataBuilder, DocumentWSDataType, NewDocumentUser}, }, errors::CollaborateResult, }; @@ -42,27 +42,32 @@ impl ClientDocEditor { let doc_id = doc_id.to_string(); let user_id = user.user_id()?; let rev_manager = Arc::new(rev_manager); - let sink_data_provider = Arc::new(RwLock::new(VecDeque::new())); - let data_provider = Arc::new(DocumentSinkDataProviderAdapter { - rev_manager: rev_manager.clone(), - data_provider: sink_data_provider.clone(), - }); - let stream_consumer = Arc::new(DocumentWebSocketSteamConsumerAdapter { + let combined_sink = Arc::new(CombinedSink::new(rev_manager.clone())); + let ws_stream_consumer = Arc::new(DocumentWebSocketSteamConsumerAdapter { doc_id: doc_id.clone(), editor_cmd_sender: editor_cmd_sender.clone(), rev_manager: rev_manager.clone(), user: user.clone(), - sink_data_provider: sink_data_provider.clone(), + combined_sink: combined_sink.clone(), }); - let editor_ws = Arc::new(EditorWebSocket::new(&doc_id, ws, data_provider, stream_consumer)); - notify_user_conn(&user_id, &doc_id, rev_manager.clone(), sink_data_provider.clone()).await; + let ws_stream_provider = Arc::new(DocumentWSSinkDataProviderAdapter(combined_sink.clone())); + let editor_ws = Arc::new(EditorWebSocket::new( + &doc_id, + ws, + ws_stream_provider, + ws_stream_consumer, + )); + // + notify_user_conn(&user_id, &doc_id, rev_manager.clone(), combined_sink.clone()).await; + + // listen_document_ws_state( &user_id, &doc_id, editor_ws.scribe_state(), rev_manager.clone(), - sink_data_provider, + combined_sink, ); let editor = Arc::new(Self { @@ -210,78 +215,12 @@ fn spawn_edit_queue(doc_id: &str, delta: RichTextDelta, _pool: Arc, - rev_manager: Arc, - user: Arc, - sink_data_provider: SinkDataProvider, -} - -impl DocumentWebSocketSteamConsumer for DocumentWebSocketSteamConsumerAdapter { - fn receive_push_revision(&self, bytes: Bytes) -> FutureResult<(), FlowyError> { - let user = self.user.clone(); - let rev_manager = self.rev_manager.clone(); - let edit_cmd_tx = self.editor_cmd_sender.clone(); - let sink_data_provider = self.sink_data_provider.clone(); - let doc_id = self.doc_id.clone(); - FutureResult::new(async move { - let user_id = user.user_id()?; - if let Some(revision) = handle_push_rev(&doc_id, &user_id, edit_cmd_tx, rev_manager, bytes).await? { - sink_data_provider.write().await.push_back(revision.into()); - } - Ok(()) - }) - } - - fn receive_ack_revision(&self, rev_id: i64) -> FutureResult<(), FlowyError> { - let rev_manager = self.rev_manager.clone(); - FutureResult::new(async move { - let _ = rev_manager.ack_revision(rev_id).await?; - Ok(()) - }) - } - - fn send_revision_in_range(&self, range: RevisionRange) -> FutureResult<(), FlowyError> { - let rev_manager = self.rev_manager.clone(); - let sink_data_provider = self.sink_data_provider.clone(); - FutureResult::new(async move { - let revision = rev_manager.mk_revisions(range).await?; - sink_data_provider.write().await.push_back(revision.into()); - Ok(()) - }) - } -} - -async fn notify_user_conn( - user_id: &str, - doc_id: &str, - rev_manager: Arc, - sink_data_provider: SinkDataProvider, -) { - let need_notify = match sink_data_provider.read().await.front() { - None => true, - Some(data) => data.ty != DocumentWSDataType::UserConnect, - }; - - if need_notify { - let document_conn = DocumentConnected { - user_id: user_id.to_owned(), - doc_id: doc_id.to_owned(), - rev_id: rev_manager.latest_rev_id(), - }; - - let data = WsDocumentDataBuilder::build_document_conn_message(doc_id, document_conn); - sink_data_provider.write().await.push_front(data); - } -} - fn listen_document_ws_state( user_id: &str, doc_id: &str, mut subscriber: broadcast::Receiver, rev_manager: Arc, - sink_data_provider: SinkDataProvider, + sink_data_provider: Arc, ) { let user_id = user_id.to_owned(); let doc_id = doc_id.to_owned(); @@ -301,38 +240,79 @@ fn listen_document_ws_state( }); } -type SinkDataProvider = Arc>>; - -struct DocumentSinkDataProviderAdapter { +async fn notify_user_conn( + user_id: &str, + doc_id: &str, rev_manager: Arc, - data_provider: SinkDataProvider, + combined_sink: Arc, +) { + let need_notify = match combined_sink.front().await { + None => true, + Some(data) => data.ty != DocumentWSDataType::UserConnect, + }; + + if need_notify { + let new_connect = NewDocumentUser { + user_id: user_id.to_owned(), + doc_id: doc_id.to_owned(), + rev_id: rev_manager.latest_rev_id(), + }; + + let data = DocumentWSDataBuilder::build_new_document_user_message(doc_id, new_connect); + combined_sink.push_front(data).await; + } } -impl DocumentSinkDataProvider for DocumentSinkDataProviderAdapter { - fn next(&self) -> FutureResult, FlowyError> { - let rev_manager = self.rev_manager.clone(); - let data_provider = self.data_provider.clone(); +struct DocumentWebSocketSteamConsumerAdapter { + doc_id: String, + editor_cmd_sender: UnboundedSender, + rev_manager: Arc, + user: Arc, + combined_sink: Arc, +} +impl DocumentWSSteamConsumer for DocumentWebSocketSteamConsumerAdapter { + fn receive_push_revision(&self, bytes: Bytes) -> FutureResult<(), FlowyError> { + let user = self.user.clone(); + let rev_manager = self.rev_manager.clone(); + let edit_cmd_tx = self.editor_cmd_sender.clone(); + let combined_sink = self.combined_sink.clone(); + let doc_id = self.doc_id.clone(); FutureResult::new(async move { - if data_provider.read().await.is_empty() { - match rev_manager.next_sync_revision().await? { - Some(rev) => { - tracing::debug!("[DocumentSinkDataProvider]: {}:{:?}", rev.doc_id, rev.rev_id); - Ok(Some(rev.into())) - }, - None => Ok(None), - } - } else { - match data_provider.read().await.front() { - None => Ok(None), - Some(data) => { - tracing::debug!("[DocumentSinkDataProvider]: {}:{:?}", data.doc_id, data.ty); - Ok(Some(data.clone())) - }, - } + let user_id = user.user_id()?; + if let Some(revision) = handle_push_rev(&doc_id, &user_id, edit_cmd_tx, rev_manager, bytes).await? { + combined_sink.push_back(revision.into()).await; } + Ok(()) }) } + + fn receive_ack(&self, id: String, ty: DocumentWSDataType) -> FutureResult<(), FlowyError> { + let combined_sink = self.combined_sink.clone(); + FutureResult::new(async move { combined_sink.ack(id, ty).await }) + } + + fn receive_new_user_connect(&self, _new_user: NewDocumentUser) -> FutureResult<(), FlowyError> { + FutureResult::new(async move { Ok(()) }) + } + + fn send_revision_in_range(&self, range: RevisionRange) -> FutureResult<(), FlowyError> { + let rev_manager = self.rev_manager.clone(); + let combined_sink = self.combined_sink.clone(); + FutureResult::new(async move { + let revision = rev_manager.mk_revisions(range).await?; + combined_sink.push_back(revision.into()).await; + Ok(()) + }) + } +} + +struct DocumentWSSinkDataProviderAdapter(Arc); +impl DocumentWSSinkDataProvider for DocumentWSSinkDataProviderAdapter { + fn next(&self) -> FutureResult, FlowyError> { + let combined_sink = self.0.clone(); + FutureResult::new(async move { combined_sink.next().await }) + } } #[tracing::instrument(level = "debug", skip(edit_cmd_tx, rev_manager, bytes))] @@ -396,6 +376,101 @@ pub(crate) async fn handle_push_rev( ))) } +#[derive(Clone)] +enum SourceType { + Shared, + Revision, +} + +#[derive(Clone)] +struct CombinedSink { + shared: Arc>>, + rev_manager: Arc, + source_ty: Arc>, +} + +impl CombinedSink { + fn new(rev_manager: Arc) -> Self { + CombinedSink { + shared: Arc::new(RwLock::new(VecDeque::new())), + rev_manager, + source_ty: Arc::new(RwLock::new(SourceType::Shared)), + } + } + + // FIXME: return Option<&DocumentWSData> would be better + async fn front(&self) -> Option { self.shared.read().await.front().cloned() } + + async fn push_front(&self, data: DocumentWSData) { self.shared.write().await.push_front(data); } + + async fn push_back(&self, data: DocumentWSData) { self.shared.write().await.push_back(data); } + + async fn next(&self) -> FlowyResult> { + let source_ty = self.source_ty.read().await.clone(); + match source_ty { + SourceType::Shared => match self.shared.read().await.front() { + None => { + *self.source_ty.write().await = SourceType::Revision; + Ok(None) + }, + Some(data) => { + tracing::debug!("[DocumentSinkDataProvider]: {}:{:?}", data.doc_id, data.ty); + Ok(Some(data.clone())) + }, + }, + SourceType::Revision => { + if !self.shared.read().await.is_empty() { + *self.source_ty.write().await = SourceType::Shared; + return Ok(None); + } + + match self.rev_manager.next_sync_revision().await? { + Some(rev) => { + tracing::debug!("[DocumentSinkDataProvider]: {}:{:?}", rev.doc_id, rev.rev_id); + Ok(Some(rev.into())) + }, + None => Ok(None), + } + }, + } + } + + async fn ack(&self, id: String, _ty: DocumentWSDataType) -> FlowyResult<()> { + // let _ = self.rev_manager.ack_revision(id).await?; + let source_ty = self.source_ty.read().await.clone(); + match source_ty { + SourceType::Shared => { + let should_pop = match self.shared.read().await.front() { + None => false, + Some(val) => { + if val.id == id { + true + } else { + tracing::error!("The front element's {} is not equal to the {}", val.id, id); + false + } + }, + }; + if should_pop { + let _ = self.shared.write().await.pop_front(); + } + }, + SourceType::Revision => { + match id.parse::() { + Ok(rev_id) => { + let _ = self.rev_manager.ack_revision(rev_id).await?; + }, + Err(e) => { + tracing::error!("Parse rev_id from {} failed. {}", id, e); + }, + }; + }, + } + + Ok(()) + } +} + #[cfg(feature = "flowy_unit_test")] impl ClientDocEditor { pub async fn doc_json(&self) -> FlowyResult { diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor_web_socket.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor_web_socket.rs index 1f8ba327f1..d4315b230f 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor_web_socket.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor_web_socket.rs @@ -1,11 +1,11 @@ use crate::services::doc::{DocumentWebSocket, DocumentWsHandler, SYNC_INTERVAL_IN_MILLIS}; use async_stream::stream; use bytes::Bytes; -use flowy_collaboration::entities::ws::{DocumentWSData, DocumentWSDataType}; +use flowy_collaboration::entities::ws::{DocumentWSData, DocumentWSDataType, NewDocumentUser}; use flowy_error::{internal_error, FlowyError, FlowyResult}; use futures::stream::StreamExt; use lib_infra::future::FutureResult; -use lib_ot::revision::{RevId, RevisionRange}; +use lib_ot::revision::RevisionRange; use lib_ws::WSConnectState; use std::{convert::TryFrom, sync::Arc}; use tokio::{ @@ -20,8 +20,8 @@ use tokio::{ pub(crate) struct EditorWebSocket { doc_id: String, - data_provider: Arc, - stream_consumer: Arc, + data_provider: Arc, + stream_consumer: Arc, ws: Arc, ws_msg_tx: UnboundedSender, ws_msg_rx: Option>, @@ -33,8 +33,8 @@ impl EditorWebSocket { pub(crate) fn new( doc_id: &str, ws: Arc, - data_provider: Arc, - stream_consumer: Arc, + data_provider: Arc, + stream_consumer: Arc, ) -> Self { let (ws_msg_tx, ws_msg_rx) = mpsc::unbounded_channel(); let (stop_sync_tx, _) = tokio::sync::broadcast::channel(2); @@ -97,15 +97,16 @@ impl DocumentWsHandler for EditorWebSocket { } } -pub trait DocumentWebSocketSteamConsumer: Send + Sync { +pub trait DocumentWSSteamConsumer: Send + Sync { fn receive_push_revision(&self, bytes: Bytes) -> FutureResult<(), FlowyError>; - fn receive_ack_revision(&self, rev_id: i64) -> FutureResult<(), FlowyError>; + fn receive_ack(&self, id: String, ty: DocumentWSDataType) -> FutureResult<(), FlowyError>; + fn receive_new_user_connect(&self, new_user: NewDocumentUser) -> FutureResult<(), FlowyError>; fn send_revision_in_range(&self, range: RevisionRange) -> FutureResult<(), FlowyError>; } pub(crate) struct DocumentWebSocketStream { doc_id: String, - consumer: Arc, + consumer: Arc, ws_msg_rx: Option>, stop_rx: Option, } @@ -113,7 +114,7 @@ pub(crate) struct DocumentWebSocketStream { impl DocumentWebSocketStream { pub(crate) fn new( doc_id: &str, - consumer: Arc, + consumer: Arc, ws_msg_rx: mpsc::UnboundedReceiver, stop_rx: SinkStopRx, ) -> Self { @@ -166,7 +167,7 @@ impl DocumentWebSocketStream { doc_id: _, ty, data, - id: _, + id, } = msg; let bytes = spawn_blocking(move || Bytes::from(data)) .await @@ -181,11 +182,13 @@ impl DocumentWebSocketStream { let range = RevisionRange::try_from(bytes)?; let _ = self.consumer.send_revision_in_range(range).await?; }, - DocumentWSDataType::Acked => { - let rev_id = RevId::try_from(bytes)?; - let _ = self.consumer.receive_ack_revision(rev_id.into()).await; + DocumentWSDataType::Ack => { + // let rev_id = RevId::try_from(bytes)?; + let _ = self.consumer.receive_ack(id, ty).await; }, DocumentWSDataType::UserConnect => { + let new_user = NewDocumentUser::try_from(bytes)?; + let _ = self.consumer.receive_new_user_connect(new_user).await; // Notify the user that someone has connected to this document }, } @@ -198,12 +201,12 @@ pub(crate) type Tick = (); pub(crate) type SinkStopRx = broadcast::Receiver<()>; pub(crate) type SinkStopTx = broadcast::Sender<()>; -pub trait DocumentSinkDataProvider: Send + Sync { +pub trait DocumentWSSinkDataProvider: Send + Sync { fn next(&self) -> FutureResult, FlowyError>; } pub(crate) struct DocumentWebSocketSink { - provider: Arc, + provider: Arc, ws_sender: Arc, stop_rx: Option, doc_id: String, @@ -212,7 +215,7 @@ pub(crate) struct DocumentWebSocketSink { impl DocumentWebSocketSink { pub(crate) fn new( doc_id: &str, - provider: Arc, + provider: Arc, ws_sender: Arc, stop_rx: SinkStopRx, ) -> Self { diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs index b3d12b56ae..267845f6ab 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/cache.rs @@ -1,24 +1,27 @@ use crate::{ errors::FlowyError, - services::doc::revision::{ - cache::{ - disk::{Persistence, RevisionDiskCache}, - memory::{RevisionMemoryCache, RevisionMemoryCacheDelegate}, - sync::RevisionSyncSeq, - }, - RevisionRecord, + services::doc::revision::cache::{ + disk::{Persistence, RevisionDiskCache}, + memory::{RevisionMemoryCache, RevisionMemoryCacheDelegate}, }, sql_tables::{RevChangeset, RevTableState}, }; +use dashmap::DashMap; use flowy_database::ConnectionPool; use flowy_error::{internal_error, FlowyResult}; use lib_infra::future::FutureResult; -use lib_ot::revision::{RevState, Revision, RevisionRange}; -use std::sync::{ - atomic::{AtomicI64, Ordering::SeqCst}, - Arc, +use lib_ot::{ + errors::OTError, + revision::{RevState, Revision, RevisionRange}, }; -use tokio::task::spawn_blocking; +use std::{ + collections::VecDeque, + sync::{ + atomic::{AtomicI64, Ordering::SeqCst}, + Arc, + }, +}; +use tokio::{sync::RwLock, task::spawn_blocking}; type DocRevisionDiskCache = dyn RevisionDiskCache; @@ -157,9 +160,79 @@ impl RevisionMemoryCacheDelegate for Arc { } } -#[cfg(feature = "flowy_unit_test")] -impl RevisionCache { - pub fn disk_cache(&self) -> Arc { self.disk_cache.clone() } - - pub fn memory_cache(&self) -> Arc { self.sync_seq.clone() } +#[derive(Clone)] +pub struct RevisionRecord { + pub revision: Revision, + pub state: RevState, +} + +impl RevisionRecord { + pub fn ack(&mut self) { self.state = RevState::Acked; } +} + +struct RevisionSyncSeq { + revs_map: Arc>, + local_revs: Arc>>, +} + +impl std::default::Default for RevisionSyncSeq { + fn default() -> Self { + let local_revs = Arc::new(RwLock::new(VecDeque::new())); + RevisionSyncSeq { + revs_map: Arc::new(DashMap::new()), + local_revs, + } + } +} + +impl RevisionSyncSeq { + fn new() -> Self { RevisionSyncSeq::default() } + + async fn add_revision(&self, record: RevisionRecord) -> Result<(), OTError> { + // The last revision's rev_id must be greater than the new one. + if let Some(rev_id) = self.local_revs.read().await.back() { + if *rev_id >= record.revision.rev_id { + return Err(OTError::revision_id_conflict() + .context(format!("The new revision's id must be greater than {}", rev_id))); + } + } + self.local_revs.write().await.push_back(record.revision.rev_id); + self.revs_map.insert(record.revision.rev_id, record); + Ok(()) + } + + async fn ack_revision(&self, rev_id: &i64) -> FlowyResult<()> { + if let Some(pop_rev_id) = self.next_sync_rev_id().await { + if &pop_rev_id != rev_id { + let desc = format!( + "The ack rev_id:{} is not equal to the current rev_id:{}", + rev_id, pop_rev_id + ); + // tracing::error!("{}", desc); + return Err(FlowyError::internal().context(desc)); + } + + tracing::debug!("pop revision {}", pop_rev_id); + self.revs_map.remove(&pop_rev_id); + let _ = self.local_revs.write().await.pop_front(); + } + Ok(()) + } + + async fn next_sync_revision(&self) -> Option<(i64, RevisionRecord)> { + match self.local_revs.read().await.front() { + None => None, + Some(rev_id) => self.revs_map.get(rev_id).map(|r| (*r.key(), r.value().clone())), + } + } + + async fn next_sync_rev_id(&self) -> Option { self.local_revs.read().await.front().copied() } +} + +#[cfg(feature = "flowy_unit_test")] +impl RevisionSyncSeq { + #[allow(dead_code)] + pub fn revs_map(&self) -> Arc> { self.revs_map.clone() } + #[allow(dead_code)] + pub fn pending_revs(&self) -> Arc>> { self.local_revs.clone() } } diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/mod.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/mod.rs index 916b334e4c..431c0af4c7 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/mod.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/mod.rs @@ -2,8 +2,5 @@ mod cache; mod disk; mod memory; -mod model; -mod sync; pub use cache::*; -pub use model::*; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/model.rs b/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/model.rs deleted file mode 100644 index f19b351fd9..0000000000 --- a/frontend/rust-lib/flowy-document/src/services/doc/revision/cache/model.rs +++ /dev/null @@ -1,15 +0,0 @@ -use lib_ot::revision::{RevState, Revision}; -use tokio::sync::broadcast; - -pub type RevIdReceiver = broadcast::Receiver; -pub type RevIdSender = broadcast::Sender; - -#[derive(Clone)] -pub struct RevisionRecord { - pub revision: Revision, - pub state: RevState, -} - -impl RevisionRecord { - pub fn ack(&mut self) { self.state = RevState::Acked; } -} diff --git a/frontend/rust-lib/flowy-net/src/services/mock/ws_mock.rs b/frontend/rust-lib/flowy-net/src/services/mock/ws_mock.rs index ea06008889..45b405b1f9 100644 --- a/frontend/rust-lib/flowy-net/src/services/mock/ws_mock.rs +++ b/frontend/rust-lib/flowy-net/src/services/mock/ws_mock.rs @@ -5,7 +5,7 @@ use flowy_collaboration::{ core::sync::{RevisionUser, ServerDocManager, ServerDocPersistence, SyncResponse}, entities::{ doc::Doc, - ws::{DocumentWSData, DocumentWSDataType}, + ws::{DocumentWSData, DocumentWSDataBuilder, DocumentWSDataType, NewDocumentUser}, }, errors::CollaborateError, Revision, @@ -111,7 +111,7 @@ impl MockDocServer { async fn handle_ws_data(&self, ws_data: DocumentWSData) -> mpsc::Receiver { let bytes = Bytes::from(ws_data.data); match ws_data.ty { - DocumentWSDataType::Acked => { + DocumentWSDataType::Ack => { unimplemented!() }, DocumentWSDataType::PushRev => { @@ -133,7 +133,16 @@ impl MockDocServer { unimplemented!() }, DocumentWSDataType::UserConnect => { - unimplemented!() + let new_user = NewDocumentUser::try_from(bytes).unwrap(); + let (tx, rx) = mpsc::channel(1); + let data = DocumentWSDataBuilder::build_ack_message(&new_user.doc_id, &ws_data.id); + let user = Arc::new(MockDocUser { + user_id: new_user.user_id, + tx, + }) as Arc; + + user.recv(SyncResponse::Ack(data)); + rx }, } } diff --git a/frontend/rust-lib/flowy-test/src/doc_script.rs b/frontend/rust-lib/flowy-test/src/doc_script.rs index d5cb59825a..984534a5f9 100644 --- a/frontend/rust-lib/flowy-test/src/doc_script.rs +++ b/frontend/rust-lib/flowy-test/src/doc_script.rs @@ -46,8 +46,6 @@ impl EditorTest { async fn run_script(&mut self, script: EditorScript) { let rev_manager = self.editor.rev_manager(); let cache = rev_manager.revision_cache(); - let _memory_cache = cache.memory_cache(); - let _disk_cache = cache.disk_cache(); let doc_id = self.editor.doc_id.clone(); let _user_id = self.sdk.user_session.user_id().unwrap(); let ws_manager = self.sdk.ws_manager.clone(); diff --git a/shared-lib/flowy-collaboration/src/core/sync/synchronizer.rs b/shared-lib/flowy-collaboration/src/core/sync/synchronizer.rs index 3c01cb3a22..8593fb1c90 100644 --- a/shared-lib/flowy-collaboration/src/core/sync/synchronizer.rs +++ b/shared-lib/flowy-collaboration/src/core/sync/synchronizer.rs @@ -1,6 +1,6 @@ use crate::{ core::document::Document, - entities::ws::{DocumentWSData, WsDocumentDataBuilder}, + entities::ws::{DocumentWSData, DocumentWSDataBuilder}, }; use lib_ot::{ core::OperationTransformable, @@ -59,9 +59,9 @@ impl RevisionSynchronizer { if server_base_rev_id == revision.base_rev_id || server_rev_id == revision.rev_id { // The rev is in the right order, just compose it. let _ = self.compose_revision(&revision)?; - user.recv(SyncResponse::Ack(WsDocumentDataBuilder::build_acked_message( + user.recv(SyncResponse::Ack(DocumentWSDataBuilder::build_ack_message( &revision.doc_id, - revision.rev_id, + &revision.rev_id.to_string(), ))); let rev_id = revision.rev_id; let doc_id = self.doc_id.clone(); @@ -78,14 +78,14 @@ impl RevisionSynchronizer { start: server_rev_id, end: revision.rev_id, }; - let msg = WsDocumentDataBuilder::build_push_pull_message(&self.doc_id, range); + let msg = DocumentWSDataBuilder::build_push_pull_message(&self.doc_id, range); user.recv(SyncResponse::Pull(msg)); } }, Ordering::Equal => { // Do nothing log::warn!("Applied revision rev_id is the same as cur_rev_id"); - let data = WsDocumentDataBuilder::build_acked_message(&revision.doc_id, revision.rev_id); + let data = DocumentWSDataBuilder::build_ack_message(&revision.doc_id, &revision.rev_id.to_string()); user.recv(SyncResponse::Ack(data)); }, Ordering::Greater => { @@ -93,7 +93,7 @@ impl RevisionSynchronizer { // send the prime delta to the client. Client should compose the this prime // delta. let cli_revision = self.transform_revision(&revision)?; - let data = WsDocumentDataBuilder::build_push_rev_message(&self.doc_id, cli_revision); + let data = DocumentWSDataBuilder::build_push_rev_message(&self.doc_id, cli_revision); user.recv(SyncResponse::Push(data)); }, } diff --git a/shared-lib/flowy-collaboration/src/entities/ws/ws.rs b/shared-lib/flowy-collaboration/src/entities/ws/ws.rs index 818a07cbf3..edbfd11ba1 100644 --- a/shared-lib/flowy-collaboration/src/entities/ws/ws.rs +++ b/shared-lib/flowy-collaboration/src/entities/ws/ws.rs @@ -1,13 +1,14 @@ use crate::errors::CollaborateError; use bytes::Bytes; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; -use lib_ot::revision::{RevId, Revision, RevisionRange}; +use lib_infra::uuid; +use lib_ot::revision::{Revision, RevisionRange}; use std::convert::{TryFrom, TryInto}; #[derive(Debug, Clone, ProtoBuf_Enum, Eq, PartialEq, Hash)] pub enum DocumentWSDataType { // The frontend receives the Acked means the backend has accepted the revision - Acked = 0, + Ack = 0, // The frontend receives the PushRev event means the backend is pushing the new revision to frontend PushRev = 1, // The fronted receives the PullRev event means the backend try to pull the revision from frontend @@ -25,7 +26,7 @@ impl DocumentWSDataType { } impl std::default::Default for DocumentWSDataType { - fn default() -> Self { DocumentWSDataType::Acked } + fn default() -> Self { DocumentWSDataType::Ack } } #[derive(ProtoBuf, Default, Debug, Clone)] @@ -39,8 +40,8 @@ pub struct DocumentWSData { #[pb(index = 3)] pub data: Vec, - #[pb(index = 4, one_of)] - pub id: Option, + #[pb(index = 4)] + pub id: String, } impl std::convert::From for DocumentWSData { @@ -52,13 +53,13 @@ impl std::convert::From for DocumentWSData { doc_id, ty: DocumentWSDataType::PushRev, data: bytes.to_vec(), - id: Some(rev_id), + id: rev_id.to_string(), } } } -pub struct WsDocumentDataBuilder(); -impl WsDocumentDataBuilder { +pub struct DocumentWSDataBuilder(); +impl DocumentWSDataBuilder { // DocumentWSDataType::PushRev -> Revision pub fn build_push_rev_message(doc_id: &str, revision: Revision) -> DocumentWSData { let rev_id = revision.rev_id; @@ -67,7 +68,7 @@ impl WsDocumentDataBuilder { doc_id: doc_id.to_string(), ty: DocumentWSDataType::PushRev, data: bytes.to_vec(), - id: Some(rev_id), + id: rev_id.to_string(), } } @@ -78,39 +79,35 @@ impl WsDocumentDataBuilder { doc_id: doc_id.to_string(), ty: DocumentWSDataType::PullRev, data: bytes.to_vec(), - id: None, + id: uuid(), } } - // DocumentWSDataType::Acked -> RevId - pub fn build_acked_message(doc_id: &str, rev_id: i64) -> DocumentWSData { - let cloned_rev_id = rev_id; - let rev_id: RevId = rev_id.into(); - let bytes: Bytes = rev_id.try_into().unwrap(); - + // DocumentWSDataType::Ack -> RevId + pub fn build_ack_message(doc_id: &str, id: &str) -> DocumentWSData { DocumentWSData { doc_id: doc_id.to_string(), - ty: DocumentWSDataType::Acked, - data: bytes.to_vec(), - id: Some(cloned_rev_id), + ty: DocumentWSDataType::Ack, + data: vec![], + id: id.to_string(), } } // DocumentWSDataType::UserConnect -> DocumentConnected - pub fn build_document_conn_message(doc_id: &str, document_conn: DocumentConnected) -> DocumentWSData { - let rev_id = document_conn.rev_id; - let bytes: Bytes = document_conn.try_into().unwrap(); + pub fn build_new_document_user_message(doc_id: &str, new_document_user: NewDocumentUser) -> DocumentWSData { + let id = new_document_user.user_id.clone(); + let bytes: Bytes = new_document_user.try_into().unwrap(); DocumentWSData { doc_id: doc_id.to_string(), ty: DocumentWSDataType::UserConnect, data: bytes.to_vec(), - id: Some(rev_id), + id, } } } #[derive(ProtoBuf, Default, Debug, Clone)] -pub struct DocumentConnected { +pub struct NewDocumentUser { #[pb(index = 1)] pub user_id: String, diff --git a/shared-lib/flowy-collaboration/src/protobuf/model/ws.rs b/shared-lib/flowy-collaboration/src/protobuf/model/ws.rs index 703c6b305f..878b20fb0e 100644 --- a/shared-lib/flowy-collaboration/src/protobuf/model/ws.rs +++ b/shared-lib/flowy-collaboration/src/protobuf/model/ws.rs @@ -29,8 +29,7 @@ pub struct DocumentWSData { pub doc_id: ::std::string::String, pub ty: DocumentWSDataType, pub data: ::std::vec::Vec, - // message oneof groups - pub one_of_id: ::std::option::Option, + pub id: ::std::string::String, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, @@ -42,11 +41,6 @@ impl<'a> ::std::default::Default for &'a DocumentWSData { } } -#[derive(Clone,PartialEq,Debug)] -pub enum DocumentWSData_oneof_one_of_id { - id(i64), -} - impl DocumentWSData { pub fn new() -> DocumentWSData { ::std::default::Default::default() @@ -85,7 +79,7 @@ impl DocumentWSData { self.ty } pub fn clear_ty(&mut self) { - self.ty = DocumentWSDataType::Acked; + self.ty = DocumentWSDataType::Ack; } // Param is passed by value, moved @@ -119,29 +113,30 @@ impl DocumentWSData { ::std::mem::replace(&mut self.data, ::std::vec::Vec::new()) } - // int64 id = 4; + // string id = 4; - pub fn get_id(&self) -> i64 { - match self.one_of_id { - ::std::option::Option::Some(DocumentWSData_oneof_one_of_id::id(v)) => v, - _ => 0, - } + pub fn get_id(&self) -> &str { + &self.id } pub fn clear_id(&mut self) { - self.one_of_id = ::std::option::Option::None; - } - - pub fn has_id(&self) -> bool { - match self.one_of_id { - ::std::option::Option::Some(DocumentWSData_oneof_one_of_id::id(..)) => true, - _ => false, - } + self.id.clear(); } // Param is passed by value, moved - pub fn set_id(&mut self, v: i64) { - self.one_of_id = ::std::option::Option::Some(DocumentWSData_oneof_one_of_id::id(v)) + pub fn set_id(&mut self, v: ::std::string::String) { + self.id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_id(&mut self) -> &mut ::std::string::String { + &mut self.id + } + + // Take field + pub fn take_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.id, ::std::string::String::new()) } } @@ -164,10 +159,7 @@ impl ::protobuf::Message for DocumentWSData { ::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.data)?; }, 4 => { - if wire_type != ::protobuf::wire_format::WireTypeVarint { - return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); - } - self.one_of_id = ::std::option::Option::Some(DocumentWSData_oneof_one_of_id::id(is.read_int64()?)); + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.id)?; }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; @@ -184,18 +176,14 @@ impl ::protobuf::Message for DocumentWSData { if !self.doc_id.is_empty() { my_size += ::protobuf::rt::string_size(1, &self.doc_id); } - if self.ty != DocumentWSDataType::Acked { + if self.ty != DocumentWSDataType::Ack { my_size += ::protobuf::rt::enum_size(2, self.ty); } if !self.data.is_empty() { my_size += ::protobuf::rt::bytes_size(3, &self.data); } - if let ::std::option::Option::Some(ref v) = self.one_of_id { - match v { - &DocumentWSData_oneof_one_of_id::id(v) => { - my_size += ::protobuf::rt::value_size(4, v, ::protobuf::wire_format::WireTypeVarint); - }, - }; + if !self.id.is_empty() { + my_size += ::protobuf::rt::string_size(4, &self.id); } my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); self.cached_size.set(my_size); @@ -206,18 +194,14 @@ impl ::protobuf::Message for DocumentWSData { if !self.doc_id.is_empty() { os.write_string(1, &self.doc_id)?; } - if self.ty != DocumentWSDataType::Acked { + if self.ty != DocumentWSDataType::Ack { os.write_enum(2, ::protobuf::ProtobufEnum::value(&self.ty))?; } if !self.data.is_empty() { os.write_bytes(3, &self.data)?; } - if let ::std::option::Option::Some(ref v) = self.one_of_id { - match v { - &DocumentWSData_oneof_one_of_id::id(v) => { - os.write_int64(4, v)?; - }, - }; + if !self.id.is_empty() { + os.write_string(4, &self.id)?; } os.write_unknown_fields(self.get_unknown_fields())?; ::std::result::Result::Ok(()) @@ -272,10 +256,10 @@ impl ::protobuf::Message for DocumentWSData { |m: &DocumentWSData| { &m.data }, |m: &mut DocumentWSData| { &mut m.data }, )); - fields.push(::protobuf::reflect::accessor::make_singular_i64_accessor::<_>( + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "id", - DocumentWSData::has_id, - DocumentWSData::get_id, + |m: &DocumentWSData| { &m.id }, + |m: &mut DocumentWSData| { &mut m.id }, )); ::protobuf::reflect::MessageDescriptor::new_pb_name::( "DocumentWSData", @@ -294,9 +278,9 @@ impl ::protobuf::Message for DocumentWSData { impl ::protobuf::Clear for DocumentWSData { fn clear(&mut self) { self.doc_id.clear(); - self.ty = DocumentWSDataType::Acked; + self.ty = DocumentWSDataType::Ack; self.data.clear(); - self.one_of_id = ::std::option::Option::None; + self.id.clear(); self.unknown_fields.clear(); } } @@ -314,7 +298,7 @@ impl ::protobuf::reflect::ProtobufValue for DocumentWSData { } #[derive(PartialEq,Clone,Default)] -pub struct DocumentConnected { +pub struct NewDocumentUser { // message fields pub user_id: ::std::string::String, pub doc_id: ::std::string::String, @@ -324,14 +308,14 @@ pub struct DocumentConnected { pub cached_size: ::protobuf::CachedSize, } -impl<'a> ::std::default::Default for &'a DocumentConnected { - fn default() -> &'a DocumentConnected { - ::default_instance() +impl<'a> ::std::default::Default for &'a NewDocumentUser { + fn default() -> &'a NewDocumentUser { + ::default_instance() } } -impl DocumentConnected { - pub fn new() -> DocumentConnected { +impl NewDocumentUser { + pub fn new() -> NewDocumentUser { ::std::default::Default::default() } @@ -403,7 +387,7 @@ impl DocumentConnected { } } -impl ::protobuf::Message for DocumentConnected { +impl ::protobuf::Message for NewDocumentUser { fn is_initialized(&self) -> bool { true } @@ -491,8 +475,8 @@ impl ::protobuf::Message for DocumentConnected { Self::descriptor_static() } - fn new() -> DocumentConnected { - DocumentConnected::new() + fn new() -> NewDocumentUser { + NewDocumentUser::new() } fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { @@ -501,34 +485,34 @@ impl ::protobuf::Message for DocumentConnected { let mut fields = ::std::vec::Vec::new(); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "user_id", - |m: &DocumentConnected| { &m.user_id }, - |m: &mut DocumentConnected| { &mut m.user_id }, + |m: &NewDocumentUser| { &m.user_id }, + |m: &mut NewDocumentUser| { &mut m.user_id }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "doc_id", - |m: &DocumentConnected| { &m.doc_id }, - |m: &mut DocumentConnected| { &mut m.doc_id }, + |m: &NewDocumentUser| { &m.doc_id }, + |m: &mut NewDocumentUser| { &mut m.doc_id }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeInt64>( "rev_id", - |m: &DocumentConnected| { &m.rev_id }, - |m: &mut DocumentConnected| { &mut m.rev_id }, + |m: &NewDocumentUser| { &m.rev_id }, + |m: &mut NewDocumentUser| { &mut m.rev_id }, )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "DocumentConnected", + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "NewDocumentUser", fields, file_descriptor_proto() ) }) } - fn default_instance() -> &'static DocumentConnected { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(DocumentConnected::new) + fn default_instance() -> &'static NewDocumentUser { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(NewDocumentUser::new) } } -impl ::protobuf::Clear for DocumentConnected { +impl ::protobuf::Clear for NewDocumentUser { fn clear(&mut self) { self.user_id.clear(); self.doc_id.clear(); @@ -537,13 +521,13 @@ impl ::protobuf::Clear for DocumentConnected { } } -impl ::std::fmt::Debug for DocumentConnected { +impl ::std::fmt::Debug for NewDocumentUser { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { ::protobuf::text_format::fmt(self, f) } } -impl ::protobuf::reflect::ProtobufValue for DocumentConnected { +impl ::protobuf::reflect::ProtobufValue for NewDocumentUser { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { ::protobuf::reflect::ReflectValueRef::Message(self) } @@ -551,7 +535,7 @@ impl ::protobuf::reflect::ProtobufValue for DocumentConnected { #[derive(Clone,PartialEq,Eq,Debug,Hash)] pub enum DocumentWSDataType { - Acked = 0, + Ack = 0, PushRev = 1, PullRev = 2, UserConnect = 3, @@ -564,7 +548,7 @@ impl ::protobuf::ProtobufEnum for DocumentWSDataType { fn from_i32(value: i32) -> ::std::option::Option { match value { - 0 => ::std::option::Option::Some(DocumentWSDataType::Acked), + 0 => ::std::option::Option::Some(DocumentWSDataType::Ack), 1 => ::std::option::Option::Some(DocumentWSDataType::PushRev), 2 => ::std::option::Option::Some(DocumentWSDataType::PullRev), 3 => ::std::option::Option::Some(DocumentWSDataType::UserConnect), @@ -574,7 +558,7 @@ impl ::protobuf::ProtobufEnum for DocumentWSDataType { fn values() -> &'static [Self] { static values: &'static [DocumentWSDataType] = &[ - DocumentWSDataType::Acked, + DocumentWSDataType::Ack, DocumentWSDataType::PushRev, DocumentWSDataType::PullRev, DocumentWSDataType::UserConnect, @@ -595,7 +579,7 @@ impl ::std::marker::Copy for DocumentWSDataType { impl ::std::default::Default for DocumentWSDataType { fn default() -> Self { - DocumentWSDataType::Acked + DocumentWSDataType::Ack } } @@ -606,47 +590,46 @@ impl ::protobuf::reflect::ProtobufValue for DocumentWSDataType { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x08ws.proto\"\x7f\n\x0eDocumentWSData\x12\x15\n\x06doc_id\x18\x01\x20\ + \n\x08ws.proto\"p\n\x0eDocumentWSData\x12\x15\n\x06doc_id\x18\x01\x20\ \x01(\tR\x05docId\x12#\n\x02ty\x18\x02\x20\x01(\x0e2\x13.DocumentWSDataT\ - ypeR\x02ty\x12\x12\n\x04data\x18\x03\x20\x01(\x0cR\x04data\x12\x10\n\x02\ - id\x18\x04\x20\x01(\x03H\0R\x02idB\x0b\n\tone_of_id\"Z\n\x11DocumentConn\ - ected\x12\x17\n\x07user_id\x18\x01\x20\x01(\tR\x06userId\x12\x15\n\x06do\ - c_id\x18\x02\x20\x01(\tR\x05docId\x12\x15\n\x06rev_id\x18\x03\x20\x01(\ - \x03R\x05revId*J\n\x12DocumentWSDataType\x12\t\n\x05Acked\x10\0\x12\x0b\ - \n\x07PushRev\x10\x01\x12\x0b\n\x07PullRev\x10\x02\x12\x0f\n\x0bUserConn\ - ect\x10\x03J\x9a\x05\n\x06\x12\x04\0\0\x12\x01\n\x08\n\x01\x0c\x12\x03\0\ - \0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x07\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\x16\n\x0c\n\x05\x04\ - \0\x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\ - \x0b\x11\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x14\x15\n\x0b\n\x04\x04\ - \0\x02\x01\x12\x03\x04\x04\x1e\n\x0c\n\x05\x04\0\x02\x01\x06\x12\x03\x04\ - \x04\x16\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\x17\x19\n\x0c\n\x05\ - \x04\0\x02\x01\x03\x12\x03\x04\x1c\x1d\n\x0b\n\x04\x04\0\x02\x02\x12\x03\ - \x05\x04\x13\n\x0c\n\x05\x04\0\x02\x02\x05\x12\x03\x05\x04\t\n\x0c\n\x05\ - \x04\0\x02\x02\x01\x12\x03\x05\n\x0e\n\x0c\n\x05\x04\0\x02\x02\x03\x12\ - \x03\x05\x11\x12\n\x0b\n\x04\x04\0\x08\0\x12\x03\x06\x04%\n\x0c\n\x05\ - \x04\0\x08\0\x01\x12\x03\x06\n\x13\n\x0b\n\x04\x04\0\x02\x03\x12\x03\x06\ - \x16#\n\x0c\n\x05\x04\0\x02\x03\x05\x12\x03\x06\x16\x1b\n\x0c\n\x05\x04\ - \0\x02\x03\x01\x12\x03\x06\x1c\x1e\n\x0c\n\x05\x04\0\x02\x03\x03\x12\x03\ - \x06!\"\n\n\n\x02\x04\x01\x12\x04\x08\0\x0c\x01\n\n\n\x03\x04\x01\x01\ - \x12\x03\x08\x08\x19\n\x0b\n\x04\x04\x01\x02\0\x12\x03\t\x04\x17\n\x0c\n\ - \x05\x04\x01\x02\0\x05\x12\x03\t\x04\n\n\x0c\n\x05\x04\x01\x02\0\x01\x12\ - \x03\t\x0b\x12\n\x0c\n\x05\x04\x01\x02\0\x03\x12\x03\t\x15\x16\n\x0b\n\ - \x04\x04\x01\x02\x01\x12\x03\n\x04\x16\n\x0c\n\x05\x04\x01\x02\x01\x05\ - \x12\x03\n\x04\n\n\x0c\n\x05\x04\x01\x02\x01\x01\x12\x03\n\x0b\x11\n\x0c\ - \n\x05\x04\x01\x02\x01\x03\x12\x03\n\x14\x15\n\x0b\n\x04\x04\x01\x02\x02\ - \x12\x03\x0b\x04\x15\n\x0c\n\x05\x04\x01\x02\x02\x05\x12\x03\x0b\x04\t\n\ - \x0c\n\x05\x04\x01\x02\x02\x01\x12\x03\x0b\n\x10\n\x0c\n\x05\x04\x01\x02\ - \x02\x03\x12\x03\x0b\x13\x14\n\n\n\x02\x05\0\x12\x04\r\0\x12\x01\n\n\n\ - \x03\x05\0\x01\x12\x03\r\x05\x17\n\x0b\n\x04\x05\0\x02\0\x12\x03\x0e\x04\ - \x0e\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\x0e\x04\t\n\x0c\n\x05\x05\0\x02\ - \0\x02\x12\x03\x0e\x0c\r\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x0f\x04\x10\n\ - \x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x0f\x04\x0b\n\x0c\n\x05\x05\0\x02\ - \x01\x02\x12\x03\x0f\x0e\x0f\n\x0b\n\x04\x05\0\x02\x02\x12\x03\x10\x04\ - \x10\n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\x10\x04\x0b\n\x0c\n\x05\x05\0\ - \x02\x02\x02\x12\x03\x10\x0e\x0f\n\x0b\n\x04\x05\0\x02\x03\x12\x03\x11\ - \x04\x14\n\x0c\n\x05\x05\0\x02\x03\x01\x12\x03\x11\x04\x0f\n\x0c\n\x05\ - \x05\0\x02\x03\x02\x12\x03\x11\x12\x13b\x06proto3\ + ypeR\x02ty\x12\x12\n\x04data\x18\x03\x20\x01(\x0cR\x04data\x12\x0e\n\x02\ + id\x18\x04\x20\x01(\tR\x02id\"X\n\x0fNewDocumentUser\x12\x17\n\x07user_i\ + d\x18\x01\x20\x01(\tR\x06userId\x12\x15\n\x06doc_id\x18\x02\x20\x01(\tR\ + \x05docId\x12\x15\n\x06rev_id\x18\x03\x20\x01(\x03R\x05revId*H\n\x12Docu\ + mentWSDataType\x12\x07\n\x03Ack\x10\0\x12\x0b\n\x07PushRev\x10\x01\x12\ + \x0b\n\x07PullRev\x10\x02\x12\x0f\n\x0bUserConnect\x10\x03J\xff\x04\n\ + \x06\x12\x04\0\0\x12\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\ + \x12\x04\x02\0\x07\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\x16\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\ + \x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\x0b\x11\n\x0c\n\x05\ + \x04\0\x02\0\x03\x12\x03\x03\x14\x15\n\x0b\n\x04\x04\0\x02\x01\x12\x03\ + \x04\x04\x1e\n\x0c\n\x05\x04\0\x02\x01\x06\x12\x03\x04\x04\x16\n\x0c\n\ + \x05\x04\0\x02\x01\x01\x12\x03\x04\x17\x19\n\x0c\n\x05\x04\0\x02\x01\x03\ + \x12\x03\x04\x1c\x1d\n\x0b\n\x04\x04\0\x02\x02\x12\x03\x05\x04\x13\n\x0c\ + \n\x05\x04\0\x02\x02\x05\x12\x03\x05\x04\t\n\x0c\n\x05\x04\0\x02\x02\x01\ + \x12\x03\x05\n\x0e\n\x0c\n\x05\x04\0\x02\x02\x03\x12\x03\x05\x11\x12\n\ + \x0b\n\x04\x04\0\x02\x03\x12\x03\x06\x04\x12\n\x0c\n\x05\x04\0\x02\x03\ + \x05\x12\x03\x06\x04\n\n\x0c\n\x05\x04\0\x02\x03\x01\x12\x03\x06\x0b\r\n\ + \x0c\n\x05\x04\0\x02\x03\x03\x12\x03\x06\x10\x11\n\n\n\x02\x04\x01\x12\ + \x04\x08\0\x0c\x01\n\n\n\x03\x04\x01\x01\x12\x03\x08\x08\x17\n\x0b\n\x04\ + \x04\x01\x02\0\x12\x03\t\x04\x17\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03\t\ + \x04\n\n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03\t\x0b\x12\n\x0c\n\x05\x04\ + \x01\x02\0\x03\x12\x03\t\x15\x16\n\x0b\n\x04\x04\x01\x02\x01\x12\x03\n\ + \x04\x16\n\x0c\n\x05\x04\x01\x02\x01\x05\x12\x03\n\x04\n\n\x0c\n\x05\x04\ + \x01\x02\x01\x01\x12\x03\n\x0b\x11\n\x0c\n\x05\x04\x01\x02\x01\x03\x12\ + \x03\n\x14\x15\n\x0b\n\x04\x04\x01\x02\x02\x12\x03\x0b\x04\x15\n\x0c\n\ + \x05\x04\x01\x02\x02\x05\x12\x03\x0b\x04\t\n\x0c\n\x05\x04\x01\x02\x02\ + \x01\x12\x03\x0b\n\x10\n\x0c\n\x05\x04\x01\x02\x02\x03\x12\x03\x0b\x13\ + \x14\n\n\n\x02\x05\0\x12\x04\r\0\x12\x01\n\n\n\x03\x05\0\x01\x12\x03\r\ + \x05\x17\n\x0b\n\x04\x05\0\x02\0\x12\x03\x0e\x04\x0c\n\x0c\n\x05\x05\0\ + \x02\0\x01\x12\x03\x0e\x04\x07\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x0e\n\ + \x0b\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x0f\x04\x10\n\x0c\n\x05\x05\0\x02\ + \x01\x01\x12\x03\x0f\x04\x0b\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x0f\ + \x0e\x0f\n\x0b\n\x04\x05\0\x02\x02\x12\x03\x10\x04\x10\n\x0c\n\x05\x05\0\ + \x02\x02\x01\x12\x03\x10\x04\x0b\n\x0c\n\x05\x05\0\x02\x02\x02\x12\x03\ + \x10\x0e\x0f\n\x0b\n\x04\x05\0\x02\x03\x12\x03\x11\x04\x14\n\x0c\n\x05\ + \x05\0\x02\x03\x01\x12\x03\x11\x04\x0f\n\x0c\n\x05\x05\0\x02\x03\x02\x12\ + \x03\x11\x12\x13b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/shared-lib/flowy-collaboration/src/protobuf/proto/ws.proto b/shared-lib/flowy-collaboration/src/protobuf/proto/ws.proto index 9d0517d576..9101964b8a 100644 --- a/shared-lib/flowy-collaboration/src/protobuf/proto/ws.proto +++ b/shared-lib/flowy-collaboration/src/protobuf/proto/ws.proto @@ -4,15 +4,15 @@ message DocumentWSData { string doc_id = 1; DocumentWSDataType ty = 2; bytes data = 3; - oneof one_of_id { int64 id = 4; }; + string id = 4; } -message DocumentConnected { +message NewDocumentUser { string user_id = 1; string doc_id = 2; int64 rev_id = 3; } enum DocumentWSDataType { - Acked = 0; + Ack = 0; PushRev = 1; PullRev = 2; UserConnect = 3; diff --git a/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs b/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs index 21677dfc6d..f37c5353c4 100644 --- a/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs +++ b/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs @@ -61,7 +61,7 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { | "NewDocUser" | "DocIdentifier" | "DocumentWSData" - | "DocumentConnected" + | "NewDocumentUser" | "WSError" | "WSMessage" | "Revision" diff --git a/shared-lib/lib-ws/src/msg.rs b/shared-lib/lib-ws/src/msg.rs index dc61309e26..bc5f53f697 100644 --- a/shared-lib/lib-ws/src/msg.rs +++ b/shared-lib/lib-ws/src/msg.rs @@ -3,7 +3,6 @@ use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use std::convert::TryInto; use tokio_tungstenite::tungstenite::Message as TokioMessage; -// Opti: using four bytes of the data to represent the source #[derive(ProtoBuf, Debug, Clone, Default)] pub struct WSMessage { #[pb(index = 1)] From 936e1336247941eb80b5eaa051a70ab5e42e8288 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 19 Dec 2021 21:29:33 +0800 Subject: [PATCH 36/39] rename crates --- backend/Cargo.lock | 16 ++++---- backend/Cargo.toml | 4 +- backend/src/entities/workspace.rs | 2 +- backend/src/services/app/app.rs | 2 +- backend/src/services/app/router.rs | 4 +- backend/src/services/app/sql_builder.rs | 2 +- backend/src/services/trash/router.rs | 2 +- backend/src/services/trash/trash.rs | 2 +- backend/src/services/user/auth.rs | 2 +- backend/src/services/user/router.rs | 2 +- backend/src/services/user/user_default.rs | 4 +- backend/src/services/view/router.rs | 2 +- backend/src/services/view/sql_builder.rs | 2 +- backend/src/services/view/view.rs | 2 +- backend/src/services/workspace/router.rs | 2 +- backend/src/services/workspace/sql_builder.rs | 2 +- backend/src/services/workspace/workspace.rs | 2 +- backend/tests/api/auth.rs | 2 +- backend/tests/api/doc.rs | 2 +- backend/tests/api/workspace.rs | 2 +- backend/tests/util/helper.rs | 4 +- .../ios/Runner.xcodeproj/project.pbxproj | 4 +- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- .../lib/user/application/sign_in_bloc.dart | 2 +- .../lib/user/application/sign_up_bloc.dart | 2 +- .../app_flowy/lib/user/domain/auth_state.dart | 2 +- .../app_flowy/lib/user/domain/i_auth.dart | 4 +- .../app_flowy/lib/user/domain/i_splash.dart | 4 +- .../lib/user/infrastructure/i_auth_impl.dart | 4 +- .../user/infrastructure/i_splash_impl.dart | 4 +- .../user/infrastructure/repos/auth_repo.dart | 2 +- .../lib/user/presentation/sign_in_screen.dart | 2 +- .../lib/user/presentation/sign_up_screen.dart | 2 +- .../user/presentation/skip_log_in_screen.dart | 2 +- .../lib/user/presentation/splash_screen.dart | 2 +- .../lib/user/presentation/welcome_screen.dart | 2 +- .../workspace/application/app/app_bloc.dart | 4 +- .../workspace/application/doc/doc_bloc.dart | 4 +- .../workspace/application/doc/share_bloc.dart | 4 +- .../application/home/home_listen_bloc.dart | 2 +- .../workspace/application/menu/menu_bloc.dart | 2 +- .../application/menu/menu_user_bloc.dart | 2 +- .../application/trash/trash_bloc.dart | 2 +- .../workspace/application/view/view_bloc.dart | 2 +- .../application/workspace/welcome_bloc.dart | 2 +- .../app_flowy/lib/workspace/domain/i_app.dart | 2 +- .../lib/workspace/domain/i_share.dart | 2 +- .../lib/workspace/domain/i_trash.dart | 2 +- .../lib/workspace/domain/i_user.dart | 6 +-- .../lib/workspace/domain/i_view.dart | 2 +- .../lib/workspace/domain/i_workspace.dart | 2 +- .../app_flowy/lib/workspace/domain/image.dart | 2 +- .../lib/workspace/domain/view_ext.dart | 2 +- .../infrastructure/deps_resolver.dart | 6 +-- .../workspace/infrastructure/i_app_impl.dart | 2 +- .../infrastructure/i_share_impl.dart | 2 +- .../infrastructure/i_trash_impl.dart | 2 +- .../workspace/infrastructure/i_user_impl.dart | 4 +- .../workspace/infrastructure/i_view_impl.dart | 2 +- .../infrastructure/i_workspace_impl.dart | 2 +- .../infrastructure/repos/app_repo.dart | 8 ++-- .../infrastructure/repos/doc_repo.dart | 2 +- .../infrastructure/repos/share_repo.dart | 2 +- .../infrastructure/repos/trash_repo.dart | 2 +- .../infrastructure/repos/user_repo.dart | 4 +- .../infrastructure/repos/view_repo.dart | 6 +-- .../infrastructure/repos/workspace_repo.dart | 8 ++-- .../presentation/home/home_screen.dart | 4 +- .../presentation/stack_page/doc/doc_page.dart | 2 +- .../stack_page/doc/doc_stack_page.dart | 4 +- .../stack_page/trash/widget/trash_cell.dart | 2 +- .../presentation/widgets/home_top_bar.dart | 4 +- .../presentation/widgets/menu/menu.dart | 6 +-- .../menu/widget/app/header/add_button.dart | 2 +- .../menu/widget/app/header/header.dart | 2 +- .../widgets/menu/widget/app/menu_app.dart | 4 +- .../widgets/menu/widget/app/section/item.dart | 2 +- .../menu/widget/app/section/section.dart | 2 +- .../widgets/menu/widget/menu_user.dart | 2 +- .../flowy_sdk/lib/dispatch/dispatch.dart | 4 +- .../app_create.pb.dart | 0 .../app_create.pbenum.dart | 0 .../app_create.pbjson.dart | 0 .../app_create.pbserver.dart | 0 .../app_query.pb.dart | 0 .../app_query.pbenum.dart | 0 .../app_query.pbjson.dart | 0 .../app_query.pbserver.dart | 0 .../app_update.pb.dart | 0 .../app_update.pbenum.dart | 0 .../app_update.pbjson.dart | 0 .../app_update.pbserver.dart | 0 .../errors.pb.dart | 0 .../errors.pbenum.dart | 0 .../errors.pbjson.dart | 0 .../errors.pbserver.dart | 0 .../export.pb.dart | 0 .../export.pbenum.dart | 0 .../export.pbjson.dart | 0 .../export.pbserver.dart | 0 .../protobuf.dart | 0 .../trash_create.pb.dart | 0 .../trash_create.pbenum.dart | 0 .../trash_create.pbjson.dart | 0 .../trash_create.pbserver.dart | 0 .../view_create.pb.dart | 0 .../view_create.pbenum.dart | 0 .../view_create.pbjson.dart | 0 .../view_create.pbserver.dart | 0 .../view_query.pb.dart | 0 .../view_query.pbenum.dart | 0 .../view_query.pbjson.dart | 0 .../view_query.pbserver.dart | 0 .../view_update.pb.dart | 0 .../view_update.pbenum.dart | 0 .../view_update.pbjson.dart | 0 .../view_update.pbserver.dart | 0 .../workspace_create.pb.dart | 0 .../workspace_create.pbenum.dart | 0 .../workspace_create.pbjson.dart | 0 .../workspace_create.pbserver.dart | 0 .../workspace_query.pb.dart | 0 .../workspace_query.pbenum.dart | 0 .../workspace_query.pbjson.dart | 0 .../workspace_query.pbserver.dart | 0 .../workspace_setting.pb.dart | 0 .../workspace_setting.pbenum.dart | 0 .../workspace_setting.pbjson.dart | 0 .../workspace_setting.pbserver.dart | 0 .../workspace_update.pb.dart | 0 .../workspace_update.pbenum.dart | 0 .../workspace_update.pbjson.dart | 0 .../workspace_update.pbserver.dart | 0 .../auth.pb.dart | 0 .../auth.pbenum.dart | 0 .../auth.pbjson.dart | 0 .../auth.pbserver.dart | 0 .../errors.pb.dart | 0 .../errors.pbenum.dart | 0 .../errors.pbjson.dart | 0 .../errors.pbserver.dart | 0 .../protobuf.dart | 0 .../user_profile.pb.dart | 0 .../user_profile.pbenum.dart | 0 .../user_profile.pbjson.dart | 0 .../user_profile.pbserver.dart | 0 frontend/rust-lib/flowy-core/Cargo.toml | 2 +- .../core/aggregate_tasks/workspace_task.rs | 2 +- .../flowy-core/src/core/core_context.rs | 2 +- .../flowy-core/src/core/event_handler.rs | 2 +- frontend/rust-lib/flowy-core/src/lib.rs | 4 +- .../src/services/view/controller.rs | 2 +- .../src/services/view/event_handler.rs | 2 +- .../src/services/workspace/controller.rs | 2 +- .../src/services/workspace/event_handler.rs | 2 +- frontend/rust-lib/flowy-user/Cargo.toml | 2 +- .../rust-lib/flowy-user/src/entities/mod.rs | 2 +- .../src/services/server/server_api.rs | 2 +- .../src/services/user/user_session.rs | 2 +- .../flowy-user/src/sql_tables/user.rs | 2 +- shared-lib/Cargo.lock | 8 ++-- shared-lib/Cargo.toml | 4 +- shared-lib/backend-service/Cargo.toml | 4 +- .../backend-service/src/user_request.rs | 2 +- .../backend-service/src/workspace_request.rs | 2 +- .../Cargo.toml | 2 +- .../Flowy.toml | 0 .../src/entities/app/app_create.rs | 0 .../src/entities/app/app_query.rs | 0 .../src/entities/app/app_update.rs | 0 .../src/entities/app/mod.rs | 0 .../src/entities/mod.rs | 0 .../src/entities/share/export.rs | 0 .../src/entities/share/mod.rs | 0 .../src/entities/trash/mod.rs | 0 .../src/entities/trash/trash_create.rs | 0 .../src/entities/view/mod.rs | 0 .../src/entities/view/view_create.rs | 0 .../src/entities/view/view_query.rs | 0 .../src/entities/view/view_update.rs | 0 .../src/entities/workspace/mod.rs | 0 .../entities/workspace/workspace_create.rs | 0 .../src/entities/workspace/workspace_query.rs | 0 .../entities/workspace/workspace_setting.rs | 0 .../entities/workspace/workspace_update.rs | 0 .../src/lib.rs | 0 .../src/macros.rs | 0 .../src/parser/app/app_color_style.rs | 0 .../src/parser/app/app_desc.rs | 0 .../src/parser/app/app_id.rs | 0 .../src/parser/app/app_name.rs | 0 .../src/parser/app/mod.rs | 0 .../src/parser/mod.rs | 0 .../src/parser/trash/mod.rs | 0 .../src/parser/trash/trash_id.rs | 0 .../src/parser/view/delta_data.rs | 0 .../src/parser/view/mod.rs | 0 .../src/parser/view/view_desc.rs | 0 .../src/parser/view/view_id.rs | 0 .../src/parser/view/view_name.rs | 0 .../src/parser/view/view_thumbnail.rs | 0 .../src/parser/workspace/mod.rs | 0 .../src/parser/workspace/workspace_desc.rs | 0 .../src/parser/workspace/workspace_id.rs | 0 .../src/parser/workspace/workspace_name.rs | 0 .../src/protobuf/mod.rs | 0 .../src/protobuf/model/app_create.rs | 0 .../src/protobuf/model/app_query.rs | 0 .../src/protobuf/model/app_update.rs | 0 .../src/protobuf/model/errors.rs | 0 .../src/protobuf/model/export.rs | 0 .../src/protobuf/model/mod.rs | 0 .../src/protobuf/model/trash_create.rs | 0 .../src/protobuf/model/view_create.rs | 0 .../src/protobuf/model/view_query.rs | 0 .../src/protobuf/model/view_update.rs | 0 .../src/protobuf/model/workspace_create.rs | 0 .../src/protobuf/model/workspace_query.rs | 0 .../src/protobuf/model/workspace_setting.rs | 0 .../src/protobuf/model/workspace_update.rs | 0 .../src/protobuf/proto/app_create.proto | 0 .../src/protobuf/proto/app_query.proto | 0 .../src/protobuf/proto/app_update.proto | 0 .../src/protobuf/proto/errors.proto | 0 .../src/protobuf/proto/export.proto | 0 .../src/protobuf/proto/trash_create.proto | 0 .../src/protobuf/proto/view_create.proto | 0 .../src/protobuf/proto/view_query.proto | 0 .../src/protobuf/proto/view_update.proto | 0 .../src/protobuf/proto/workspace_create.proto | 0 .../src/protobuf/proto/workspace_query.proto | 0 .../protobuf/proto/workspace_setting.proto | 0 .../src/protobuf/proto/workspace_update.proto | 0 .../src/user_default.rs | 0 .../src/derive_cache/derive_cache.rs | 38 +++++++++---------- .../Cargo.toml | 2 +- .../Flowy.toml | 0 .../src/entities/auth.rs | 0 .../src/entities/mod.rs | 0 .../src/entities/user_profile.rs | 0 .../src/lib.rs | 0 .../src/parser/mod.rs | 0 .../src/parser/user_email.rs | 0 .../src/parser/user_id.rs | 0 .../src/parser/user_name.rs | 0 .../src/parser/user_password.rs | 0 .../src/parser/user_workspace.rs | 0 .../src/protobuf/mod.rs | 0 .../src/protobuf/model/auth.rs | 0 .../src/protobuf/model/errors.rs | 0 .../src/protobuf/model/mod.rs | 0 .../src/protobuf/model/user_profile.rs | 0 .../src/protobuf/proto/auth.proto | 0 .../src/protobuf/proto/errors.proto | 0 .../src/protobuf/proto/user_profile.proto | 0 255 files changed, 166 insertions(+), 166 deletions(-) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/app_create.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/app_create.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/app_create.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/app_create.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/app_query.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/app_query.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/app_query.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/app_query.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/app_update.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/app_update.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/app_update.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/app_update.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/errors.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/errors.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/errors.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/errors.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/export.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/export.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/export.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/export.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/protobuf.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/trash_create.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/trash_create.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/trash_create.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/trash_create.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/view_create.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/view_create.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/view_create.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/view_create.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/view_query.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/view_query.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/view_query.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/view_query.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/view_update.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/view_update.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/view_update.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/view_update.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/workspace_create.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/workspace_create.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/workspace_create.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/workspace_create.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/workspace_query.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/workspace_query.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/workspace_query.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/workspace_query.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/workspace_setting.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/workspace_setting.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/workspace_setting.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/workspace_setting.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/workspace_update.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/workspace_update.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/workspace_update.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-core-infra => flowy-core-data-model}/workspace_update.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-user-infra => flowy-user-data-model}/auth.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-user-infra => flowy-user-data-model}/auth.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-user-infra => flowy-user-data-model}/auth.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-user-infra => flowy-user-data-model}/auth.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-user-infra => flowy-user-data-model}/errors.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-user-infra => flowy-user-data-model}/errors.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-user-infra => flowy-user-data-model}/errors.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-user-infra => flowy-user-data-model}/errors.pbserver.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-user-infra => flowy-user-data-model}/protobuf.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-user-infra => flowy-user-data-model}/user_profile.pb.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-user-infra => flowy-user-data-model}/user_profile.pbenum.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-user-infra => flowy-user-data-model}/user_profile.pbjson.dart (100%) rename frontend/app_flowy/packages/flowy_sdk/lib/protobuf/{flowy-user-infra => flowy-user-data-model}/user_profile.pbserver.dart (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/Cargo.toml (95%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/Flowy.toml (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/entities/app/app_create.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/entities/app/app_query.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/entities/app/app_update.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/entities/app/mod.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/entities/mod.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/entities/share/export.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/entities/share/mod.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/entities/trash/mod.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/entities/trash/trash_create.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/entities/view/mod.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/entities/view/view_create.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/entities/view/view_query.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/entities/view/view_update.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/entities/workspace/mod.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/entities/workspace/workspace_create.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/entities/workspace/workspace_query.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/entities/workspace/workspace_setting.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/entities/workspace/workspace_update.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/lib.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/macros.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/parser/app/app_color_style.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/parser/app/app_desc.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/parser/app/app_id.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/parser/app/app_name.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/parser/app/mod.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/parser/mod.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/parser/trash/mod.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/parser/trash/trash_id.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/parser/view/delta_data.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/parser/view/mod.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/parser/view/view_desc.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/parser/view/view_id.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/parser/view/view_name.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/parser/view/view_thumbnail.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/parser/workspace/mod.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/parser/workspace/workspace_desc.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/parser/workspace/workspace_id.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/parser/workspace/workspace_name.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/protobuf/mod.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/protobuf/model/app_create.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/protobuf/model/app_query.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/protobuf/model/app_update.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/protobuf/model/errors.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/protobuf/model/export.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/protobuf/model/mod.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/protobuf/model/trash_create.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/protobuf/model/view_create.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/protobuf/model/view_query.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/protobuf/model/view_update.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/protobuf/model/workspace_create.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/protobuf/model/workspace_query.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/protobuf/model/workspace_setting.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/protobuf/model/workspace_update.rs (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/protobuf/proto/app_create.proto (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/protobuf/proto/app_query.proto (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/protobuf/proto/app_update.proto (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/protobuf/proto/errors.proto (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/protobuf/proto/export.proto (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/protobuf/proto/trash_create.proto (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/protobuf/proto/view_create.proto (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/protobuf/proto/view_query.proto (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/protobuf/proto/view_update.proto (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/protobuf/proto/workspace_create.proto (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/protobuf/proto/workspace_query.proto (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/protobuf/proto/workspace_setting.proto (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/protobuf/proto/workspace_update.proto (100%) rename shared-lib/{flowy-core-infra => flowy-core-data-model}/src/user_default.rs (100%) rename shared-lib/{flowy-user-infra => flowy-user-data-model}/Cargo.toml (95%) rename shared-lib/{flowy-user-infra => flowy-user-data-model}/Flowy.toml (100%) rename shared-lib/{flowy-user-infra => flowy-user-data-model}/src/entities/auth.rs (100%) rename shared-lib/{flowy-user-infra => flowy-user-data-model}/src/entities/mod.rs (100%) rename shared-lib/{flowy-user-infra => flowy-user-data-model}/src/entities/user_profile.rs (100%) rename shared-lib/{flowy-user-infra => flowy-user-data-model}/src/lib.rs (100%) rename shared-lib/{flowy-user-infra => flowy-user-data-model}/src/parser/mod.rs (100%) rename shared-lib/{flowy-user-infra => flowy-user-data-model}/src/parser/user_email.rs (100%) rename shared-lib/{flowy-user-infra => flowy-user-data-model}/src/parser/user_id.rs (100%) rename shared-lib/{flowy-user-infra => flowy-user-data-model}/src/parser/user_name.rs (100%) rename shared-lib/{flowy-user-infra => flowy-user-data-model}/src/parser/user_password.rs (100%) rename shared-lib/{flowy-user-infra => flowy-user-data-model}/src/parser/user_workspace.rs (100%) rename shared-lib/{flowy-user-infra => flowy-user-data-model}/src/protobuf/mod.rs (100%) rename shared-lib/{flowy-user-infra => flowy-user-data-model}/src/protobuf/model/auth.rs (100%) rename shared-lib/{flowy-user-infra => flowy-user-data-model}/src/protobuf/model/errors.rs (100%) rename shared-lib/{flowy-user-infra => flowy-user-data-model}/src/protobuf/model/mod.rs (100%) rename shared-lib/{flowy-user-infra => flowy-user-data-model}/src/protobuf/model/user_profile.rs (100%) rename shared-lib/{flowy-user-infra => flowy-user-data-model}/src/protobuf/proto/auth.proto (100%) rename shared-lib/{flowy-user-infra => flowy-user-data-model}/src/protobuf/proto/errors.proto (100%) rename shared-lib/{flowy-user-infra => flowy-user-data-model}/src/protobuf/proto/user_profile.proto (100%) diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 45622458a5..3d7e98dffd 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -456,13 +456,13 @@ dependencies = [ "dashmap", "derive_more", "flowy-collaboration", - "flowy-core-infra", + "flowy-core-data-model", "flowy-document", "flowy-net", "flowy-sdk", "flowy-test", "flowy-user", - "flowy-user-infra", + "flowy-user-data-model", "futures", "futures-core", "futures-util", @@ -508,8 +508,8 @@ dependencies = [ "config", "derive_more", "flowy-collaboration", - "flowy-core-infra", - "flowy-user-infra", + "flowy-core-data-model", + "flowy-user-data-model", "hyper", "lazy_static", "log", @@ -1246,7 +1246,7 @@ dependencies = [ "diesel", "diesel_derives", "flowy-collaboration", - "flowy-core-infra", + "flowy-core-data-model", "flowy-database", "flowy-derive", "flowy-document", @@ -1271,7 +1271,7 @@ dependencies = [ ] [[package]] -name = "flowy-core-infra" +name = "flowy-core-data-model" version = "0.1.0" dependencies = [ "bytes", @@ -1453,7 +1453,7 @@ dependencies = [ "flowy-derive", "flowy-error", "flowy-net", - "flowy-user-infra", + "flowy-user-data-model", "futures-core", "lazy_static", "lib-dispatch", @@ -1476,7 +1476,7 @@ dependencies = [ ] [[package]] -name = "flowy-user-infra" +name = "flowy-user-data-model" version = "0.1.0" dependencies = [ "bytes", diff --git a/backend/Cargo.toml b/backend/Cargo.toml index defc585ff0..95662e4223 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -59,8 +59,8 @@ pin-project = "1.0.0" byteorder = {version = "1.3.4"} async-stream = "0.3.2" -flowy-user-infra = { path = "../shared-lib/flowy-user-infra" } -flowy-core-infra = { path = "../shared-lib/flowy-core-infra" } +flowy-user-data-model = { path = "../shared-lib/flowy-user-data-model" } +flowy-core-data-model = { path = "../shared-lib/flowy-core-data-model" } flowy-collaboration = { path = "../shared-lib/flowy-collaboration" } lib-ws = { path = "../shared-lib/lib-ws" } lib-ot = { path = "../shared-lib/lib-ot" } diff --git a/backend/src/entities/workspace.rs b/backend/src/entities/workspace.rs index 689ab68271..605d61c89f 100644 --- a/backend/src/entities/workspace.rs +++ b/backend/src/entities/workspace.rs @@ -1,5 +1,5 @@ use chrono::Utc; -use flowy_core_infra::protobuf::{App, RepeatedView, Trash, TrashType, View, ViewType, Workspace}; +use flowy_core_data_model::protobuf::{App, RepeatedView, Trash, TrashType, View, ViewType, Workspace}; use protobuf::ProtobufEnum; pub(crate) const WORKSPACE_TABLE: &str = "workspace_table"; diff --git a/backend/src/services/app/app.rs b/backend/src/services/app/app.rs index 2f3f41e762..10a74cc33a 100644 --- a/backend/src/services/app/app.rs +++ b/backend/src/services/app/app.rs @@ -7,7 +7,7 @@ use crate::{ use crate::services::trash::read_trash_ids; use backend_service::errors::{invalid_params, ServerError}; use chrono::Utc; -use flowy_core_infra::{ +use flowy_core_data_model::{ parser::{ app::{AppDesc, AppName}, workspace::WorkspaceId, diff --git a/backend/src/services/app/router.rs b/backend/src/services/app/router.rs index aa9820d06b..572ab49255 100644 --- a/backend/src/services/app/router.rs +++ b/backend/src/services/app/router.rs @@ -3,7 +3,7 @@ use actix_web::{ HttpResponse, }; use backend_service::errors::{invalid_params, ServerError}; -use flowy_core_infra::protobuf::{AppIdentifier, CreateAppParams, UpdateAppParams}; +use flowy_core_data_model::protobuf::{AppIdentifier, CreateAppParams, UpdateAppParams}; use protobuf::Message; use sqlx::PgPool; @@ -17,7 +17,7 @@ use crate::services::{ }; use anyhow::Context; use backend_service::response::FlowyResponse; -use flowy_core_infra::parser::app::{AppDesc, AppName}; +use flowy_core_data_model::parser::app::{AppDesc, AppName}; pub async fn create_handler( payload: Payload, diff --git a/backend/src/services/app/sql_builder.rs b/backend/src/services/app/sql_builder.rs index 7fb6b2bcad..97d17d469b 100644 --- a/backend/src/services/app/sql_builder.rs +++ b/backend/src/services/app/sql_builder.rs @@ -4,7 +4,7 @@ use crate::{ }; use backend_service::errors::{invalid_params, ServerError}; use chrono::{DateTime, NaiveDateTime, Utc}; -use flowy_core_infra::{ +use flowy_core_data_model::{ parser::app::AppId, protobuf::{App, ColorStyle}, }; diff --git a/backend/src/services/trash/router.rs b/backend/src/services/trash/router.rs index 6233e33fec..3d19a24bbf 100644 --- a/backend/src/services/trash/router.rs +++ b/backend/src/services/trash/router.rs @@ -13,7 +13,7 @@ use backend_service::{ errors::{invalid_params, ServerError}, response::FlowyResponse, }; -use flowy_core_infra::{parser::trash::TrashId, protobuf::TrashIdentifiers}; +use flowy_core_data_model::{parser::trash::TrashId, protobuf::TrashIdentifiers}; use sqlx::PgPool; use uuid::Uuid; diff --git a/backend/src/services/trash/trash.rs b/backend/src/services/trash/trash.rs index ddecb66d61..d71913ef99 100644 --- a/backend/src/services/trash/trash.rs +++ b/backend/src/services/trash/trash.rs @@ -9,7 +9,7 @@ use crate::{ }; use ::protobuf::ProtobufEnum; use backend_service::errors::ServerError; -use flowy_core_infra::protobuf::{RepeatedTrash, Trash, TrashType}; +use flowy_core_data_model::protobuf::{RepeatedTrash, Trash, TrashType}; use sqlx::{postgres::PgArguments, Postgres, Row}; use uuid::Uuid; diff --git a/backend/src/services/user/auth.rs b/backend/src/services/user/auth.rs index 16e8367940..ed69a95826 100644 --- a/backend/src/services/user/auth.rs +++ b/backend/src/services/user/auth.rs @@ -9,7 +9,7 @@ use backend_service::{ response::FlowyResponse, }; use chrono::Utc; -use flowy_user_infra::{ +use flowy_user_data_model::{ parser::{UserEmail, UserName, UserPassword}, protobuf::{SignInParams, SignInResponse, SignUpParams, SignUpResponse, UpdateUserParams, UserProfile}, }; diff --git a/backend/src/services/user/router.rs b/backend/src/services/user/router.rs index b13d4c5e95..c4f6c18c59 100644 --- a/backend/src/services/user/router.rs +++ b/backend/src/services/user/router.rs @@ -7,7 +7,7 @@ use actix_web::{ use sqlx::PgPool; use backend_service::{errors::ServerError, response::FlowyResponse}; -use flowy_user_infra::protobuf::{SignInParams, SignUpParams, UpdateUserParams}; +use flowy_user_data_model::protobuf::{SignInParams, SignUpParams, UpdateUserParams}; use crate::{ entities::token::Token, diff --git a/backend/src/services/user/user_default.rs b/backend/src/services/user/user_default.rs index 477cc600fb..79fa24f86e 100644 --- a/backend/src/services/user/user_default.rs +++ b/backend/src/services/user/user_default.rs @@ -10,7 +10,7 @@ use crate::services::view::{create_view_with_args, sql_builder::NewViewSqlBuilde use backend_service::errors::ServerError; use chrono::Utc; use flowy_collaboration::core::document::default::initial_string; -use flowy_core_infra::protobuf::Workspace; +use flowy_core_data_model::protobuf::Workspace; use std::convert::TryInto; #[allow(dead_code)] @@ -19,7 +19,7 @@ pub async fn create_default_workspace( user_id: &str, ) -> Result { let time = Utc::now(); - let workspace: Workspace = flowy_core_infra::user_default::create_default_workspace(time) + let workspace: Workspace = flowy_core_data_model::user_default::create_default_workspace(time) .try_into() .unwrap(); diff --git a/backend/src/services/view/router.rs b/backend/src/services/view/router.rs index 0cbd7f44ac..d165d3635b 100644 --- a/backend/src/services/view/router.rs +++ b/backend/src/services/view/router.rs @@ -13,7 +13,7 @@ use backend_service::{ errors::{invalid_params, ServerError}, response::FlowyResponse, }; -use flowy_core_infra::{ +use flowy_core_data_model::{ parser::view::{ViewDesc, ViewName, ViewThumbnail}, protobuf::{CreateViewParams, QueryViewRequest, UpdateViewParams, ViewIdentifier}, }; diff --git a/backend/src/services/view/sql_builder.rs b/backend/src/services/view/sql_builder.rs index 6fc935d5cb..77e9501bd2 100644 --- a/backend/src/services/view/sql_builder.rs +++ b/backend/src/services/view/sql_builder.rs @@ -4,7 +4,7 @@ use crate::{ }; use backend_service::errors::{invalid_params, ServerError}; use chrono::{DateTime, NaiveDateTime, Utc}; -use flowy_core_infra::{ +use flowy_core_data_model::{ parser::view::ViewId, protobuf::{View, ViewType}, }; diff --git a/backend/src/services/view/view.rs b/backend/src/services/view/view.rs index 5dd1055d0e..9f7c6b161a 100644 --- a/backend/src/services/view/view.rs +++ b/backend/src/services/view/view.rs @@ -11,7 +11,7 @@ use crate::{ use backend_service::errors::{invalid_params, ServerError}; use chrono::Utc; use flowy_collaboration::protobuf::CreateDocParams; -use flowy_core_infra::{ +use flowy_core_data_model::{ parser::{ app::AppId, view::{ViewDesc, ViewName, ViewThumbnail}, diff --git a/backend/src/services/workspace/router.rs b/backend/src/services/workspace/router.rs index 984a713bcb..9e8050db4e 100644 --- a/backend/src/services/workspace/router.rs +++ b/backend/src/services/workspace/router.rs @@ -18,7 +18,7 @@ use backend_service::{ errors::{invalid_params, ServerError}, response::FlowyResponse, }; -use flowy_core_infra::{ +use flowy_core_data_model::{ parser::workspace::{WorkspaceDesc, WorkspaceName}, protobuf::{CreateWorkspaceParams, UpdateWorkspaceParams, WorkspaceIdentifier}, }; diff --git a/backend/src/services/workspace/sql_builder.rs b/backend/src/services/workspace/sql_builder.rs index 9f198d6234..e8e55bb6a8 100644 --- a/backend/src/services/workspace/sql_builder.rs +++ b/backend/src/services/workspace/sql_builder.rs @@ -4,7 +4,7 @@ use crate::{ }; use backend_service::errors::{invalid_params, ServerError}; use chrono::{DateTime, NaiveDateTime, Utc}; -use flowy_core_infra::{parser::workspace::WorkspaceId, protobuf::Workspace}; +use flowy_core_data_model::{parser::workspace::WorkspaceId, protobuf::Workspace}; use sqlx::postgres::PgArguments; use uuid::Uuid; diff --git a/backend/src/services/workspace/workspace.rs b/backend/src/services/workspace/workspace.rs index 39a419c6fb..81bc051a11 100644 --- a/backend/src/services/workspace/workspace.rs +++ b/backend/src/services/workspace/workspace.rs @@ -6,7 +6,7 @@ use crate::{ }; use anyhow::Context; use backend_service::errors::{invalid_params, ServerError}; -use flowy_core_infra::{ +use flowy_core_data_model::{ parser::workspace::WorkspaceId, protobuf::{RepeatedApp, RepeatedWorkspace, Workspace}, }; diff --git a/backend/tests/api/auth.rs b/backend/tests/api/auth.rs index a2772fff3d..3b98a8a947 100644 --- a/backend/tests/api/auth.rs +++ b/backend/tests/api/auth.rs @@ -1,6 +1,6 @@ use crate::util::helper::{spawn_user_server, TestUserServer}; use backend_service::errors::ErrorCode; -use flowy_user_infra::entities::{SignInParams, SignUpParams, SignUpResponse, UpdateUserParams}; +use flowy_user_data_model::entities::{SignInParams, SignUpParams, SignUpResponse, UpdateUserParams}; #[actix_rt::test] async fn user_register() { diff --git a/backend/tests/api/doc.rs b/backend/tests/api/doc.rs index 83b5d71285..ce7b753442 100644 --- a/backend/tests/api/doc.rs +++ b/backend/tests/api/doc.rs @@ -1,6 +1,6 @@ use crate::util::helper::ViewTest; use flowy_collaboration::entities::doc::DocIdentifier; -use flowy_core_infra::entities::view::ViewIdentifiers; +use flowy_core_data_model::entities::view::ViewIdentifiers; #[actix_rt::test] async fn doc_read() { diff --git a/backend/tests/api/workspace.rs b/backend/tests/api/workspace.rs index abfb6294c0..741d1da2fd 100644 --- a/backend/tests/api/workspace.rs +++ b/backend/tests/api/workspace.rs @@ -1,6 +1,6 @@ #![allow(clippy::all)] use crate::util::helper::*; -use flowy_core_infra::entities::{ +use flowy_core_data_model::entities::{ app::{AppIdentifier, UpdateAppParams}, trash::{TrashIdentifier, TrashIdentifiers, TrashType}, view::{UpdateViewParams, ViewIdentifier}, diff --git a/backend/tests/util/helper.rs b/backend/tests/util/helper.rs index 42438bbb41..39fe680a7e 100644 --- a/backend/tests/util/helper.rs +++ b/backend/tests/util/helper.rs @@ -10,9 +10,9 @@ use backend_service::{ workspace_request::*, }; use flowy_collaboration::entities::doc::{Doc, DocIdentifier}; -use flowy_core_infra::entities::prelude::*; +use flowy_core_data_model::entities::prelude::*; use flowy_document::services::server::read_doc_request; -use flowy_user_infra::entities::*; +use flowy_user_data_model::entities::*; use sqlx::{Connection, Executor, PgConnection, PgPool}; use uuid::Uuid; diff --git a/frontend/app_flowy/ios/Runner.xcodeproj/project.pbxproj b/frontend/app_flowy/ios/Runner.xcodeproj/project.pbxproj index 48c4dd313d..c5e6758eb6 100644 --- a/frontend/app_flowy/ios/Runner.xcodeproj/project.pbxproj +++ b/frontend/app_flowy/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 50; objects = { /* Begin PBXBuildFile section */ @@ -156,7 +156,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1020; + LastUpgradeCheck = 1300; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { diff --git a/frontend/app_flowy/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/frontend/app_flowy/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index a28140cfdb..3db53b6e1f 100644 --- a/frontend/app_flowy/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/frontend/app_flowy/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ HttpRequestBuilder { HttpRequestBuilder::new().middleware(crate::middleware::BACKEND_API_MIDDLEWARE.clone()) diff --git a/shared-lib/backend-service/src/workspace_request.rs b/shared-lib/backend-service/src/workspace_request.rs index 8aa1ad640a..02c4cfdc11 100644 --- a/shared-lib/backend-service/src/workspace_request.rs +++ b/shared-lib/backend-service/src/workspace_request.rs @@ -1,5 +1,5 @@ use crate::{configuration::HEADER_TOKEN, errors::ServerError, request::HttpRequestBuilder}; -use flowy_core_infra::entities::prelude::*; +use flowy_core_data_model::entities::prelude::*; pub(crate) fn request_builder() -> HttpRequestBuilder { HttpRequestBuilder::new().middleware(crate::middleware::BACKEND_API_MIDDLEWARE.clone()) diff --git a/shared-lib/flowy-core-infra/Cargo.toml b/shared-lib/flowy-core-data-model/Cargo.toml similarity index 95% rename from shared-lib/flowy-core-infra/Cargo.toml rename to shared-lib/flowy-core-data-model/Cargo.toml index e3420abe0a..3b0b97b052 100644 --- a/shared-lib/flowy-core-infra/Cargo.toml +++ b/shared-lib/flowy-core-data-model/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "flowy-core-infra" +name = "flowy-core-data-model" version = "0.1.0" edition = "2018" diff --git a/shared-lib/flowy-core-infra/Flowy.toml b/shared-lib/flowy-core-data-model/Flowy.toml similarity index 100% rename from shared-lib/flowy-core-infra/Flowy.toml rename to shared-lib/flowy-core-data-model/Flowy.toml diff --git a/shared-lib/flowy-core-infra/src/entities/app/app_create.rs b/shared-lib/flowy-core-data-model/src/entities/app/app_create.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/entities/app/app_create.rs rename to shared-lib/flowy-core-data-model/src/entities/app/app_create.rs diff --git a/shared-lib/flowy-core-infra/src/entities/app/app_query.rs b/shared-lib/flowy-core-data-model/src/entities/app/app_query.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/entities/app/app_query.rs rename to shared-lib/flowy-core-data-model/src/entities/app/app_query.rs diff --git a/shared-lib/flowy-core-infra/src/entities/app/app_update.rs b/shared-lib/flowy-core-data-model/src/entities/app/app_update.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/entities/app/app_update.rs rename to shared-lib/flowy-core-data-model/src/entities/app/app_update.rs diff --git a/shared-lib/flowy-core-infra/src/entities/app/mod.rs b/shared-lib/flowy-core-data-model/src/entities/app/mod.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/entities/app/mod.rs rename to shared-lib/flowy-core-data-model/src/entities/app/mod.rs diff --git a/shared-lib/flowy-core-infra/src/entities/mod.rs b/shared-lib/flowy-core-data-model/src/entities/mod.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/entities/mod.rs rename to shared-lib/flowy-core-data-model/src/entities/mod.rs diff --git a/shared-lib/flowy-core-infra/src/entities/share/export.rs b/shared-lib/flowy-core-data-model/src/entities/share/export.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/entities/share/export.rs rename to shared-lib/flowy-core-data-model/src/entities/share/export.rs diff --git a/shared-lib/flowy-core-infra/src/entities/share/mod.rs b/shared-lib/flowy-core-data-model/src/entities/share/mod.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/entities/share/mod.rs rename to shared-lib/flowy-core-data-model/src/entities/share/mod.rs diff --git a/shared-lib/flowy-core-infra/src/entities/trash/mod.rs b/shared-lib/flowy-core-data-model/src/entities/trash/mod.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/entities/trash/mod.rs rename to shared-lib/flowy-core-data-model/src/entities/trash/mod.rs diff --git a/shared-lib/flowy-core-infra/src/entities/trash/trash_create.rs b/shared-lib/flowy-core-data-model/src/entities/trash/trash_create.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/entities/trash/trash_create.rs rename to shared-lib/flowy-core-data-model/src/entities/trash/trash_create.rs diff --git a/shared-lib/flowy-core-infra/src/entities/view/mod.rs b/shared-lib/flowy-core-data-model/src/entities/view/mod.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/entities/view/mod.rs rename to shared-lib/flowy-core-data-model/src/entities/view/mod.rs diff --git a/shared-lib/flowy-core-infra/src/entities/view/view_create.rs b/shared-lib/flowy-core-data-model/src/entities/view/view_create.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/entities/view/view_create.rs rename to shared-lib/flowy-core-data-model/src/entities/view/view_create.rs diff --git a/shared-lib/flowy-core-infra/src/entities/view/view_query.rs b/shared-lib/flowy-core-data-model/src/entities/view/view_query.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/entities/view/view_query.rs rename to shared-lib/flowy-core-data-model/src/entities/view/view_query.rs diff --git a/shared-lib/flowy-core-infra/src/entities/view/view_update.rs b/shared-lib/flowy-core-data-model/src/entities/view/view_update.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/entities/view/view_update.rs rename to shared-lib/flowy-core-data-model/src/entities/view/view_update.rs diff --git a/shared-lib/flowy-core-infra/src/entities/workspace/mod.rs b/shared-lib/flowy-core-data-model/src/entities/workspace/mod.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/entities/workspace/mod.rs rename to shared-lib/flowy-core-data-model/src/entities/workspace/mod.rs diff --git a/shared-lib/flowy-core-infra/src/entities/workspace/workspace_create.rs b/shared-lib/flowy-core-data-model/src/entities/workspace/workspace_create.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/entities/workspace/workspace_create.rs rename to shared-lib/flowy-core-data-model/src/entities/workspace/workspace_create.rs diff --git a/shared-lib/flowy-core-infra/src/entities/workspace/workspace_query.rs b/shared-lib/flowy-core-data-model/src/entities/workspace/workspace_query.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/entities/workspace/workspace_query.rs rename to shared-lib/flowy-core-data-model/src/entities/workspace/workspace_query.rs diff --git a/shared-lib/flowy-core-infra/src/entities/workspace/workspace_setting.rs b/shared-lib/flowy-core-data-model/src/entities/workspace/workspace_setting.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/entities/workspace/workspace_setting.rs rename to shared-lib/flowy-core-data-model/src/entities/workspace/workspace_setting.rs diff --git a/shared-lib/flowy-core-infra/src/entities/workspace/workspace_update.rs b/shared-lib/flowy-core-data-model/src/entities/workspace/workspace_update.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/entities/workspace/workspace_update.rs rename to shared-lib/flowy-core-data-model/src/entities/workspace/workspace_update.rs diff --git a/shared-lib/flowy-core-infra/src/lib.rs b/shared-lib/flowy-core-data-model/src/lib.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/lib.rs rename to shared-lib/flowy-core-data-model/src/lib.rs diff --git a/shared-lib/flowy-core-infra/src/macros.rs b/shared-lib/flowy-core-data-model/src/macros.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/macros.rs rename to shared-lib/flowy-core-data-model/src/macros.rs diff --git a/shared-lib/flowy-core-infra/src/parser/app/app_color_style.rs b/shared-lib/flowy-core-data-model/src/parser/app/app_color_style.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/parser/app/app_color_style.rs rename to shared-lib/flowy-core-data-model/src/parser/app/app_color_style.rs diff --git a/shared-lib/flowy-core-infra/src/parser/app/app_desc.rs b/shared-lib/flowy-core-data-model/src/parser/app/app_desc.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/parser/app/app_desc.rs rename to shared-lib/flowy-core-data-model/src/parser/app/app_desc.rs diff --git a/shared-lib/flowy-core-infra/src/parser/app/app_id.rs b/shared-lib/flowy-core-data-model/src/parser/app/app_id.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/parser/app/app_id.rs rename to shared-lib/flowy-core-data-model/src/parser/app/app_id.rs diff --git a/shared-lib/flowy-core-infra/src/parser/app/app_name.rs b/shared-lib/flowy-core-data-model/src/parser/app/app_name.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/parser/app/app_name.rs rename to shared-lib/flowy-core-data-model/src/parser/app/app_name.rs diff --git a/shared-lib/flowy-core-infra/src/parser/app/mod.rs b/shared-lib/flowy-core-data-model/src/parser/app/mod.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/parser/app/mod.rs rename to shared-lib/flowy-core-data-model/src/parser/app/mod.rs diff --git a/shared-lib/flowy-core-infra/src/parser/mod.rs b/shared-lib/flowy-core-data-model/src/parser/mod.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/parser/mod.rs rename to shared-lib/flowy-core-data-model/src/parser/mod.rs diff --git a/shared-lib/flowy-core-infra/src/parser/trash/mod.rs b/shared-lib/flowy-core-data-model/src/parser/trash/mod.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/parser/trash/mod.rs rename to shared-lib/flowy-core-data-model/src/parser/trash/mod.rs diff --git a/shared-lib/flowy-core-infra/src/parser/trash/trash_id.rs b/shared-lib/flowy-core-data-model/src/parser/trash/trash_id.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/parser/trash/trash_id.rs rename to shared-lib/flowy-core-data-model/src/parser/trash/trash_id.rs diff --git a/shared-lib/flowy-core-infra/src/parser/view/delta_data.rs b/shared-lib/flowy-core-data-model/src/parser/view/delta_data.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/parser/view/delta_data.rs rename to shared-lib/flowy-core-data-model/src/parser/view/delta_data.rs diff --git a/shared-lib/flowy-core-infra/src/parser/view/mod.rs b/shared-lib/flowy-core-data-model/src/parser/view/mod.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/parser/view/mod.rs rename to shared-lib/flowy-core-data-model/src/parser/view/mod.rs diff --git a/shared-lib/flowy-core-infra/src/parser/view/view_desc.rs b/shared-lib/flowy-core-data-model/src/parser/view/view_desc.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/parser/view/view_desc.rs rename to shared-lib/flowy-core-data-model/src/parser/view/view_desc.rs diff --git a/shared-lib/flowy-core-infra/src/parser/view/view_id.rs b/shared-lib/flowy-core-data-model/src/parser/view/view_id.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/parser/view/view_id.rs rename to shared-lib/flowy-core-data-model/src/parser/view/view_id.rs diff --git a/shared-lib/flowy-core-infra/src/parser/view/view_name.rs b/shared-lib/flowy-core-data-model/src/parser/view/view_name.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/parser/view/view_name.rs rename to shared-lib/flowy-core-data-model/src/parser/view/view_name.rs diff --git a/shared-lib/flowy-core-infra/src/parser/view/view_thumbnail.rs b/shared-lib/flowy-core-data-model/src/parser/view/view_thumbnail.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/parser/view/view_thumbnail.rs rename to shared-lib/flowy-core-data-model/src/parser/view/view_thumbnail.rs diff --git a/shared-lib/flowy-core-infra/src/parser/workspace/mod.rs b/shared-lib/flowy-core-data-model/src/parser/workspace/mod.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/parser/workspace/mod.rs rename to shared-lib/flowy-core-data-model/src/parser/workspace/mod.rs diff --git a/shared-lib/flowy-core-infra/src/parser/workspace/workspace_desc.rs b/shared-lib/flowy-core-data-model/src/parser/workspace/workspace_desc.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/parser/workspace/workspace_desc.rs rename to shared-lib/flowy-core-data-model/src/parser/workspace/workspace_desc.rs diff --git a/shared-lib/flowy-core-infra/src/parser/workspace/workspace_id.rs b/shared-lib/flowy-core-data-model/src/parser/workspace/workspace_id.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/parser/workspace/workspace_id.rs rename to shared-lib/flowy-core-data-model/src/parser/workspace/workspace_id.rs diff --git a/shared-lib/flowy-core-infra/src/parser/workspace/workspace_name.rs b/shared-lib/flowy-core-data-model/src/parser/workspace/workspace_name.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/parser/workspace/workspace_name.rs rename to shared-lib/flowy-core-data-model/src/parser/workspace/workspace_name.rs diff --git a/shared-lib/flowy-core-infra/src/protobuf/mod.rs b/shared-lib/flowy-core-data-model/src/protobuf/mod.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/protobuf/mod.rs rename to shared-lib/flowy-core-data-model/src/protobuf/mod.rs diff --git a/shared-lib/flowy-core-infra/src/protobuf/model/app_create.rs b/shared-lib/flowy-core-data-model/src/protobuf/model/app_create.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/protobuf/model/app_create.rs rename to shared-lib/flowy-core-data-model/src/protobuf/model/app_create.rs diff --git a/shared-lib/flowy-core-infra/src/protobuf/model/app_query.rs b/shared-lib/flowy-core-data-model/src/protobuf/model/app_query.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/protobuf/model/app_query.rs rename to shared-lib/flowy-core-data-model/src/protobuf/model/app_query.rs diff --git a/shared-lib/flowy-core-infra/src/protobuf/model/app_update.rs b/shared-lib/flowy-core-data-model/src/protobuf/model/app_update.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/protobuf/model/app_update.rs rename to shared-lib/flowy-core-data-model/src/protobuf/model/app_update.rs diff --git a/shared-lib/flowy-core-infra/src/protobuf/model/errors.rs b/shared-lib/flowy-core-data-model/src/protobuf/model/errors.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/protobuf/model/errors.rs rename to shared-lib/flowy-core-data-model/src/protobuf/model/errors.rs diff --git a/shared-lib/flowy-core-infra/src/protobuf/model/export.rs b/shared-lib/flowy-core-data-model/src/protobuf/model/export.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/protobuf/model/export.rs rename to shared-lib/flowy-core-data-model/src/protobuf/model/export.rs diff --git a/shared-lib/flowy-core-infra/src/protobuf/model/mod.rs b/shared-lib/flowy-core-data-model/src/protobuf/model/mod.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/protobuf/model/mod.rs rename to shared-lib/flowy-core-data-model/src/protobuf/model/mod.rs diff --git a/shared-lib/flowy-core-infra/src/protobuf/model/trash_create.rs b/shared-lib/flowy-core-data-model/src/protobuf/model/trash_create.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/protobuf/model/trash_create.rs rename to shared-lib/flowy-core-data-model/src/protobuf/model/trash_create.rs diff --git a/shared-lib/flowy-core-infra/src/protobuf/model/view_create.rs b/shared-lib/flowy-core-data-model/src/protobuf/model/view_create.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/protobuf/model/view_create.rs rename to shared-lib/flowy-core-data-model/src/protobuf/model/view_create.rs diff --git a/shared-lib/flowy-core-infra/src/protobuf/model/view_query.rs b/shared-lib/flowy-core-data-model/src/protobuf/model/view_query.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/protobuf/model/view_query.rs rename to shared-lib/flowy-core-data-model/src/protobuf/model/view_query.rs diff --git a/shared-lib/flowy-core-infra/src/protobuf/model/view_update.rs b/shared-lib/flowy-core-data-model/src/protobuf/model/view_update.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/protobuf/model/view_update.rs rename to shared-lib/flowy-core-data-model/src/protobuf/model/view_update.rs diff --git a/shared-lib/flowy-core-infra/src/protobuf/model/workspace_create.rs b/shared-lib/flowy-core-data-model/src/protobuf/model/workspace_create.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/protobuf/model/workspace_create.rs rename to shared-lib/flowy-core-data-model/src/protobuf/model/workspace_create.rs diff --git a/shared-lib/flowy-core-infra/src/protobuf/model/workspace_query.rs b/shared-lib/flowy-core-data-model/src/protobuf/model/workspace_query.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/protobuf/model/workspace_query.rs rename to shared-lib/flowy-core-data-model/src/protobuf/model/workspace_query.rs diff --git a/shared-lib/flowy-core-infra/src/protobuf/model/workspace_setting.rs b/shared-lib/flowy-core-data-model/src/protobuf/model/workspace_setting.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/protobuf/model/workspace_setting.rs rename to shared-lib/flowy-core-data-model/src/protobuf/model/workspace_setting.rs diff --git a/shared-lib/flowy-core-infra/src/protobuf/model/workspace_update.rs b/shared-lib/flowy-core-data-model/src/protobuf/model/workspace_update.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/protobuf/model/workspace_update.rs rename to shared-lib/flowy-core-data-model/src/protobuf/model/workspace_update.rs diff --git a/shared-lib/flowy-core-infra/src/protobuf/proto/app_create.proto b/shared-lib/flowy-core-data-model/src/protobuf/proto/app_create.proto similarity index 100% rename from shared-lib/flowy-core-infra/src/protobuf/proto/app_create.proto rename to shared-lib/flowy-core-data-model/src/protobuf/proto/app_create.proto diff --git a/shared-lib/flowy-core-infra/src/protobuf/proto/app_query.proto b/shared-lib/flowy-core-data-model/src/protobuf/proto/app_query.proto similarity index 100% rename from shared-lib/flowy-core-infra/src/protobuf/proto/app_query.proto rename to shared-lib/flowy-core-data-model/src/protobuf/proto/app_query.proto diff --git a/shared-lib/flowy-core-infra/src/protobuf/proto/app_update.proto b/shared-lib/flowy-core-data-model/src/protobuf/proto/app_update.proto similarity index 100% rename from shared-lib/flowy-core-infra/src/protobuf/proto/app_update.proto rename to shared-lib/flowy-core-data-model/src/protobuf/proto/app_update.proto diff --git a/shared-lib/flowy-core-infra/src/protobuf/proto/errors.proto b/shared-lib/flowy-core-data-model/src/protobuf/proto/errors.proto similarity index 100% rename from shared-lib/flowy-core-infra/src/protobuf/proto/errors.proto rename to shared-lib/flowy-core-data-model/src/protobuf/proto/errors.proto diff --git a/shared-lib/flowy-core-infra/src/protobuf/proto/export.proto b/shared-lib/flowy-core-data-model/src/protobuf/proto/export.proto similarity index 100% rename from shared-lib/flowy-core-infra/src/protobuf/proto/export.proto rename to shared-lib/flowy-core-data-model/src/protobuf/proto/export.proto diff --git a/shared-lib/flowy-core-infra/src/protobuf/proto/trash_create.proto b/shared-lib/flowy-core-data-model/src/protobuf/proto/trash_create.proto similarity index 100% rename from shared-lib/flowy-core-infra/src/protobuf/proto/trash_create.proto rename to shared-lib/flowy-core-data-model/src/protobuf/proto/trash_create.proto diff --git a/shared-lib/flowy-core-infra/src/protobuf/proto/view_create.proto b/shared-lib/flowy-core-data-model/src/protobuf/proto/view_create.proto similarity index 100% rename from shared-lib/flowy-core-infra/src/protobuf/proto/view_create.proto rename to shared-lib/flowy-core-data-model/src/protobuf/proto/view_create.proto diff --git a/shared-lib/flowy-core-infra/src/protobuf/proto/view_query.proto b/shared-lib/flowy-core-data-model/src/protobuf/proto/view_query.proto similarity index 100% rename from shared-lib/flowy-core-infra/src/protobuf/proto/view_query.proto rename to shared-lib/flowy-core-data-model/src/protobuf/proto/view_query.proto diff --git a/shared-lib/flowy-core-infra/src/protobuf/proto/view_update.proto b/shared-lib/flowy-core-data-model/src/protobuf/proto/view_update.proto similarity index 100% rename from shared-lib/flowy-core-infra/src/protobuf/proto/view_update.proto rename to shared-lib/flowy-core-data-model/src/protobuf/proto/view_update.proto diff --git a/shared-lib/flowy-core-infra/src/protobuf/proto/workspace_create.proto b/shared-lib/flowy-core-data-model/src/protobuf/proto/workspace_create.proto similarity index 100% rename from shared-lib/flowy-core-infra/src/protobuf/proto/workspace_create.proto rename to shared-lib/flowy-core-data-model/src/protobuf/proto/workspace_create.proto diff --git a/shared-lib/flowy-core-infra/src/protobuf/proto/workspace_query.proto b/shared-lib/flowy-core-data-model/src/protobuf/proto/workspace_query.proto similarity index 100% rename from shared-lib/flowy-core-infra/src/protobuf/proto/workspace_query.proto rename to shared-lib/flowy-core-data-model/src/protobuf/proto/workspace_query.proto diff --git a/shared-lib/flowy-core-infra/src/protobuf/proto/workspace_setting.proto b/shared-lib/flowy-core-data-model/src/protobuf/proto/workspace_setting.proto similarity index 100% rename from shared-lib/flowy-core-infra/src/protobuf/proto/workspace_setting.proto rename to shared-lib/flowy-core-data-model/src/protobuf/proto/workspace_setting.proto diff --git a/shared-lib/flowy-core-infra/src/protobuf/proto/workspace_update.proto b/shared-lib/flowy-core-data-model/src/protobuf/proto/workspace_update.proto similarity index 100% rename from shared-lib/flowy-core-infra/src/protobuf/proto/workspace_update.proto rename to shared-lib/flowy-core-data-model/src/protobuf/proto/workspace_update.proto diff --git a/shared-lib/flowy-core-infra/src/user_default.rs b/shared-lib/flowy-core-data-model/src/user_default.rs similarity index 100% rename from shared-lib/flowy-core-infra/src/user_default.rs rename to shared-lib/flowy-core-data-model/src/user_default.rs diff --git a/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs b/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs index f37c5353c4..5f7896e8b9 100644 --- a/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs +++ b/shared-lib/flowy-derive/src/derive_cache/derive_cache.rs @@ -21,6 +21,24 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { | "FlowyError" | "SubscribeObject" | "NetworkState" + | "SignInRequest" + | "SignInParams" + | "SignInResponse" + | "SignUpRequest" + | "SignUpParams" + | "SignUpResponse" + | "UserToken" + | "UserProfile" + | "UpdateUserRequest" + | "UpdateUserParams" + | "CreateDocParams" + | "Doc" + | "UpdateDocParams" + | "DocDelta" + | "NewDocUser" + | "DocIdentifier" + | "DocumentWSData" + | "NewDocumentUser" | "QueryAppRequest" | "AppIdentifier" | "CreateAppRequest" @@ -54,29 +72,11 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { | "RepeatedView" | "ExportRequest" | "ExportData" - | "CreateDocParams" - | "Doc" - | "UpdateDocParams" - | "DocDelta" - | "NewDocUser" - | "DocIdentifier" - | "DocumentWSData" - | "NewDocumentUser" | "WSError" | "WSMessage" | "Revision" | "RevId" | "RevisionRange" - | "SignInRequest" - | "SignInParams" - | "SignInResponse" - | "SignUpRequest" - | "SignUpParams" - | "SignUpResponse" - | "UserToken" - | "UserProfile" - | "UpdateUserRequest" - | "UpdateUserParams" => TypeCategory::Protobuf, "WorkspaceEvent" | "WorkspaceNotification" @@ -86,10 +86,10 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { | "NetworkType" | "UserEvent" | "UserNotification" + | "DocumentWSDataType" | "TrashType" | "ViewType" | "ExportType" - | "DocumentWSDataType" | "ErrorCode" | "WSModule" | "RevType" diff --git a/shared-lib/flowy-user-infra/Cargo.toml b/shared-lib/flowy-user-data-model/Cargo.toml similarity index 95% rename from shared-lib/flowy-user-infra/Cargo.toml rename to shared-lib/flowy-user-data-model/Cargo.toml index 5e0afba7c9..1765d05d11 100644 --- a/shared-lib/flowy-user-infra/Cargo.toml +++ b/shared-lib/flowy-user-data-model/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "flowy-user-infra" +name = "flowy-user-data-model" version = "0.1.0" edition = "2018" diff --git a/shared-lib/flowy-user-infra/Flowy.toml b/shared-lib/flowy-user-data-model/Flowy.toml similarity index 100% rename from shared-lib/flowy-user-infra/Flowy.toml rename to shared-lib/flowy-user-data-model/Flowy.toml diff --git a/shared-lib/flowy-user-infra/src/entities/auth.rs b/shared-lib/flowy-user-data-model/src/entities/auth.rs similarity index 100% rename from shared-lib/flowy-user-infra/src/entities/auth.rs rename to shared-lib/flowy-user-data-model/src/entities/auth.rs diff --git a/shared-lib/flowy-user-infra/src/entities/mod.rs b/shared-lib/flowy-user-data-model/src/entities/mod.rs similarity index 100% rename from shared-lib/flowy-user-infra/src/entities/mod.rs rename to shared-lib/flowy-user-data-model/src/entities/mod.rs diff --git a/shared-lib/flowy-user-infra/src/entities/user_profile.rs b/shared-lib/flowy-user-data-model/src/entities/user_profile.rs similarity index 100% rename from shared-lib/flowy-user-infra/src/entities/user_profile.rs rename to shared-lib/flowy-user-data-model/src/entities/user_profile.rs diff --git a/shared-lib/flowy-user-infra/src/lib.rs b/shared-lib/flowy-user-data-model/src/lib.rs similarity index 100% rename from shared-lib/flowy-user-infra/src/lib.rs rename to shared-lib/flowy-user-data-model/src/lib.rs diff --git a/shared-lib/flowy-user-infra/src/parser/mod.rs b/shared-lib/flowy-user-data-model/src/parser/mod.rs similarity index 100% rename from shared-lib/flowy-user-infra/src/parser/mod.rs rename to shared-lib/flowy-user-data-model/src/parser/mod.rs diff --git a/shared-lib/flowy-user-infra/src/parser/user_email.rs b/shared-lib/flowy-user-data-model/src/parser/user_email.rs similarity index 100% rename from shared-lib/flowy-user-infra/src/parser/user_email.rs rename to shared-lib/flowy-user-data-model/src/parser/user_email.rs diff --git a/shared-lib/flowy-user-infra/src/parser/user_id.rs b/shared-lib/flowy-user-data-model/src/parser/user_id.rs similarity index 100% rename from shared-lib/flowy-user-infra/src/parser/user_id.rs rename to shared-lib/flowy-user-data-model/src/parser/user_id.rs diff --git a/shared-lib/flowy-user-infra/src/parser/user_name.rs b/shared-lib/flowy-user-data-model/src/parser/user_name.rs similarity index 100% rename from shared-lib/flowy-user-infra/src/parser/user_name.rs rename to shared-lib/flowy-user-data-model/src/parser/user_name.rs diff --git a/shared-lib/flowy-user-infra/src/parser/user_password.rs b/shared-lib/flowy-user-data-model/src/parser/user_password.rs similarity index 100% rename from shared-lib/flowy-user-infra/src/parser/user_password.rs rename to shared-lib/flowy-user-data-model/src/parser/user_password.rs diff --git a/shared-lib/flowy-user-infra/src/parser/user_workspace.rs b/shared-lib/flowy-user-data-model/src/parser/user_workspace.rs similarity index 100% rename from shared-lib/flowy-user-infra/src/parser/user_workspace.rs rename to shared-lib/flowy-user-data-model/src/parser/user_workspace.rs diff --git a/shared-lib/flowy-user-infra/src/protobuf/mod.rs b/shared-lib/flowy-user-data-model/src/protobuf/mod.rs similarity index 100% rename from shared-lib/flowy-user-infra/src/protobuf/mod.rs rename to shared-lib/flowy-user-data-model/src/protobuf/mod.rs diff --git a/shared-lib/flowy-user-infra/src/protobuf/model/auth.rs b/shared-lib/flowy-user-data-model/src/protobuf/model/auth.rs similarity index 100% rename from shared-lib/flowy-user-infra/src/protobuf/model/auth.rs rename to shared-lib/flowy-user-data-model/src/protobuf/model/auth.rs diff --git a/shared-lib/flowy-user-infra/src/protobuf/model/errors.rs b/shared-lib/flowy-user-data-model/src/protobuf/model/errors.rs similarity index 100% rename from shared-lib/flowy-user-infra/src/protobuf/model/errors.rs rename to shared-lib/flowy-user-data-model/src/protobuf/model/errors.rs diff --git a/shared-lib/flowy-user-infra/src/protobuf/model/mod.rs b/shared-lib/flowy-user-data-model/src/protobuf/model/mod.rs similarity index 100% rename from shared-lib/flowy-user-infra/src/protobuf/model/mod.rs rename to shared-lib/flowy-user-data-model/src/protobuf/model/mod.rs diff --git a/shared-lib/flowy-user-infra/src/protobuf/model/user_profile.rs b/shared-lib/flowy-user-data-model/src/protobuf/model/user_profile.rs similarity index 100% rename from shared-lib/flowy-user-infra/src/protobuf/model/user_profile.rs rename to shared-lib/flowy-user-data-model/src/protobuf/model/user_profile.rs diff --git a/shared-lib/flowy-user-infra/src/protobuf/proto/auth.proto b/shared-lib/flowy-user-data-model/src/protobuf/proto/auth.proto similarity index 100% rename from shared-lib/flowy-user-infra/src/protobuf/proto/auth.proto rename to shared-lib/flowy-user-data-model/src/protobuf/proto/auth.proto diff --git a/shared-lib/flowy-user-infra/src/protobuf/proto/errors.proto b/shared-lib/flowy-user-data-model/src/protobuf/proto/errors.proto similarity index 100% rename from shared-lib/flowy-user-infra/src/protobuf/proto/errors.proto rename to shared-lib/flowy-user-data-model/src/protobuf/proto/errors.proto diff --git a/shared-lib/flowy-user-infra/src/protobuf/proto/user_profile.proto b/shared-lib/flowy-user-data-model/src/protobuf/proto/user_profile.proto similarity index 100% rename from shared-lib/flowy-user-infra/src/protobuf/proto/user_profile.proto rename to shared-lib/flowy-user-data-model/src/protobuf/proto/user_profile.proto From 16c702b1e180905777076f8e90c0bd88e477403c Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 20 Dec 2021 12:06:17 +0800 Subject: [PATCH 37/39] fix listen on websocket error --- .../flowy-net/src/services/ws/manager.rs | 49 ++++++++++--------- frontend/rust-lib/flowy-sdk/src/lib.rs | 9 +++- 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/frontend/rust-lib/flowy-net/src/services/ws/manager.rs b/frontend/rust-lib/flowy-net/src/services/ws/manager.rs index 53a94f6b1c..fe1351063b 100644 --- a/frontend/rust-lib/flowy-net/src/services/ws/manager.rs +++ b/frontend/rust-lib/flowy-net/src/services/ws/manager.rs @@ -24,7 +24,6 @@ impl WsManager { local_web_socket() }; let (status_notifier, _) = broadcast::channel(10); - listen_on_websocket(ws.clone()); WsManager { inner: ws, connect_type: RwLock::new(NetworkType::default()), @@ -36,7 +35,6 @@ impl WsManager { pub async fn start(&self, token: String) -> Result<(), FlowyError> { let addr = format!("{}/{}", self.addr, token); self.inner.stop_connect().await?; - let _ = self.inner.start_connect(addr).await?; Ok(()) } @@ -79,28 +77,33 @@ impl WsManager { pub fn ws_sender(&self) -> Result, FlowyError> { self.inner.ws_sender() } } -#[tracing::instrument(level = "debug", skip(ws))] -fn listen_on_websocket(ws: Arc) { - let mut notify = ws.subscribe_connect_state(); - let _ = tokio::spawn(async move { - loop { - match notify.recv().await { - Ok(state) => { - tracing::info!("Websocket state changed: {}", state); - match state { - WSConnectState::Init => {}, - WSConnectState::Connected => {}, - WSConnectState::Connecting => {}, - WSConnectState::Disconnected => retry_connect(ws.clone(), 100).await, - } - }, - Err(e) => { - tracing::error!("Websocket state notify error: {:?}", e); - break; - }, +#[tracing::instrument(level = "debug", skip(manager))] +pub fn listen_on_websocket(manager: Arc) { + if cfg!(feature = "http_server") { + let ws = manager.inner.clone(); + let mut notify = manager.inner.subscribe_connect_state(); + let _ = tokio::spawn(async move { + loop { + match notify.recv().await { + Ok(state) => { + tracing::info!("Websocket state changed: {}", state); + match state { + WSConnectState::Init => {}, + WSConnectState::Connected => {}, + WSConnectState::Connecting => {}, + WSConnectState::Disconnected => retry_connect(ws.clone(), 100).await, + } + }, + Err(e) => { + tracing::error!("Websocket state notify error: {:?}", e); + break; + }, + } } - } - }); + }); + } else { + // do nothing + }; } async fn retry_connect(ws: Arc, count: usize) { diff --git a/frontend/rust-lib/flowy-sdk/src/lib.rs b/frontend/rust-lib/flowy-sdk/src/lib.rs index 68c15436aa..6c9de4ea3c 100644 --- a/frontend/rust-lib/flowy-sdk/src/lib.rs +++ b/frontend/rust-lib/flowy-sdk/src/lib.rs @@ -5,7 +5,10 @@ use crate::deps_resolve::{DocumentDepsResolver, WorkspaceDepsResolver}; use backend_service::configuration::ClientServerConfiguration; 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_net::{ + entities::NetworkType, + services::ws::{listen_on_websocket, WsManager}, +}; use flowy_user::{ prelude::UserStatus, services::user::{UserSession, UserSessionConfig}, @@ -113,8 +116,10 @@ fn _init( dispatch.spawn(async move { user_session.init(); - _listen_user_status(ws_manager, subscribe_user_status, core.clone()).await; + listen_on_websocket(ws_manager.clone()); + _listen_user_status(ws_manager.clone(), subscribe_user_status, core.clone()).await; }); + dispatch.spawn(async move { _listen_network_status(subscribe_network_type, cloned_core).await; }); From ef491f4276d8145ed7b5a4139441e1ee1d3657ee Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 20 Dec 2021 14:26:26 +0800 Subject: [PATCH 38/39] mv lib-sqlite to rust-lib --- frontend/rust-lib/Cargo.toml | 3 +- frontend/rust-lib/flowy-core/Cargo.toml | 3 +- frontend/rust-lib/flowy-database/Cargo.toml | 2 +- frontend/rust-lib/flowy-error/Cargo.toml | 2 +- frontend/rust-lib/flowy-user/Cargo.toml | 3 +- .../rust-lib}/lib-sqlite/Cargo.toml | 0 .../rust-lib}/lib-sqlite/src/conn_ext.rs | 0 .../rust-lib}/lib-sqlite/src/database.rs | 0 .../rust-lib}/lib-sqlite/src/errors.rs | 0 .../rust-lib}/lib-sqlite/src/lib.rs | 0 .../rust-lib}/lib-sqlite/src/pool.rs | 0 .../rust-lib}/lib-sqlite/src/pragma.rs | 0 shared-lib/Cargo.lock | 153 ------------------ shared-lib/Cargo.toml | 1 - 14 files changed, 5 insertions(+), 162 deletions(-) rename {shared-lib => frontend/rust-lib}/lib-sqlite/Cargo.toml (100%) rename {shared-lib => frontend/rust-lib}/lib-sqlite/src/conn_ext.rs (100%) rename {shared-lib => frontend/rust-lib}/lib-sqlite/src/database.rs (100%) rename {shared-lib => frontend/rust-lib}/lib-sqlite/src/errors.rs (100%) rename {shared-lib => frontend/rust-lib}/lib-sqlite/src/lib.rs (100%) rename {shared-lib => frontend/rust-lib}/lib-sqlite/src/pool.rs (100%) rename {shared-lib => frontend/rust-lib}/lib-sqlite/src/pragma.rs (100%) diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index 166b328009..8565d7ed6f 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -2,6 +2,7 @@ members = [ "lib-dispatch", "lib-log", + "lib-sqlite", "flowy-net", "flowy-sdk", "dart-ffi", @@ -14,7 +15,5 @@ members = [ "flowy-error", ] -exclude = ["../backend"] - [profile.dev] split-debuginfo = "unpacked" diff --git a/frontend/rust-lib/flowy-core/Cargo.toml b/frontend/rust-lib/flowy-core/Cargo.toml index 98735674ad..3644c6ff20 100644 --- a/frontend/rust-lib/flowy-core/Cargo.toml +++ b/frontend/rust-lib/flowy-core/Cargo.toml @@ -10,7 +10,6 @@ flowy-core-data-model = { path = "../../../shared-lib/flowy-core-data-model" } flowy-collaboration = { path = "../../../shared-lib/flowy-collaboration" } flowy-derive = { path = "../../../shared-lib/flowy-derive" } lib-ot = { path = "../../../shared-lib/lib-ot" } -lib-sqlite = { path = "../../../shared-lib/lib-sqlite" } backend-service = { path = "../../../shared-lib/backend-service" } lib-infra = { path = "../../../shared-lib/lib-infra" } @@ -20,7 +19,7 @@ flowy-error = { path = "../flowy-error", features = ["db", "backend"]} flowy-net = { path = "../flowy-net" } dart-notify = { path = "../dart-notify" } lib-dispatch = { path = "../lib-dispatch" } - +lib-sqlite = { path = "../lib-sqlite" } parking_lot = "0.11" protobuf = {version = "2.18.0"} diff --git a/frontend/rust-lib/flowy-database/Cargo.toml b/frontend/rust-lib/flowy-database/Cargo.toml index c2e3f64fd4..c5a6c5ac46 100644 --- a/frontend/rust-lib/flowy-database/Cargo.toml +++ b/frontend/rust-lib/flowy-database/Cargo.toml @@ -9,6 +9,6 @@ edition = "2018" diesel = {version = "1.4.8", features = ["sqlite"]} diesel_derives = {version = "1.4.1", features = ["sqlite"]} diesel_migrations = {version = "1.4.0", features = ["sqlite"]} -lib-sqlite = { path = "../../../shared-lib/lib-sqlite" } +lib-sqlite = { path = "../lib-sqlite" } log = "0.4" lazy_static = "1.4.0" \ No newline at end of file diff --git a/frontend/rust-lib/flowy-error/Cargo.toml b/frontend/rust-lib/flowy-error/Cargo.toml index 5ec55b475e..16da001014 100644 --- a/frontend/rust-lib/flowy-error/Cargo.toml +++ b/frontend/rust-lib/flowy-error/Cargo.toml @@ -18,8 +18,8 @@ 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} +lib-sqlite = { path = "../lib-sqlite", optional = true } [features] collaboration = ["flowy-collaboration"] diff --git a/frontend/rust-lib/flowy-user/Cargo.toml b/frontend/rust-lib/flowy-user/Cargo.toml index cf07372af4..aaec7a42d9 100644 --- a/frontend/rust-lib/flowy-user/Cargo.toml +++ b/frontend/rust-lib/flowy-user/Cargo.toml @@ -9,9 +9,7 @@ edition = "2018" flowy-user-data-model = { path = "../../../shared-lib/flowy-user-data-model" } backend-service = { path = "../../../shared-lib/backend-service" } flowy-derive = { path = "../../../shared-lib/flowy-derive" } -lib-sqlite = { path = "../../../shared-lib/lib-sqlite" } lib-infra = { path = "../../../shared-lib/lib-infra" } - flowy-collaboration = { path = "../../../shared-lib/flowy-collaboration", optional = true} derive_more = {version = "0.99", features = ["display"]} @@ -20,6 +18,7 @@ flowy-net = { path = "../flowy-net" } dart-notify = { path = "../dart-notify" } lib-dispatch = { path = "../lib-dispatch" } flowy-error = { path = "../flowy-error", features = ["db", "backend"] } +lib-sqlite = { path = "../lib-sqlite" } tracing = { version = "0.1", features = ["log"] } diff --git a/shared-lib/lib-sqlite/Cargo.toml b/frontend/rust-lib/lib-sqlite/Cargo.toml similarity index 100% rename from shared-lib/lib-sqlite/Cargo.toml rename to frontend/rust-lib/lib-sqlite/Cargo.toml diff --git a/shared-lib/lib-sqlite/src/conn_ext.rs b/frontend/rust-lib/lib-sqlite/src/conn_ext.rs similarity index 100% rename from shared-lib/lib-sqlite/src/conn_ext.rs rename to frontend/rust-lib/lib-sqlite/src/conn_ext.rs diff --git a/shared-lib/lib-sqlite/src/database.rs b/frontend/rust-lib/lib-sqlite/src/database.rs similarity index 100% rename from shared-lib/lib-sqlite/src/database.rs rename to frontend/rust-lib/lib-sqlite/src/database.rs diff --git a/shared-lib/lib-sqlite/src/errors.rs b/frontend/rust-lib/lib-sqlite/src/errors.rs similarity index 100% rename from shared-lib/lib-sqlite/src/errors.rs rename to frontend/rust-lib/lib-sqlite/src/errors.rs diff --git a/shared-lib/lib-sqlite/src/lib.rs b/frontend/rust-lib/lib-sqlite/src/lib.rs similarity index 100% rename from shared-lib/lib-sqlite/src/lib.rs rename to frontend/rust-lib/lib-sqlite/src/lib.rs diff --git a/shared-lib/lib-sqlite/src/pool.rs b/frontend/rust-lib/lib-sqlite/src/pool.rs similarity index 100% rename from shared-lib/lib-sqlite/src/pool.rs rename to frontend/rust-lib/lib-sqlite/src/pool.rs diff --git a/shared-lib/lib-sqlite/src/pragma.rs b/frontend/rust-lib/lib-sqlite/src/pragma.rs similarity index 100% rename from shared-lib/lib-sqlite/src/pragma.rs rename to frontend/rust-lib/lib-sqlite/src/pragma.rs diff --git a/shared-lib/Cargo.lock b/shared-lib/Cargo.lock index 21e17e240e..1994b54cb1 100644 --- a/shared-lib/Cargo.lock +++ b/shared-lib/Cargo.lock @@ -185,15 +185,6 @@ dependencies = [ "syn", ] -[[package]] -name = "addr2line" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" -dependencies = [ - "gimli", -] - [[package]] name = "adler" version = "1.0.2" @@ -297,21 +288,6 @@ dependencies = [ "uuid", ] -[[package]] -name = "backtrace" -version = "0.3.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321629d8ba6513061f26707241fa9bc89524ff1cd7a915a97ef0c62c666ce1b6" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - [[package]] name = "base-x" version = "0.2.8" @@ -539,38 +515,6 @@ dependencies = [ "syn", ] -[[package]] -name = "diesel" -version = "1.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b28135ecf6b7d446b43e27e225622a038cc4e2930a1022f51cdb97ada19b8e4d" -dependencies = [ - "byteorder", - "diesel_derives", - "libsqlite3-sys", -] - -[[package]] -name = "diesel_derives" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "diesel_migrations" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf3cde8413353dc7f5d72fa8ce0b99a560a359d2c5ef1e5817ca731cd9008f4c" -dependencies = [ - "migrations_internals", - "migrations_macros", -] - [[package]] name = "digest" version = "0.9.0" @@ -624,15 +568,6 @@ dependencies = [ "termcolor", ] -[[package]] -name = "error-chain" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" -dependencies = [ - "backtrace", -] - [[package]] name = "error-code" version = "0.1.0" @@ -922,12 +857,6 @@ dependencies = [ "wasi 0.10.0+wasi-snapshot-preview1", ] -[[package]] -name = "gimli" -version = "0.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" - [[package]] name = "glob" version = "0.3.0" @@ -1174,21 +1103,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "lib-sqlite" -version = "0.1.0" -dependencies = [ - "diesel", - "diesel_derives", - "diesel_migrations", - "error-chain", - "lazy_static", - "libsqlite3-sys", - "log", - "r2d2", - "scheduled-thread-pool", -] - [[package]] name = "lib-ws" version = "0.1.0" @@ -1222,17 +1136,6 @@ version = "0.2.107" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbe5e23404da5b4f555ef85ebed98fb4083e55a00c317800bc2a50ede9f3d219" -[[package]] -name = "libsqlite3-sys" -version = "0.22.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290b64917f8b0cb885d9de0f9959fe1f775d7fa12f1da2db9001c1c8ab60f89d" -dependencies = [ - "cc", - "pkg-config", - "vcpkg", -] - [[package]] name = "linked-hash-map" version = "0.5.4" @@ -1293,27 +1196,6 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" -[[package]] -name = "migrations_internals" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b4fc84e4af020b837029e017966f86a1c2d5e83e64b589963d5047525995860" -dependencies = [ - "diesel", -] - -[[package]] -name = "migrations_macros" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9753f12909fd8d923f75ae5c3258cae1ed3c8ec052e1b38c93c21a6d157f789c" -dependencies = [ - "migrations_internals", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "mime" version = "0.3.16" @@ -1419,15 +1301,6 @@ dependencies = [ "libc", ] -[[package]] -name = "object" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.8.0" @@ -1622,17 +1495,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "r2d2" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "545c5bc2b880973c9c10e4067418407a0ccaa3091781d1671d46eb35107cb26f" -dependencies = [ - "log", - "parking_lot", - "scheduled-thread-pool", -] - [[package]] name = "rand" version = "0.7.3" @@ -1784,12 +1646,6 @@ dependencies = [ "winreg", ] -[[package]] -name = "rustc-demangle" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" - [[package]] name = "rustc_version" version = "0.2.3" @@ -1824,15 +1680,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "scheduled-thread-pool" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc6f74fd1204073fa02d5d5d68bec8021be4c38690b61264b2fdb48083d0e7d7" -dependencies = [ - "parking_lot", -] - [[package]] name = "scopeguard" version = "1.1.0" diff --git a/shared-lib/Cargo.toml b/shared-lib/Cargo.toml index 9737c6c83c..d4b8372f8c 100644 --- a/shared-lib/Cargo.toml +++ b/shared-lib/Cargo.toml @@ -5,7 +5,6 @@ members = [ "flowy-collaboration", "lib-ot", "lib-ws", - "lib-sqlite", "lib-infra", "backend-service", "flowy-derive", From d3a00b14b02f357a23d2827ed922a76d0ff8e919 Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 20 Dec 2021 15:37:37 +0800 Subject: [PATCH 39/39] enable local web socket --- .../flowy-document/src/services/controller.rs | 2 +- .../src/services/doc/edit/editor.rs | 316 ++--------------- ..._edit_cmd_queue.rs => editor_cmd_queue.rs} | 0 .../src/services/doc/edit/mod.rs | 6 +- .../flowy-document/src/services/doc/mod.rs | 2 +- .../http_ws_impl.rs} | 41 ++- .../services/doc/web_socket/local_ws_impl.rs | 18 + .../src/services/doc/web_socket/mod.rs | 7 + .../src/services/doc/web_socket/web_socket.rs | 333 ++++++++++++++++++ 9 files changed, 406 insertions(+), 319 deletions(-) rename frontend/rust-lib/flowy-document/src/services/doc/edit/{editor_edit_cmd_queue.rs => editor_cmd_queue.rs} (100%) rename frontend/rust-lib/flowy-document/src/services/doc/{edit/editor_web_socket.rs => web_socket/http_ws_impl.rs} (90%) create mode 100644 frontend/rust-lib/flowy-document/src/services/doc/web_socket/local_ws_impl.rs create mode 100644 frontend/rust-lib/flowy-document/src/services/doc/web_socket/mod.rs create mode 100644 frontend/rust-lib/flowy-document/src/services/doc/web_socket/web_socket.rs diff --git a/frontend/rust-lib/flowy-document/src/services/controller.rs b/frontend/rust-lib/flowy-document/src/services/controller.rs index 7ea9a59fe1..7d14d166a0 100644 --- a/frontend/rust-lib/flowy-document/src/services/controller.rs +++ b/frontend/rust-lib/flowy-document/src/services/controller.rs @@ -171,7 +171,7 @@ impl OpenDocCache { pub(crate) fn remove(&self, id: &str) { let doc_id = id.to_string(); match self.get(id) { - Ok(editor) => editor.stop_sync(), + Ok(editor) => editor.stop(), Err(e) => log::error!("{}", e), } self.inner.remove(&doc_id); diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs index f179507f58..f64f05e77d 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor.rs @@ -1,29 +1,27 @@ -use crate::{errors::FlowyError, module::DocumentUser, services::doc::*}; -use bytes::Bytes; -use flowy_collaboration::{ - core::document::history::UndoResult, - entities::{ - doc::DocDelta, - ws::{DocumentWSData, DocumentWSDataBuilder, DocumentWSDataType, NewDocumentUser}, +use crate::{ + errors::FlowyError, + module::DocumentUser, + services::doc::{ + web_socket::{initialize_document_web_socket, DocumentWebSocketContext, EditorWebSocket}, + *, }, - errors::CollaborateResult, }; +use bytes::Bytes; +use flowy_collaboration::{core::document::history::UndoResult, entities::doc::DocDelta, errors::CollaborateResult}; use flowy_database::ConnectionPool; use flowy_error::{internal_error, FlowyResult}; -use lib_infra::future::FutureResult; use lib_ot::{ core::Interval, - revision::{RevId, RevType, Revision, RevisionRange}, + revision::{RevId, RevType, Revision}, rich_text::{RichTextAttribute, RichTextDelta}, }; -use lib_ws::WSConnectState; -use std::{collections::VecDeque, sync::Arc}; -use tokio::sync::{broadcast, mpsc, mpsc::UnboundedSender, oneshot, RwLock}; +use std::sync::Arc; +use tokio::sync::{mpsc, mpsc::UnboundedSender, oneshot}; pub struct ClientDocEditor { pub doc_id: String, rev_manager: Arc, - editor_ws: Arc, + editor_ws: Arc, editor_cmd_sender: UnboundedSender, user: Arc, } @@ -42,34 +40,16 @@ impl ClientDocEditor { let doc_id = doc_id.to_string(); let user_id = user.user_id()?; let rev_manager = Arc::new(rev_manager); - let combined_sink = Arc::new(CombinedSink::new(rev_manager.clone())); - let ws_stream_consumer = Arc::new(DocumentWebSocketSteamConsumerAdapter { - doc_id: doc_id.clone(), + + let context = DocumentWebSocketContext { + doc_id: doc_id.to_owned(), + user_id: user_id.clone(), editor_cmd_sender: editor_cmd_sender.clone(), rev_manager: rev_manager.clone(), - user: user.clone(), - combined_sink: combined_sink.clone(), - }); - let ws_stream_provider = Arc::new(DocumentWSSinkDataProviderAdapter(combined_sink.clone())); - let editor_ws = Arc::new(EditorWebSocket::new( - &doc_id, ws, - ws_stream_provider, - ws_stream_consumer, - )); - - // - notify_user_conn(&user_id, &doc_id, rev_manager.clone(), combined_sink.clone()).await; - - // - listen_document_ws_state( - &user_id, - &doc_id, - editor_ws.scribe_state(), - rev_manager.clone(), - combined_sink, - ); + }; + let editor_ws = initialize_document_web_socket(context).await; let editor = Arc::new(Self { doc_id, rev_manager, @@ -203,9 +183,9 @@ impl ClientDocEditor { } #[tracing::instrument(level = "debug", skip(self))] - pub fn stop_sync(&self) { self.editor_ws.stop(); } + pub fn stop(&self) { self.editor_ws.stop_web_socket(); } - pub(crate) fn ws_handler(&self) -> Arc { self.editor_ws.clone() } + pub(crate) fn ws_handler(&self) -> Arc { self.editor_ws.ws_handler() } } fn spawn_edit_queue(doc_id: &str, delta: RichTextDelta, _pool: Arc) -> UnboundedSender { @@ -215,262 +195,6 @@ fn spawn_edit_queue(doc_id: &str, delta: RichTextDelta, _pool: Arc, - rev_manager: Arc, - sink_data_provider: Arc, -) { - let user_id = user_id.to_owned(); - let doc_id = doc_id.to_owned(); - - tokio::spawn(async move { - while let Ok(state) = subscriber.recv().await { - match state { - WSConnectState::Init => {}, - WSConnectState::Connecting => {}, - WSConnectState::Connected => { - // self.notify_user_conn() - notify_user_conn(&user_id, &doc_id, rev_manager.clone(), sink_data_provider.clone()).await; - }, - WSConnectState::Disconnected => {}, - } - } - }); -} - -async fn notify_user_conn( - user_id: &str, - doc_id: &str, - rev_manager: Arc, - combined_sink: Arc, -) { - let need_notify = match combined_sink.front().await { - None => true, - Some(data) => data.ty != DocumentWSDataType::UserConnect, - }; - - if need_notify { - let new_connect = NewDocumentUser { - user_id: user_id.to_owned(), - doc_id: doc_id.to_owned(), - rev_id: rev_manager.latest_rev_id(), - }; - - let data = DocumentWSDataBuilder::build_new_document_user_message(doc_id, new_connect); - combined_sink.push_front(data).await; - } -} - -struct DocumentWebSocketSteamConsumerAdapter { - doc_id: String, - editor_cmd_sender: UnboundedSender, - rev_manager: Arc, - user: Arc, - combined_sink: Arc, -} - -impl DocumentWSSteamConsumer for DocumentWebSocketSteamConsumerAdapter { - fn receive_push_revision(&self, bytes: Bytes) -> FutureResult<(), FlowyError> { - let user = self.user.clone(); - let rev_manager = self.rev_manager.clone(); - let edit_cmd_tx = self.editor_cmd_sender.clone(); - let combined_sink = self.combined_sink.clone(); - let doc_id = self.doc_id.clone(); - FutureResult::new(async move { - let user_id = user.user_id()?; - if let Some(revision) = handle_push_rev(&doc_id, &user_id, edit_cmd_tx, rev_manager, bytes).await? { - combined_sink.push_back(revision.into()).await; - } - Ok(()) - }) - } - - fn receive_ack(&self, id: String, ty: DocumentWSDataType) -> FutureResult<(), FlowyError> { - let combined_sink = self.combined_sink.clone(); - FutureResult::new(async move { combined_sink.ack(id, ty).await }) - } - - fn receive_new_user_connect(&self, _new_user: NewDocumentUser) -> FutureResult<(), FlowyError> { - FutureResult::new(async move { Ok(()) }) - } - - fn send_revision_in_range(&self, range: RevisionRange) -> FutureResult<(), FlowyError> { - let rev_manager = self.rev_manager.clone(); - let combined_sink = self.combined_sink.clone(); - FutureResult::new(async move { - let revision = rev_manager.mk_revisions(range).await?; - combined_sink.push_back(revision.into()).await; - Ok(()) - }) - } -} - -struct DocumentWSSinkDataProviderAdapter(Arc); -impl DocumentWSSinkDataProvider for DocumentWSSinkDataProviderAdapter { - fn next(&self) -> FutureResult, FlowyError> { - let combined_sink = self.0.clone(); - FutureResult::new(async move { combined_sink.next().await }) - } -} - -#[tracing::instrument(level = "debug", skip(edit_cmd_tx, rev_manager, bytes))] -pub(crate) async fn handle_push_rev( - doc_id: &str, - user_id: &str, - edit_cmd_tx: UnboundedSender, - rev_manager: Arc, - bytes: Bytes, -) -> FlowyResult> { - // Transform the revision - let (ret, rx) = oneshot::channel::>(); - let _ = edit_cmd_tx.send(EditorCommand::ProcessRemoteRevision { bytes, ret }); - let TransformDeltas { - client_prime, - server_prime, - server_rev_id, - } = rx.await.map_err(internal_error)??; - - if rev_manager.rev_id() >= server_rev_id.value { - // Ignore this push revision if local_rev_id >= server_rev_id - return Ok(None); - } - - // compose delta - let (ret, rx) = oneshot::channel::>(); - let msg = EditorCommand::ComposeDelta { - delta: client_prime.clone(), - ret, - }; - let _ = edit_cmd_tx.send(msg); - let md5 = rx.await.map_err(internal_error)??; - - // update rev id - rev_manager.update_rev_id_counter_value(server_rev_id.clone().into()); - let (local_base_rev_id, local_rev_id) = rev_manager.next_rev_id(); - let delta_data = client_prime.to_bytes(); - // save the revision - let revision = Revision::new( - &doc_id, - local_base_rev_id, - local_rev_id, - delta_data, - RevType::Remote, - &user_id, - md5.clone(), - ); - - let _ = rev_manager.add_remote_revision(&revision).await?; - - // send the server_prime delta - let delta_data = server_prime.to_bytes(); - Ok(Some(Revision::new( - &doc_id, - local_base_rev_id, - local_rev_id, - delta_data, - RevType::Remote, - &user_id, - md5, - ))) -} - -#[derive(Clone)] -enum SourceType { - Shared, - Revision, -} - -#[derive(Clone)] -struct CombinedSink { - shared: Arc>>, - rev_manager: Arc, - source_ty: Arc>, -} - -impl CombinedSink { - fn new(rev_manager: Arc) -> Self { - CombinedSink { - shared: Arc::new(RwLock::new(VecDeque::new())), - rev_manager, - source_ty: Arc::new(RwLock::new(SourceType::Shared)), - } - } - - // FIXME: return Option<&DocumentWSData> would be better - async fn front(&self) -> Option { self.shared.read().await.front().cloned() } - - async fn push_front(&self, data: DocumentWSData) { self.shared.write().await.push_front(data); } - - async fn push_back(&self, data: DocumentWSData) { self.shared.write().await.push_back(data); } - - async fn next(&self) -> FlowyResult> { - let source_ty = self.source_ty.read().await.clone(); - match source_ty { - SourceType::Shared => match self.shared.read().await.front() { - None => { - *self.source_ty.write().await = SourceType::Revision; - Ok(None) - }, - Some(data) => { - tracing::debug!("[DocumentSinkDataProvider]: {}:{:?}", data.doc_id, data.ty); - Ok(Some(data.clone())) - }, - }, - SourceType::Revision => { - if !self.shared.read().await.is_empty() { - *self.source_ty.write().await = SourceType::Shared; - return Ok(None); - } - - match self.rev_manager.next_sync_revision().await? { - Some(rev) => { - tracing::debug!("[DocumentSinkDataProvider]: {}:{:?}", rev.doc_id, rev.rev_id); - Ok(Some(rev.into())) - }, - None => Ok(None), - } - }, - } - } - - async fn ack(&self, id: String, _ty: DocumentWSDataType) -> FlowyResult<()> { - // let _ = self.rev_manager.ack_revision(id).await?; - let source_ty = self.source_ty.read().await.clone(); - match source_ty { - SourceType::Shared => { - let should_pop = match self.shared.read().await.front() { - None => false, - Some(val) => { - if val.id == id { - true - } else { - tracing::error!("The front element's {} is not equal to the {}", val.id, id); - false - } - }, - }; - if should_pop { - let _ = self.shared.write().await.pop_front(); - } - }, - SourceType::Revision => { - match id.parse::() { - Ok(rev_id) => { - let _ = self.rev_manager.ack_revision(rev_id).await?; - }, - Err(e) => { - tracing::error!("Parse rev_id from {} failed. {}", id, e); - }, - }; - }, - } - - Ok(()) - } -} - #[cfg(feature = "flowy_unit_test")] impl ClientDocEditor { pub async fn doc_json(&self) -> FlowyResult { diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor_edit_cmd_queue.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/editor_cmd_queue.rs similarity index 100% rename from frontend/rust-lib/flowy-document/src/services/doc/edit/editor_edit_cmd_queue.rs rename to frontend/rust-lib/flowy-document/src/services/doc/edit/editor_cmd_queue.rs diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/mod.rs b/frontend/rust-lib/flowy-document/src/services/doc/edit/mod.rs index cfbe4f27f1..d186ee6957 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/mod.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/edit/mod.rs @@ -1,7 +1,5 @@ mod editor; -mod editor_edit_cmd_queue; -mod editor_web_socket; +mod editor_cmd_queue; pub use editor::*; -pub(crate) use editor_edit_cmd_queue::*; -pub use editor_web_socket::*; +pub(crate) use editor_cmd_queue::*; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/mod.rs b/frontend/rust-lib/flowy-document/src/services/doc/mod.rs index 6b9355e13a..68353587eb 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/mod.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/mod.rs @@ -1,6 +1,6 @@ pub mod edit; pub mod revision; - +mod web_socket; pub use crate::services::ws_handlers::*; pub use edit::*; pub use revision::*; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor_web_socket.rs b/frontend/rust-lib/flowy-document/src/services/doc/web_socket/http_ws_impl.rs similarity index 90% rename from frontend/rust-lib/flowy-document/src/services/doc/edit/editor_web_socket.rs rename to frontend/rust-lib/flowy-document/src/services/doc/web_socket/http_ws_impl.rs index d4315b230f..e4ab97b5aa 100644 --- a/frontend/rust-lib/flowy-document/src/services/doc/edit/editor_web_socket.rs +++ b/frontend/rust-lib/flowy-document/src/services/doc/web_socket/http_ws_impl.rs @@ -1,4 +1,7 @@ -use crate::services::doc::{DocumentWebSocket, DocumentWsHandler, SYNC_INTERVAL_IN_MILLIS}; +use crate::services::{ + doc::{web_socket::web_socket::EditorWebSocket, SYNC_INTERVAL_IN_MILLIS}, + ws_handlers::{DocumentWebSocket, DocumentWsHandler}, +}; use async_stream::stream; use bytes::Bytes; use flowy_collaboration::entities::ws::{DocumentWSData, DocumentWSDataType, NewDocumentUser}; @@ -18,7 +21,7 @@ use tokio::{ time::{interval, Duration}, }; -pub(crate) struct EditorWebSocket { +pub struct EditorHttpWebSocket { doc_id: String, data_provider: Arc, stream_consumer: Arc, @@ -29,8 +32,8 @@ pub(crate) struct EditorWebSocket { state: broadcast::Sender, } -impl EditorWebSocket { - pub(crate) fn new( +impl EditorHttpWebSocket { + pub fn new( doc_id: &str, ws: Arc, data_provider: Arc, @@ -40,7 +43,7 @@ impl EditorWebSocket { let (stop_sync_tx, _) = tokio::sync::broadcast::channel(2); let doc_id = doc_id.to_string(); let (state, _) = broadcast::channel(2); - let mut manager = EditorWebSocket { + let mut manager = EditorHttpWebSocket { doc_id, data_provider, stream_consumer, @@ -50,11 +53,11 @@ impl EditorWebSocket { stop_sync_tx, state, }; - manager.start_sync(); + manager.start_web_socket(); manager } - fn start_sync(&mut self) { + fn start_web_socket(&mut self) { let ws_msg_rx = self.ws_msg_rx.take().expect("Only take once"); let sink = DocumentWebSocketSink::new( &self.doc_id, @@ -72,16 +75,20 @@ impl EditorWebSocket { tokio::spawn(stream.run()); } - pub(crate) fn stop(&self) { + pub fn scribe_state(&self) -> broadcast::Receiver { self.state.subscribe() } +} + +impl EditorWebSocket for Arc { + fn stop_web_socket(&self) { if self.stop_sync_tx.send(()).is_ok() { tracing::debug!("{} stop sync", self.doc_id) } } - pub(crate) fn scribe_state(&self) -> broadcast::Receiver { self.state.subscribe() } + fn ws_handler(&self) -> Arc { self.clone() } } -impl DocumentWsHandler for EditorWebSocket { +impl DocumentWsHandler for EditorHttpWebSocket { fn receive(&self, doc_data: DocumentWSData) { match self.ws_msg_tx.send(doc_data) { Ok(_) => {}, @@ -104,7 +111,7 @@ pub trait DocumentWSSteamConsumer: Send + Sync { fn send_revision_in_range(&self, range: RevisionRange) -> FutureResult<(), FlowyError>; } -pub(crate) struct DocumentWebSocketStream { +pub struct DocumentWebSocketStream { doc_id: String, consumer: Arc, ws_msg_rx: Option>, @@ -112,7 +119,7 @@ pub(crate) struct DocumentWebSocketStream { } impl DocumentWebSocketStream { - pub(crate) fn new( + pub fn new( doc_id: &str, consumer: Arc, ws_msg_rx: mpsc::UnboundedReceiver, @@ -197,15 +204,15 @@ impl DocumentWebSocketStream { } } -pub(crate) type Tick = (); -pub(crate) type SinkStopRx = broadcast::Receiver<()>; -pub(crate) type SinkStopTx = broadcast::Sender<()>; +pub type Tick = (); +pub type SinkStopRx = broadcast::Receiver<()>; +pub type SinkStopTx = broadcast::Sender<()>; pub trait DocumentWSSinkDataProvider: Send + Sync { fn next(&self) -> FutureResult, FlowyError>; } -pub(crate) struct DocumentWebSocketSink { +pub struct DocumentWebSocketSink { provider: Arc, ws_sender: Arc, stop_rx: Option, @@ -213,7 +220,7 @@ pub(crate) struct DocumentWebSocketSink { } impl DocumentWebSocketSink { - pub(crate) fn new( + pub fn new( doc_id: &str, provider: Arc, ws_sender: Arc, diff --git a/frontend/rust-lib/flowy-document/src/services/doc/web_socket/local_ws_impl.rs b/frontend/rust-lib/flowy-document/src/services/doc/web_socket/local_ws_impl.rs new file mode 100644 index 0000000000..6f2d1082d4 --- /dev/null +++ b/frontend/rust-lib/flowy-document/src/services/doc/web_socket/local_ws_impl.rs @@ -0,0 +1,18 @@ +use crate::services::doc::{web_socket::EditorWebSocket, DocumentWsHandler}; +use flowy_collaboration::entities::ws::DocumentWSData; +use lib_ws::WSConnectState; +use std::sync::Arc; + +pub(crate) struct EditorLocalWebSocket {} + +impl EditorWebSocket for Arc { + fn stop_web_socket(&self) {} + + fn ws_handler(&self) -> Arc { self.clone() } +} + +impl DocumentWsHandler for EditorLocalWebSocket { + fn receive(&self, _doc_data: DocumentWSData) {} + + fn connect_state_changed(&self, _state: &WSConnectState) {} +} diff --git a/frontend/rust-lib/flowy-document/src/services/doc/web_socket/mod.rs b/frontend/rust-lib/flowy-document/src/services/doc/web_socket/mod.rs new file mode 100644 index 0000000000..519cff4c02 --- /dev/null +++ b/frontend/rust-lib/flowy-document/src/services/doc/web_socket/mod.rs @@ -0,0 +1,7 @@ +#![allow(clippy::module_inception)] +mod http_ws_impl; +mod local_ws_impl; +mod web_socket; + +pub(crate) use http_ws_impl::*; +pub(crate) use web_socket::*; diff --git a/frontend/rust-lib/flowy-document/src/services/doc/web_socket/web_socket.rs b/frontend/rust-lib/flowy-document/src/services/doc/web_socket/web_socket.rs new file mode 100644 index 0000000000..4d41d06259 --- /dev/null +++ b/frontend/rust-lib/flowy-document/src/services/doc/web_socket/web_socket.rs @@ -0,0 +1,333 @@ +use crate::services::doc::{ + web_socket::{ + local_ws_impl::EditorLocalWebSocket, + DocumentWSSinkDataProvider, + DocumentWSSteamConsumer, + EditorHttpWebSocket, + }, + DocumentMD5, + DocumentWebSocket, + DocumentWsHandler, + EditorCommand, + RevisionManager, + TransformDeltas, +}; +use bytes::Bytes; +use flowy_collaboration::{ + entities::ws::{DocumentWSData, DocumentWSDataBuilder, DocumentWSDataType, NewDocumentUser}, + errors::CollaborateResult, +}; +use flowy_error::{internal_error, FlowyError, FlowyResult}; +use lib_infra::future::FutureResult; +use lib_ot::revision::{RevType, Revision, RevisionRange}; +use lib_ws::WSConnectState; +use std::{collections::VecDeque, sync::Arc}; +use tokio::sync::{broadcast, mpsc::UnboundedSender, oneshot, RwLock}; + +pub(crate) trait EditorWebSocket: Send + Sync { + fn stop_web_socket(&self); + fn ws_handler(&self) -> Arc; +} + +pub(crate) struct DocumentWebSocketContext { + pub(crate) doc_id: String, + pub(crate) user_id: String, + pub(crate) editor_cmd_sender: UnboundedSender, + pub(crate) rev_manager: Arc, + pub(crate) ws: Arc, +} + +pub(crate) async fn initialize_document_web_socket(ctx: DocumentWebSocketContext) -> Arc { + if cfg!(feature = "http_server") { + let combined_sink = Arc::new(CombinedSink::new(ctx.rev_manager.clone())); + let ws_stream_consumer = Arc::new(DocumentWebSocketSteamConsumerAdapter { + doc_id: ctx.doc_id.clone(), + user_id: ctx.user_id.clone(), + editor_cmd_sender: ctx.editor_cmd_sender.clone(), + rev_manager: ctx.rev_manager.clone(), + combined_sink: combined_sink.clone(), + }); + let ws_stream_provider = DocumentWSSinkDataProviderAdapter(combined_sink.clone()); + let editor_ws = Arc::new(EditorHttpWebSocket::new( + &ctx.doc_id, + ctx.ws.clone(), + Arc::new(ws_stream_provider), + ws_stream_consumer, + )); + + notify_user_conn( + &ctx.user_id, + &ctx.doc_id, + ctx.rev_manager.clone(), + combined_sink.clone(), + ) + .await; + + listen_document_ws_state( + &ctx.user_id, + &ctx.doc_id, + editor_ws.scribe_state(), + ctx.rev_manager.clone(), + combined_sink, + ); + + Arc::new(editor_ws) + } else { + Arc::new(Arc::new(EditorLocalWebSocket {})) + } +} + +async fn notify_user_conn( + user_id: &str, + doc_id: &str, + rev_manager: Arc, + combined_sink: Arc, +) { + let need_notify = match combined_sink.front().await { + None => true, + Some(data) => data.ty != DocumentWSDataType::UserConnect, + }; + + if need_notify { + let new_connect = NewDocumentUser { + user_id: user_id.to_owned(), + doc_id: doc_id.to_owned(), + rev_id: rev_manager.latest_rev_id(), + }; + + let data = DocumentWSDataBuilder::build_new_document_user_message(doc_id, new_connect); + combined_sink.push_front(data).await; + } +} + +fn listen_document_ws_state( + user_id: &str, + doc_id: &str, + mut subscriber: broadcast::Receiver, + rev_manager: Arc, + sink_data_provider: Arc, +) { + let user_id = user_id.to_owned(); + let doc_id = doc_id.to_owned(); + + tokio::spawn(async move { + while let Ok(state) = subscriber.recv().await { + match state { + WSConnectState::Init => {}, + WSConnectState::Connecting => {}, + WSConnectState::Connected => { + // self.notify_user_conn() + notify_user_conn(&user_id, &doc_id, rev_manager.clone(), sink_data_provider.clone()).await; + }, + WSConnectState::Disconnected => {}, + } + } + }); +} + +pub(crate) struct DocumentWebSocketSteamConsumerAdapter { + pub(crate) doc_id: String, + pub(crate) user_id: String, + pub(crate) editor_cmd_sender: UnboundedSender, + pub(crate) rev_manager: Arc, + pub(crate) combined_sink: Arc, +} + +impl DocumentWSSteamConsumer for DocumentWebSocketSteamConsumerAdapter { + fn receive_push_revision(&self, bytes: Bytes) -> FutureResult<(), FlowyError> { + let user_id = self.user_id.clone(); + let rev_manager = self.rev_manager.clone(); + let edit_cmd_tx = self.editor_cmd_sender.clone(); + let combined_sink = self.combined_sink.clone(); + let doc_id = self.doc_id.clone(); + FutureResult::new(async move { + if let Some(revision) = handle_push_rev(&doc_id, &user_id, edit_cmd_tx, rev_manager, bytes).await? { + combined_sink.push_back(revision.into()).await; + } + Ok(()) + }) + } + + fn receive_ack(&self, id: String, ty: DocumentWSDataType) -> FutureResult<(), FlowyError> { + let combined_sink = self.combined_sink.clone(); + FutureResult::new(async move { combined_sink.ack(id, ty).await }) + } + + fn receive_new_user_connect(&self, _new_user: NewDocumentUser) -> FutureResult<(), FlowyError> { + FutureResult::new(async move { Ok(()) }) + } + + fn send_revision_in_range(&self, range: RevisionRange) -> FutureResult<(), FlowyError> { + let rev_manager = self.rev_manager.clone(); + let combined_sink = self.combined_sink.clone(); + FutureResult::new(async move { + let revision = rev_manager.mk_revisions(range).await?; + combined_sink.push_back(revision.into()).await; + Ok(()) + }) + } +} + +pub(crate) struct DocumentWSSinkDataProviderAdapter(pub(crate) Arc); +impl DocumentWSSinkDataProvider for DocumentWSSinkDataProviderAdapter { + fn next(&self) -> FutureResult, FlowyError> { + let combined_sink = self.0.clone(); + FutureResult::new(async move { combined_sink.next().await }) + } +} + +#[tracing::instrument(level = "debug", skip(edit_cmd_tx, rev_manager, bytes))] +pub(crate) async fn handle_push_rev( + doc_id: &str, + user_id: &str, + edit_cmd_tx: UnboundedSender, + rev_manager: Arc, + bytes: Bytes, +) -> FlowyResult> { + // Transform the revision + let (ret, rx) = oneshot::channel::>(); + let _ = edit_cmd_tx.send(EditorCommand::ProcessRemoteRevision { bytes, ret }); + let TransformDeltas { + client_prime, + server_prime, + server_rev_id, + } = rx.await.map_err(internal_error)??; + + if rev_manager.rev_id() >= server_rev_id.value { + // Ignore this push revision if local_rev_id >= server_rev_id + return Ok(None); + } + + // compose delta + let (ret, rx) = oneshot::channel::>(); + let msg = EditorCommand::ComposeDelta { + delta: client_prime.clone(), + ret, + }; + let _ = edit_cmd_tx.send(msg); + let md5 = rx.await.map_err(internal_error)??; + + // update rev id + rev_manager.update_rev_id_counter_value(server_rev_id.clone().into()); + let (local_base_rev_id, local_rev_id) = rev_manager.next_rev_id(); + let delta_data = client_prime.to_bytes(); + // save the revision + let revision = Revision::new( + &doc_id, + local_base_rev_id, + local_rev_id, + delta_data, + RevType::Remote, + &user_id, + md5.clone(), + ); + + let _ = rev_manager.add_remote_revision(&revision).await?; + + // send the server_prime delta + let delta_data = server_prime.to_bytes(); + Ok(Some(Revision::new( + &doc_id, + local_base_rev_id, + local_rev_id, + delta_data, + RevType::Remote, + &user_id, + md5, + ))) +} + +#[derive(Clone)] +enum SourceType { + Shared, + Revision, +} + +#[derive(Clone)] +pub(crate) struct CombinedSink { + shared: Arc>>, + rev_manager: Arc, + source_ty: Arc>, +} + +impl CombinedSink { + pub(crate) fn new(rev_manager: Arc) -> Self { + CombinedSink { + shared: Arc::new(RwLock::new(VecDeque::new())), + rev_manager, + source_ty: Arc::new(RwLock::new(SourceType::Shared)), + } + } + + // FIXME: return Option<&DocumentWSData> would be better + pub(crate) async fn front(&self) -> Option { self.shared.read().await.front().cloned() } + + pub(crate) async fn push_front(&self, data: DocumentWSData) { self.shared.write().await.push_front(data); } + + async fn push_back(&self, data: DocumentWSData) { self.shared.write().await.push_back(data); } + + async fn next(&self) -> FlowyResult> { + let source_ty = self.source_ty.read().await.clone(); + match source_ty { + SourceType::Shared => match self.shared.read().await.front() { + None => { + *self.source_ty.write().await = SourceType::Revision; + Ok(None) + }, + Some(data) => { + tracing::debug!("[DocumentSinkDataProvider]: {}:{:?}", data.doc_id, data.ty); + Ok(Some(data.clone())) + }, + }, + SourceType::Revision => { + if !self.shared.read().await.is_empty() { + *self.source_ty.write().await = SourceType::Shared; + return Ok(None); + } + + match self.rev_manager.next_sync_revision().await? { + Some(rev) => { + tracing::debug!("[DocumentSinkDataProvider]: {}:{:?}", rev.doc_id, rev.rev_id); + Ok(Some(rev.into())) + }, + None => Ok(None), + } + }, + } + } + + async fn ack(&self, id: String, _ty: DocumentWSDataType) -> FlowyResult<()> { + // let _ = self.rev_manager.ack_revision(id).await?; + let source_ty = self.source_ty.read().await.clone(); + match source_ty { + SourceType::Shared => { + let should_pop = match self.shared.read().await.front() { + None => false, + Some(val) => { + if val.id == id { + true + } else { + tracing::error!("The front element's {} is not equal to the {}", val.id, id); + false + } + }, + }; + if should_pop { + let _ = self.shared.write().await.pop_front(); + } + }, + SourceType::Revision => { + match id.parse::() { + Ok(rev_id) => { + let _ = self.rev_manager.ack_revision(rev_id).await?; + }, + Err(e) => { + tracing::error!("Parse rev_id from {} failed. {}", id, e); + }, + }; + }, + } + + Ok(()) + } +}