From 321286bed2503202a10216add5983c2b5cf1971a Mon Sep 17 00:00:00 2001 From: Zack Fu Zi Xiang Date: Mon, 9 Sep 2024 16:07:28 +0800 Subject: [PATCH 1/8] chore: use into --- libs/client-api-test/src/test_client.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libs/client-api-test/src/test_client.rs b/libs/client-api-test/src/test_client.rs index dd771365..fab9d3d2 100644 --- a/libs/client-api-test/src/test_client.rs +++ b/libs/client-api-test/src/test_client.rs @@ -236,11 +236,10 @@ impl TestClient { }) .await .unwrap(); - let db_doc_state = db_collab_collab_resp.encode_collab.doc_state; Collab::new_with_source( CollabOrigin::Server, &db_id, - DataSource::DocStateV1(db_doc_state.to_vec()), + db_collab_collab_resp.encode_collab.into(), vec![], false, ) From 9281fbdf546942e2d2f9e0e7f329030b7cbfe178 Mon Sep 17 00:00:00 2001 From: Zack Fu Zi Xiang Date: Mon, 9 Sep 2024 17:02:13 +0800 Subject: [PATCH 2/8] chore: add some doc about database relation --- src/biz/workspace/publish_dup.rs | 34 ++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/biz/workspace/publish_dup.rs b/src/biz/workspace/publish_dup.rs index 7abb8500..cd8a3d01 100644 --- a/src/biz/workspace/publish_dup.rs +++ b/src/biz/workspace/publish_dup.rs @@ -684,6 +684,24 @@ impl PublishCollabDuplicator { // handle row relations // collect all map ref with `database_id` fields // deep copy those database + // + // db_collab: Object { + // "database": Object { + // "fields": Object { `database_fields` + // "MBaTsr": Object { + // "type_option": Object { `type_option` + // "10": Object { + // "database_id": String("e7a18802-1594-4d44-9542-38c7b471ebc2") + // // we need to duplicate this database and replace the id + // } + // ... + // }, + // }, + // ... + // }, + // }, + // } + // let mut txn = db_collab.context.transact_mut(); let database_fields: MapRef = db_collab .data @@ -745,6 +763,22 @@ impl PublishCollabDuplicator { data.insert(&mut txn, "database_id", new_db_id.clone()); // update relation cells + // db_row_collb: Object { + // "data": Object { + // "cells": Object { + // "MBaTsr": Object { + // "data": Array [ + // String("eefb5700-8cf7-411e-9596-f60b9a51916e"), + // String("23d5e054-42c8-4754-ad69-527e4ffc1e46"), + // // above are published row ids of related database + // // we need to replace them with respective duplicated row ids + // ], + // "field_type": Number(10), + // // use this condition to filter out relation cells + // }, + // }, + // }, + // } let cells: MapRef = db_row_collab .data .get_with_path(&txn, ["data", "cells"]) From e22f3163273ae8f5971872ed713dbfd4dbfbca64 Mon Sep 17 00:00:00 2001 From: Zack Fu Zi Xiang Date: Tue, 10 Sep 2024 12:48:55 +0800 Subject: [PATCH 3/8] feat: partially use database body --- src/biz/workspace/publish_dup.rs | 88 ++++++++++++-------------------- 1 file changed, 34 insertions(+), 54 deletions(-) diff --git a/src/biz/workspace/publish_dup.rs b/src/biz/workspace/publish_dup.rs index 2898250c..fe1d744a 100644 --- a/src/biz/workspace/publish_dup.rs +++ b/src/biz/workspace/publish_dup.rs @@ -4,6 +4,7 @@ use collab::core::collab::DataSource; use collab::preclude::Collab; use collab::preclude::MapExt; +use collab_database::database::DatabaseBody; use collab_database::entity::FieldType; use collab_database::views::DatabaseViews; use collab_database::workspace_database::WorkspaceDatabaseBody; @@ -669,7 +670,9 @@ impl PublishCollabDuplicator { ) -> Result<(String, String, bool), AppError> { // collab of database let mut db_collab = collab_from_doc_state(published_db.database_collab.clone(), "")?; - let pub_db_id = get_database_id_from_collab(&db_collab)?; + let db_body = DatabaseBody::from_collab(&db_collab) + .ok_or_else(|| AppError::RecordNotFound("no database body found".to_string()))?; + let pub_db_id = db_body.get_database_id(&db_collab.context.transact()); // check if the database is already duplicated if let Some(db_id) = self.duplicated_refs.get(&pub_db_id).cloned().flatten() { @@ -682,62 +685,39 @@ impl PublishCollabDuplicator { { // handle row relations - // collect all map ref with `database_id` fields - // deep copy those database - // - // db_collab: Object { - // "database": Object { - // "fields": Object { `database_fields` - // "MBaTsr": Object { - // "type_option": Object { `type_option` - // "10": Object { - // "database_id": String("e7a18802-1594-4d44-9542-38c7b471ebc2") - // // we need to duplicate this database and replace the id - // } - // ... - // }, - // }, - // ... - // }, - // }, - // } - // let mut txn = db_collab.context.transact_mut(); - let database_fields: MapRef = db_collab - .data - .get_with_path(&txn, ["database", "fields"]) - .ok_or_else(|| AppError::RecordNotFound("no fields found in database".to_string()))?; - let mut type_option_values = vec![]; - for (_, out) in database_fields.iter(&txn) { - if let Ok(m1) = out.cast::() { - if let Some(type_option) = m1.get(&txn, "type_option") { - if let Ok(m2) = type_option.cast::() { - for (_, out2) in m2.iter(&txn) { - if let Ok(m3) = out2.cast::() { - type_option_values.push(m3); - } + let all_fields = db_body.fields.get_all_fields(&txn); + for mut field in all_fields { + for (key, type_option_value) in field.type_options.iter_mut() { + if *key == FieldType::Relation.type_id() { + if let Some(pub_db_id) = type_option_value.get_mut("database_id") { + if let any::Any::String(pub_db_id_str) = pub_db_id { + if let Some(related_db_view) = + published_db.database_relations.get(pub_db_id_str.as_ref()) + { + if let Some(_dup_view_id) = self + .deep_copy_view(related_db_view, &self.dest_view_id.to_string()) + .await? + { + if let Some(dup_db_id) = self + .duplicated_refs + .get(pub_db_id_str.as_ref()) + .cloned() + .flatten() + { + *pub_db_id = any::Any::String(dup_db_id.into()); + db_body.fields.update_field(&mut txn, &field.id, |f| { + f.set_type_option( + FieldType::Relation.into(), + Some(type_option_value.clone()), + ); + }); + }; + }; + }; } - } - } - } - } - for m in type_option_values { - if let Some(Out::Any(any::Any::String(pub_db_id))) = m.get(&txn, "database_id") { - if let Some(related_db_view) = published_db.database_relations.get(pub_db_id.as_ref()) { - if let Some(_dup_view_id) = self - .deep_copy_view(related_db_view, &self.dest_view_id.to_string()) - .await? - { - if let Some(dup_db_id) = self - .duplicated_refs - .get(pub_db_id.as_ref()) - .cloned() - .flatten() - { - m.insert(&mut txn, "database_id", dup_db_id.as_str()); - }; }; - }; + } } } } From f7244f1217685c07a0938af8c4823c5aa9a6bc92 Mon Sep 17 00:00:00 2001 From: Zack Fu Zi Xiang Date: Tue, 10 Sep 2024 13:12:03 +0800 Subject: [PATCH 4/8] chore: use database body for tests --- tests/workspace/publish.rs | 43 ++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/tests/workspace/publish.rs b/tests/workspace/publish.rs index 85ded439..c087f2ca 100644 --- a/tests/workspace/publish.rs +++ b/tests/workspace/publish.rs @@ -9,6 +9,8 @@ use client_api::entity::{ use client_api_test::TestClient; use client_api_test::{generate_unique_registered_user_client, localhost_client}; use collab::util::MapExt; +use collab_database::database::DatabaseBody; +use collab_database::entity::FieldType; use collab_database::views::DatabaseViews; use collab_database::workspace_database::WorkspaceDatabaseBody; use collab_document::document::Document; @@ -21,8 +23,6 @@ use shared_entity::dto::workspace_dto::PublishedDuplicate; use std::collections::{HashMap, HashSet}; use std::thread::sleep; use std::time::Duration; -use yrs::types::Map; -use yrs::MapRef; use crate::workspace::published_data::{self}; @@ -1200,31 +1200,24 @@ async fn duplicate_to_workspace_db_with_relation() { .get_db_collab_from_view(&workspace_id_2, &related_db.view_id) .await; - let fields: MapRef = db_with_rel_col_collab + let related_db_id: String = related_db_collab .data - .get_with_path(&db_with_rel_col_collab.transact(), ["database", "fields"]) + .get_with_path(&related_db_collab.transact(), ["database", "id"]) .unwrap(); - for (_k, v) in fields.iter(&db_with_rel_col_collab.transact()) { - for related_col_db_id in v - .cast::() - .unwrap() - .get(&db_with_rel_col_collab.transact(), "type_option") - .unwrap() - .cast::() - .unwrap() - .iter(&db_with_rel_col_collab.transact()) - .map(|(_k, v)| v.cast::().unwrap()) - .flat_map(|v| v.get(&db_with_rel_col_collab.transact(), "database_id")) - .map(|v| v.to_string(&db_with_rel_col_collab.transact())) - .filter(|v| !v.is_empty()) - { - let related_db_id: String = related_db_collab - .data - .get_with_path(&related_db_collab.transact(), ["database", "id"]) - .unwrap(); - assert_eq!(related_db_id, related_col_db_id); - } - } + + let rel_col_db_body = DatabaseBody::from_collab(&db_with_rel_col_collab).unwrap(); + let txn = db_with_rel_col_collab.transact(); + let all_fields = rel_col_db_body.fields.get_all_fields(&txn); + all_fields + .iter() + .map(|f| &f.type_options) + .flat_map(|t| t.iter()) + .filter(|(k, _v)| **k == FieldType::Relation.type_id()) + .map(|(_k, v)| v) + .flat_map(|v| v.iter()) + .for_each(|(_k, db_id)| { + assert_eq!(db_id.to_string(), related_db_id); + }); } } } From 5564fab4c513cf55d9e04fc013e74c2be11ec08a Mon Sep 17 00:00:00 2001 From: Zack Fu Zi Xiang Date: Tue, 10 Sep 2024 14:45:21 +0800 Subject: [PATCH 5/8] chore: fix compile --- libs/client-api-test/src/test_client.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/client-api-test/src/test_client.rs b/libs/client-api-test/src/test_client.rs index f2ab07d7..fb242040 100644 --- a/libs/client-api-test/src/test_client.rs +++ b/libs/client-api-test/src/test_client.rs @@ -218,7 +218,7 @@ impl TestClient { pub async fn get_db_collab_from_view(&mut self, workspace_id: &str, view_id: &str) -> Collab { let mut ws_db_collab = self.get_workspace_database_collab(workspace_id).await; - let ws_db_body = WorkspaceDatabaseBody::new(&mut ws_db_collab); + let ws_db_body = WorkspaceDatabaseBody::open(&mut ws_db_collab); let txn = ws_db_collab.transact(); let db_id = ws_db_body .get_all_database_meta(&txn) From 7ea64502070b55ea7acbeb82fbd539445814b081 Mon Sep 17 00:00:00 2001 From: Zack Fu Zi Xiang Date: Tue, 10 Sep 2024 18:53:25 +0800 Subject: [PATCH 6/8] chore: refactor to use database body --- src/biz/workspace/publish_dup.rs | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/src/biz/workspace/publish_dup.rs b/src/biz/workspace/publish_dup.rs index 4dbbc4c5..7f55059f 100644 --- a/src/biz/workspace/publish_dup.rs +++ b/src/biz/workspace/publish_dup.rs @@ -6,7 +6,6 @@ use collab::preclude::Collab; use collab::preclude::MapExt; use collab_database::database::DatabaseBody; use collab_database::entity::FieldType; -use collab_database::views::DatabaseViews; use collab_database::workspace_database::WorkspaceDatabaseBody; use collab_document::blocks::DocumentData; use collab_document::document::Document; @@ -817,25 +816,9 @@ impl PublishCollabDuplicator { let mut new_db_view_ids: Vec = vec![]; { let mut txn = db_collab.context.transact_mut(); - let container = db_collab - .data - .get(&txn, "database") - .ok_or_else(|| AppError::RecordNotFound("no database found in collab".to_string()))? - .cast::() - .map_err(|err| AppError::Unhandled(format!("not a map: {:?}", err)))?; - container.insert(&mut txn, "id", new_db_id.clone()); - - let view_map = { - let map_ref = db_collab - .data - .get_with_path(&txn, ["database", "views"]) - .ok_or_else(|| AppError::RecordNotFound("no views found in database".to_string()))?; - DatabaseViews::new(CollabOrigin::Empty, map_ref, None) - }; - - // create new database views based on published views - let mut db_views = view_map.get_all_views(&txn); + db_body.root.insert(&mut txn, "id", new_db_id.clone()); + let mut db_views = db_body.views.get_all_views(&txn); for db_view in db_views.iter_mut() { let new_db_view_id = if db_view.id == publish_view_id { self @@ -873,9 +856,9 @@ impl PublishCollabDuplicator { metas.insert(&mut txn, "iid", new_view_id); // insert updated views back to db - view_map.clear(&mut txn); + db_body.views.clear(&mut txn); for view in db_views { - view_map.insert_view(&mut txn, view); + db_body.views.insert_view(&mut txn, view); } } From 936d492c4e8b250c01990ec3255c7013d14a45ea Mon Sep 17 00:00:00 2001 From: Zack Fu Zi Xiang Date: Tue, 10 Sep 2024 19:05:14 +0800 Subject: [PATCH 7/8] chore: use dbbody to replace iid --- src/biz/workspace/publish_dup.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/biz/workspace/publish_dup.rs b/src/biz/workspace/publish_dup.rs index 7f55059f..fedd40c4 100644 --- a/src/biz/workspace/publish_dup.rs +++ b/src/biz/workspace/publish_dup.rs @@ -849,11 +849,7 @@ impl PublishCollabDuplicator { } // update database metas iid - let metas: MapRef = db_collab - .data - .get_with_path(&txn, ["database", "metas"]) - .ok_or_else(|| AppError::RecordNotFound("no metas found in database".to_string()))?; - metas.insert(&mut txn, "iid", new_view_id); + db_body.metas.insert(&mut txn, "iid", new_view_id); // insert updated views back to db db_body.views.clear(&mut txn); From 9337b4aa90bb43974e344570ecc957dd9f35dd9d Mon Sep 17 00:00:00 2001 From: Zack Fu Zi Xiang Date: Tue, 10 Sep 2024 19:28:21 +0800 Subject: [PATCH 8/8] chore: use database body for getting database id --- src/biz/workspace/publish_dup.rs | 14 -------------- tests/workspace/publish.rs | 8 +++----- 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/src/biz/workspace/publish_dup.rs b/src/biz/workspace/publish_dup.rs index fedd40c4..54bbf713 100644 --- a/src/biz/workspace/publish_dup.rs +++ b/src/biz/workspace/publish_dup.rs @@ -1064,20 +1064,6 @@ pub fn collab_from_doc_state(doc_state: Vec, object_id: &str) -> Result Result { - let txn = db_collab.context.transact(); - let db_map = db_collab - .get_with_txn(&txn, "database") - .ok_or_else(|| AppError::RecordNotFound("no database found in database collab".to_string()))? - .cast::() - .map_err(|err| AppError::RecordNotFound(format!("database not a map: {:?}", err)))?; - let db_id = db_map - .get(&txn, "id") - .ok_or_else(|| AppError::RecordNotFound("no id found in database".to_string()))? - .to_string(&txn); - Ok(db_id) -} - fn to_folder_view_icon(icon: workspace_dto::ViewIcon) -> collab_folder::ViewIcon { collab_folder::ViewIcon { ty: to_folder_view_icon_type(icon.ty), diff --git a/tests/workspace/publish.rs b/tests/workspace/publish.rs index 288f6c91..e75e768b 100644 --- a/tests/workspace/publish.rs +++ b/tests/workspace/publish.rs @@ -1,8 +1,6 @@ use app_error::ErrorCode; use appflowy_cloud::biz::collab::folder_view::collab_folder_to_folder_view; -use appflowy_cloud::biz::workspace::publish_dup::{ - collab_from_doc_state, get_database_id_from_collab, -}; +use appflowy_cloud::biz::workspace::publish_dup::collab_from_doc_state; use client_api::entity::{ AFRole, GlobalComment, PublishCollabItem, PublishCollabMetadata, QueryCollab, QueryCollabParams, }; @@ -962,7 +960,7 @@ async fn duplicate_to_workspace_doc_inline_database() { .unwrap(); let db_doc_state = db_collab_collab_resp.encode_collab.doc_state; let db_collab = collab_from_doc_state(db_doc_state.to_vec(), "").unwrap(); - let dup_db_id = get_database_id_from_collab(&db_collab).unwrap(); + let dup_db_id = DatabaseBody::database_id_from_collab(&db_collab).unwrap(); assert_ne!(dup_db_id, pub_db_id); let view_map = { @@ -1225,7 +1223,7 @@ async fn duplicate_to_workspace_db_with_relation() { fn get_database_id_and_row_ids(published_db_blob: &[u8]) -> (String, HashSet) { let pub_db_data = serde_json::from_slice::(published_db_blob).unwrap(); let db_collab = collab_from_doc_state(pub_db_data.database_collab, "").unwrap(); - let pub_db_id = get_database_id_from_collab(&db_collab).unwrap(); + let pub_db_id = DatabaseBody::database_id_from_collab(&db_collab).unwrap(); let row_ids: HashSet = pub_db_data.database_row_collabs.into_keys().collect(); (pub_db_id, row_ids) }