Browse Source

[server]: delete the trash's target

appflowy 3 years ago
parent
commit
818aff46d4

+ 1 - 1
app_flowy/.vscode/settings.json

@@ -1,6 +1,6 @@
 {
     "[dart]": {
-        "editor.formatOnSave": true,
+        "editor.formatOnSave": false,
         "editor.formatOnType": true,
         "editor.rulers": [
             120

+ 1 - 1
app_flowy/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scroll_bar.dart

@@ -173,7 +173,7 @@ class ScrollbarState extends State<StyledScrollbar> {
               ),
             ),
           )
-        ]).opacity(showHandle ? 1.0 : 0.0, animate: true);
+        ]).opacity(showHandle ? 1.0 : 0.0, animate: false);
       },
     );
   }

+ 1 - 1
backend/scripts/database/database.mk

@@ -9,7 +9,7 @@ export ROOT = "./scripts/database"
 init_postgres:
 	${ROOT}/init_postgres.sh
 
-init_database:
+init_database: init_postgres
 	${ROOT}/init_database.sh
 
 reset_db:

+ 1 - 1
backend/src/service/trash/router.rs

@@ -31,7 +31,7 @@ pub async fn create_handler(
         .begin()
         .await
         .context("Failed to acquire a Postgres connection to create trash")?;
-    log::error!("😁create handler: {:?}", params);
+
     let _ = create_trash(&mut transaction, make_records(params)?, logged_user).await?;
 
     transaction

+ 43 - 2
backend/src/service/trash/trash.rs

@@ -9,7 +9,7 @@ use crate::{
 use ::protobuf::ProtobufEnum;
 use flowy_net::errors::ServerError;
 use flowy_workspace::protobuf::{RepeatedTrash, Trash, TrashType};
-use sqlx::{postgres::PgArguments, Postgres};
+use sqlx::{postgres::PgArguments, Postgres, Row};
 use uuid::Uuid;
 
 pub(crate) async fn create_trash(
@@ -33,10 +33,25 @@ pub(crate) async fn create_trash(
     Ok(())
 }
 
+#[tracing::instrument(skip(transaction, user), fields(delete_rows), err)]
 pub(crate) async fn delete_all_trash(
     transaction: &mut DBTransaction<'_>,
     user: &LoggedUser,
 ) -> Result<(), ServerError> {
+    let (sql, args) = SqlBuilder::select(TRASH_TABLE)
+        .and_where_eq("user_id", &user.user_id)
+        .build()?;
+    let rows = sqlx::query_with(&sql, args)
+        .fetch_all(transaction as &mut DBTransaction<'_>)
+        .await
+        .map_err(map_sqlx_error)?
+        .into_iter()
+        .map(|row| (row.get("id"), row.get("ty")))
+        .collect::<Vec<(Uuid, i32)>>();
+    tracing::Span::current().record("delete_rows", &format!("{:?}", rows).as_str());
+    let affected_row_count = rows.len();
+    let _ = delete_trash_targets(transaction as &mut DBTransaction<'_>, rows).await?;
+
     let (sql, args) = SqlBuilder::delete(TRASH_TABLE)
         .and_where_eq("user_id", &user.user_id)
         .build()?;
@@ -44,8 +59,9 @@ pub(crate) async fn delete_all_trash(
         .execute(transaction as &mut DBTransaction<'_>)
         .await
         .map_err(map_sqlx_error)?;
-
     tracing::Span::current().record("affected_row", &result.rows_affected());
+    debug_assert_eq!(affected_row_count as u64, result.rows_affected());
+
     Ok(())
 }
 
@@ -76,6 +92,12 @@ pub(crate) async fn delete_trash(
             },
         }
 
+        let _ = delete_trash_targets(
+            transaction as &mut DBTransaction<'_>,
+            vec![(trash_table.id.clone(), trash_table.ty)],
+        )
+        .await?;
+
         // Delete the trash table
         let (sql, args) = SqlBuilder::delete(TRASH_TABLE).and_where_eq("id", &trash_id).build()?;
         let _ = sqlx::query_with(&sql, args)
@@ -86,6 +108,25 @@ pub(crate) async fn delete_trash(
     Ok(())
 }
 
+async fn delete_trash_targets(
+    transaction: &mut DBTransaction<'_>,
+    targets: Vec<(Uuid, i32)>,
+) -> Result<(), ServerError> {
+    for (id, ty) in targets {
+        match TrashType::from_i32(ty) {
+            None => log::error!("Parser trash type with value: {} failed", ty),
+            Some(ty) => match ty {
+                TrashType::Unknown => {},
+                TrashType::View => {
+                    let _ = delete_view(transaction as &mut DBTransaction<'_>, vec![id]).await;
+                },
+            },
+        }
+    }
+
+    Ok(())
+}
+
 pub(crate) async fn read_trash_ids(
     user: &LoggedUser,
     transaction: &mut DBTransaction<'_>,

+ 10 - 0
rust-lib/flowy-workspace/src/entities/trash/trash_create.rs

@@ -1,5 +1,6 @@
 use crate::impl_def_and_def_mut;
 use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
+use std::fmt::Formatter;
 
 #[derive(PartialEq, Debug, ProtoBuf_Enum, Clone)]
 pub enum TrashType {
@@ -32,6 +33,15 @@ pub struct TrashIdentifiers {
     pub delete_all: bool,
 }
 
+impl std::fmt::Display for TrashIdentifiers {
+    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+        f.write_str(&format!(
+            "{:?}",
+            &self.items.iter().map(|item| &item.id).collect::<Vec<_>>()
+        ))
+    }
+}
+
 impl TrashIdentifiers {
     pub fn all() -> TrashIdentifiers {
         TrashIdentifiers {

+ 33 - 22
rust-lib/flowy-workspace/src/services/trash_can.rs

@@ -67,7 +67,16 @@ impl TrashCan {
 
     #[tracing::instrument(level = "debug", skip(self)  err)]
     pub async fn restore_all(&self) -> WorkspaceResult<()> {
-        let repeated_trash = self.delete_all_trash_on_local()?;
+        let repeated_trash = thread::scope(|_s| {
+            let conn = self.database.db_connection()?;
+            conn.immediate_transaction::<_, WorkspaceError, _>(|| {
+                let repeated_trash = TrashTableSql::read_all(&*conn)?;
+                let _ = TrashTableSql::delete_all(&*conn)?;
+                Ok(repeated_trash)
+            })
+        })
+        .unwrap()?;
+
         let identifiers: TrashIdentifiers = repeated_trash.items.clone().into();
         let (tx, mut rx) = mpsc::channel::<WorkspaceResult<()>>(1);
         let _ = self.notify.send(TrashEvent::Putback(identifiers, tx));
@@ -78,34 +87,39 @@ impl TrashCan {
         Ok(())
     }
 
-    #[tracing::instrument(level = "debug", skip(self)  err)]
+    #[tracing::instrument(level = "debug", skip(self), err)]
     pub async fn delete_all(&self) -> WorkspaceResult<()> {
-        let repeated_trash = self.delete_all_trash_on_local()?;
-        let identifiers: TrashIdentifiers = repeated_trash.items.clone().into();
-
-        let (tx, mut rx) = mpsc::channel::<WorkspaceResult<()>>(1);
-        let _ = self.notify.send(TrashEvent::Delete(identifiers, tx));
-        let _ = rx.recv().await;
+        let repeated_trash = TrashTableSql::read_all(&*(self.database.db_connection()?))?;
+        let trash_identifiers: TrashIdentifiers = repeated_trash.items.clone().into();
+        let _ = self.delete_with_identifiers(trash_identifiers.clone()).await?;
 
         notify_trash_num_changed(RepeatedTrash { items: vec![] });
         let _ = self.delete_all_trash_on_server().await?;
         Ok(())
     }
 
-    fn delete_all_trash_on_local(&self) -> WorkspaceResult<RepeatedTrash> {
-        let conn = self.database.db_connection()?;
-        conn.immediate_transaction::<_, WorkspaceError, _>(|| {
-            let repeated_trash = TrashTableSql::read_all(&*conn)?;
-            let _ = TrashTableSql::delete_all(&*conn)?;
-            Ok(repeated_trash)
-        })
+    #[tracing::instrument(level = "debug", skip(self), err)]
+    pub async fn delete(&self, trash_identifiers: TrashIdentifiers) -> WorkspaceResult<()> {
+        let _ = self.delete_with_identifiers(trash_identifiers.clone()).await?;
+        notify_trash_num_changed(TrashTableSql::read_all(&*(self.database.db_connection()?))?);
+        let _ = self.delete_trash_on_server(trash_identifiers)?;
+
+        Ok(())
     }
 
-    #[tracing::instrument(level = "debug", skip(self)  err)]
-    pub async fn delete(&self, trash_identifiers: TrashIdentifiers) -> WorkspaceResult<()> {
+    #[tracing::instrument(level = "debug", skip(self), fields(delete_trash_ids), err)]
+    pub async fn delete_with_identifiers(&self, trash_identifiers: TrashIdentifiers) -> WorkspaceResult<()> {
         let (tx, mut rx) = mpsc::channel::<WorkspaceResult<()>>(1);
+        tracing::Span::current().record("delete_trash_ids", &format!("{}", trash_identifiers).as_str());
         let _ = self.notify.send(TrashEvent::Delete(trash_identifiers.clone(), tx));
-        let _ = rx.recv().await;
+
+        match rx.recv().await {
+            None => {},
+            Some(result) => match result {
+                Ok(_) => {},
+                Err(e) => log::error!("{}", e),
+            },
+        }
 
         let conn = self.database.db_connection()?;
         conn.immediate_transaction::<_, WorkspaceError, _>(|| {
@@ -114,10 +128,6 @@ impl TrashCan {
             }
             Ok(())
         })?;
-
-        notify_trash_num_changed(TrashTableSql::read_all(&conn)?);
-        let _ = self.delete_trash_on_server(trash_identifiers)?;
-
         Ok(())
     }
 
@@ -212,6 +222,7 @@ impl TrashCan {
         spawn(async move {
             match server.read_trash(&token).await {
                 Ok(repeated_trash) => {
+                    log::debug!("Remote trash count: {}", repeated_trash.items.len());
                     match pool.get() {
                         Ok(conn) => {
                             let result = conn.immediate_transaction::<_, WorkspaceError, _>(|| {

+ 2 - 1
rust-lib/flowy-workspace/src/services/view_controller.rs

@@ -302,8 +302,9 @@ async fn handle_trash_event(
     }
 }
 
-#[tracing::instrument(skip(repeated_view), err)]
+#[tracing::instrument(skip(repeated_view), fields(view_count), err)]
 fn notify_view_num_changed(belong_to_id: &str, repeated_view: RepeatedView) -> WorkspaceResult<()> {
+    tracing::Span::current().record("view_count", &format!("{}", repeated_view.len()).as_str());
     send_dart_notification(&belong_to_id, WorkspaceNotification::AppViewsChanged)
         .payload(repeated_view)
         .send();