[rust]:delete app from trash

This commit is contained in:
appflowy 2021-10-31 11:41:22 +08:00
parent 3387301554
commit 5d0ef5baf3
17 changed files with 100 additions and 107 deletions

View File

@ -31,7 +31,7 @@ class TrashBloc extends Bloc<TrashEvent, TrashState> {
yield* _handleResult(result); yield* _handleResult(result);
}, },
delete: (e) async* { delete: (e) async* {
final result = await trasnManager.deleteViews([e.trashId]); final result = await trasnManager.deleteViews([e.trash]);
yield* _handleResult(result); yield* _handleResult(result);
}, },
deleteAll: (e) async* { deleteAll: (e) async* {
@ -75,7 +75,7 @@ class TrashEvent with _$TrashEvent {
const factory TrashEvent.initial() = Initial; const factory TrashEvent.initial() = Initial;
const factory TrashEvent.didReceiveTrash(List<Trash> trash) = ReceiveTrash; const factory TrashEvent.didReceiveTrash(List<Trash> trash) = ReceiveTrash;
const factory TrashEvent.putback(String trashId) = Putback; const factory TrashEvent.putback(String trashId) = Putback;
const factory TrashEvent.delete(String trashId) = Delete; const factory TrashEvent.delete(Trash trash) = Delete;
const factory TrashEvent.restoreAll() = RestoreAll; const factory TrashEvent.restoreAll() = RestoreAll;
const factory TrashEvent.deleteAll() = DeleteAll; const factory TrashEvent.deleteAll() = DeleteAll;
} }

View File

@ -32,9 +32,9 @@ class _$TrashEventTearOff {
); );
} }
Delete delete(String trashId) { Delete delete(Trash trash) {
return Delete( return Delete(
trashId, trash,
); );
} }
@ -57,7 +57,7 @@ mixin _$TrashEvent {
required TResult Function() initial, required TResult Function() initial,
required TResult Function(List<Trash> trash) didReceiveTrash, required TResult Function(List<Trash> trash) didReceiveTrash,
required TResult Function(String trashId) putback, required TResult Function(String trashId) putback,
required TResult Function(String trashId) delete, required TResult Function(Trash trash) delete,
required TResult Function() restoreAll, required TResult Function() restoreAll,
required TResult Function() deleteAll, required TResult Function() deleteAll,
}) => }) =>
@ -67,7 +67,7 @@ mixin _$TrashEvent {
TResult Function()? initial, TResult Function()? initial,
TResult Function(List<Trash> trash)? didReceiveTrash, TResult Function(List<Trash> trash)? didReceiveTrash,
TResult Function(String trashId)? putback, TResult Function(String trashId)? putback,
TResult Function(String trashId)? delete, TResult Function(Trash trash)? delete,
TResult Function()? restoreAll, TResult Function()? restoreAll,
TResult Function()? deleteAll, TResult Function()? deleteAll,
required TResult orElse(), required TResult orElse(),
@ -152,7 +152,7 @@ class _$Initial implements Initial {
required TResult Function() initial, required TResult Function() initial,
required TResult Function(List<Trash> trash) didReceiveTrash, required TResult Function(List<Trash> trash) didReceiveTrash,
required TResult Function(String trashId) putback, required TResult Function(String trashId) putback,
required TResult Function(String trashId) delete, required TResult Function(Trash trash) delete,
required TResult Function() restoreAll, required TResult Function() restoreAll,
required TResult Function() deleteAll, required TResult Function() deleteAll,
}) { }) {
@ -165,7 +165,7 @@ class _$Initial implements Initial {
TResult Function()? initial, TResult Function()? initial,
TResult Function(List<Trash> trash)? didReceiveTrash, TResult Function(List<Trash> trash)? didReceiveTrash,
TResult Function(String trashId)? putback, TResult Function(String trashId)? putback,
TResult Function(String trashId)? delete, TResult Function(Trash trash)? delete,
TResult Function()? restoreAll, TResult Function()? restoreAll,
TResult Function()? deleteAll, TResult Function()? deleteAll,
required TResult orElse(), required TResult orElse(),
@ -278,7 +278,7 @@ class _$ReceiveTrash implements ReceiveTrash {
required TResult Function() initial, required TResult Function() initial,
required TResult Function(List<Trash> trash) didReceiveTrash, required TResult Function(List<Trash> trash) didReceiveTrash,
required TResult Function(String trashId) putback, required TResult Function(String trashId) putback,
required TResult Function(String trashId) delete, required TResult Function(Trash trash) delete,
required TResult Function() restoreAll, required TResult Function() restoreAll,
required TResult Function() deleteAll, required TResult Function() deleteAll,
}) { }) {
@ -291,7 +291,7 @@ class _$ReceiveTrash implements ReceiveTrash {
TResult Function()? initial, TResult Function()? initial,
TResult Function(List<Trash> trash)? didReceiveTrash, TResult Function(List<Trash> trash)? didReceiveTrash,
TResult Function(String trashId)? putback, TResult Function(String trashId)? putback,
TResult Function(String trashId)? delete, TResult Function(Trash trash)? delete,
TResult Function()? restoreAll, TResult Function()? restoreAll,
TResult Function()? deleteAll, TResult Function()? deleteAll,
required TResult orElse(), required TResult orElse(),
@ -407,7 +407,7 @@ class _$Putback implements Putback {
required TResult Function() initial, required TResult Function() initial,
required TResult Function(List<Trash> trash) didReceiveTrash, required TResult Function(List<Trash> trash) didReceiveTrash,
required TResult Function(String trashId) putback, required TResult Function(String trashId) putback,
required TResult Function(String trashId) delete, required TResult Function(Trash trash) delete,
required TResult Function() restoreAll, required TResult Function() restoreAll,
required TResult Function() deleteAll, required TResult Function() deleteAll,
}) { }) {
@ -420,7 +420,7 @@ class _$Putback implements Putback {
TResult Function()? initial, TResult Function()? initial,
TResult Function(List<Trash> trash)? didReceiveTrash, TResult Function(List<Trash> trash)? didReceiveTrash,
TResult Function(String trashId)? putback, TResult Function(String trashId)? putback,
TResult Function(String trashId)? delete, TResult Function(Trash trash)? delete,
TResult Function()? restoreAll, TResult Function()? restoreAll,
TResult Function()? deleteAll, TResult Function()? deleteAll,
required TResult orElse(), required TResult orElse(),
@ -474,7 +474,7 @@ abstract class Putback implements TrashEvent {
abstract class $DeleteCopyWith<$Res> { abstract class $DeleteCopyWith<$Res> {
factory $DeleteCopyWith(Delete value, $Res Function(Delete) then) = factory $DeleteCopyWith(Delete value, $Res Function(Delete) then) =
_$DeleteCopyWithImpl<$Res>; _$DeleteCopyWithImpl<$Res>;
$Res call({String trashId}); $Res call({Trash trash});
} }
/// @nodoc /// @nodoc
@ -488,13 +488,13 @@ class _$DeleteCopyWithImpl<$Res> extends _$TrashEventCopyWithImpl<$Res>
@override @override
$Res call({ $Res call({
Object? trashId = freezed, Object? trash = freezed,
}) { }) {
return _then(Delete( return _then(Delete(
trashId == freezed trash == freezed
? _value.trashId ? _value.trash
: trashId // ignore: cast_nullable_to_non_nullable : trash // ignore: cast_nullable_to_non_nullable
as String, as Trash,
)); ));
} }
} }
@ -502,27 +502,27 @@ class _$DeleteCopyWithImpl<$Res> extends _$TrashEventCopyWithImpl<$Res>
/// @nodoc /// @nodoc
class _$Delete implements Delete { class _$Delete implements Delete {
const _$Delete(this.trashId); const _$Delete(this.trash);
@override @override
final String trashId; final Trash trash;
@override @override
String toString() { String toString() {
return 'TrashEvent.delete(trashId: $trashId)'; return 'TrashEvent.delete(trash: $trash)';
} }
@override @override
bool operator ==(dynamic other) { bool operator ==(dynamic other) {
return identical(this, other) || return identical(this, other) ||
(other is Delete && (other is Delete &&
(identical(other.trashId, trashId) || (identical(other.trash, trash) ||
const DeepCollectionEquality().equals(other.trashId, trashId))); const DeepCollectionEquality().equals(other.trash, trash)));
} }
@override @override
int get hashCode => int get hashCode =>
runtimeType.hashCode ^ const DeepCollectionEquality().hash(trashId); runtimeType.hashCode ^ const DeepCollectionEquality().hash(trash);
@JsonKey(ignore: true) @JsonKey(ignore: true)
@override @override
@ -535,11 +535,11 @@ class _$Delete implements Delete {
required TResult Function() initial, required TResult Function() initial,
required TResult Function(List<Trash> trash) didReceiveTrash, required TResult Function(List<Trash> trash) didReceiveTrash,
required TResult Function(String trashId) putback, required TResult Function(String trashId) putback,
required TResult Function(String trashId) delete, required TResult Function(Trash trash) delete,
required TResult Function() restoreAll, required TResult Function() restoreAll,
required TResult Function() deleteAll, required TResult Function() deleteAll,
}) { }) {
return delete(trashId); return delete(trash);
} }
@override @override
@ -548,13 +548,13 @@ class _$Delete implements Delete {
TResult Function()? initial, TResult Function()? initial,
TResult Function(List<Trash> trash)? didReceiveTrash, TResult Function(List<Trash> trash)? didReceiveTrash,
TResult Function(String trashId)? putback, TResult Function(String trashId)? putback,
TResult Function(String trashId)? delete, TResult Function(Trash trash)? delete,
TResult Function()? restoreAll, TResult Function()? restoreAll,
TResult Function()? deleteAll, TResult Function()? deleteAll,
required TResult orElse(), required TResult orElse(),
}) { }) {
if (delete != null) { if (delete != null) {
return delete(trashId); return delete(trash);
} }
return orElse(); return orElse();
} }
@ -591,9 +591,9 @@ class _$Delete implements Delete {
} }
abstract class Delete implements TrashEvent { abstract class Delete implements TrashEvent {
const factory Delete(String trashId) = _$Delete; const factory Delete(Trash trash) = _$Delete;
String get trashId => throw _privateConstructorUsedError; Trash get trash => throw _privateConstructorUsedError;
@JsonKey(ignore: true) @JsonKey(ignore: true)
$DeleteCopyWith<Delete> get copyWith => throw _privateConstructorUsedError; $DeleteCopyWith<Delete> get copyWith => throw _privateConstructorUsedError;
} }
@ -639,7 +639,7 @@ class _$RestoreAll implements RestoreAll {
required TResult Function() initial, required TResult Function() initial,
required TResult Function(List<Trash> trash) didReceiveTrash, required TResult Function(List<Trash> trash) didReceiveTrash,
required TResult Function(String trashId) putback, required TResult Function(String trashId) putback,
required TResult Function(String trashId) delete, required TResult Function(Trash trash) delete,
required TResult Function() restoreAll, required TResult Function() restoreAll,
required TResult Function() deleteAll, required TResult Function() deleteAll,
}) { }) {
@ -652,7 +652,7 @@ class _$RestoreAll implements RestoreAll {
TResult Function()? initial, TResult Function()? initial,
TResult Function(List<Trash> trash)? didReceiveTrash, TResult Function(List<Trash> trash)? didReceiveTrash,
TResult Function(String trashId)? putback, TResult Function(String trashId)? putback,
TResult Function(String trashId)? delete, TResult Function(Trash trash)? delete,
TResult Function()? restoreAll, TResult Function()? restoreAll,
TResult Function()? deleteAll, TResult Function()? deleteAll,
required TResult orElse(), required TResult orElse(),
@ -738,7 +738,7 @@ class _$DeleteAll implements DeleteAll {
required TResult Function() initial, required TResult Function() initial,
required TResult Function(List<Trash> trash) didReceiveTrash, required TResult Function(List<Trash> trash) didReceiveTrash,
required TResult Function(String trashId) putback, required TResult Function(String trashId) putback,
required TResult Function(String trashId) delete, required TResult Function(Trash trash) delete,
required TResult Function() restoreAll, required TResult Function() restoreAll,
required TResult Function() deleteAll, required TResult Function() deleteAll,
}) { }) {
@ -751,7 +751,7 @@ class _$DeleteAll implements DeleteAll {
TResult Function()? initial, TResult Function()? initial,
TResult Function(List<Trash> trash)? didReceiveTrash, TResult Function(List<Trash> trash)? didReceiveTrash,
TResult Function(String trashId)? putback, TResult Function(String trashId)? putback,
TResult Function(String trashId)? delete, TResult Function(Trash trash)? delete,
TResult Function()? restoreAll, TResult Function()? restoreAll,
TResult Function()? deleteAll, TResult Function()? deleteAll,
required TResult orElse(), required TResult orElse(),

View File

@ -8,7 +8,7 @@ abstract class ITrash {
Future<Either<Unit, WorkspaceError>> putback(String trashId); Future<Either<Unit, WorkspaceError>> putback(String trashId);
Future<Either<Unit, WorkspaceError>> deleteViews(List<String> trashIds); Future<Either<Unit, WorkspaceError>> deleteViews(List<Trash> trashList);
Future<Either<Unit, WorkspaceError>> restoreAll(); Future<Either<Unit, WorkspaceError>> restoreAll();

View File

@ -25,8 +25,8 @@ class ITrashImpl implements ITrash {
} }
@override @override
Future<Either<Unit, WorkspaceError>> deleteViews(List<String> trashIds) { Future<Either<Unit, WorkspaceError>> deleteViews(List<Trash> trashList) {
return repo.deleteViews(trashIds); return repo.deleteViews(trashList);
} }
@override @override

View File

@ -36,7 +36,7 @@ class IWorkspaceListenerImpl extends IWorkspaceListener {
@override @override
void start({WorkspaceAppsChangedCallback? addAppCallback, WorkspaceUpdatedCallback? updatedCallback}) { void start({WorkspaceAppsChangedCallback? addAppCallback, WorkspaceUpdatedCallback? updatedCallback}) {
repo.startListening(createApp: addAppCallback, update: updatedCallback); repo.startListening(appsChanged: addAppCallback, update: updatedCallback);
} }
@override @override

View File

@ -21,12 +21,14 @@ class TrashRepo {
return WorkspaceEventPutbackTrash(id).send(); return WorkspaceEventPutbackTrash(id).send();
} }
Future<Either<Unit, WorkspaceError>> deleteViews(List<String> viewIds) { Future<Either<Unit, WorkspaceError>> deleteViews(List<Trash> trashList) {
final trashIdentifiers = TrashIdentifiers( final items = trashList.map((trash) {
items: viewIds.map((id) => TrashIdentifier.create() return TrashIdentifier.create()
..id = id ..id = trash.id
..ty = TrashType.View)); ..ty = trash.ty;
});
final trashIdentifiers = TrashIdentifiers(items: items);
return WorkspaceEventDeleteTrash(trashIdentifiers).send(); return WorkspaceEventDeleteTrash(trashIdentifiers).send();
} }

View File

@ -160,7 +160,7 @@ class _TrashStackPageState extends State<TrashStackPage> {
onRestore: () { onRestore: () {
context.read<TrashBloc>().add(TrashEvent.putback(object.id)); context.read<TrashBloc>().add(TrashEvent.putback(object.id));
}, },
onDelete: () => context.read<TrashBloc>().add(TrashEvent.delete(object.id)), onDelete: () => context.read<TrashBloc>().add(TrashEvent.delete(object)),
), ),
); );
}, },

