From d1b7fd29a6ad1108534969b59ac812981e3ce6eb Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 17 Oct 2021 22:44:51 +0800 Subject: [PATCH] [client]: crud with trash on server & fix some bugs --- .../application/trash/trash_bloc.dart | 2 +- app_flowy/lib/workspace/domain/i_trash.dart | 2 +- .../infrastructure/i_trash_impl.dart | 4 +- .../infrastructure/repos/trash_repo.dart | 11 +- .../flowy_sdk/lib/dispatch/code_gen.dart | 30 +- .../protobuf/flowy-workspace/protobuf.dart | 1 - .../flowy-workspace/trash_create.pb.dart | 67 +++- .../flowy-workspace/trash_create.pbjson.dart | 20 +- .../flowy-workspace/trash_delete.pb.dart | 99 ----- .../flowy-workspace/trash_delete.pbenum.dart | 7 - .../flowy-workspace/trash_delete.pbjson.dart | 30 -- .../trash_delete.pbserver.dart | 9 - backend/src/application.rs | 4 +- backend/src/service/trash/router.rs | 25 +- backend/src/service/trash/trash.rs | 29 +- backend/tests/api/workspace.rs | 27 +- backend/tests/helper.rs | 21 +- .../src/derive_cache/derive_cache.rs | 3 +- rust-lib/flowy-infra/Cargo.toml | 2 +- rust-lib/flowy-infra/src/retry/future.rs | 26 +- rust-lib/flowy-net/src/config.rs | 2 + .../src/entities/app/app_delete.rs | 2 +- .../flowy-workspace/src/entities/trash/mod.rs | 2 - .../src/entities/trash/trash_create.rs | 23 +- .../src/entities/trash/trash_delete.rs | 13 - rust-lib/flowy-workspace/src/event.rs | 2 +- .../src/handlers/trash_handler.rs | 8 +- rust-lib/flowy-workspace/src/module.rs | 2 +- .../flowy-workspace/src/protobuf/model/mod.rs | 3 - .../src/protobuf/model/trash_create.rs | 295 +++++++++++--- .../src/protobuf/model/trash_delete.rs | 368 ------------------ .../src/protobuf/proto/trash_create.proto | 5 +- .../src/protobuf/proto/trash_delete.proto | 8 - .../src/services/app_controller.rs | 55 ++- rust-lib/flowy-workspace/src/services/mod.rs | 1 + .../src/services/server/mod.rs | 8 + .../src/services/server/server_api.rs | 24 +- .../src/services/server/server_api_mock.rs | 16 + .../flowy-workspace/src/services/trash_can.rs | 237 +++++++---- rust-lib/flowy-workspace/src/services/util.rs | 72 ++++ .../src/services/view_controller.rs | 61 ++- .../src/services/workspace_controller.rs | 1 + .../src/sql_tables/app/app_sql.rs | 13 +- .../src/sql_tables/view/view_sql.rs | 2 +- .../tests/workspace/view_test.rs | 6 +- 45 files changed, 810 insertions(+), 838 deletions(-) delete mode 100644 app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/trash_delete.pb.dart delete mode 100644 app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/trash_delete.pbenum.dart delete mode 100644 app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/trash_delete.pbjson.dart delete mode 100644 app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/trash_delete.pbserver.dart delete mode 100644 rust-lib/flowy-workspace/src/entities/trash/trash_delete.rs delete mode 100644 rust-lib/flowy-workspace/src/protobuf/model/trash_delete.rs delete mode 100644 rust-lib/flowy-workspace/src/protobuf/proto/trash_delete.proto create mode 100644 rust-lib/flowy-workspace/src/services/util.rs diff --git a/app_flowy/lib/workspace/application/trash/trash_bloc.dart b/app_flowy/lib/workspace/application/trash/trash_bloc.dart index 8e9b0afdc5..8928131910 100644 --- a/app_flowy/lib/workspace/application/trash/trash_bloc.dart +++ b/app_flowy/lib/workspace/application/trash/trash_bloc.dart @@ -34,7 +34,7 @@ class TrashBloc extends Bloc { ); }, delete: (e) async* { - final result = await iTrash.delete(e.trashId); + final result = await iTrash.deleteViews([e.trashId]); result.fold((l) {}, (error) {}); }, deleteAll: (e) async* {}, diff --git a/app_flowy/lib/workspace/domain/i_trash.dart b/app_flowy/lib/workspace/domain/i_trash.dart index 69963bccd1..1c9c7313d3 100644 --- a/app_flowy/lib/workspace/domain/i_trash.dart +++ b/app_flowy/lib/workspace/domain/i_trash.dart @@ -8,7 +8,7 @@ abstract class ITrash { Future> putback(String trashId); - Future> delete(String trashId); + Future> deleteViews(List trashIds); } typedef TrashUpdatedCallback = void Function(Either, WorkspaceError> trashOrFailed); diff --git a/app_flowy/lib/workspace/infrastructure/i_trash_impl.dart b/app_flowy/lib/workspace/infrastructure/i_trash_impl.dart index ac5aa6fe1b..19578defd0 100644 --- a/app_flowy/lib/workspace/infrastructure/i_trash_impl.dart +++ b/app_flowy/lib/workspace/infrastructure/i_trash_impl.dart @@ -25,8 +25,8 @@ class ITrashImpl implements ITrash { } @override - Future> delete(String trashId) { - return repo.delete(trashId); + Future> deleteViews(List trashIds) { + return repo.deleteViews(trashIds); } } diff --git a/app_flowy/lib/workspace/infrastructure/repos/trash_repo.dart b/app_flowy/lib/workspace/infrastructure/repos/trash_repo.dart index 80d73bbeea..46a4653303 100644 --- a/app_flowy/lib/workspace/infrastructure/repos/trash_repo.dart +++ b/app_flowy/lib/workspace/infrastructure/repos/trash_repo.dart @@ -8,7 +8,6 @@ import 'package:flowy_sdk/protobuf/flowy-dart-notify/subject.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-workspace/trash_create.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-workspace/trash_delete.pb.dart'; import 'package:flowy_sdk/rust_stream.dart'; class TrashRepo { @@ -22,9 +21,13 @@ class TrashRepo { return WorkspaceEventPutbackTrash(id).send(); } - Future> delete(String trashId) { - final id = TrashIdentifier.create()..id = trashId; - return WorkspaceEventDeleteTrash(id).send(); + Future> deleteViews(List viewIds) { + final trashIdentifiers = TrashIdentifiers( + items: viewIds.map((id) => TrashIdentifier.create() + ..id = id + ..ty = TrashType.View)); + + return WorkspaceEventDeleteTrash(trashIdentifiers).send(); } } diff --git a/app_flowy/packages/flowy_sdk/lib/dispatch/code_gen.dart b/app_flowy/packages/flowy_sdk/lib/dispatch/code_gen.dart index d6b086d59b..c5264caa02 100644 --- a/app_flowy/packages/flowy_sdk/lib/dispatch/code_gen.dart +++ b/app_flowy/packages/flowy_sdk/lib/dispatch/code_gen.dart @@ -303,7 +303,7 @@ class WorkspaceEventPutbackTrash { } class WorkspaceEventDeleteTrash { - TrashIdentifier request; + TrashIdentifiers request; WorkspaceEventDeleteTrash(this.request); Future> send() { @@ -319,6 +319,34 @@ class WorkspaceEventDeleteTrash { } } +class WorkspaceEventRestoreAll { + WorkspaceEventRestoreAll(); + + 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)), + )); + } +} + +class WorkspaceEventDeleteAll { + WorkspaceEventDeleteAll(); + + 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)), + )); + } +} + class WorkspaceEventInitWorkspace { WorkspaceEventInitWorkspace(); diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/protobuf.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/protobuf.dart index 9f0a099add..cc3dd5d3f9 100644 --- a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/protobuf.dart +++ b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/protobuf.dart @@ -5,7 +5,6 @@ export './app_query.pb.dart'; export './workspace_delete.pb.dart'; export './observable.pb.dart'; export './errors.pb.dart'; -export './trash_delete.pb.dart'; export './workspace_update.pb.dart'; export './app_create.pb.dart'; export './workspace_query.pb.dart'; diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/trash_create.pb.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/trash_create.pb.dart index c078f05b67..b4e46d194c 100644 --- a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/trash_create.pb.dart +++ b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/trash_create.pb.dart @@ -14,15 +14,56 @@ import 'trash_create.pbenum.dart'; export 'trash_create.pbenum.dart'; -class CreateTrashParams extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'CreateTrashParams', createEmptyInstance: create) +class TrashIdentifiers extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'TrashIdentifiers', createEmptyInstance: create) + ..pc(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'items', $pb.PbFieldType.PM, subBuilder: TrashIdentifier.create) + ..hasRequiredFields = false + ; + + TrashIdentifiers._() : super(); + factory TrashIdentifiers({ + $core.Iterable? items, + }) { + final _result = create(); + if (items != null) { + _result.items.addAll(items); + } + return _result; + } + factory TrashIdentifiers.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory TrashIdentifiers.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') + TrashIdentifiers clone() => TrashIdentifiers()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + TrashIdentifiers copyWith(void Function(TrashIdentifiers) updates) => super.copyWith((message) => updates(message as TrashIdentifiers)) as TrashIdentifiers; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static TrashIdentifiers create() => TrashIdentifiers._(); + TrashIdentifiers createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static TrashIdentifiers getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static TrashIdentifiers? _defaultInstance; + + @$pb.TagNumber(1) + $core.List get items => $_getList(0); +} + +class TrashIdentifier extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'TrashIdentifier', createEmptyInstance: create) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id') ..e(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'ty', $pb.PbFieldType.OE, defaultOrMaker: TrashType.Unknown, valueOf: TrashType.valueOf, enumValues: TrashType.values) ..hasRequiredFields = false ; - CreateTrashParams._() : super(); - factory CreateTrashParams({ + TrashIdentifier._() : super(); + factory TrashIdentifier({ $core.String? id, TrashType? ty, }) { @@ -35,26 +76,26 @@ class CreateTrashParams extends $pb.GeneratedMessage { } return _result; } - factory CreateTrashParams.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory CreateTrashParams.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + factory TrashIdentifier.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory TrashIdentifier.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') - CreateTrashParams clone() => CreateTrashParams()..mergeFromMessage(this); + TrashIdentifier clone() => TrashIdentifier()..mergeFromMessage(this); @$core.Deprecated( 'Using this can add significant overhead to your binary. ' 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 'Will be removed in next major version') - CreateTrashParams copyWith(void Function(CreateTrashParams) updates) => super.copyWith((message) => updates(message as CreateTrashParams)) as CreateTrashParams; // ignore: deprecated_member_use + TrashIdentifier copyWith(void Function(TrashIdentifier) updates) => super.copyWith((message) => updates(message as TrashIdentifier)) as TrashIdentifier; // ignore: deprecated_member_use $pb.BuilderInfo get info_ => _i; @$core.pragma('dart2js:noInline') - static CreateTrashParams create() => CreateTrashParams._(); - CreateTrashParams createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); + static TrashIdentifier create() => TrashIdentifier._(); + TrashIdentifier createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); @$core.pragma('dart2js:noInline') - static CreateTrashParams getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static CreateTrashParams? _defaultInstance; + static TrashIdentifier getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static TrashIdentifier? _defaultInstance; @$pb.TagNumber(1) $core.String get id => $_getSZ(0); diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/trash_create.pbjson.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/trash_create.pbjson.dart index 0297e735c3..cc34e7e780 100644 --- a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/trash_create.pbjson.dart +++ b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/trash_create.pbjson.dart @@ -19,17 +19,27 @@ const TrashType$json = const { /// Descriptor for `TrashType`. Decode as a `google.protobuf.EnumDescriptorProto`. final $typed_data.Uint8List trashTypeDescriptor = $convert.base64Decode('CglUcmFzaFR5cGUSCwoHVW5rbm93bhAAEggKBFZpZXcQAQ=='); -@$core.Deprecated('Use createTrashParamsDescriptor instead') -const CreateTrashParams$json = const { - '1': 'CreateTrashParams', +@$core.Deprecated('Use trashIdentifiersDescriptor instead') +const TrashIdentifiers$json = const { + '1': 'TrashIdentifiers', + '2': const [ + const {'1': 'items', '3': 1, '4': 3, '5': 11, '6': '.TrashIdentifier', '10': 'items'}, + ], +}; + +/// Descriptor for `TrashIdentifiers`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List trashIdentifiersDescriptor = $convert.base64Decode('ChBUcmFzaElkZW50aWZpZXJzEiYKBWl0ZW1zGAEgAygLMhAuVHJhc2hJZGVudGlmaWVyUgVpdGVtcw=='); +@$core.Deprecated('Use trashIdentifierDescriptor instead') +const TrashIdentifier$json = const { + '1': 'TrashIdentifier', '2': const [ const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'}, const {'1': 'ty', '3': 2, '4': 1, '5': 14, '6': '.TrashType', '10': 'ty'}, ], }; -/// Descriptor for `CreateTrashParams`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List createTrashParamsDescriptor = $convert.base64Decode('ChFDcmVhdGVUcmFzaFBhcmFtcxIOCgJpZBgBIAEoCVICaWQSGgoCdHkYAiABKA4yCi5UcmFzaFR5cGVSAnR5'); +/// Descriptor for `TrashIdentifier`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List trashIdentifierDescriptor = $convert.base64Decode('Cg9UcmFzaElkZW50aWZpZXISDgoCaWQYASABKAlSAmlkEhoKAnR5GAIgASgOMgouVHJhc2hUeXBlUgJ0eQ=='); @$core.Deprecated('Use trashDescriptor instead') const Trash$json = const { '1': 'Trash', diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/trash_delete.pb.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/trash_delete.pb.dart deleted file mode 100644 index f0cd4c65be..0000000000 --- a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/trash_delete.pb.dart +++ /dev/null @@ -1,99 +0,0 @@ -/// -// Generated code. Do not modify. -// source: trash_delete.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 TrashIdentifier extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'TrashIdentifier', createEmptyInstance: create) - ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id') - ..hasRequiredFields = false - ; - - TrashIdentifier._() : super(); - factory TrashIdentifier({ - $core.String? id, - }) { - final _result = create(); - if (id != null) { - _result.id = id; - } - return _result; - } - factory TrashIdentifier.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory TrashIdentifier.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') - TrashIdentifier clone() => TrashIdentifier()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - TrashIdentifier copyWith(void Function(TrashIdentifier) updates) => super.copyWith((message) => updates(message as TrashIdentifier)) as TrashIdentifier; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static TrashIdentifier create() => TrashIdentifier._(); - TrashIdentifier createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static TrashIdentifier getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static TrashIdentifier? _defaultInstance; - - @$pb.TagNumber(1) - $core.String get id => $_getSZ(0); - @$pb.TagNumber(1) - set id($core.String v) { $_setString(0, v); } - @$pb.TagNumber(1) - $core.bool hasId() => $_has(0); - @$pb.TagNumber(1) - void clearId() => clearField(1); -} - -class TrashIdentifiers extends $pb.GeneratedMessage { - static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'TrashIdentifiers', createEmptyInstance: create) - ..pPS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'ids') - ..hasRequiredFields = false - ; - - TrashIdentifiers._() : super(); - factory TrashIdentifiers({ - $core.Iterable<$core.String>? ids, - }) { - final _result = create(); - if (ids != null) { - _result.ids.addAll(ids); - } - return _result; - } - factory TrashIdentifiers.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); - factory TrashIdentifiers.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') - TrashIdentifiers clone() => TrashIdentifiers()..mergeFromMessage(this); - @$core.Deprecated( - 'Using this can add significant overhead to your binary. ' - 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' - 'Will be removed in next major version') - TrashIdentifiers copyWith(void Function(TrashIdentifiers) updates) => super.copyWith((message) => updates(message as TrashIdentifiers)) as TrashIdentifiers; // ignore: deprecated_member_use - $pb.BuilderInfo get info_ => _i; - @$core.pragma('dart2js:noInline') - static TrashIdentifiers create() => TrashIdentifiers._(); - TrashIdentifiers createEmptyInstance() => create(); - static $pb.PbList createRepeated() => $pb.PbList(); - @$core.pragma('dart2js:noInline') - static TrashIdentifiers getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static TrashIdentifiers? _defaultInstance; - - @$pb.TagNumber(1) - $core.List<$core.String> get ids => $_getList(0); -} - diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/trash_delete.pbenum.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/trash_delete.pbenum.dart deleted file mode 100644 index 6d5f0d0377..0000000000 --- a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/trash_delete.pbenum.dart +++ /dev/null @@ -1,7 +0,0 @@ -/// -// Generated code. Do not modify. -// source: trash_delete.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/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/trash_delete.pbjson.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/trash_delete.pbjson.dart deleted file mode 100644 index 450cf92672..0000000000 --- a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/trash_delete.pbjson.dart +++ /dev/null @@ -1,30 +0,0 @@ -/// -// Generated code. Do not modify. -// source: trash_delete.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 trashIdentifierDescriptor instead') -const TrashIdentifier$json = const { - '1': 'TrashIdentifier', - '2': const [ - const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'}, - ], -}; - -/// Descriptor for `TrashIdentifier`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List trashIdentifierDescriptor = $convert.base64Decode('Cg9UcmFzaElkZW50aWZpZXISDgoCaWQYASABKAlSAmlk'); -@$core.Deprecated('Use trashIdentifiersDescriptor instead') -const TrashIdentifiers$json = const { - '1': 'TrashIdentifiers', - '2': const [ - const {'1': 'ids', '3': 1, '4': 3, '5': 9, '10': 'ids'}, - ], -}; - -/// Descriptor for `TrashIdentifiers`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List trashIdentifiersDescriptor = $convert.base64Decode('ChBUcmFzaElkZW50aWZpZXJzEhAKA2lkcxgBIAMoCVIDaWRz'); diff --git a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/trash_delete.pbserver.dart b/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/trash_delete.pbserver.dart deleted file mode 100644 index 324916470e..0000000000 --- a/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-workspace/trash_delete.pbserver.dart +++ /dev/null @@ -1,9 +0,0 @@ -/// -// Generated code. Do not modify. -// source: trash_delete.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 'trash_delete.pb.dart'; - diff --git a/backend/src/application.rs b/backend/src/application.rs index 47771fa1fe..217f5ee629 100644 --- a/backend/src/application.rs +++ b/backend/src/application.rs @@ -2,7 +2,7 @@ use std::{net::TcpListener, time::Duration}; use actix::Actor; use actix_identity::{CookieIdentityPolicy, IdentityService}; -use actix_web::{dev::Server, web, web::Data, App, HttpServer, Scope}; +use actix_web::{dev::Server, middleware, web, web::Data, App, HttpServer, Scope}; use sqlx::{postgres::PgPoolOptions, PgPool}; use tokio::time::interval; @@ -51,7 +51,7 @@ pub fn run(listener: TcpListener, app_ctx: AppContext) -> Result, logged_user: LoggedUser, ) -> Result { - let params: CreateTrashParams = parse_from_payload(payload).await?; + let params: TrashIdentifiers = parse_from_payload(payload).await?; let mut transaction = pool .begin() .await .context("Failed to acquire a Postgres connection to create trash")?; - - let trash_id = check_trash_id(params.id)?; - let ty = TrashTypeParser::parse(params.ty.value()).map_err(invalid_params)?; - let _ = create_trash(&mut transaction, trash_id, ty, logged_user).await?; + log::error!("😁create handler: {:?}", params); + let _ = create_trash(&mut transaction, make_records(params)?, logged_user).await?; transaction .commit() @@ -54,8 +53,7 @@ pub async fn delete_handler( .await .context("Failed to acquire a Postgres connection to delete trash")?; - let trash_ids = check_trash_ids(params.ids.into_vec())?; - let _ = delete_trash(&mut transaction, trash_ids, &logged_user).await?; + let _ = delete_trash(&mut transaction, make_records(params)?, &logged_user).await?; transaction .commit() .await @@ -86,10 +84,11 @@ fn check_trash_id(id: String) -> Result { Ok(trash_id) } -fn check_trash_ids(ids: Vec) -> Result, ServerError> { - let mut trash_ids = vec![]; - for id in ids { - trash_ids.push(check_trash_id(id)?) +fn make_records(identifiers: TrashIdentifiers) -> Result, ServerError> { + let mut records = vec![]; + for identifier in identifiers.items { + let ty = TrashTypeParser::parse(identifier.ty.value()).map_err(invalid_params)?; + records.push((check_trash_id(identifier.id.to_owned())?, ty)); } - Ok(trash_ids) + Ok(records) } diff --git a/backend/src/service/trash/trash.rs b/backend/src/service/trash/trash.rs index b7d40a2651..879f8c2d8e 100644 --- a/backend/src/service/trash/trash.rs +++ b/backend/src/service/trash/trash.rs @@ -8,36 +8,37 @@ use crate::{ }; use ::protobuf::ProtobufEnum; use flowy_net::errors::ServerError; -use flowy_workspace::protobuf::{RepeatedTrash, Trash, TrashIdentifiers, TrashType}; +use flowy_workspace::protobuf::{RepeatedTrash, Trash, TrashType}; use sqlx::{postgres::PgArguments, Postgres}; use uuid::Uuid; pub(crate) async fn create_trash( transaction: &mut DBTransaction<'_>, - trash_id: Uuid, - ty: i32, + records: Vec<(Uuid, i32)>, user: LoggedUser, ) -> Result<(), ServerError> { - let (sql, args) = SqlBuilder::create(TRASH_TABLE) - .add_arg("id", trash_id) - .add_arg("user_id", &user.user_id) - .add_arg("ty", ty) - .build()?; + for (trash_id, ty) in records { + let (sql, args) = SqlBuilder::create(TRASH_TABLE) + .add_arg("id", trash_id) + .add_arg("user_id", &user.user_id) + .add_arg("ty", ty) + .build()?; - let _ = sqlx::query_with(&sql, args) - .execute(transaction) - .await - .map_err(map_sqlx_error)?; + let _ = sqlx::query_with(&sql, args) + .execute(transaction as &mut DBTransaction<'_>) + .await + .map_err(map_sqlx_error)?; + } Ok(()) } pub(crate) async fn delete_trash( transaction: &mut DBTransaction<'_>, - trash_ids: Vec, + records: Vec<(Uuid, i32)>, _user: &LoggedUser, ) -> Result<(), ServerError> { - for trash_id in trash_ids { + for (trash_id, _) in records { // Read the trash_table and delete the original table according to the TrashType let (sql, args) = SqlBuilder::select(TRASH_TABLE) .add_field("*") diff --git a/backend/tests/api/workspace.rs b/backend/tests/api/workspace.rs index 2589aae45e..a8c4ac1169 100644 --- a/backend/tests/api/workspace.rs +++ b/backend/tests/api/workspace.rs @@ -1,7 +1,6 @@ use crate::helper::*; use flowy_workspace::entities::{ app::{AppIdentifier, DeleteAppParams, UpdateAppParams}, - trash::{CreateTrashParams, TrashIdentifiers, TrashType}, view::{UpdateViewParams, ViewIdentifier}, workspace::{CreateWorkspaceParams, DeleteWorkspaceParams, QueryWorkspaceParams, UpdateWorkspaceParams}, }; @@ -98,11 +97,7 @@ async fn app_read_with_belongs_in_trash() { let _ = create_test_view(&test.server, &test.app.id).await; let view = create_test_view(&test.server, &test.app.id).await; - let params = CreateTrashParams { - id: view.id.clone(), - ty: TrashType::View, - }; - test.server.create_trash(params).await; + test.server.create_view_trash(&view.id).await; let read_params = AppIdentifier::new(&test.app.id); let app = test.server.read_app(read_params).await.unwrap(); @@ -159,13 +154,7 @@ async fn view_update() { #[actix_rt::test] async fn view_delete() { let test = ViewTest::new().await; - - // delete - let params = CreateTrashParams { - id: test.view.id.clone(), - ty: TrashType::View, - }; - test.server.create_trash(params).await; + test.server.create_view_trash(&test.view.id).await; let trash_ids = test .server @@ -186,16 +175,8 @@ async fn view_delete() { #[actix_rt::test] async fn view_delete_and_then_delete_the_trash_record() { let test = ViewTest::new().await; - let params = CreateTrashParams { - id: test.view.id.clone(), - ty: TrashType::View, - }; - test.server.create_trash(params).await; - test.server - .delete_trash(TrashIdentifiers { - ids: vec![test.view.id.clone()], - }) - .await; + test.server.create_view_trash(&test.view.id).await; + test.server.delete_view_trash(&test.view.id).await; assert_eq!(test.server.read_trash().await.is_empty(), true); } diff --git a/backend/tests/helper.rs b/backend/tests/helper.rs index f6230c9f89..802b602aa6 100644 --- a/backend/tests/helper.rs +++ b/backend/tests/helper.rs @@ -122,14 +122,27 @@ impl TestUserServer { delete_view_request(self.user_token(), params, &url).await.unwrap(); } - pub async fn create_trash(&self, params: CreateTrashParams) { + pub async fn create_view_trash(&self, view_id: &str) { + let identifier = TrashIdentifier { + id: view_id.to_string(), + ty: TrashType::View, + }; let url = format!("{}/api/trash", self.http_addr()); - create_trash_request(self.user_token(), params, &url).await.unwrap(); + create_trash_request(self.user_token(), vec![identifier].into(), &url) + .await + .unwrap(); } - pub async fn delete_trash(&self, params: TrashIdentifiers) { + pub async fn delete_view_trash(&self, trash_id: &str) { let url = format!("{}/api/trash", self.http_addr()); - delete_trash_request(self.user_token(), params, &url).await.unwrap(); + + let identifier = TrashIdentifier { + id: trash_id.to_string(), + ty: TrashType::View, + }; + delete_trash_request(self.user_token(), vec![identifier].into(), &url) + .await + .unwrap(); } pub async fn read_trash(&self) -> RepeatedTrash { diff --git a/rust-lib/flowy-derive/src/derive_cache/derive_cache.rs b/rust-lib/flowy-derive/src/derive_cache/derive_cache.rs index ecbee465a9..21c2446b29 100644 --- a/rust-lib/flowy-derive/src/derive_cache/derive_cache.rs +++ b/rust-lib/flowy-derive/src/derive_cache/derive_cache.rs @@ -38,9 +38,8 @@ pub fn category_from_str(type_str: &str) -> TypeCategory { | "QueryWorkspaceRequest" | "QueryWorkspaceParams" | "CurrentWorkspace" - | "TrashIdentifier" | "TrashIdentifiers" - | "CreateTrashParams" + | "TrashIdentifier" | "Trash" | "RepeatedTrash" | "UpdateViewRequest" diff --git a/rust-lib/flowy-infra/Cargo.toml b/rust-lib/flowy-infra/Cargo.toml index d96339652d..88fbfbb911 100644 --- a/rust-lib/flowy-infra/Cargo.toml +++ b/rust-lib/flowy-infra/Cargo.toml @@ -19,5 +19,5 @@ chrono = "0.4.19" bytes = { version = "1.0" } pin-project = "1.0" futures-core = { version = "0.3", default-features = false } -tokio = { version = "1.0", features = ["time"] } +tokio = { version = "1.0", features = ["time", "rt"] } rand = "0.8.3" \ No newline at end of file diff --git a/rust-lib/flowy-infra/src/retry/future.rs b/rust-lib/flowy-infra/src/retry/future.rs index 35b15077b0..d31d76a3d4 100644 --- a/rust-lib/flowy-infra/src/retry/future.rs +++ b/rust-lib/flowy-infra/src/retry/future.rs @@ -1,3 +1,4 @@ +use crate::retry::FixedInterval; use pin_project::pin_project; use std::{ future::Future, @@ -5,7 +6,10 @@ use std::{ pin::Pin, task::{Context, Poll}, }; -use tokio::time::{sleep_until, Duration, Instant, Sleep}; +use tokio::{ + task::JoinHandle, + time::{sleep_until, Duration, Instant, Sleep}, +}; #[pin_project(project = RetryStateProj)] enum RetryState @@ -171,9 +175,8 @@ pub trait Action: Send + Sync { fn run(&mut self) -> Self::Future; } - -// impl>, F: FnMut() -> T> Action for F { -// type Future = T; +// impl>, F: FnMut() -> T + Send + Sync> +// Action for F { type Future = T; // type Item = R; // type Error = E; // @@ -187,3 +190,18 @@ pub trait Condition { impl bool> Condition for F { fn should_retry(&mut self, error: &E) -> bool { self(error) } } + +pub fn spawn_retry( + millis: u64, + retry_count: usize, + action: A, +) -> JoinHandle> +where + A::Item: Send + Sync, + A::Error: Send + Sync, + ::Future: Send + Sync, +{ + let strategy = FixedInterval::from_millis(millis).take(retry_count); + let retry = Retry::spawn(strategy, action); + tokio::spawn(async move { retry.await }) +} diff --git a/rust-lib/flowy-net/src/config.rs b/rust-lib/flowy-net/src/config.rs index 585c1e4f86..4b00925411 100644 --- a/rust-lib/flowy-net/src/config.rs +++ b/rust-lib/flowy-net/src/config.rs @@ -47,5 +47,7 @@ impl ServerConfig { pub fn doc_url(&self) -> String { format!("{}{}/api/doc", self.scheme(), self.host) } + pub fn trash_url(&self) -> String { format!("{}{}/api/trash", self.scheme(), self.host) } + pub fn ws_addr(&self) -> String { format!("{}://{}/ws", self.ws_schema, self.host) } } diff --git a/rust-lib/flowy-workspace/src/entities/app/app_delete.rs b/rust-lib/flowy-workspace/src/entities/app/app_delete.rs index 0a9213ad8f..b43f9ad9fa 100644 --- a/rust-lib/flowy-workspace/src/entities/app/app_delete.rs +++ b/rust-lib/flowy-workspace/src/entities/app/app_delete.rs @@ -8,7 +8,7 @@ pub struct DeleteAppRequest { pub app_id: String, } -#[derive(Default, ProtoBuf)] +#[derive(Default, ProtoBuf, Clone)] pub struct DeleteAppParams { #[pb(index = 1)] pub app_id: String, diff --git a/rust-lib/flowy-workspace/src/entities/trash/mod.rs b/rust-lib/flowy-workspace/src/entities/trash/mod.rs index 76305cd84d..fcc84e4f3f 100644 --- a/rust-lib/flowy-workspace/src/entities/trash/mod.rs +++ b/rust-lib/flowy-workspace/src/entities/trash/mod.rs @@ -1,6 +1,4 @@ pub mod parser; mod trash_create; -mod trash_delete; pub use trash_create::*; -pub use trash_delete::*; diff --git a/rust-lib/flowy-workspace/src/entities/trash/trash_create.rs b/rust-lib/flowy-workspace/src/entities/trash/trash_create.rs index cc123e8239..554ea490a0 100644 --- a/rust-lib/flowy-workspace/src/entities/trash/trash_create.rs +++ b/rust-lib/flowy-workspace/src/entities/trash/trash_create.rs @@ -24,7 +24,28 @@ impl std::default::Default for TrashType { } #[derive(PartialEq, ProtoBuf, Default, Debug, Clone)] -pub struct CreateTrashParams { +pub struct TrashIdentifiers { + #[pb(index = 1)] + pub items: Vec, +} + +impl std::convert::From> for TrashIdentifiers { + fn from(items: Vec) -> Self { TrashIdentifiers { items } } +} + +impl std::convert::From> for TrashIdentifiers { + fn from(trash: Vec) -> Self { + let items = trash + .into_iter() + .map(|t| TrashIdentifier { id: t.id, ty: t.ty }) + .collect::>(); + + TrashIdentifiers { items } + } +} + +#[derive(PartialEq, ProtoBuf, Default, Debug, Clone)] +pub struct TrashIdentifier { #[pb(index = 1)] pub id: String, diff --git a/rust-lib/flowy-workspace/src/entities/trash/trash_delete.rs b/rust-lib/flowy-workspace/src/entities/trash/trash_delete.rs deleted file mode 100644 index 3baccb05e6..0000000000 --- a/rust-lib/flowy-workspace/src/entities/trash/trash_delete.rs +++ /dev/null @@ -1,13 +0,0 @@ -use flowy_derive::ProtoBuf; - -#[derive(PartialEq, ProtoBuf, Default, Debug, Clone)] -pub struct TrashIdentifier { - #[pb(index = 1)] - pub id: String, -} - -#[derive(PartialEq, ProtoBuf, Default, Debug, Clone)] -pub struct TrashIdentifiers { - #[pb(index = 1)] - pub ids: Vec, -} diff --git a/rust-lib/flowy-workspace/src/event.rs b/rust-lib/flowy-workspace/src/event.rs index 7f0c5ffd91..3184ad94e6 100644 --- a/rust-lib/flowy-workspace/src/event.rs +++ b/rust-lib/flowy-workspace/src/event.rs @@ -58,7 +58,7 @@ pub enum WorkspaceEvent { #[event(input = "TrashIdentifier")] PutbackTrash = 301, - #[event(input = "TrashIdentifier")] + #[event(input = "TrashIdentifiers")] DeleteTrash = 302, #[event()] diff --git a/rust-lib/flowy-workspace/src/handlers/trash_handler.rs b/rust-lib/flowy-workspace/src/handlers/trash_handler.rs index 655e013d36..1676d80469 100644 --- a/rust-lib/flowy-workspace/src/handlers/trash_handler.rs +++ b/rust-lib/flowy-workspace/src/handlers/trash_handler.rs @@ -1,5 +1,5 @@ use crate::{ - entities::trash::{RepeatedTrash, TrashIdentifier}, + entities::trash::{RepeatedTrash, TrashIdentifier, TrashIdentifiers}, errors::WorkspaceError, services::TrashCan, }; @@ -22,12 +22,12 @@ pub(crate) async fn putback_trash_handler( Ok(()) } -#[tracing::instrument(skip(identifier, controller), err)] +#[tracing::instrument(skip(identifiers, controller), err)] pub(crate) async fn delete_trash_handler( - identifier: Data, + identifiers: Data, controller: Unit>, ) -> Result<(), WorkspaceError> { - let _ = controller.delete(&identifier.id).await?; + let _ = controller.delete(identifiers.into_inner()).await?; Ok(()) } diff --git a/rust-lib/flowy-workspace/src/module.rs b/rust-lib/flowy-workspace/src/module.rs index e866c266c6..82b9ba3ce9 100644 --- a/rust-lib/flowy-workspace/src/module.rs +++ b/rust-lib/flowy-workspace/src/module.rs @@ -38,7 +38,7 @@ pub fn mk_workspace( ) -> Arc { let server = construct_workspace_server(server_config); - let trash_can = Arc::new(TrashCan::new(database.clone())); + let trash_can = Arc::new(TrashCan::new(database.clone(), server.clone(), user.clone())); let view_controller = Arc::new(ViewController::new( user.clone(), diff --git a/rust-lib/flowy-workspace/src/protobuf/model/mod.rs b/rust-lib/flowy-workspace/src/protobuf/model/mod.rs index 7b4b0694fa..b5e0d70209 100644 --- a/rust-lib/flowy-workspace/src/protobuf/model/mod.rs +++ b/rust-lib/flowy-workspace/src/protobuf/model/mod.rs @@ -18,9 +18,6 @@ pub use observable::*; mod errors; pub use errors::*; -mod trash_delete; -pub use trash_delete::*; - mod workspace_update; pub use workspace_update::*; diff --git a/rust-lib/flowy-workspace/src/protobuf/model/trash_create.rs b/rust-lib/flowy-workspace/src/protobuf/model/trash_create.rs index a849ae8c71..8585c56b0e 100644 --- a/rust-lib/flowy-workspace/src/protobuf/model/trash_create.rs +++ b/rust-lib/flowy-workspace/src/protobuf/model/trash_create.rs @@ -24,7 +24,173 @@ // const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_22_1; #[derive(PartialEq,Clone,Default)] -pub struct CreateTrashParams { +pub struct TrashIdentifiers { + // message fields + pub items: ::protobuf::RepeatedField, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a TrashIdentifiers { + fn default() -> &'a TrashIdentifiers { + ::default_instance() + } +} + +impl TrashIdentifiers { + pub fn new() -> TrashIdentifiers { + ::std::default::Default::default() + } + + // repeated .TrashIdentifier items = 1; + + + pub fn get_items(&self) -> &[TrashIdentifier] { + &self.items + } + pub fn clear_items(&mut self) { + self.items.clear(); + } + + // Param is passed by value, moved + pub fn set_items(&mut self, v: ::protobuf::RepeatedField) { + self.items = v; + } + + // Mutable pointer to the field. + pub fn mut_items(&mut self) -> &mut ::protobuf::RepeatedField { + &mut self.items + } + + // Take field + pub fn take_items(&mut self) -> ::protobuf::RepeatedField { + ::std::mem::replace(&mut self.items, ::protobuf::RepeatedField::new()) + } +} + +impl ::protobuf::Message for TrashIdentifiers { + fn is_initialized(&self) -> bool { + for v in &self.items { + if !v.is_initialized() { + return false; + } + }; + 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_repeated_message_into(wire_type, is, &mut self.items)?; + }, + _ => { + ::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; + for value in &self.items { + let len = value.compute_size(); + my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; + }; + 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<()> { + for v in &self.items { + os.write_tag(1, ::protobuf::wire_format::WireTypeLengthDelimited)?; + os.write_raw_varint32(v.get_cached_size())?; + v.write_to_with_cached_sizes(os)?; + }; + 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() -> TrashIdentifiers { + TrashIdentifiers::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_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( + "items", + |m: &TrashIdentifiers| { &m.items }, + |m: &mut TrashIdentifiers| { &mut m.items }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "TrashIdentifiers", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static TrashIdentifiers { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(TrashIdentifiers::new) + } +} + +impl ::protobuf::Clear for TrashIdentifiers { + fn clear(&mut self) { + self.items.clear(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for TrashIdentifiers { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for TrashIdentifiers { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + +#[derive(PartialEq,Clone,Default)] +pub struct TrashIdentifier { // message fields pub id: ::std::string::String, pub ty: TrashType, @@ -33,14 +199,14 @@ pub struct CreateTrashParams { pub cached_size: ::protobuf::CachedSize, } -impl<'a> ::std::default::Default for &'a CreateTrashParams { - fn default() -> &'a CreateTrashParams { - ::default_instance() +impl<'a> ::std::default::Default for &'a TrashIdentifier { + fn default() -> &'a TrashIdentifier { + ::default_instance() } } -impl CreateTrashParams { - pub fn new() -> CreateTrashParams { +impl TrashIdentifier { + pub fn new() -> TrashIdentifier { ::std::default::Default::default() } @@ -86,7 +252,7 @@ impl CreateTrashParams { } } -impl ::protobuf::Message for CreateTrashParams { +impl ::protobuf::Message for TrashIdentifier { fn is_initialized(&self) -> bool { true } @@ -161,8 +327,8 @@ impl ::protobuf::Message for CreateTrashParams { Self::descriptor_static() } - fn new() -> CreateTrashParams { - CreateTrashParams::new() + fn new() -> TrashIdentifier { + TrashIdentifier::new() } fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { @@ -171,29 +337,29 @@ impl ::protobuf::Message for CreateTrashParams { let mut fields = ::std::vec::Vec::new(); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( "id", - |m: &CreateTrashParams| { &m.id }, - |m: &mut CreateTrashParams| { &mut m.id }, + |m: &TrashIdentifier| { &m.id }, + |m: &mut TrashIdentifier| { &mut m.id }, )); fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( "ty", - |m: &CreateTrashParams| { &m.ty }, - |m: &mut CreateTrashParams| { &mut m.ty }, + |m: &TrashIdentifier| { &m.ty }, + |m: &mut TrashIdentifier| { &mut m.ty }, )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "CreateTrashParams", + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "TrashIdentifier", fields, file_descriptor_proto() ) }) } - fn default_instance() -> &'static CreateTrashParams { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(CreateTrashParams::new) + fn default_instance() -> &'static TrashIdentifier { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(TrashIdentifier::new) } } -impl ::protobuf::Clear for CreateTrashParams { +impl ::protobuf::Clear for TrashIdentifier { fn clear(&mut self) { self.id.clear(); self.ty = TrashType::Unknown; @@ -201,13 +367,13 @@ impl ::protobuf::Clear for CreateTrashParams { } } -impl ::std::fmt::Debug for CreateTrashParams { +impl ::std::fmt::Debug for TrashIdentifier { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { ::protobuf::text_format::fmt(self, f) } } -impl ::protobuf::reflect::ProtobufValue for CreateTrashParams { +impl ::protobuf::reflect::ProtobufValue for TrashIdentifier { fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { ::protobuf::reflect::ReflectValueRef::Message(self) } @@ -732,47 +898,52 @@ impl ::protobuf::reflect::ProtobufValue for TrashType { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x12trash_create.proto\"?\n\x11CreateTrashParams\x12\x0e\n\x02id\x18\ - \x01\x20\x01(\tR\x02id\x12\x1a\n\x02ty\x18\x02\x20\x01(\x0e2\n.TrashType\ - R\x02ty\"\x8d\x01\n\x05Trash\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\ - \x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\x12#\n\rmodified_time\x18\ - \x03\x20\x01(\x03R\x0cmodifiedTime\x12\x1f\n\x0bcreate_time\x18\x04\x20\ - \x01(\x03R\ncreateTime\x12\x1a\n\x02ty\x18\x05\x20\x01(\x0e2\n.TrashType\ - R\x02ty\"-\n\rRepeatedTrash\x12\x1c\n\x05items\x18\x01\x20\x03(\x0b2\x06\ - .TrashR\x05items*\"\n\tTrashType\x12\x0b\n\x07Unknown\x10\0\x12\x08\n\ - \x04View\x10\x01J\x8a\x05\n\x06\x12\x04\0\0\x13\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\x19\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x12\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\r\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x10\x11\n\x0b\n\ - \x04\x04\0\x02\x01\x12\x03\x04\x04\x15\n\x0c\n\x05\x04\0\x02\x01\x06\x12\ - \x03\x04\x04\r\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\x0e\x10\n\x0c\n\ - \x05\x04\0\x02\x01\x03\x12\x03\x04\x13\x14\n\n\n\x02\x04\x01\x12\x04\x06\ - \0\x0c\x01\n\n\n\x03\x04\x01\x01\x12\x03\x06\x08\r\n\x0b\n\x04\x04\x01\ - \x02\0\x12\x03\x07\x04\x12\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03\x07\x04\ - \n\n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03\x07\x0b\r\n\x0c\n\x05\x04\x01\ - \x02\0\x03\x12\x03\x07\x10\x11\n\x0b\n\x04\x04\x01\x02\x01\x12\x03\x08\ - \x04\x14\n\x0c\n\x05\x04\x01\x02\x01\x05\x12\x03\x08\x04\n\n\x0c\n\x05\ - \x04\x01\x02\x01\x01\x12\x03\x08\x0b\x0f\n\x0c\n\x05\x04\x01\x02\x01\x03\ - \x12\x03\x08\x12\x13\n\x0b\n\x04\x04\x01\x02\x02\x12\x03\t\x04\x1c\n\x0c\ - \n\x05\x04\x01\x02\x02\x05\x12\x03\t\x04\t\n\x0c\n\x05\x04\x01\x02\x02\ - \x01\x12\x03\t\n\x17\n\x0c\n\x05\x04\x01\x02\x02\x03\x12\x03\t\x1a\x1b\n\ - \x0b\n\x04\x04\x01\x02\x03\x12\x03\n\x04\x1a\n\x0c\n\x05\x04\x01\x02\x03\ - \x05\x12\x03\n\x04\t\n\x0c\n\x05\x04\x01\x02\x03\x01\x12\x03\n\n\x15\n\ - \x0c\n\x05\x04\x01\x02\x03\x03\x12\x03\n\x18\x19\n\x0b\n\x04\x04\x01\x02\ - \x04\x12\x03\x0b\x04\x15\n\x0c\n\x05\x04\x01\x02\x04\x06\x12\x03\x0b\x04\ - \r\n\x0c\n\x05\x04\x01\x02\x04\x01\x12\x03\x0b\x0e\x10\n\x0c\n\x05\x04\ - \x01\x02\x04\x03\x12\x03\x0b\x13\x14\n\n\n\x02\x04\x02\x12\x04\r\0\x0f\ - \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\x1d\n\x0c\n\x05\x04\x02\x02\0\x04\x12\x03\x0e\x04\x0c\n\ - \x0c\n\x05\x04\x02\x02\0\x06\x12\x03\x0e\r\x12\n\x0c\n\x05\x04\x02\x02\0\ - \x01\x12\x03\x0e\x13\x18\n\x0c\n\x05\x04\x02\x02\0\x03\x12\x03\x0e\x1b\ - \x1c\n\n\n\x02\x05\0\x12\x04\x10\0\x13\x01\n\n\n\x03\x05\0\x01\x12\x03\ - \x10\x05\x0e\n\x0b\n\x04\x05\0\x02\0\x12\x03\x11\x04\x10\n\x0c\n\x05\x05\ - \0\x02\0\x01\x12\x03\x11\x04\x0b\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x11\ - \x0e\x0f\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x12\x04\r\n\x0c\n\x05\x05\0\ - \x02\x01\x01\x12\x03\x12\x04\x08\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\ - \x12\x0b\x0cb\x06proto3\ + \n\x12trash_create.proto\":\n\x10TrashIdentifiers\x12&\n\x05items\x18\ + \x01\x20\x03(\x0b2\x10.TrashIdentifierR\x05items\"=\n\x0fTrashIdentifier\ + \x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x1a\n\x02ty\x18\x02\x20\ + \x01(\x0e2\n.TrashTypeR\x02ty\"\x8d\x01\n\x05Trash\x12\x0e\n\x02id\x18\ + \x01\x20\x01(\tR\x02id\x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\x12\ + #\n\rmodified_time\x18\x03\x20\x01(\x03R\x0cmodifiedTime\x12\x1f\n\x0bcr\ + eate_time\x18\x04\x20\x01(\x03R\ncreateTime\x12\x1a\n\x02ty\x18\x05\x20\ + \x01(\x0e2\n.TrashTypeR\x02ty\"-\n\rRepeatedTrash\x12\x1c\n\x05items\x18\ + \x01\x20\x03(\x0b2\x06.TrashR\x05items*\"\n\tTrashType\x12\x0b\n\x07Unkn\ + own\x10\0\x12\x08\n\x04View\x10\x01J\xe7\x05\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\x04\x01\n\n\ + \n\x03\x04\0\x01\x12\x03\x02\x08\x18\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\ + \x04'\n\x0c\n\x05\x04\0\x02\0\x04\x12\x03\x03\x04\x0c\n\x0c\n\x05\x04\0\ + \x02\0\x06\x12\x03\x03\r\x1c\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\x1d\ + \"\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03%&\n\n\n\x02\x04\x01\x12\x04\ + \x05\0\x08\x01\n\n\n\x03\x04\x01\x01\x12\x03\x05\x08\x17\n\x0b\n\x04\x04\ + \x01\x02\0\x12\x03\x06\x04\x12\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03\x06\ + \x04\n\n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03\x06\x0b\r\n\x0c\n\x05\x04\ + \x01\x02\0\x03\x12\x03\x06\x10\x11\n\x0b\n\x04\x04\x01\x02\x01\x12\x03\ + \x07\x04\x15\n\x0c\n\x05\x04\x01\x02\x01\x06\x12\x03\x07\x04\r\n\x0c\n\ + \x05\x04\x01\x02\x01\x01\x12\x03\x07\x0e\x10\n\x0c\n\x05\x04\x01\x02\x01\ + \x03\x12\x03\x07\x13\x14\n\n\n\x02\x04\x02\x12\x04\t\0\x0f\x01\n\n\n\x03\ + \x04\x02\x01\x12\x03\t\x08\r\n\x0b\n\x04\x04\x02\x02\0\x12\x03\n\x04\x12\ + \n\x0c\n\x05\x04\x02\x02\0\x05\x12\x03\n\x04\n\n\x0c\n\x05\x04\x02\x02\0\ + \x01\x12\x03\n\x0b\r\n\x0c\n\x05\x04\x02\x02\0\x03\x12\x03\n\x10\x11\n\ + \x0b\n\x04\x04\x02\x02\x01\x12\x03\x0b\x04\x14\n\x0c\n\x05\x04\x02\x02\ + \x01\x05\x12\x03\x0b\x04\n\n\x0c\n\x05\x04\x02\x02\x01\x01\x12\x03\x0b\ + \x0b\x0f\n\x0c\n\x05\x04\x02\x02\x01\x03\x12\x03\x0b\x12\x13\n\x0b\n\x04\ + \x04\x02\x02\x02\x12\x03\x0c\x04\x1c\n\x0c\n\x05\x04\x02\x02\x02\x05\x12\ + \x03\x0c\x04\t\n\x0c\n\x05\x04\x02\x02\x02\x01\x12\x03\x0c\n\x17\n\x0c\n\ + \x05\x04\x02\x02\x02\x03\x12\x03\x0c\x1a\x1b\n\x0b\n\x04\x04\x02\x02\x03\ + \x12\x03\r\x04\x1a\n\x0c\n\x05\x04\x02\x02\x03\x05\x12\x03\r\x04\t\n\x0c\ + \n\x05\x04\x02\x02\x03\x01\x12\x03\r\n\x15\n\x0c\n\x05\x04\x02\x02\x03\ + \x03\x12\x03\r\x18\x19\n\x0b\n\x04\x04\x02\x02\x04\x12\x03\x0e\x04\x15\n\ + \x0c\n\x05\x04\x02\x02\x04\x06\x12\x03\x0e\x04\r\n\x0c\n\x05\x04\x02\x02\ + \x04\x01\x12\x03\x0e\x0e\x10\n\x0c\n\x05\x04\x02\x02\x04\x03\x12\x03\x0e\ + \x13\x14\n\n\n\x02\x04\x03\x12\x04\x10\0\x12\x01\n\n\n\x03\x04\x03\x01\ + \x12\x03\x10\x08\x15\n\x0b\n\x04\x04\x03\x02\0\x12\x03\x11\x04\x1d\n\x0c\ + \n\x05\x04\x03\x02\0\x04\x12\x03\x11\x04\x0c\n\x0c\n\x05\x04\x03\x02\0\ + \x06\x12\x03\x11\r\x12\n\x0c\n\x05\x04\x03\x02\0\x01\x12\x03\x11\x13\x18\ + \n\x0c\n\x05\x04\x03\x02\0\x03\x12\x03\x11\x1b\x1c\n\n\n\x02\x05\0\x12\ + \x04\x13\0\x16\x01\n\n\n\x03\x05\0\x01\x12\x03\x13\x05\x0e\n\x0b\n\x04\ + \x05\0\x02\0\x12\x03\x14\x04\x10\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\x14\ + \x04\x0b\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x14\x0e\x0f\n\x0b\n\x04\x05\ + \0\x02\x01\x12\x03\x15\x04\r\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x15\ + \x04\x08\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x15\x0b\x0cb\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/rust-lib/flowy-workspace/src/protobuf/model/trash_delete.rs b/rust-lib/flowy-workspace/src/protobuf/model/trash_delete.rs deleted file mode 100644 index 5f36aa510f..0000000000 --- a/rust-lib/flowy-workspace/src/protobuf/model/trash_delete.rs +++ /dev/null @@ -1,368 +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 `trash_delete.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 TrashIdentifier { - // message fields - pub id: ::std::string::String, - // special fields - pub unknown_fields: ::protobuf::UnknownFields, - pub cached_size: ::protobuf::CachedSize, -} - -impl<'a> ::std::default::Default for &'a TrashIdentifier { - fn default() -> &'a TrashIdentifier { - ::default_instance() - } -} - -impl TrashIdentifier { - pub fn new() -> TrashIdentifier { - ::std::default::Default::default() - } - - // string id = 1; - - - pub fn get_id(&self) -> &str { - &self.id - } - pub fn clear_id(&mut self) { - self.id.clear(); - } - - // Param is passed by value, moved - 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()) - } -} - -impl ::protobuf::Message for TrashIdentifier { - 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.id)?; - }, - _ => { - ::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.id.is_empty() { - my_size += ::protobuf::rt::string_size(1, &self.id); - } - 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.id.is_empty() { - os.write_string(1, &self.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() -> TrashIdentifier { - TrashIdentifier::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>( - "id", - |m: &TrashIdentifier| { &m.id }, - |m: &mut TrashIdentifier| { &mut m.id }, - )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "TrashIdentifier", - fields, - file_descriptor_proto() - ) - }) - } - - fn default_instance() -> &'static TrashIdentifier { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(TrashIdentifier::new) - } -} - -impl ::protobuf::Clear for TrashIdentifier { - fn clear(&mut self) { - self.id.clear(); - self.unknown_fields.clear(); - } -} - -impl ::std::fmt::Debug for TrashIdentifier { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - ::protobuf::text_format::fmt(self, f) - } -} - -impl ::protobuf::reflect::ProtobufValue for TrashIdentifier { - fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { - ::protobuf::reflect::ReflectValueRef::Message(self) - } -} - -#[derive(PartialEq,Clone,Default)] -pub struct TrashIdentifiers { - // message fields - pub ids: ::protobuf::RepeatedField<::std::string::String>, - // special fields - pub unknown_fields: ::protobuf::UnknownFields, - pub cached_size: ::protobuf::CachedSize, -} - -impl<'a> ::std::default::Default for &'a TrashIdentifiers { - fn default() -> &'a TrashIdentifiers { - ::default_instance() - } -} - -impl TrashIdentifiers { - pub fn new() -> TrashIdentifiers { - ::std::default::Default::default() - } - - // repeated string ids = 1; - - - pub fn get_ids(&self) -> &[::std::string::String] { - &self.ids - } - pub fn clear_ids(&mut self) { - self.ids.clear(); - } - - // Param is passed by value, moved - pub fn set_ids(&mut self, v: ::protobuf::RepeatedField<::std::string::String>) { - self.ids = v; - } - - // Mutable pointer to the field. - pub fn mut_ids(&mut self) -> &mut ::protobuf::RepeatedField<::std::string::String> { - &mut self.ids - } - - // Take field - pub fn take_ids(&mut self) -> ::protobuf::RepeatedField<::std::string::String> { - ::std::mem::replace(&mut self.ids, ::protobuf::RepeatedField::new()) - } -} - -impl ::protobuf::Message for TrashIdentifiers { - 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_repeated_string_into(wire_type, is, &mut self.ids)?; - }, - _ => { - ::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; - for value in &self.ids { - my_size += ::protobuf::rt::string_size(1, &value); - }; - 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<()> { - for v in &self.ids { - os.write_string(1, &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() -> TrashIdentifiers { - TrashIdentifiers::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_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( - "ids", - |m: &TrashIdentifiers| { &m.ids }, - |m: &mut TrashIdentifiers| { &mut m.ids }, - )); - ::protobuf::reflect::MessageDescriptor::new_pb_name::( - "TrashIdentifiers", - fields, - file_descriptor_proto() - ) - }) - } - - fn default_instance() -> &'static TrashIdentifiers { - static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; - instance.get(TrashIdentifiers::new) - } -} - -impl ::protobuf::Clear for TrashIdentifiers { - fn clear(&mut self) { - self.ids.clear(); - self.unknown_fields.clear(); - } -} - -impl ::std::fmt::Debug for TrashIdentifiers { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - ::protobuf::text_format::fmt(self, f) - } -} - -impl ::protobuf::reflect::ProtobufValue for TrashIdentifiers { - fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { - ::protobuf::reflect::ReflectValueRef::Message(self) - } -} - -static file_descriptor_proto_data: &'static [u8] = b"\ - \n\x12trash_delete.proto\"!\n\x0fTrashIdentifier\x12\x0e\n\x02id\x18\x01\ - \x20\x01(\tR\x02id\"$\n\x10TrashIdentifiers\x12\x10\n\x03ids\x18\x01\x20\ - \x03(\tR\x03idsJ\xbe\x01\n\x06\x12\x04\0\0\x07\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\x17\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x12\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\r\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x10\x11\n\n\n\x02\ - \x04\x01\x12\x04\x05\0\x07\x01\n\n\n\x03\x04\x01\x01\x12\x03\x05\x08\x18\ - \n\x0b\n\x04\x04\x01\x02\0\x12\x03\x06\x04\x1c\n\x0c\n\x05\x04\x01\x02\0\ - \x04\x12\x03\x06\x04\x0c\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03\x06\r\x13\ - \n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03\x06\x14\x17\n\x0c\n\x05\x04\x01\ - \x02\0\x03\x12\x03\x06\x1a\x1bb\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/rust-lib/flowy-workspace/src/protobuf/proto/trash_create.proto b/rust-lib/flowy-workspace/src/protobuf/proto/trash_create.proto index 2e310b2dd6..608da1af7a 100644 --- a/rust-lib/flowy-workspace/src/protobuf/proto/trash_create.proto +++ b/rust-lib/flowy-workspace/src/protobuf/proto/trash_create.proto @@ -1,6 +1,9 @@ syntax = "proto3"; -message CreateTrashParams { +message TrashIdentifiers { + repeated TrashIdentifier items = 1; +} +message TrashIdentifier { string id = 1; TrashType ty = 2; } diff --git a/rust-lib/flowy-workspace/src/protobuf/proto/trash_delete.proto b/rust-lib/flowy-workspace/src/protobuf/proto/trash_delete.proto deleted file mode 100644 index ac0111cdbb..0000000000 --- a/rust-lib/flowy-workspace/src/protobuf/proto/trash_delete.proto +++ /dev/null @@ -1,8 +0,0 @@ -syntax = "proto3"; - -message TrashIdentifier { - string id = 1; -} -message TrashIdentifiers { - repeated string ids = 1; -} diff --git a/rust-lib/flowy-workspace/src/services/app_controller.rs b/rust-lib/flowy-workspace/src/services/app_controller.rs index 33c359a6fa..e3be4596e3 100644 --- a/rust-lib/flowy-workspace/src/services/app_controller.rs +++ b/rust-lib/flowy-workspace/src/services/app_controller.rs @@ -8,24 +8,18 @@ use crate::{ }; use flowy_database::SqliteConnection; + use std::sync::Arc; pub(crate) struct AppController { user: Arc, - sql: Arc, database: Arc, server: Server, } impl AppController { pub(crate) fn new(user: Arc, database: Arc, server: Server) -> Self { - let sql = Arc::new(AppTableSql {}); - Self { - user, - sql, - database, - server, - } + Self { user, database, server } } #[tracing::instrument(level = "debug", skip(self), err)] @@ -47,12 +41,12 @@ impl AppController { pub(crate) fn save_app(&self, app: App, conn: &SqliteConnection) -> Result<(), WorkspaceError> { let app_table = AppTable::new(app.clone()); - let _ = self.sql.create_app(app_table, &*conn)?; + let _ = AppTableSql::create_app(app_table, &*conn)?; Ok(()) } pub(crate) async fn read_app(&self, params: AppIdentifier) -> Result { - let app_table = self.sql.read_app(¶ms.app_id, &*self.database.db_connection()?)?; + let app_table = AppTableSql::read_app(¶ms.app_id, &*self.database.db_connection()?)?; let _ = self.read_app_on_server(params)?; Ok(app_table.into()) } @@ -61,7 +55,7 @@ impl AppController { pub(crate) async fn delete_app(&self, app_id: &str) -> Result<(), WorkspaceError> { let conn = &*self.database.db_connection()?; conn.immediate_transaction::<_, WorkspaceError, _>(|| { - let app = self.sql.delete_app(app_id, &*conn)?; + let app = AppTableSql::delete_app(app_id, &*conn)?; let apps = self.read_local_apps(&app.workspace_id, &*conn)?; send_dart_notification(&app.workspace_id, WorkspaceNotification::WorkspaceDeleteApp) .payload(apps) @@ -74,7 +68,7 @@ impl AppController { } fn read_local_apps(&self, workspace_id: &str, conn: &SqliteConnection) -> Result { - let app_tables = self.sql.read_apps(workspace_id, false, conn)?; + let app_tables = AppTableSql::read_apps(workspace_id, false, conn)?; let apps = app_tables.into_iter().map(|table| table.into()).collect::>(); Ok(RepeatedApp { items: apps }) } @@ -84,8 +78,8 @@ impl AppController { let app_id = changeset.id.clone(); let conn = &*self.database.db_connection()?; conn.immediate_transaction::<_, WorkspaceError, _>(|| { - let _ = self.sql.update_app(changeset, conn)?; - let app: App = self.sql.read_app(&app_id, conn)?.into(); + let _ = AppTableSql::update_app(changeset, conn)?; + let app: App = AppTableSql::read_app(&app_id, conn)?.into(); send_dart_notification(&app_id, WorkspaceNotification::AppUpdated) .payload(app) .send(); @@ -137,6 +131,18 @@ impl AppController { }, } }); + // let action = RetryAction::new(self.server.clone(), self.user.clone(), move + // |token, server| { let params = params.clone(); + // async move { + // match server.delete_app(&token, params).await { + // Ok(_) => {}, + // Err(e) => log::error!("Delete app failed: {:?}", e), + // } + // Ok::<(), WorkspaceError>(()) + // } + // }); + // + // spawn_retry(500, 3, action); Ok(()) } @@ -144,14 +150,27 @@ impl AppController { fn read_app_on_server(&self, params: AppIdentifier) -> Result<(), WorkspaceError> { let token = self.user.token()?; let server = self.server.clone(); + let pool = self.database.db_pool()?; spawn(async move { // Opti: retry? match server.read_app(&token, params).await { - Ok(option) => match option { - None => {}, - Some(_app) => {}, + Ok(Some(app)) => match pool.get() { + Ok(conn) => { + let app_table = AppTable::new(app.clone()); + let result = AppTableSql::create_app(app_table, &*conn); + match result { + Ok(_) => { + send_dart_notification(&app.id, WorkspaceNotification::AppUpdated) + .payload(app) + .send(); + }, + Err(e) => log::error!("Save app failed: {:?}", e), + } + }, + Err(e) => log::error!("Require db connection failed: {:?}", e), }, - Err(_) => {}, + Ok(None) => {}, + Err(e) => log::error!("Read app failed: {:?}", e), } }); Ok(()) diff --git a/rust-lib/flowy-workspace/src/services/mod.rs b/rust-lib/flowy-workspace/src/services/mod.rs index 0ea771e46a..328cf047ab 100644 --- a/rust-lib/flowy-workspace/src/services/mod.rs +++ b/rust-lib/flowy-workspace/src/services/mod.rs @@ -8,5 +8,6 @@ mod database; mod helper; pub mod server; mod trash_can; +mod util; mod view_controller; mod workspace_controller; diff --git a/rust-lib/flowy-workspace/src/services/server/mod.rs b/rust-lib/flowy-workspace/src/services/server/mod.rs index 7f8be31720..627cd8fe47 100644 --- a/rust-lib/flowy-workspace/src/services/server/mod.rs +++ b/rust-lib/flowy-workspace/src/services/server/mod.rs @@ -9,6 +9,7 @@ pub use server_api_mock::*; use crate::{ entities::{ app::{App, AppIdentifier, CreateAppParams, DeleteAppParams, UpdateAppParams}, + trash::{RepeatedTrash, TrashIdentifiers}, view::{CreateViewParams, DeleteViewParams, UpdateViewParams, View, ViewIdentifier}, workspace::{ CreateWorkspaceParams, @@ -58,6 +59,13 @@ pub trait WorkspaceServerAPI { fn update_app(&self, token: &str, params: UpdateAppParams) -> ResultFuture<(), WorkspaceError>; fn delete_app(&self, token: &str, params: DeleteAppParams) -> ResultFuture<(), WorkspaceError>; + + // Trash + fn create_trash(&self, token: &str, params: TrashIdentifiers) -> ResultFuture<(), WorkspaceError>; + + fn delete_trash(&self, token: &str, params: TrashIdentifiers) -> ResultFuture<(), WorkspaceError>; + + fn read_trash(&self, token: &str) -> ResultFuture; } pub(crate) fn construct_workspace_server(config: &ServerConfig) -> Arc { diff --git a/rust-lib/flowy-workspace/src/services/server/server_api.rs b/rust-lib/flowy-workspace/src/services/server/server_api.rs index 8389f23b7a..bfd134edef 100644 --- a/rust-lib/flowy-workspace/src/services/server/server_api.rs +++ b/rust-lib/flowy-workspace/src/services/server/server_api.rs @@ -1,7 +1,7 @@ use crate::{ entities::{ app::{App, AppIdentifier, CreateAppParams, DeleteAppParams, UpdateAppParams}, - trash::CreateTrashParams, + trash::{RepeatedTrash, TrashIdentifiers}, view::{CreateViewParams, DeleteViewParams, UpdateViewParams, View, ViewIdentifier}, workspace::{ CreateWorkspaceParams, @@ -15,8 +15,6 @@ use crate::{ errors::WorkspaceError, services::server::WorkspaceServerAPI, }; - -use crate::entities::trash::{RepeatedTrash, TrashIdentifiers}; use flowy_infra::future::ResultFuture; use flowy_net::{config::*, request::HttpRequestBuilder}; @@ -104,6 +102,24 @@ impl WorkspaceServerAPI for WorkspaceServer { let url = self.config.app_url(); ResultFuture::new(async move { delete_app_request(&token, params, &url).await }) } + + fn create_trash(&self, token: &str, params: TrashIdentifiers) -> ResultFuture<(), WorkspaceError> { + let token = token.to_owned(); + let url = self.config.trash_url(); + ResultFuture::new(async move { create_trash_request(&token, params, &url).await }) + } + + fn delete_trash(&self, token: &str, params: TrashIdentifiers) -> ResultFuture<(), WorkspaceError> { + let token = token.to_owned(); + let url = self.config.trash_url(); + ResultFuture::new(async move { delete_trash_request(&token, params, &url).await }) + } + + fn read_trash(&self, token: &str) -> ResultFuture { + let token = token.to_owned(); + let url = self.config.trash_url(); + ResultFuture::new(async move { read_trash_request(&token, &url).await }) + } } pub(crate) fn request_builder() -> HttpRequestBuilder { @@ -250,7 +266,7 @@ pub async fn delete_view_request(token: &str, params: DeleteViewParams, url: &st Ok(()) } -pub async fn create_trash_request(token: &str, params: CreateTrashParams, url: &str) -> Result<(), WorkspaceError> { +pub async fn create_trash_request(token: &str, params: TrashIdentifiers, url: &str) -> Result<(), WorkspaceError> { let _ = request_builder() .post(&url.to_owned()) .header(HEADER_TOKEN, token) diff --git a/rust-lib/flowy-workspace/src/services/server/server_api_mock.rs b/rust-lib/flowy-workspace/src/services/server/server_api_mock.rs index 37e21beed9..127e200872 100644 --- a/rust-lib/flowy-workspace/src/services/server/server_api_mock.rs +++ b/rust-lib/flowy-workspace/src/services/server/server_api_mock.rs @@ -1,6 +1,7 @@ use crate::{ entities::{ app::{App, AppIdentifier, CreateAppParams, DeleteAppParams, RepeatedApp, UpdateAppParams}, + trash::{RepeatedTrash, TrashIdentifiers}, view::{CreateViewParams, DeleteViewParams, RepeatedView, UpdateViewParams, View, ViewIdentifier}, workspace::{ CreateWorkspaceParams, @@ -106,4 +107,19 @@ impl WorkspaceServerAPI for WorkspaceServerMock { fn delete_app(&self, _token: &str, _params: DeleteAppParams) -> ResultFuture<(), WorkspaceError> { ResultFuture::new(async { Ok(()) }) } + + fn create_trash(&self, _token: &str, _params: TrashIdentifiers) -> ResultFuture<(), WorkspaceError> { + ResultFuture::new(async { Ok(()) }) + } + + fn delete_trash(&self, _token: &str, _params: TrashIdentifiers) -> ResultFuture<(), WorkspaceError> { + ResultFuture::new(async { Ok(()) }) + } + + fn read_trash(&self, _token: &str) -> ResultFuture { + ResultFuture::new(async { + let repeated_trash = RepeatedTrash { items: vec![] }; + Ok(repeated_trash) + }) + } } diff --git a/rust-lib/flowy-workspace/src/services/trash_can.rs b/rust-lib/flowy-workspace/src/services/trash_can.rs index 49aa7c19cf..d6dedd67d4 100644 --- a/rust-lib/flowy-workspace/src/services/trash_can.rs +++ b/rust-lib/flowy-workspace/src/services/trash_can.rs @@ -1,59 +1,42 @@ use crate::{ - entities::trash::{RepeatedTrash, Trash, TrashType}, + entities::trash::{RepeatedTrash, Trash, TrashIdentifier, TrashIdentifiers, TrashType}, errors::{WorkspaceError, WorkspaceResult}, - module::WorkspaceDatabase, + module::{WorkspaceDatabase, WorkspaceUser}, notify::{send_anonymous_dart_notification, WorkspaceNotification}, + services::{helper::spawn, server::Server}, sql_tables::trash::TrashTableSql, }; use crossbeam_utils::thread; use flowy_database::SqliteConnection; + use std::sync::Arc; use tokio::sync::{broadcast, mpsc}; -#[derive(Clone)] -pub enum TrashEvent { - NewTrash(TrashType, Vec, mpsc::Sender>), - Putback(TrashType, Vec, mpsc::Sender>), - Delete(TrashType, Vec, mpsc::Sender>), -} - -impl TrashEvent { - pub fn select(self, s: TrashType) -> Option { - match &self { - TrashEvent::Putback(source, _, _) => { - if source == &s { - return Some(self); - } - }, - TrashEvent::Delete(source, _, _) => { - if source == &s { - return Some(self); - } - }, - TrashEvent::NewTrash(source, _, _) => { - if source == &s { - return Some(self); - } - }, - } - None - } -} - pub struct TrashCan { pub database: Arc, notify: broadcast::Sender, + server: Server, + user: Arc, } impl TrashCan { - pub fn new(database: Arc) -> Self { + pub fn new(database: Arc, server: Server, user: Arc) -> Self { let (tx, _) = broadcast::channel(10); - Self { database, notify: tx } + Self { + database, + notify: tx, + server, + user, + } } + pub(crate) fn init(&self) -> Result<(), WorkspaceError> { Ok(()) } + pub fn read_trash(&self, conn: &SqliteConnection) -> Result { let repeated_trash = TrashTableSql::read_all(&*conn)?; + + let _ = self.read_trash_on_server()?; Ok(repeated_trash) } @@ -73,22 +56,26 @@ impl TrashCan { let _ = thread::scope(|_s| { let conn = self.database.db_connection()?; let _ = conn.immediate_transaction::<_, WorkspaceError, _>(|| { + let repeated_trash = TrashTableSql::read_all(&conn)?; let _ = TrashTableSql::delete_trash(trash_id, &*conn)?; - let _ = self.notify_dart_trash_did_update(&conn)?; + notify_trash_num_changed(repeated_trash); Ok(()) })?; Ok::<(), WorkspaceError>(()) }) .unwrap()?; - tracing::Span::current().record( - "putback", - &format!("{:?}: {}", &trash_table.ty, trash_table.id).as_str(), - ); - let _ = self - .notify - .send(TrashEvent::Putback(trash_table.ty.into(), vec![trash_table.id], tx)); + let identifier = TrashIdentifier { + id: trash_table.id, + ty: trash_table.ty.into(), + }; + let _ = self.delete_trash_on_server(TrashIdentifiers { + items: vec![identifier.clone()], + })?; + + tracing::Span::current().record("putback", &format!("{:?}", &identifier).as_str()); + let _ = self.notify.send(TrashEvent::Putback(vec![identifier].into(), tx)); let _ = rx.recv().await.unwrap()?; Ok(()) } @@ -100,15 +87,20 @@ impl TrashCan { pub fn delete_all(&self) -> WorkspaceResult<()> { Ok(()) } #[tracing::instrument(level = "debug", skip(self) err)] - pub async fn delete(&self, trash_id: &str) -> WorkspaceResult<()> { + pub async fn delete(&self, trash_identifiers: TrashIdentifiers) -> WorkspaceResult<()> { let (tx, mut rx) = mpsc::channel::>(1); - let trash_table = TrashTableSql::read(trash_id, &*self.database.db_connection()?)?; - let _ = self - .notify - .send(TrashEvent::Delete(trash_table.ty.into(), vec![trash_table.id], tx)); - + let _ = self.notify.send(TrashEvent::Delete(trash_identifiers.clone(), tx)); let _ = rx.recv().await.unwrap()?; - let _ = TrashTableSql::delete_trash(trash_id, &*self.database.db_connection()?)?; + + let conn = self.database.db_connection()?; + conn.immediate_transaction::<_, WorkspaceError, _>(|| { + for trash_identifier in &trash_identifiers.items { + let _ = TrashTableSql::delete_trash(&trash_identifier.id, &conn)?; + } + Ok(()) + })?; + + let _ = self.delete_trash_on_server(trash_identifiers)?; Ok(()) } @@ -123,48 +115,147 @@ impl TrashCan { pub async fn add>(&self, trash: Vec) -> Result<(), WorkspaceError> { let (tx, mut rx) = mpsc::channel::>(1); let trash = trash.into_iter().map(|t| t.into()).collect::>(); - let mut ids = vec![]; - let mut trash_type = None; + let mut items = vec![]; let _ = thread::scope(|_s| { let conn = self.database.db_connection()?; conn.immediate_transaction::<_, WorkspaceError, _>(|| { - for t in trash { - if trash_type == None { - trash_type = Some(t.ty.clone()); - } - - if trash_type.as_ref().unwrap() != &t.ty { - return Err(WorkspaceError::internal()); - } - let trash_id = t.id.clone(); + for t in &trash { log::debug!("create trash: {:?}", t); - let _ = TrashTableSql::create_trash(t.into(), &*conn)?; - ids.push(trash_id); + items.push(TrashIdentifier { + id: t.id.clone(), + ty: t.ty.clone(), + }); + let _ = TrashTableSql::create_trash(t.clone().into(), &*conn)?; } - let _ = self.notify_dart_trash_did_update(&conn)?; + self.create_trash_on_server(trash); + let repeated_trash = TrashTableSql::read_all(&conn)?; + notify_trash_num_changed(repeated_trash); Ok(()) })?; Ok::<(), WorkspaceError>(()) }) .unwrap()?; - if let Some(trash_type) = trash_type { - let _ = self.notify.send(TrashEvent::NewTrash(trash_type, ids, tx)); - let _ = rx.recv().await.unwrap()?; - } + let _ = self.notify.send(TrashEvent::NewTrash(items.into(), tx)); + let _ = rx.recv().await.unwrap()?; Ok(()) } pub fn subscribe(&self) -> broadcast::Receiver { self.notify.subscribe() } +} - fn notify_dart_trash_did_update(&self, conn: &SqliteConnection) -> WorkspaceResult<()> { - // Opti: only push the changeset - let repeated_trash = TrashTableSql::read_all(conn)?; - send_anonymous_dart_notification(WorkspaceNotification::TrashUpdated) - .payload(repeated_trash) - .send(); +impl TrashCan { + #[tracing::instrument(level = "debug", skip(self, trash), err)] + fn create_trash_on_server>(&self, trash: T) -> WorkspaceResult<()> { + let token = self.user.token()?; + let trash_identifiers = trash.into(); + let server = self.server.clone(); + // TODO: retry? + let _ = tokio::spawn(async move { + match server.create_trash(&token, trash_identifiers).await { + Ok(_) => {}, + Err(e) => log::error!("Create trash failed: {:?}", e), + } + }); + Ok(()) + } + #[tracing::instrument(level = "debug", skip(self, trash), err)] + fn delete_trash_on_server>(&self, trash: T) -> WorkspaceResult<()> { + let token = self.user.token()?; + let trash_identifiers = trash.into(); + let server = self.server.clone(); + let _ = tokio::spawn(async move { + match server.delete_trash(&token, trash_identifiers).await { + Ok(_) => {}, + Err(e) => log::error!("Delete trash failed: {:?}", e), + } + }); + Ok(()) + } + + #[tracing::instrument(level = "debug", skip(self), err)] + fn read_trash_on_server(&self) -> WorkspaceResult<()> { + let token = self.user.token()?; + let server = self.server.clone(); + let pool = self.database.db_pool()?; + + spawn(async move { + match server.read_trash(&token).await { + Ok(repeated_trash) => { + match pool.get() { + Ok(conn) => { + let result = conn.immediate_transaction::<_, WorkspaceError, _>(|| { + for trash in &repeated_trash.items { + let _ = TrashTableSql::create_trash(trash.clone().into(), &*conn)?; + } + Ok(()) + }); + + match result { + Ok(_) => { + // FIXME: User may modify the trash(add/putback) before the flying request comes + // back that will cause the trash list to be outdated. + // TODO: impl with operation transform + notify_trash_num_changed(repeated_trash); + }, + Err(e) => log::error!("Save trash failed: {:?}", e), + } + }, + Err(e) => log::error!("Require db connection failed: {:?}", e), + } + }, + Err(e) => log::error!("Read trash failed: {:?}", e), + } + }); Ok(()) } } + +#[tracing::instrument(skip(repeated_trash), fields(trash_count))] +fn notify_trash_num_changed(repeated_trash: RepeatedTrash) { + tracing::Span::current().record("trash_count", &repeated_trash.len()); + + send_anonymous_dart_notification(WorkspaceNotification::TrashUpdated) + .payload(repeated_trash) + .send(); +} + +#[derive(Clone)] +pub enum TrashEvent { + NewTrash(TrashIdentifiers, mpsc::Sender>), + Putback(TrashIdentifiers, mpsc::Sender>), + Delete(TrashIdentifiers, mpsc::Sender>), +} + +impl TrashEvent { + pub fn select(self, s: TrashType) -> Option { + match self { + TrashEvent::Putback(mut identifiers, sender) => { + identifiers.items.retain(|item| item.ty == s); + if identifiers.items.is_empty() { + None + } else { + Some(TrashEvent::Putback(identifiers, sender)) + } + }, + TrashEvent::Delete(mut identifiers, sender) => { + identifiers.items.retain(|item| item.ty == s); + if identifiers.items.is_empty() { + None + } else { + Some(TrashEvent::Delete(identifiers, sender)) + } + }, + TrashEvent::NewTrash(mut identifiers, sender) => { + identifiers.items.retain(|item| item.ty == s); + if identifiers.items.is_empty() { + None + } else { + Some(TrashEvent::NewTrash(identifiers, sender)) + } + }, + } + } +} diff --git a/rust-lib/flowy-workspace/src/services/util.rs b/rust-lib/flowy-workspace/src/services/util.rs new file mode 100644 index 0000000000..8090d85dc7 --- /dev/null +++ b/rust-lib/flowy-workspace/src/services/util.rs @@ -0,0 +1,72 @@ +use crate::{module::WorkspaceUser, services::server::Server}; +use flowy_infra::retry::Action; +use pin_project::pin_project; +use std::{ + future::Future, + marker::PhantomData, + pin::Pin, + sync::Arc, + task::{Context, Poll}, +}; + +pub(crate) type Builder = Box Fut + Send + Sync>; + +pub(crate) struct RetryAction { + token: String, + server: Server, + user: Arc, + builder: Builder, + phantom: PhantomData<(T, E)>, +} + +impl RetryAction { + pub(crate) fn new(server: Server, user: Arc, builder: F) -> Self + where + Fut: Future> + Send + Sync + 'static, + F: Fn(String, Server) -> Fut + Send + Sync + 'static, + { + let token = user.token().unwrap_or("".to_owned()); + Self { + token, + server, + user, + builder: Box::new(builder), + phantom: PhantomData, + } + } +} + +impl Action for RetryAction +where + Fut: Future> + Send + Sync + 'static, + T: Send + Sync + 'static, + E: Send + Sync + 'static, +{ + type Future = Pin> + Send + Sync>>; + type Item = T; + type Error = E; + + fn run(&mut self) -> Self::Future { + let fut = (self.builder)(self.token.clone(), self.server.clone()); + Box::pin(RetryActionFut { fut: Box::pin(fut) }) + } +} + +#[pin_project] +struct RetryActionFut { + #[pin] + fut: Pin> + Send + Sync>>, +} + +impl Future for RetryActionFut +where + T: Send + Sync + 'static, + E: Send + Sync + 'static, +{ + type Output = Result; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let mut this = self.project(); + this.fut.as_mut().poll(cx) + } +} diff --git a/rust-lib/flowy-workspace/src/services/view_controller.rs b/rust-lib/flowy-workspace/src/services/view_controller.rs index fab248a337..494630cf44 100644 --- a/rust-lib/flowy-workspace/src/services/view_controller.rs +++ b/rust-lib/flowy-workspace/src/services/view_controller.rs @@ -8,7 +8,7 @@ use crate::{ }; use crate::{ - entities::view::{DeleteViewParams, RepeatedView, ViewIdentifier}, + entities::view::{RepeatedView, ViewIdentifier}, errors::internal_error, module::WorkspaceUser, notify::WorkspaceNotification, @@ -21,6 +21,7 @@ use flowy_document::{ }; use crate::{entities::trash::TrashType, errors::WorkspaceResult}; + use futures::{FutureExt, StreamExt}; use std::sync::Arc; @@ -171,34 +172,31 @@ impl ViewController { Ok(()) } - // #[tracing::instrument(skip(self), err)] - // fn delete_view_on_server(&self, view_ids: Vec) -> Result<(), - // WorkspaceError> { let token = self.user.token()?; - // let server = self.server.clone(); - // let params = DeleteViewParams { view_ids }; - // spawn(async move { - // match server.delete_view(&token, params).await { - // Ok(_) => {}, - // Err(e) => { - // // TODO: retry? - // log::error!("Delete view failed: {:?}", e); - // }, - // } - // }); - // Ok(()) - // } - #[tracing::instrument(skip(self), err)] fn read_view_on_server(&self, params: ViewIdentifier) -> Result<(), WorkspaceError> { let token = self.user.token()?; let server = self.server.clone(); + let pool = self.database.db_pool()?; + // Opti: retry? spawn(async move { match server.read_view(&token, params).await { - Ok(_) => {}, - Err(e) => { - // TODO: retry? - log::error!("Read view failed: {:?}", e); + Ok(Some(view)) => match pool.get() { + Ok(conn) => { + let view_table = ViewTable::new(view.clone()); + let result = ViewTableSql::create_view(view_table, &conn); + match result { + Ok(_) => { + send_dart_notification(&view.id, WorkspaceNotification::ViewUpdated) + .payload(view.clone()) + .send(); + }, + Err(e) => log::error!("Save view failed: {:?}", e), + } + }, + Err(e) => log::error!("Require db connection failed: {:?}", e), }, + Ok(None) => {}, + Err(e) => log::error!("Read view failed: {:?}", e), } }); Ok(()) @@ -238,12 +236,12 @@ async fn handle_trash_event( let db_result = database.db_connection(); match event { - TrashEvent::NewTrash(_, view_ids, ret) | TrashEvent::Putback(_, view_ids, ret) => { + TrashEvent::NewTrash(identifiers, ret) | TrashEvent::Putback(identifiers, ret) => { let result = || { let conn = &*db_result?; let _ = conn.immediate_transaction::<_, WorkspaceError, _>(|| { - for view_id in view_ids { - let _ = notify_view_num_did_change(&view_id, conn, trash_can.clone())?; + for identifier in identifiers.items { + let _ = notify_view_num_changed(&identifier.id, conn, trash_can.clone())?; } Ok(()) })?; @@ -251,14 +249,14 @@ async fn handle_trash_event( }; let _ = ret.send(result()).await; }, - TrashEvent::Delete(_, delete_ids, ret) => { + TrashEvent::Delete(identifiers, ret) => { let result = || { let conn = &*db_result?; let _ = conn.immediate_transaction::<_, WorkspaceError, _>(|| { - for view_id in delete_ids { - let _ = ViewTableSql::delete_view(&view_id, conn)?; - let _ = document.delete(view_id.clone().into())?; - let _ = notify_view_num_did_change(&view_id, conn, trash_can.clone())?; + for identifier in identifiers.items { + let _ = ViewTableSql::delete_view(&identifier.id, conn)?; + let _ = document.delete(identifier.id.clone().into())?; + let _ = notify_view_num_changed(&identifier.id, conn, trash_can.clone())?; } Ok(()) })?; @@ -270,9 +268,10 @@ async fn handle_trash_event( } #[tracing::instrument(skip(conn, trash_can), err)] -fn notify_view_num_did_change(view_id: &str, conn: &SqliteConnection, trash_can: Arc) -> WorkspaceResult<()> { +fn notify_view_num_changed(view_id: &str, conn: &SqliteConnection, trash_can: Arc) -> WorkspaceResult<()> { let view_table = ViewTableSql::read_view(view_id, conn)?; let repeated_view = read_belonging_view(&view_table.belong_to_id, trash_can, conn)?; + send_dart_notification(&view_table.belong_to_id, WorkspaceNotification::AppViewsChanged) .payload(repeated_view) .send(); diff --git a/rust-lib/flowy-workspace/src/services/workspace_controller.rs b/rust-lib/flowy-workspace/src/services/workspace_controller.rs index 4a0703a142..92e18a8595 100644 --- a/rust-lib/flowy-workspace/src/services/workspace_controller.rs +++ b/rust-lib/flowy-workspace/src/services/workspace_controller.rs @@ -45,6 +45,7 @@ impl WorkspaceController { } pub fn init(&self) -> Result<(), WorkspaceError> { + let _ = self.trash_can.init()?; let _ = self.view_controller.init()?; Ok(()) } diff --git a/rust-lib/flowy-workspace/src/sql_tables/app/app_sql.rs b/rust-lib/flowy-workspace/src/sql_tables/app/app_sql.rs index 062875bd76..ec08493147 100644 --- a/rust-lib/flowy-workspace/src/sql_tables/app/app_sql.rs +++ b/rust-lib/flowy-workspace/src/sql_tables/app/app_sql.rs @@ -11,7 +11,7 @@ use flowy_database::{ pub struct AppTableSql {} impl AppTableSql { - pub(crate) fn create_app(&self, app_table: AppTable, conn: &SqliteConnection) -> Result<(), WorkspaceError> { + 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), _ => { @@ -22,16 +22,12 @@ impl AppTableSql { Ok(()) } - pub(crate) fn update_app( - &self, - changeset: AppTableChangeset, - conn: &SqliteConnection, - ) -> Result<(), WorkspaceError> { + pub(crate) fn update_app(changeset: AppTableChangeset, conn: &SqliteConnection) -> Result<(), WorkspaceError> { diesel_update_table!(app_table, changeset, conn); Ok(()) } - pub(crate) fn read_app(&self, 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(); // if let Some(is_trash) = is_trash { @@ -43,7 +39,6 @@ impl AppTableSql { } pub(crate) fn read_apps( - &self, workspace_id: &str, is_trash: bool, conn: &SqliteConnection, @@ -56,7 +51,7 @@ impl AppTableSql { Ok(app_table) } - pub(crate) fn delete_app(&self, 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)?; diff --git a/rust-lib/flowy-workspace/src/sql_tables/view/view_sql.rs b/rust-lib/flowy-workspace/src/sql_tables/view/view_sql.rs index 798b4672d8..c5fba8cde9 100644 --- a/rust-lib/flowy-workspace/src/sql_tables/view/view_sql.rs +++ b/rust-lib/flowy-workspace/src/sql_tables/view/view_sql.rs @@ -5,7 +5,7 @@ use crate::{ }; use flowy_database::{ prelude::*, - schema::{trash_table, view_table, view_table::dsl}, + schema::{view_table, view_table::dsl}, SqliteConnection, }; diff --git a/rust-lib/flowy-workspace/tests/workspace/view_test.rs b/rust-lib/flowy-workspace/tests/workspace/view_test.rs index af25f596d6..0d51418df3 100644 --- a/rust-lib/flowy-workspace/tests/workspace/view_test.rs +++ b/rust-lib/flowy-workspace/tests/workspace/view_test.rs @@ -1,5 +1,8 @@ use flowy_test::{workspace::*, FlowyTest}; -use flowy_workspace::entities::{trash::TrashIdentifier, view::*}; +use flowy_workspace::entities::{ + trash::{TrashIdentifier, TrashType}, + view::*, +}; #[tokio::test] #[should_panic] @@ -24,6 +27,7 @@ async fn view_delete_and_putback() { &test.sdk, TrashIdentifier { id: test.view.id.clone(), + ty: TrashType::View, }, ) .await;