View File

@ -101,6 +101,7 @@ pub(crate) async fn update_app(
Ok(()) Ok(())
} }
#[tracing::instrument(skip(transaction), err)]
pub(crate) async fn delete_app(transaction: &mut DBTransaction<'_>, app_id: Uuid) -> Result<(), ServerError> { pub(crate) async fn delete_app(transaction: &mut DBTransaction<'_>, app_id: Uuid) -> Result<(), ServerError> {
let (sql, args) = SqlBuilder::delete(APP_TABLE).and_where_eq("id", app_id).build()?; let (sql, args) = SqlBuilder::delete(APP_TABLE).and_where_eq("id", app_id).build()?;
let _ = sqlx::query_with(&sql, args) let _ = sqlx::query_with(&sql, args)

View File

@ -59,7 +59,7 @@ pub async fn delete_handler(
let _ = delete_all_trash(&mut transaction, &logged_user).await?; let _ = delete_all_trash(&mut transaction, &logged_user).await?;
} else { } else {
let records = make_records(params)?; let records = make_records(params)?;
let _ = delete_trash(&mut transaction, records, &logged_user).await?; let _ = delete_trash(&mut transaction, records).await?;
} }
transaction transaction

View File

@ -13,6 +13,7 @@ use flowy_workspace::protobuf::{RepeatedTrash, Trash, TrashType};
use sqlx::{postgres::PgArguments, Postgres, Row}; use sqlx::{postgres::PgArguments, Postgres, Row};
use uuid::Uuid; use uuid::Uuid;
#[tracing::instrument(skip(transaction, user), err)]
pub(crate) async fn create_trash( pub(crate) async fn create_trash(
transaction: &mut DBTransaction<'_>, transaction: &mut DBTransaction<'_>,
records: Vec<(Uuid, i32)>, records: Vec<(Uuid, i32)>,
@ -66,10 +67,10 @@ pub(crate) async fn delete_all_trash(
Ok(()) Ok(())
} }
#[tracing::instrument(skip(transaction), err)]
pub(crate) async fn delete_trash( pub(crate) async fn delete_trash(
transaction: &mut DBTransaction<'_>, transaction: &mut DBTransaction<'_>,
records: Vec<(Uuid, i32)>, records: Vec<(Uuid, i32)>,
_user: &LoggedUser,
) -> Result<(), ServerError> { ) -> Result<(), ServerError> {
for (trash_id, _) in records { for (trash_id, _) in records {
// Read the trash_table and delete the original table according to the TrashType // Read the trash_table and delete the original table according to the TrashType
@ -99,6 +100,7 @@ pub(crate) async fn delete_trash(
Ok(()) Ok(())
} }
#[tracing::instrument(skip(transaction, targets), err)]
async fn delete_trash_targets( async fn delete_trash_targets(
transaction: &mut DBTransaction<'_>, transaction: &mut DBTransaction<'_>,
targets: Vec<(Uuid, i32)>, targets: Vec<(Uuid, i32)>,
@ -134,6 +136,7 @@ pub(crate) async fn read_trash_ids(
Ok(ids) Ok(ids)
} }
#[tracing::instrument(skip(transaction, user), err)]
pub(crate) async fn read_trash( pub(crate) async fn read_trash(
transaction: &mut DBTransaction<'_>, transaction: &mut DBTransaction<'_>,
user: &LoggedUser, user: &LoggedUser,

View File

@ -44,6 +44,7 @@ pub(crate) async fn update_view(
Ok(()) Ok(())
} }
#[tracing::instrument(skip(transaction), err)]
pub(crate) async fn delete_view(transaction: &mut DBTransaction<'_>, view_ids: Vec<Uuid>) -> Result<(), ServerError> { pub(crate) async fn delete_view(transaction: &mut DBTransaction<'_>, view_ids: Vec<Uuid>) -> Result<(), ServerError> {
for view_id in view_ids { for view_id in view_ids {
let (sql, args) = SqlBuilder::delete(VIEW_TABLE).and_where_eq("id", &view_id).build()?; let (sql, args) = SqlBuilder::delete(VIEW_TABLE).and_where_eq("id", &view_id).build()?;

View File

@ -66,6 +66,7 @@ pub(crate) async fn delete_workspace(
Ok(()) Ok(())
} }
#[tracing::instrument(skip(transaction, logged_user), err)]
pub async fn read_workspaces( pub async fn read_workspaces(
transaction: &mut DBTransaction<'_>, transaction: &mut DBTransaction<'_>,
workspace_id: Option<String>, workspace_id: Option<String>,
@ -109,7 +110,7 @@ pub async fn read_workspaces(
Ok(repeated_workspace) Ok(repeated_workspace)
} }
// transaction must be commit from caller #[tracing::instrument(skip(transaction, user), fields(app_count), err)]
async fn read_workspace_apps<'c>( async fn read_workspace_apps<'c>(
user: &LoggedUser, user: &LoggedUser,
transaction: &mut DBTransaction<'_>, transaction: &mut DBTransaction<'_>,
@ -126,6 +127,7 @@ async fn read_workspace_apps<'c>(
.await .await
.map_err(map_sqlx_error)?; .map_err(map_sqlx_error)?;
tracing::Span::current().record("app_count", &app_tables.len());
let mut apps = vec![]; let mut apps = vec![];
for table in app_tables { for table in app_tables {
let app = read_app(transaction, table.id, user).await?; let app = read_app(transaction, table.id, user).await?;

View File

@ -47,7 +47,7 @@ impl AppController {
conn.immediate_transaction::<_, WorkspaceError, _>(|| { conn.immediate_transaction::<_, WorkspaceError, _>(|| {
let _ = self.save_app(app.clone(), &*conn)?; let _ = self.save_app(app.clone(), &*conn)?;
let _ = notify_app_num_changed(&app.workspace_id, self.trash_can.clone(), conn)?; let _ = notify_apps_changed(&app.workspace_id, self.trash_can.clone(), conn)?;
Ok(()) Ok(())
})?; })?;
@ -179,6 +179,7 @@ impl AppController {
} }
} }
#[tracing::instrument(level = "debug", skip(database, trash_can))]
async fn handle_trash_event(database: Arc<dyn WorkspaceDatabase>, trash_can: Arc<TrashCan>, event: TrashEvent) { async fn handle_trash_event(database: Arc<dyn WorkspaceDatabase>, trash_can: Arc<TrashCan>, event: TrashEvent) {
let db_result = database.db_connection(); let db_result = database.db_connection();
match event { match event {
@ -188,7 +189,7 @@ async fn handle_trash_event(database: Arc<dyn WorkspaceDatabase>, trash_can: Arc
let _ = conn.immediate_transaction::<_, WorkspaceError, _>(|| { let _ = conn.immediate_transaction::<_, WorkspaceError, _>(|| {
for identifier in identifiers.items { for identifier in identifiers.items {
let app_table = AppTableSql::read_app(&identifier.id, conn)?; let app_table = AppTableSql::read_app(&identifier.id, conn)?;
let _ = notify_app_num_changed(&app_table.workspace_id, trash_can.clone(), conn)?; let _ = notify_apps_changed(&app_table.workspace_id, trash_can.clone(), conn)?;
} }
Ok(()) Ok(())
})?; })?;
@ -208,7 +209,7 @@ async fn handle_trash_event(database: Arc<dyn WorkspaceDatabase>, trash_can: Arc
} }
for notify_id in notify_ids { for notify_id in notify_ids {
let _ = notify_app_num_changed(&notify_id, trash_can.clone(), conn)?; let _ = notify_apps_changed(&notify_id, trash_can.clone(), conn)?;
} }
Ok(()) Ok(())
})?; })?;
@ -220,11 +221,7 @@ async fn handle_trash_event(database: Arc<dyn WorkspaceDatabase>, trash_can: Arc
} }
#[tracing::instrument(skip(workspace_id, trash_can, conn), err)] #[tracing::instrument(skip(workspace_id, trash_can, conn), err)]
fn notify_app_num_changed( fn notify_apps_changed(workspace_id: &str, trash_can: Arc<TrashCan>, conn: &SqliteConnection) -> WorkspaceResult<()> {
workspace_id: &str,
trash_can: Arc<TrashCan>,
conn: &SqliteConnection,
) -> WorkspaceResult<()> {
let repeated_app = read_local_workspace_apps(workspace_id, trash_can, conn)?; let repeated_app = read_local_workspace_apps(workspace_id, trash_can, conn)?;
send_dart_notification(workspace_id, WorkspaceNotification::WorkspaceAppsChanged) send_dart_notification(workspace_id, WorkspaceNotification::WorkspaceAppsChanged)
.payload(repeated_app) .payload(repeated_app)
@ -232,7 +229,7 @@ fn notify_app_num_changed(
Ok(()) Ok(())
} }
fn read_local_workspace_apps( pub fn read_local_workspace_apps(
workspace_id: &str, workspace_id: &str,
trash_can: Arc<TrashCan>, trash_can: Arc<TrashCan>,
conn: &SqliteConnection, conn: &SqliteConnection,

View File

@ -9,7 +9,7 @@ use crate::{
use crossbeam_utils::thread; use crossbeam_utils::thread;
use flowy_database::SqliteConnection; use flowy_database::SqliteConnection;
use std::sync::Arc; use std::{fmt::Formatter, sync::Arc};
use tokio::sync::{broadcast, mpsc}; use tokio::sync::{broadcast, mpsc};
pub struct TrashCan { pub struct TrashCan {
@ -41,7 +41,7 @@ impl TrashCan {
let conn = self.database.db_connection()?; let conn = self.database.db_connection()?;
conn.immediate_transaction::<_, WorkspaceError, _>(|| { conn.immediate_transaction::<_, WorkspaceError, _>(|| {
let _ = TrashTableSql::delete_trash(trash_id, &*conn)?; let _ = TrashTableSql::delete_trash(trash_id, &*conn)?;
notify_trash_num_changed(TrashTableSql::read_all(&conn)?); notify_trash_changed(TrashTableSql::read_all(&conn)?);
Ok(()) Ok(())
})?; })?;
@ -82,7 +82,7 @@ impl TrashCan {
let _ = self.notify.send(TrashEvent::Putback(identifiers, tx)); let _ = self.notify.send(TrashEvent::Putback(identifiers, tx));
let _ = rx.recv().await; let _ = rx.recv().await;
notify_trash_num_changed(RepeatedTrash { items: vec![] }); notify_trash_changed(RepeatedTrash { items: vec![] });
let _ = self.delete_all_trash_on_server().await?; let _ = self.delete_all_trash_on_server().await?;
Ok(()) Ok(())
} }
@ -93,7 +93,7 @@ impl TrashCan {
let trash_identifiers: TrashIdentifiers = repeated_trash.items.clone().into(); let trash_identifiers: TrashIdentifiers = repeated_trash.items.clone().into();
let _ = self.delete_with_identifiers(trash_identifiers.clone()).await?; let _ = self.delete_with_identifiers(trash_identifiers.clone()).await?;
notify_trash_num_changed(RepeatedTrash { items: vec![] }); notify_trash_changed(RepeatedTrash { items: vec![] });
let _ = self.delete_all_trash_on_server().await?; let _ = self.delete_all_trash_on_server().await?;
Ok(()) Ok(())
} }
@ -101,7 +101,7 @@ impl TrashCan {
#[tracing::instrument(level = "debug", skip(self), err)] #[tracing::instrument(level = "debug", skip(self), err)]
pub async fn delete(&self, trash_identifiers: TrashIdentifiers) -> WorkspaceResult<()> { pub async fn delete(&self, trash_identifiers: TrashIdentifiers) -> WorkspaceResult<()> {
let _ = self.delete_with_identifiers(trash_identifiers.clone()).await?; let _ = self.delete_with_identifiers(trash_identifiers.clone()).await?;
notify_trash_num_changed(TrashTableSql::read_all(&*(self.database.db_connection()?))?); notify_trash_changed(TrashTableSql::read_all(&*(self.database.db_connection()?))?);
let _ = self.delete_trash_on_server(trash_identifiers)?; let _ = self.delete_trash_on_server(trash_identifiers)?;
Ok(()) Ok(())
@ -137,7 +137,7 @@ impl TrashCan {
// DELETE operations. Its not possible for us to use these commands to // DELETE operations. Its not possible for us to use these commands to
// CREATE and DROP tables operations because those are auto-commit in the // CREATE and DROP tables operations because those are auto-commit in the
// database. // database.
#[tracing::instrument(level = "debug", skip(self, trash), err)] #[tracing::instrument(level = "debug", skip(self, trash), fields(trash_count), err)]
pub async fn add<T: Into<Trash>>(&self, trash: Vec<T>) -> Result<(), WorkspaceError> { pub async fn add<T: Into<Trash>>(&self, trash: Vec<T>) -> Result<(), WorkspaceError> {
let (tx, mut rx) = mpsc::channel::<WorkspaceResult<()>>(1); let (tx, mut rx) = mpsc::channel::<WorkspaceResult<()>>(1);
let repeated_trash = trash.into_iter().map(|t| t.into()).collect::<Vec<Trash>>(); let repeated_trash = trash.into_iter().map(|t| t.into()).collect::<Vec<Trash>>();
@ -145,13 +145,15 @@ impl TrashCan {
.iter() .iter()
.map(|t| t.into()) .map(|t| t.into())
.collect::<Vec<TrashIdentifier>>(); .collect::<Vec<TrashIdentifier>>();
tracing::Span::current().record("trash_count", &identifiers.len());
let _ = thread::scope(|_s| { let _ = thread::scope(|_s| {
let conn = self.database.db_connection()?; let conn = self.database.db_connection()?;
conn.immediate_transaction::<_, WorkspaceError, _>(|| { conn.immediate_transaction::<_, WorkspaceError, _>(|| {
let _ = TrashTableSql::create_trash(repeated_trash.clone(), &*conn)?; let _ = TrashTableSql::create_trash(repeated_trash.clone(), &*conn)?;
let _ = self.create_trash_on_server(repeated_trash); let _ = self.create_trash_on_server(repeated_trash);
notify_trash_num_changed(TrashTableSql::read_all(&conn)?); notify_trash_changed(TrashTableSql::read_all(&conn)?);
Ok(()) Ok(())
})?; })?;
Ok::<(), WorkspaceError>(()) Ok::<(), WorkspaceError>(())
@ -168,7 +170,6 @@ impl TrashCan {
pub fn read_trash(&self, conn: &SqliteConnection) -> Result<RepeatedTrash, WorkspaceError> { pub fn read_trash(&self, conn: &SqliteConnection) -> Result<RepeatedTrash, WorkspaceError> {
let repeated_trash = TrashTableSql::read_all(&*conn)?; let repeated_trash = TrashTableSql::read_all(&*conn)?;
let _ = self.read_trash_on_server()?; let _ = self.read_trash_on_server()?;
Ok(repeated_trash) Ok(repeated_trash)
} }
@ -226,15 +227,15 @@ impl TrashCan {
match pool.get() { match pool.get() {
Ok(conn) => { Ok(conn) => {
let result = conn.immediate_transaction::<_, WorkspaceError, _>(|| { let result = conn.immediate_transaction::<_, WorkspaceError, _>(|| {
TrashTableSql::create_trash(repeated_trash.items.clone(), &*conn) let _ = TrashTableSql::create_trash(repeated_trash.items.clone(), &*conn)?;
TrashTableSql::read_all(&conn)
}); });
match result { match result {
Ok(_) => { Ok(repeated_trash) => {
// FIXME: User may modify the trash(add/putback) before the flying request comes // FIXME: User may modify the trash(add/putback) before the flying request comes
// back that will cause the trash list to be outdated. // back that will cause the trash list to be outdated.
// TODO: impl with operation transform notify_trash_changed(repeated_trash);
notify_trash_num_changed(repeated_trash);
}, },
Err(e) => log::error!("Save trash failed: {:?}", e), Err(e) => log::error!("Save trash failed: {:?}", e),
} }
@ -257,7 +258,7 @@ impl TrashCan {
} }
#[tracing::instrument(skip(repeated_trash), fields(trash_count))] #[tracing::instrument(skip(repeated_trash), fields(trash_count))]
fn notify_trash_num_changed(repeated_trash: RepeatedTrash) { fn notify_trash_changed(repeated_trash: RepeatedTrash) {
tracing::Span::current().record("trash_count", &repeated_trash.len()); tracing::Span::current().record("trash_count", &repeated_trash.len());
send_anonymous_dart_notification(WorkspaceNotification::TrashUpdated) send_anonymous_dart_notification(WorkspaceNotification::TrashUpdated)
.payload(repeated_trash) .payload(repeated_trash)
@ -271,6 +272,16 @@ pub enum TrashEvent {
Delete(TrashIdentifiers, mpsc::Sender<WorkspaceResult<()>>), Delete(TrashIdentifiers, mpsc::Sender<WorkspaceResult<()>>),
} }
impl std::fmt::Debug for TrashEvent {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
TrashEvent::NewTrash(identifiers, _) => f.write_str(&format!("{:?}", identifiers)),
TrashEvent::Putback(identifiers, _) => f.write_str(&format!("{:?}", identifiers)),
TrashEvent::Delete(identifiers, _) => f.write_str(&format!("{:?}", identifiers)),
}
}
}
impl TrashEvent { impl TrashEvent {
pub fn select(self, s: TrashType) -> Option<TrashEvent> { pub fn select(self, s: TrashType) -> Option<TrashEvent> {
match self { match self {

View File

@ -64,7 +64,7 @@ impl ViewController {
conn.immediate_transaction::<_, WorkspaceError, _>(|| { conn.immediate_transaction::<_, WorkspaceError, _>(|| {
let _ = self.save_view(view.clone(), conn)?; let _ = self.save_view(view.clone(), conn)?;
let _ = notify_view_num_changed(&view.belong_to_id, trash_can, &conn)?; let _ = notify_views_changed(&view.belong_to_id, trash_can, &conn)?;
Ok(()) Ok(())
})?; })?;
@ -163,7 +163,7 @@ impl ViewController {
.send(); .send();
// //
let _ = notify_view_num_changed(&updated_view.belong_to_id, self.trash_can.clone(), conn)?; let _ = notify_views_changed(&updated_view.belong_to_id, self.trash_can.clone(), conn)?;
let _ = self.update_view_on_server(params); let _ = self.update_view_on_server(params);
Ok(updated_view) Ok(updated_view)
@ -253,6 +253,7 @@ impl ViewController {
} }
} }
#[tracing::instrument(level = "debug", skip(database, document, trash_can))]
async fn handle_trash_event( async fn handle_trash_event(
database: Arc<dyn WorkspaceDatabase>, database: Arc<dyn WorkspaceDatabase>,
document: Arc<FlowyDocument>, document: Arc<FlowyDocument>,
@ -268,7 +269,7 @@ async fn handle_trash_event(
let _ = conn.immediate_transaction::<_, WorkspaceError, _>(|| { let _ = conn.immediate_transaction::<_, WorkspaceError, _>(|| {
for identifier in identifiers.items { for identifier in identifiers.items {
let view_table = ViewTableSql::read_view(&identifier.id, conn)?; let view_table = ViewTableSql::read_view(&identifier.id, conn)?;
let _ = notify_view_num_changed(&view_table.belong_to_id, trash_can.clone(), conn)?; let _ = notify_views_changed(&view_table.belong_to_id, trash_can.clone(), conn)?;
} }
Ok(()) Ok(())
})?; })?;
@ -289,7 +290,7 @@ async fn handle_trash_event(
} }
for notify_id in notify_ids { for notify_id in notify_ids {
let _ = notify_view_num_changed(&notify_id, trash_can.clone(), conn)?; let _ = notify_views_changed(&notify_id, trash_can.clone(), conn)?;
} }
Ok(()) Ok(())
@ -302,11 +303,7 @@ async fn handle_trash_event(
} }
#[tracing::instrument(skip(belong_to_id, trash_can, conn), fields(view_count), err)] #[tracing::instrument(skip(belong_to_id, trash_can, conn), fields(view_count), err)]
fn notify_view_num_changed( fn notify_views_changed(belong_to_id: &str, trash_can: Arc<TrashCan>, conn: &SqliteConnection) -> WorkspaceResult<()> {
belong_to_id: &str,
trash_can: Arc<TrashCan>,
conn: &SqliteConnection,
) -> WorkspaceResult<()> {
let repeated_view = read_local_belonging_view(belong_to_id, trash_can.clone(), conn)?; 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()); tracing::Span::current().record("view_count", &format!("{}", repeated_view.len()).as_str());
send_dart_notification(&belong_to_id, WorkspaceNotification::AppViewsChanged) send_dart_notification(&belong_to_id, WorkspaceNotification::AppViewsChanged)

View File

@ -6,7 +6,7 @@ use crate::{
errors::*, errors::*,
module::{WorkspaceDatabase, WorkspaceUser}, module::{WorkspaceDatabase, WorkspaceUser},
notify::*, notify::*,
services::{helper::spawn, server::Server, AppController, TrashCan, ViewController}, services::{helper::spawn, read_local_workspace_apps, server::Server, AppController, TrashCan, ViewController},
sql_tables::workspace::{WorkspaceTable, WorkspaceTableChangeset, WorkspaceTableSql}, sql_tables::workspace::{WorkspaceTable, WorkspaceTableChangeset, WorkspaceTableSql},
}; };
use flowy_database::SqliteConnection; use flowy_database::SqliteConnection;
@ -159,9 +159,9 @@ impl WorkspaceController {
pub(crate) async fn read_workspace_apps(&self) -> Result<RepeatedApp, WorkspaceError> { pub(crate) async fn read_workspace_apps(&self) -> Result<RepeatedApp, WorkspaceError> {
let workspace_id = get_current_workspace()?; let workspace_id = get_current_workspace()?;
let conn = self.database.db_connection()?; let conn = self.database.db_connection()?;
let apps = self.read_local_apps(&workspace_id, &*conn)?; let repeated_app = self.read_local_apps(&workspace_id, &*conn)?;
// TODO: read from server // TODO: read from server
Ok(RepeatedApp { items: apps }) Ok(repeated_app)
} }
#[tracing::instrument(level = "debug", skip(self, conn), err)] #[tracing::instrument(level = "debug", skip(self, conn), err)]
@ -176,7 +176,7 @@ impl WorkspaceController {
let mut workspaces = vec![]; let mut workspaces = vec![];
for table in workspace_tables { for table in workspace_tables {
let apps = self.read_local_apps(&table.id, conn)?; let apps = self.read_local_apps(&table.id, conn)?.into_inner();
let mut workspace: Workspace = table.into(); let mut workspace: Workspace = table.into();
workspace.apps.items = apps; workspace.apps.items = apps;
workspaces.push(workspace); workspaces.push(workspace);
@ -202,15 +202,9 @@ impl WorkspaceController {
} }
#[tracing::instrument(level = "debug", skip(self, conn), err)] #[tracing::instrument(level = "debug", skip(self, conn), err)]
fn read_local_apps(&self, workspace_id: &str, conn: &SqliteConnection) -> Result<Vec<App>, WorkspaceError> { fn read_local_apps(&self, workspace_id: &str, conn: &SqliteConnection) -> Result<RepeatedApp, WorkspaceError> {
let apps = self let repeated_app = read_local_workspace_apps(workspace_id, self.trash_can.clone(), conn)?;
.workspace_sql Ok(repeated_app)
.read_apps_belong_to_workspace(workspace_id, conn)?
.into_iter()
.map(|app_table| app_table.into())
.collect::<Vec<App>>();
Ok(apps)
} }
} }

View File

@ -1,9 +1,6 @@
use crate::{ use crate::{
errors::WorkspaceError, errors::WorkspaceError,
sql_tables::{ sql_tables::workspace::{WorkspaceTable, WorkspaceTableChangeset},
app::AppTable,
workspace::{WorkspaceTable, WorkspaceTableChangeset},
},
}; };
use diesel::SqliteConnection; use diesel::SqliteConnection;
use flowy_database::{ use flowy_database::{
@ -63,16 +60,4 @@ impl WorkspaceTableSql {
diesel_delete_table!(workspace_table, workspace_id, conn); diesel_delete_table!(workspace_table, workspace_id, conn);
Ok(()) Ok(())
} }
pub(crate) fn read_apps_belong_to_workspace(
&self,
workspace_id: &str,
conn: &SqliteConnection,
) -> Result<Vec<AppTable>, WorkspaceError> {
let workspace_table: WorkspaceTable = dsl::workspace_table
.filter(workspace_table::id.eq(workspace_id))
.first::<WorkspaceTable>(conn)?;
let apps = AppTable::belonging_to(&workspace_table).load::<AppTable>(conn)?;
Ok(apps)
}
} }