diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.lock b/frontend/appflowy_tauri/src-tauri/Cargo.lock index 81a998a4ca..89b449dac0 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.lock +++ b/frontend/appflowy_tauri/src-tauri/Cargo.lock @@ -172,7 +172,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "anyhow", "bincode", @@ -192,7 +192,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "anyhow", "bytes", @@ -837,7 +837,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "again", "anyhow", @@ -889,7 +889,7 @@ dependencies = [ [[package]] name = "client-api-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "collab-entity", "collab-rt-entity", @@ -902,7 +902,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "futures-channel", "futures-util", @@ -976,7 +976,7 @@ dependencies = [ [[package]] name = "collab" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=888780aad01b80ec0eed4cba073cba74d8ecd75e#888780aad01b80ec0eed4cba073cba74d8ecd75e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=58ed2b714806a74a4152956005374b4f8c1adf63#58ed2b714806a74a4152956005374b4f8c1adf63" dependencies = [ "anyhow", "arc-swap", @@ -1001,7 +1001,7 @@ dependencies = [ [[package]] name = "collab-database" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=888780aad01b80ec0eed4cba073cba74d8ecd75e#888780aad01b80ec0eed4cba073cba74d8ecd75e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=58ed2b714806a74a4152956005374b4f8c1adf63#58ed2b714806a74a4152956005374b4f8c1adf63" dependencies = [ "anyhow", "async-trait", @@ -1031,7 +1031,7 @@ dependencies = [ [[package]] name = "collab-document" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=888780aad01b80ec0eed4cba073cba74d8ecd75e#888780aad01b80ec0eed4cba073cba74d8ecd75e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=58ed2b714806a74a4152956005374b4f8c1adf63#58ed2b714806a74a4152956005374b4f8c1adf63" dependencies = [ "anyhow", "arc-swap", @@ -1051,7 +1051,7 @@ dependencies = [ [[package]] name = "collab-entity" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=888780aad01b80ec0eed4cba073cba74d8ecd75e#888780aad01b80ec0eed4cba073cba74d8ecd75e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=58ed2b714806a74a4152956005374b4f8c1adf63#58ed2b714806a74a4152956005374b4f8c1adf63" dependencies = [ "anyhow", "bytes", @@ -1063,6 +1063,7 @@ dependencies = [ "serde", "serde_json", "serde_repr", + "thiserror", "uuid", "walkdir", ] @@ -1070,7 +1071,7 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=888780aad01b80ec0eed4cba073cba74d8ecd75e#888780aad01b80ec0eed4cba073cba74d8ecd75e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=58ed2b714806a74a4152956005374b4f8c1adf63#58ed2b714806a74a4152956005374b4f8c1adf63" dependencies = [ "anyhow", "arc-swap", @@ -1113,7 +1114,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=888780aad01b80ec0eed4cba073cba74d8ecd75e#888780aad01b80ec0eed4cba073cba74d8ecd75e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=58ed2b714806a74a4152956005374b4f8c1adf63#58ed2b714806a74a4152956005374b4f8c1adf63" dependencies = [ "anyhow", "async-stream", @@ -1151,7 +1152,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "anyhow", "bincode", @@ -1176,7 +1177,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "anyhow", "async-trait", @@ -1193,7 +1194,7 @@ dependencies = [ [[package]] name = "collab-user" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=888780aad01b80ec0eed4cba073cba74d8ecd75e#888780aad01b80ec0eed4cba073cba74d8ecd75e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=58ed2b714806a74a4152956005374b4f8c1adf63#58ed2b714806a74a4152956005374b4f8c1adf63" dependencies = [ "anyhow", "collab", @@ -1573,7 +1574,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "anyhow", "app-error", @@ -3128,7 +3129,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "anyhow", "futures-util", @@ -3145,7 +3146,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "anyhow", "app-error", @@ -3577,7 +3578,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "anyhow", "bytes", @@ -6229,7 +6230,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.toml b/frontend/appflowy_tauri/src-tauri/Cargo.toml index a3539f0a87..9996b68c05 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.toml +++ b/frontend/appflowy_tauri/src-tauri/Cargo.toml @@ -58,7 +58,7 @@ collab-user = { version = "0.2" } # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "031cd7a15685ba5a0fc19feb75a740f7cb289996" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "4c54481d704bf2f1b5118b4f36add7fb953c0cfc" } [dependencies] serde_json.workspace = true @@ -119,13 +119,13 @@ custom-protocol = ["tauri/custom-protocol"] # To switch to the local path, run: # scripts/tool/update_collab_source.sh # ⚠️⚠️⚠️️ -collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "888780aad01b80ec0eed4cba073cba74d8ecd75e" } -collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "888780aad01b80ec0eed4cba073cba74d8ecd75e" } -collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "888780aad01b80ec0eed4cba073cba74d8ecd75e" } -collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "888780aad01b80ec0eed4cba073cba74d8ecd75e" } -collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "888780aad01b80ec0eed4cba073cba74d8ecd75e" } -collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "888780aad01b80ec0eed4cba073cba74d8ecd75e" } -collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "888780aad01b80ec0eed4cba073cba74d8ecd75e" } +collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "58ed2b714806a74a4152956005374b4f8c1adf63" } +collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "58ed2b714806a74a4152956005374b4f8c1adf63" } +collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "58ed2b714806a74a4152956005374b4f8c1adf63" } +collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "58ed2b714806a74a4152956005374b4f8c1adf63" } +collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "58ed2b714806a74a4152956005374b4f8c1adf63" } +collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "58ed2b714806a74a4152956005374b4f8c1adf63" } +collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "58ed2b714806a74a4152956005374b4f8c1adf63" } # Working directory: frontend # To update the commit ID, run: diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.lock b/frontend/appflowy_web_app/src-tauri/Cargo.lock index 6bac872d20..23b5ba3a89 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.lock +++ b/frontend/appflowy_web_app/src-tauri/Cargo.lock @@ -163,7 +163,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "anyhow", "bincode", @@ -183,7 +183,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "anyhow", "bytes", @@ -811,7 +811,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "again", "anyhow", @@ -863,7 +863,7 @@ dependencies = [ [[package]] name = "client-api-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "collab-entity", "collab-rt-entity", @@ -876,7 +876,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "futures-channel", "futures-util", @@ -959,7 +959,7 @@ dependencies = [ [[package]] name = "collab" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=888780aad01b80ec0eed4cba073cba74d8ecd75e#888780aad01b80ec0eed4cba073cba74d8ecd75e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=58ed2b714806a74a4152956005374b4f8c1adf63#58ed2b714806a74a4152956005374b4f8c1adf63" dependencies = [ "anyhow", "arc-swap", @@ -984,7 +984,7 @@ dependencies = [ [[package]] name = "collab-database" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=888780aad01b80ec0eed4cba073cba74d8ecd75e#888780aad01b80ec0eed4cba073cba74d8ecd75e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=58ed2b714806a74a4152956005374b4f8c1adf63#58ed2b714806a74a4152956005374b4f8c1adf63" dependencies = [ "anyhow", "async-trait", @@ -1014,7 +1014,7 @@ dependencies = [ [[package]] name = "collab-document" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=888780aad01b80ec0eed4cba073cba74d8ecd75e#888780aad01b80ec0eed4cba073cba74d8ecd75e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=58ed2b714806a74a4152956005374b4f8c1adf63#58ed2b714806a74a4152956005374b4f8c1adf63" dependencies = [ "anyhow", "arc-swap", @@ -1034,7 +1034,7 @@ dependencies = [ [[package]] name = "collab-entity" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=888780aad01b80ec0eed4cba073cba74d8ecd75e#888780aad01b80ec0eed4cba073cba74d8ecd75e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=58ed2b714806a74a4152956005374b4f8c1adf63#58ed2b714806a74a4152956005374b4f8c1adf63" dependencies = [ "anyhow", "bytes", @@ -1046,6 +1046,7 @@ dependencies = [ "serde", "serde_json", "serde_repr", + "thiserror", "uuid", "walkdir", ] @@ -1053,7 +1054,7 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=888780aad01b80ec0eed4cba073cba74d8ecd75e#888780aad01b80ec0eed4cba073cba74d8ecd75e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=58ed2b714806a74a4152956005374b4f8c1adf63#58ed2b714806a74a4152956005374b4f8c1adf63" dependencies = [ "anyhow", "arc-swap", @@ -1096,7 +1097,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=888780aad01b80ec0eed4cba073cba74d8ecd75e#888780aad01b80ec0eed4cba073cba74d8ecd75e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=58ed2b714806a74a4152956005374b4f8c1adf63#58ed2b714806a74a4152956005374b4f8c1adf63" dependencies = [ "anyhow", "async-stream", @@ -1134,7 +1135,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "anyhow", "bincode", @@ -1159,7 +1160,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "anyhow", "async-trait", @@ -1176,7 +1177,7 @@ dependencies = [ [[package]] name = "collab-user" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=888780aad01b80ec0eed4cba073cba74d8ecd75e#888780aad01b80ec0eed4cba073cba74d8ecd75e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=58ed2b714806a74a4152956005374b4f8c1adf63#58ed2b714806a74a4152956005374b4f8c1adf63" dependencies = [ "anyhow", "collab", @@ -1563,7 +1564,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "anyhow", "app-error", @@ -3195,7 +3196,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "anyhow", "futures-util", @@ -3212,7 +3213,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "anyhow", "app-error", @@ -3649,7 +3650,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "anyhow", "bytes", @@ -6293,7 +6294,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.toml b/frontend/appflowy_web_app/src-tauri/Cargo.toml index df62301ce5..4d0fac080c 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.toml +++ b/frontend/appflowy_web_app/src-tauri/Cargo.toml @@ -57,7 +57,7 @@ collab-user = { version = "0.2" } # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "031cd7a15685ba5a0fc19feb75a740f7cb289996" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "4c54481d704bf2f1b5118b4f36add7fb953c0cfc" } [dependencies] serde_json.workspace = true @@ -117,13 +117,13 @@ custom-protocol = ["tauri/custom-protocol"] # To switch to the local path, run: # scripts/tool/update_collab_source.sh # ⚠️⚠️⚠️️ -collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "888780aad01b80ec0eed4cba073cba74d8ecd75e" } -collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "888780aad01b80ec0eed4cba073cba74d8ecd75e" } -collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "888780aad01b80ec0eed4cba073cba74d8ecd75e" } -collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "888780aad01b80ec0eed4cba073cba74d8ecd75e" } -collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "888780aad01b80ec0eed4cba073cba74d8ecd75e" } -collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "888780aad01b80ec0eed4cba073cba74d8ecd75e" } -collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "888780aad01b80ec0eed4cba073cba74d8ecd75e" } +collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "58ed2b714806a74a4152956005374b4f8c1adf63" } +collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "58ed2b714806a74a4152956005374b4f8c1adf63" } +collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "58ed2b714806a74a4152956005374b4f8c1adf63" } +collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "58ed2b714806a74a4152956005374b4f8c1adf63" } +collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "58ed2b714806a74a4152956005374b4f8c1adf63" } +collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "58ed2b714806a74a4152956005374b4f8c1adf63" } +collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "58ed2b714806a74a4152956005374b4f8c1adf63" } # Working directory: frontend # To update the commit ID, run: diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index 69ce46307f..1b151ad1a8 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -163,7 +163,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "anyhow", "bincode", @@ -183,7 +183,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "anyhow", "bytes", @@ -729,7 +729,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "again", "anyhow", @@ -781,7 +781,7 @@ dependencies = [ [[package]] name = "client-api-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "collab-entity", "collab-rt-entity", @@ -794,7 +794,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "futures-channel", "futures-util", @@ -837,7 +837,7 @@ dependencies = [ [[package]] name = "collab" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=888780aad01b80ec0eed4cba073cba74d8ecd75e#888780aad01b80ec0eed4cba073cba74d8ecd75e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=58ed2b714806a74a4152956005374b4f8c1adf63#58ed2b714806a74a4152956005374b4f8c1adf63" dependencies = [ "anyhow", "arc-swap", @@ -862,7 +862,7 @@ dependencies = [ [[package]] name = "collab-database" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=888780aad01b80ec0eed4cba073cba74d8ecd75e#888780aad01b80ec0eed4cba073cba74d8ecd75e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=58ed2b714806a74a4152956005374b4f8c1adf63#58ed2b714806a74a4152956005374b4f8c1adf63" dependencies = [ "anyhow", "async-trait", @@ -892,7 +892,7 @@ dependencies = [ [[package]] name = "collab-document" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=888780aad01b80ec0eed4cba073cba74d8ecd75e#888780aad01b80ec0eed4cba073cba74d8ecd75e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=58ed2b714806a74a4152956005374b4f8c1adf63#58ed2b714806a74a4152956005374b4f8c1adf63" dependencies = [ "anyhow", "arc-swap", @@ -912,7 +912,7 @@ dependencies = [ [[package]] name = "collab-entity" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=888780aad01b80ec0eed4cba073cba74d8ecd75e#888780aad01b80ec0eed4cba073cba74d8ecd75e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=58ed2b714806a74a4152956005374b4f8c1adf63#58ed2b714806a74a4152956005374b4f8c1adf63" dependencies = [ "anyhow", "bytes", @@ -924,6 +924,7 @@ dependencies = [ "serde", "serde_json", "serde_repr", + "thiserror", "uuid", "walkdir", ] @@ -931,7 +932,7 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=888780aad01b80ec0eed4cba073cba74d8ecd75e#888780aad01b80ec0eed4cba073cba74d8ecd75e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=58ed2b714806a74a4152956005374b4f8c1adf63#58ed2b714806a74a4152956005374b4f8c1adf63" dependencies = [ "anyhow", "arc-swap", @@ -974,7 +975,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=888780aad01b80ec0eed4cba073cba74d8ecd75e#888780aad01b80ec0eed4cba073cba74d8ecd75e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=58ed2b714806a74a4152956005374b4f8c1adf63#58ed2b714806a74a4152956005374b4f8c1adf63" dependencies = [ "anyhow", "async-stream", @@ -1012,7 +1013,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "anyhow", "bincode", @@ -1037,7 +1038,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "anyhow", "async-trait", @@ -1054,7 +1055,7 @@ dependencies = [ [[package]] name = "collab-user" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=888780aad01b80ec0eed4cba073cba74d8ecd75e#888780aad01b80ec0eed4cba073cba74d8ecd75e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=58ed2b714806a74a4152956005374b4f8c1adf63#58ed2b714806a74a4152956005374b4f8c1adf63" dependencies = [ "anyhow", "collab", @@ -1397,7 +1398,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "anyhow", "app-error", @@ -2807,7 +2808,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "anyhow", "futures-util", @@ -2824,7 +2825,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "anyhow", "app-error", @@ -3189,7 +3190,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "anyhow", "bytes", @@ -5461,7 +5462,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=031cd7a15685ba5a0fc19feb75a740f7cb289996#031cd7a15685ba5a0fc19feb75a740f7cb289996" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=4c54481d704bf2f1b5118b4f36add7fb953c0cfc#4c54481d704bf2f1b5118b4f36add7fb953c0cfc" dependencies = [ "anyhow", "app-error", diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index e1b71129c7..17c97a0268 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -105,8 +105,8 @@ dashmap = "6.0.1" # Run the script.add_workspace_members: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "031cd7a15685ba5a0fc19feb75a740f7cb289996" } -client-api-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "031cd7a15685ba5a0fc19feb75a740f7cb289996" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "4c54481d704bf2f1b5118b4f36add7fb953c0cfc" } +client-api-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "4c54481d704bf2f1b5118b4f36add7fb953c0cfc" } [profile.dev] opt-level = 0 @@ -141,13 +141,13 @@ rocksdb = { git = "https://github.com/rust-rocksdb/rust-rocksdb", rev = "1710120 # To switch to the local path, run: # scripts/tool/update_collab_source.sh # ⚠️⚠️⚠️️ -collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "888780aad01b80ec0eed4cba073cba74d8ecd75e" } -collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "888780aad01b80ec0eed4cba073cba74d8ecd75e" } -collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "888780aad01b80ec0eed4cba073cba74d8ecd75e" } -collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "888780aad01b80ec0eed4cba073cba74d8ecd75e" } -collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "888780aad01b80ec0eed4cba073cba74d8ecd75e" } -collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "888780aad01b80ec0eed4cba073cba74d8ecd75e" } -collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "888780aad01b80ec0eed4cba073cba74d8ecd75e" } +collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "58ed2b714806a74a4152956005374b4f8c1adf63" } +collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "58ed2b714806a74a4152956005374b4f8c1adf63" } +collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "58ed2b714806a74a4152956005374b4f8c1adf63" } +collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "58ed2b714806a74a4152956005374b4f8c1adf63" } +collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "58ed2b714806a74a4152956005374b4f8c1adf63" } +collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "58ed2b714806a74a4152956005374b4f8c1adf63" } +collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "58ed2b714806a74a4152956005374b4f8c1adf63" } # Working directory: frontend # To update the commit ID, run: diff --git a/frontend/rust-lib/collab-integrate/src/collab_builder.rs b/frontend/rust-lib/collab-integrate/src/collab_builder.rs index da04bbcaa5..6e6b4834bc 100644 --- a/frontend/rust-lib/collab-integrate/src/collab_builder.rs +++ b/frontend/rust-lib/collab-integrate/src/collab_builder.rs @@ -202,10 +202,13 @@ impl AppFlowyCollabBuilder { ) -> Result>, Error> { let expected_collab_type = CollabType::Folder; assert_eq!(object.collab_type, expected_collab_type); - let collab = self.build_collab(&object, &collab_db, doc_state)?; let folder = match folder_data { - None => Folder::open(object.uid, collab, folder_notifier)?, + None => { + let collab = self.build_collab(&object, &collab_db, doc_state)?; + Folder::open(object.uid, collab, folder_notifier)? + }, Some(data) => { + let collab = self.build_collab(&object, &collab_db, doc_state)?; let folder = Folder::create(object.uid, collab, folder_notifier, data); if let Err(err) = self.write_collab_to_disk( object.uid, @@ -331,6 +334,7 @@ impl AppFlowyCollabBuilder { } /// Remove all updates in disk and write the final state vector to disk. + #[instrument(level = "trace", skip_all, err)] pub fn write_collab_to_disk( &self, uid: i64, @@ -355,6 +359,8 @@ impl AppFlowyCollabBuilder { encode_collab.doc_state.to_vec(), )?; write_txn.commit_transaction()?; + } else { + error!("collab_db is dropped"); } Ok(()) @@ -378,12 +384,12 @@ impl CollabBuilderConfig { } } -pub struct KVDBCollabPersistenceImpl { +pub struct CollabPersistenceImpl { pub db: Weak, pub uid: i64, } -impl KVDBCollabPersistenceImpl { +impl CollabPersistenceImpl { pub fn new(db: Weak, uid: i64) -> Self { Self { db, uid } } @@ -393,7 +399,7 @@ impl KVDBCollabPersistenceImpl { } } -impl CollabPersistence for KVDBCollabPersistenceImpl { +impl CollabPersistence for CollabPersistenceImpl { fn load_collab_from_disk(&self, collab: &mut Collab) { if let Some(collab_db) = self.db.upgrade() { let object_id = collab.object_id().to_string(); diff --git a/frontend/rust-lib/flowy-core/src/deps_resolve/folder_deps.rs b/frontend/rust-lib/flowy-core/src/deps_resolve/folder_deps.rs index cd387c3b1d..43584e8beb 100644 --- a/frontend/rust-lib/flowy-core/src/deps_resolve/folder_deps.rs +++ b/frontend/rust-lib/flowy-core/src/deps_resolve/folder_deps.rs @@ -472,7 +472,7 @@ impl FolderOperationHandler for DatabaseFolderOperation { ); }, }; - let result = self.0.create_database_with_params(data).await; + let result = self.0.import_database(data).await; match result { Ok(_) => Ok(()), Err(err) => { diff --git a/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs b/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs index 1bed5471d4..70f6b02be7 100644 --- a/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs +++ b/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs @@ -381,6 +381,20 @@ impl DatabaseCloudService for ServerProvider { .await } + async fn create_database_encode_collab( + &self, + object_id: &str, + collab_type: CollabType, + workspace_id: &str, + encoded_collab: EncodedCollab, + ) -> Result<(), Error> { + let server = self.get_server()?; + server + .database_service() + .create_database_encode_collab(object_id, collab_type, workspace_id, encoded_collab) + .await + } + async fn batch_get_database_encode_collab( &self, object_ids: Vec, @@ -449,13 +463,10 @@ impl DocumentCloudService for ServerProvider { document_id: &str, workspace_id: &str, ) -> Result, FlowyError> { - let workspace_id = workspace_id.to_string(); - let document_id = document_id.to_string(); let server = self.get_server()?; - server .document_service() - .get_document_doc_state(&document_id, &workspace_id) + .get_document_doc_state(document_id, workspace_id) .await } @@ -465,13 +476,11 @@ impl DocumentCloudService for ServerProvider { limit: usize, workspace_id: &str, ) -> Result, Error> { - let workspace_id = workspace_id.to_string(); let server = self.get_server()?; - let document_id = document_id.to_string(); server .document_service() - .get_document_snapshots(&document_id, limit, &workspace_id) + .get_document_snapshots(document_id, limit, workspace_id) .await } @@ -480,13 +489,23 @@ impl DocumentCloudService for ServerProvider { document_id: &str, workspace_id: &str, ) -> Result, Error> { - let workspace_id = workspace_id.to_string(); let server = self.get_server()?; - let document_id = document_id.to_string(); - server .document_service() - .get_document_data(&document_id, &workspace_id) + .get_document_data(document_id, workspace_id) + .await + } + + async fn create_document_collab( + &self, + workspace_id: &str, + document_id: &str, + encoded_collab: EncodedCollab, + ) -> Result<(), Error> { + let server = self.get_server()?; + server + .document_service() + .create_document_collab(workspace_id, document_id, encoded_collab) .await } } diff --git a/frontend/rust-lib/flowy-database-pub/src/cloud.rs b/frontend/rust-lib/flowy-database-pub/src/cloud.rs index f35ef42cfb..05214be1dc 100644 --- a/frontend/rust-lib/flowy-database-pub/src/cloud.rs +++ b/frontend/rust-lib/flowy-database-pub/src/cloud.rs @@ -47,6 +47,14 @@ pub trait DatabaseCloudService: Send + Sync { workspace_id: &str, ) -> Result, Error>; + async fn create_database_encode_collab( + &self, + object_id: &str, + collab_type: CollabType, + workspace_id: &str, + encoded_collab: EncodedCollab, + ) -> Result<(), Error>; + async fn batch_get_database_encode_collab( &self, object_ids: Vec, diff --git a/frontend/rust-lib/flowy-database2/src/event_handler.rs b/frontend/rust-lib/flowy-database2/src/event_handler.rs index 0ca12e2c50..7f6c5cce3d 100644 --- a/frontend/rust-lib/flowy-database2/src/event_handler.rs +++ b/frontend/rust-lib/flowy-database2/src/event_handler.rs @@ -2,7 +2,7 @@ use collab_database::rows::{Cell, RowId}; use lib_infra::box_any::BoxAny; use std::sync::{Arc, Weak}; use tokio::sync::oneshot; -use tracing::{error, info}; +use tracing::{info, instrument}; use flowy_error::{FlowyError, FlowyResult}; use lib_dispatch::prelude::{af_spawn, data_result_ok, AFPluginData, AFPluginState, DataResult}; @@ -35,9 +35,7 @@ pub(crate) async fn get_database_data_handler( let database_id = manager .get_database_id_with_view_id(view_id.as_ref()) .await?; - let database_editor = manager - .get_or_init_database_editor(&database_id, Some(view_id.as_ref())) - .await?; + let database_editor = manager.get_or_init_database_editor(&database_id).await?; let start = std::time::Instant::now(); let data = database_editor .open_database_view(view_id.as_ref(), None) @@ -63,9 +61,7 @@ pub(crate) async fn get_all_rows_handler( let database_id = manager .get_database_id_with_view_id(view_id.as_ref()) .await?; - let database_editor = manager - .get_or_init_database_editor(&database_id, Some(view_id.as_ref())) - .await?; + let database_editor = manager.get_or_init_database_editor(&database_id).await?; let row_details = database_editor.get_all_rows(view_id.as_ref()).await?; let rows = row_details .into_iter() @@ -892,14 +888,11 @@ pub(crate) async fn get_databases_handler( let mut items = Vec::with_capacity(metas.len()); for meta in metas { - match manager.get_database_inline_view_id(&meta.database_id).await { - Ok(view_id) => items.push(DatabaseMetaPB { + if let Some(link_view) = meta.linked_views.first() { + items.push(DatabaseMetaPB { database_id: meta.database_id, - inline_view_id: view_id, - }), - Err(err) => { - error!(?err); - }, + inline_view_id: link_view.clone(), + }) } } @@ -920,7 +913,6 @@ pub(crate) async fn set_layout_setting_handler( database_editor.set_layout_setting(&view_id, params).await?; Ok(()) } - pub(crate) async fn get_layout_setting_handler( data: AFPluginData, manager: AFPluginState>, @@ -1224,6 +1216,7 @@ pub(crate) async fn update_relation_cell_handler( Ok(()) } +#[instrument(level = "debug", skip_all, err)] pub(crate) async fn get_related_row_datas_handler( data: AFPluginData, manager: AFPluginState>, @@ -1231,15 +1224,17 @@ pub(crate) async fn get_related_row_datas_handler( let manager = upgrade_manager(manager)?; let params: GetRelatedRowDataPB = data.into_inner(); let database_editor = manager - .get_or_init_database_editor(¶ms.database_id, None) + .get_or_init_database_editor(¶ms.database_id) .await?; + let row_datas = database_editor - .get_related_rows(Some(¶ms.row_ids)) + .get_related_rows(Some(params.row_ids)) .await?; data_result_ok(RepeatedRelatedRowDataPB { rows: row_datas }) } +#[instrument(level = "debug", skip_all, err)] pub(crate) async fn get_related_database_rows_handler( data: AFPluginData, manager: AFPluginState>, @@ -1251,9 +1246,7 @@ pub(crate) async fn get_related_database_rows_handler( "[Database]: get related database rows from database_id: {}", database_id ); - let database_editor = manager - .get_or_init_database_editor(&database_id, None) - .await?; + let database_editor = manager.get_or_init_database_editor(&database_id).await?; let rows = database_editor.get_related_rows(None).await?; data_result_ok(RepeatedRelatedRowDataPB { rows }) } diff --git a/frontend/rust-lib/flowy-database2/src/manager.rs b/frontend/rust-lib/flowy-database2/src/manager.rs index a4abdefaf7..18bec2c4f8 100644 --- a/frontend/rust-lib/flowy-database2/src/manager.rs +++ b/frontend/rust-lib/flowy-database2/src/manager.rs @@ -5,6 +5,7 @@ use std::collections::HashMap; use std::sync::{Arc, Weak}; use collab::core::collab::DataSource; +use collab::core::origin::CollabOrigin; use collab::lock::RwLock; use collab::preclude::Collab; use collab_database::database::{Database, DatabaseData}; @@ -18,8 +19,9 @@ use collab_database::workspace_database::{ }; use collab_entity::{CollabObject, CollabType, EncodedCollab}; use collab_plugins::local_storage::kv::KVTransactionDB; +use rayon::prelude::*; use tokio::sync::Mutex; -use tracing::{error, info, instrument, trace}; +use tracing::{error, info, instrument, trace, warn}; use collab_integrate::collab_builder::{AppFlowyCollabBuilder, CollabBuilderConfig}; use collab_integrate::{CollabKVAction, CollabKVDB}; @@ -40,7 +42,7 @@ use crate::services::field_settings::default_field_settings_by_layout_map; use crate::services::share::csv::{CSVFormat, CSVImporter, ImportResult}; use tokio::sync::RwLock as TokioRwLock; use tokio_retry::strategy::ExponentialBackoff; -use tokio_retry::Retry; +use tokio_retry::RetryIf; pub trait DatabaseUser: Send + Sync { fn user_id(&self) -> Result; @@ -145,14 +147,7 @@ impl DatabaseManager { pub async fn get_database_inline_view_id(&self, database_id: &str) -> FlowyResult { let lock = self.workspace_database()?; let wdb = lock.read().await; - let database_collab = wdb - .get_or_create_database(database_id) - .await - .ok_or_else(|| { - FlowyError::record_not_found() - .with_context(format!("The database:{} not found", database_id)) - })?; - + let database_collab = wdb.get_or_init_database(database_id).await?; let lock_guard = database_collab.read().await; Ok(lock_guard.get_inline_view_id()) } @@ -216,15 +211,12 @@ impl DatabaseManager { view_id: &str, ) -> FlowyResult> { let database_id = self.get_database_id_with_view_id(view_id).await?; - self - .get_or_init_database_editor(&database_id, Some(view_id)) - .await + self.get_or_init_database_editor(&database_id).await } pub async fn get_or_init_database_editor( &self, database_id: &str, - _database_view_id: Option<&str>, ) -> FlowyResult> { if let Some(editor) = self.editors.lock().await.get(database_id).cloned() { return Ok(editor); @@ -245,22 +237,22 @@ impl DatabaseManager { return Ok(database_editor); } - trace!("create database editor:{}", database_id); + trace!("init database editor:{}", database_id); // When the user opens the database from the left-side bar, it may fail because the workspace database // hasn't finished syncing yet. In such cases, get_or_create_database will return None. // The workaround is to add a retry mechanism to attempt fetching the database again. - let database = Retry::spawn( + let database = RetryIf::spawn( ExponentialBackoff::from_millis(3).factor(1000).take(2), || async { trace!("retry to open database:{}", database_id); let database = workspace_database .read() .await - .get_or_create_database(database_id) - .await - .ok_or_else(|| FlowyError::collab_not_sync().with_context("open database error"))?; - Ok::<_, FlowyError>(database) + .get_or_init_database(database_id) + .await?; + Ok::<_, DatabaseError>(database) }, + |err: &DatabaseError| !err.is_no_required_data(), ) .await?; @@ -390,22 +382,22 @@ impl DatabaseManager { let lock = self.workspace_database()?; let mut wdb = lock.write().await; - let database = wdb.create_database(create_database_params)?; + let database = wdb.create_database(create_database_params).await?; let encoded_collab = database .read() .await - .encode_collab_v1(|collab| CollabType::Database.validate_require_data(collab))?; + .encode_collab_v1(|collab| CollabType::Database.validate_require_data(collab)) + .map_err(|err| FlowyError::internal().with_context(err))?; Ok(encoded_collab) } - pub async fn create_database_with_params( + pub async fn import_database( &self, params: CreateDatabaseParams, ) -> FlowyResult>> { let lock = self.workspace_database()?; let mut wdb = lock.write().await; - let database = wdb.create_database(params)?; - + let database = wdb.create_database(params).await?; Ok(database) } @@ -422,7 +414,7 @@ impl DatabaseManager { let lock = self.workspace_database()?; let mut wdb = lock.write().await; let mut params = CreateViewParams::new(database_id.clone(), database_view_id, name, layout); - if let Some(database) = wdb.get_or_create_database(&database_id).await { + if let Ok(database) = wdb.get_or_init_database(&database_id).await { let (field, layout_setting, field_settings_map) = DatabaseLayoutDepsResolver::new(database, layout) .resolve_deps_when_create_database_linked_view(&database_parent_view_id) @@ -455,7 +447,7 @@ impl DatabaseManager { let view_id = params.inline_view_id.clone(); let database_id = params.database_id.clone(); - let database = self.create_database_with_params(params).await?; + let database = self.import_database(params).await?; let encoded_database = database.read().await.encode_database_collabs().await?; let encoded_collabs = std::iter::once(encoded_database.encoded_database_collab) .chain(encoded_database.encoded_row_collabs.into_iter()) @@ -679,43 +671,28 @@ impl WorkspaceDatabaseCollabServiceImpl { object_ty: CollabType, ) -> Result, DatabaseError> { let workspace_id = self.user.workspace_id().unwrap(); - let object_id = object_id.to_string(); // Convert to String for later use trace!("[Database]: fetch {}:{} from remote", object_id, object_ty); - let weak_cloud_service = Arc::downgrade(&self.cloud_service); - let cloud_service = match weak_cloud_service.upgrade() { - None => return Err(DatabaseError::Internal(anyhow!("Cloud service is dropped"))), - Some(service) => service, - }; - let encode_collab = cloud_service - .get_database_encode_collab(&object_id, object_ty, &workspace_id) + let encode_collab = self + .cloud_service + .get_database_encode_collab(object_id, object_ty, &workspace_id) .await?; Ok(encode_collab) } - #[allow(dead_code)] async fn batch_get_encode_collab( &self, object_ids: Vec, object_ty: CollabType, ) -> Result { - let cloned_user = self.user.clone(); - let weak_cloud_service = Arc::downgrade(&self.cloud_service); - - let workspace_id = cloned_user + let workspace_id = self + .user .workspace_id() .map_err(|err| DatabaseError::Internal(err.into()))?; - match weak_cloud_service.upgrade() { - None => { - tracing::warn!("Cloud service is dropped"); - Ok(EncodeCollabByOid::default()) - }, - Some(cloud_service) => { - let updates = cloud_service - .batch_get_database_encode_collab(object_ids, object_ty, &workspace_id) - .await?; - Ok(updates) - }, - } + let updates = self + .cloud_service + .batch_get_database_encode_collab(object_ids, object_ty, &workspace_id) + .await?; + Ok(updates) } fn collab_db(&self) -> Result, DatabaseError> { @@ -758,17 +735,22 @@ impl DatabaseCollabService for WorkspaceDatabaseCollabServiceImpl { &self, object_id: &str, collab_type: CollabType, - encoded_collab: Option, + encoded_collab: Option<(EncodedCollab, bool)>, ) -> Result { let object = self.build_collab_object(object_id, collab_type.clone())?; let data_source = if self.persistence.is_collab_exist(object_id) { if encoded_collab.is_some() { - error!( + warn!( "build collab: {}:{} with both local and remote encode collab", collab_type, object_id ); } + trace!( + "build collab: {}:{} from local encode collab", + collab_type, + object_id + ); CollabPersistenceImpl { persistence: Some(self.persistence.clone()), } @@ -814,10 +796,35 @@ impl DatabaseCollabService for WorkspaceDatabaseCollabServiceImpl { }, } }, - Some(encoded_collab) => { + Some((encoded_collab, _)) => { + info!( + "build collab: {}:{} with new encode collab, {} bytes", + collab_type, + object_id, + encoded_collab.doc_state.len() + ); self .persistence .save_collab(object_id, encoded_collab.clone())?; + + // TODO(nathan): cover database rows and other database collab type + if matches!(collab_type, CollabType::Database) { + if let Ok(workspace_id) = self.user.workspace_id() { + let object_id = object_id.to_string(); + let cloned_encoded_collab = encoded_collab.clone(); + let cloud_service = self.cloud_service.clone(); + tokio::spawn(async move { + let _ = cloud_service + .create_database_encode_collab( + &object_id, + collab_type, + &workspace_id, + cloned_encoded_collab, + ) + .await; + }); + } + } encoded_collab.into() }, } @@ -830,6 +837,49 @@ impl DatabaseCollabService for WorkspaceDatabaseCollabServiceImpl { Ok(collab) } + async fn get_collabs( + &self, + mut object_ids: Vec, + collab_type: CollabType, + ) -> Result { + if object_ids.is_empty() { + return Ok(EncodeCollabByOid::new()); + } + let mut encoded_collab_by_id = EncodeCollabByOid::new(); + // 1. Collect local disk collabs into a HashMap + let local_disk_encoded_collab: HashMap = object_ids + .par_iter() + .filter_map(|object_id| { + self + .persistence + .get_encoded_collab(object_id.as_str(), collab_type.clone()) + .map(|encoded_collab| (object_id.clone(), encoded_collab)) + }) + .collect(); + trace!( + "[Database]: load {} database row from local disk", + local_disk_encoded_collab.len() + ); + object_ids.retain(|object_id| !local_disk_encoded_collab.contains_key(object_id)); + for (k, v) in local_disk_encoded_collab { + encoded_collab_by_id.insert(k, v); + } + + // 2. Fetch remaining collabs from remote + let remote_collabs = self + .batch_get_encode_collab(object_ids, collab_type) + .await?; + + trace!( + "[Database]: load {} database row from remote", + remote_collabs.len() + ); + for (k, v) in remote_collabs { + encoded_collab_by_id.insert(k, v); + } + Ok(encoded_collab_by_id) + } + fn persistence(&self) -> Option> { Some(Arc::new(DatabasePersistenceImpl { user: self.user.clone(), @@ -878,6 +928,24 @@ impl DatabaseCollabPersistenceService for DatabasePersistenceImpl { } } + fn get_encoded_collab(&self, object_id: &str, collab_type: CollabType) -> Option { + let uid = self.user.user_id().ok()?; + let db = self.user.collab_db(uid).ok()?.upgrade()?; + let read_txn = db.read_txn(); + if !read_txn.is_exist(uid, &object_id) { + return None; + } + + let mut collab = Collab::new_with_origin(CollabOrigin::Empty, object_id, vec![], false); + let mut txn = collab.transact_mut(); + let _ = read_txn.load_doc_with_txn(uid, &object_id, &mut txn); + drop(txn); + + collab + .encode_collab_v1(|collab| collab_type.validate_require_data(collab)) + .ok() + } + fn delete_collab(&self, object_id: &str) -> Result<(), DatabaseError> { let uid = self .user diff --git a/frontend/rust-lib/flowy-database2/src/services/database/database_editor.rs b/frontend/rust-lib/flowy-database2/src/services/database/database_editor.rs index d9b56f9f4f..dfd39aa619 100644 --- a/frontend/rust-lib/flowy-database2/src/services/database/database_editor.rs +++ b/frontend/rust-lib/flowy-database2/src/services/database/database_editor.rs @@ -21,7 +21,7 @@ use crate::services::share::csv::{CSVExport, CSVFormat}; use crate::services::sort::Sort; use crate::utils::cache::AnyTypeCache; use crate::DatabaseUser; -use arc_swap::{ArcSwap, ArcSwapOption}; +use arc_swap::ArcSwapOption; use async_trait::async_trait; use collab::core::collab_plugin::CollabPluginType; use collab::lock::RwLock; @@ -60,7 +60,7 @@ pub struct DatabaseEditor { #[allow(dead_code)] user: Arc, collab_builder: Arc, - is_opening: ArcSwap, + is_loading_rows: ArcSwapOption>, opening_ret_txs: Arc>>, database_cancellation: Arc>>, un_finalized_rows_cancellation: Arc>, @@ -131,7 +131,7 @@ impl DatabaseEditor { cell_cache, database_views, collab_builder, - is_opening: Default::default(), + is_loading_rows: Default::default(), opening_ret_txs: Arc::new(Default::default()), database_cancellation, un_finalized_rows_cancellation: Arc::new(Default::default()), @@ -663,12 +663,13 @@ impl DatabaseEditor { } = view_editor.v_will_create_row(params).await?; let mut database = self.database.write().await; - let (index, order_id) = database + let (index, row_order) = database .create_row_in_view(&view_editor.view_id, collab_params) .await?; - let row_detail = database.get_row_detail(&order_id.id).await; + let row_detail = database.get_row_detail(&row_order.id).await; drop(database); + trace!("[Database]: did create row: {} at {}", row_order.id, index); if let Some(row_detail) = row_detail { trace!("created row: {:?} at {}", row_detail, index); return Ok(Some(row_detail)); @@ -765,7 +766,13 @@ impl DatabaseEditor { } pub async fn init_database_row(&self, row_id: &RowId) -> FlowyResult>> { - debug!("Init database row: {}", row_id); + if let Some(is_loading) = self.is_loading_rows.load_full() { + let mut rx = is_loading.subscribe(); + trace!("[Database]: wait for loading rows when trying to init database row"); + let _ = tokio::time::timeout(Duration::from_secs(10), rx.recv()).await; + } + + debug!("[Database]: Init database row: {}", row_id); let database_row = self .database .read() @@ -1440,8 +1447,10 @@ impl DatabaseEditor { let (tx, rx) = oneshot::channel(); self.opening_ret_txs.write().await.push(tx); // Check if the database is currently being opened - if !*self.is_opening.load_full() { - self.is_opening.store(Arc::new(true)); + if self.is_loading_rows.load_full().is_none() { + self + .is_loading_rows + .store(Some(Arc::new(broadcast::channel(500).0))); let view_layout = self.database.read().await.get_database_view_layout(view_id); let new_token = CancellationToken::new(); if let Some(old_token) = self @@ -1471,7 +1480,7 @@ impl DatabaseEditor { ) }; - let mut row_metas = row_orders + let mut order_row_metas = row_orders .into_iter() .map(RowMetaPB::from) .collect::>(); @@ -1480,19 +1489,25 @@ impl DatabaseEditor { "[Database]: database: {}, num fields: {}, num rows: {}", database_id, fields.len(), - row_metas.len() + order_row_metas.len() ); let view_editor = self.database_views.get_or_init_view_editor(view_id).await?; - let blocking_read = notify_finish.is_some() || row_metas.len() < 50; + let blocking_read = notify_finish.is_some() || order_row_metas.len() < 50; let (tx, rx) = oneshot::channel(); self.async_load_rows(view_editor, Some(tx), new_token, blocking_read); if blocking_read { if let Ok(rows) = rx.await { - row_metas = rows + let mut un_order_rows = rows .into_iter() - .map(|row| RowMetaPB::from(row.as_ref())) - .collect::>(); + .map(|row| (row.id.to_string(), RowMetaPB::from(row.as_ref()))) + .collect::>(); + + order_row_metas.iter_mut().for_each(|row_meta| { + if let Some(un_order_row) = un_order_rows.remove(&row_meta.id) { + *row_meta = un_order_row; + } + }); } } @@ -1503,12 +1518,15 @@ impl DatabaseEditor { let result = Ok(DatabasePB { id: database_id, fields, - rows: row_metas, + rows: order_row_metas, layout_type: view_layout.into(), is_linked, }); // Mark that the opening process is complete - self.is_opening.store(Arc::new(false)); + if let Some(tx) = self.is_loading_rows.load_full() { + let _ = tx.send(()); + } + self.is_loading_rows.store(None); // Collect all waiting tasks and send the result let txs = std::mem::take(&mut *self.opening_ret_txs.write().await); for tx in txs { @@ -1566,7 +1584,7 @@ impl DatabaseEditor { }; let mut loaded_rows = vec![]; - const CHUNK_SIZE: usize = 10; + const CHUNK_SIZE: usize = 20; let row_orders = view_editor.row_orders.read().await; let row_orders_chunks = row_orders.chunks(CHUNK_SIZE).collect::>(); @@ -1578,32 +1596,19 @@ impl DatabaseEditor { Some(database) => database, }; - // Process the chunk of rows concurrently using async tasks - let tasks: Vec<_> = chunk_row_orders + let row_ids = chunk_row_orders .iter() - .map(|row_order| { - let db_clone = database.clone(); - async move { - // Initialize the database row - let database_row = db_clone - .read() - .await - .get_or_init_database_row(&row_order.id) - .await; - if let Some(database_row) = database_row { - let row = database_row.read().await.get_row(); - row.map(Arc::new) - } else { - None - } - } - }) + .map(|row_order| row_order.id.clone()) .collect(); - let results = join_all(tasks).await; - for row in results.into_iter().flatten() { - loaded_rows.push(row); + if let Ok(rows) = database.read().await.init_database_rows(row_ids).await { + for row in rows { + if let Some(row) = row.read().await.get_row() { + loaded_rows.push(Arc::new(row)); + } + } } + // Check for cancellation after each chunk if new_token.is_cancelled() { info!("[Database]: stop loading database rows"); @@ -1702,41 +1707,75 @@ impl DatabaseEditor { .await } - /// TODO(nathan): lazy load database rows pub async fn get_related_rows( &self, - row_ids: Option<&Vec>, + row_ids: Option>, ) -> FlowyResult> { let database = self.database.read().await; - let primary_field = database.get_primary_field().unwrap(); - let handler = TypeOptionCellExt::new(&primary_field, Some(self.cell_cache.clone())) - .get_type_option_cell_data_handler_with_field_type(FieldType::RichText) - .ok_or(FlowyError::internal())?; + let primary_field = Arc::new( + database + .get_primary_field() + .ok_or_else(|| FlowyError::internal().with_context("Primary field is not exist"))?, + ); - let row_data = { - let mut rows = database.get_all_rows().await; - if let Some(row_ids) = row_ids { - rows.retain(|row| row_ids.contains(&row.id)); - } - let mut row_data = vec![]; - for row in rows { - let title = database - .get_cell(&primary_field.id, &row.id) - .await - .cell - .and_then(|cell| handler.handle_get_boxed_cell_data(&cell, &primary_field)) - .and_then(|cell_data| cell_data.unbox_or_none()) - .unwrap_or_else(|| StringCellData("".to_string())); + let handler = Arc::new( + TypeOptionCellExt::new(&primary_field, Some(self.cell_cache.clone())) + .get_type_option_cell_data_handler_with_field_type(FieldType::RichText) + .ok_or(FlowyError::internal())?, + ); - row_data.push(RelatedRowDataPB { - row_id: row.id.to_string(), - name: title.0, - }) - } - row_data - }; + match row_ids { + None => { + warn!("Get all related rows will cause performance issue"); + let rows = database.get_all_rows().await; + let mut row_data = vec![]; + for row in rows { + let title = database + .get_cell(&primary_field.id, &row.id) + .await + .cell + .and_then(|cell| handler.handle_get_boxed_cell_data(&cell, &primary_field)) + .and_then(|cell_data| cell_data.unbox_or_none()) + .unwrap_or_else(|| StringCellData("".to_string())); + row_data.push(RelatedRowDataPB { + row_id: row.id.to_string(), + name: title.0, + }) + } + Ok(row_data) + }, + Some(row_ids) => { + let mut database_rows = vec![]; + for row_id in row_ids { + let row_id = RowId::from(row_id); + if let Some(database_row) = database.get_or_init_database_row(&row_id).await { + database_rows.push(database_row); + } + } - Ok(row_data) + let row_data_futures = database_rows.into_iter().map(|database_row| { + let handler = handler.clone(); + let cloned_primary_field = primary_field.clone(); + async move { + let row_id = database_row.read().await.row_id.to_string(); + let title = database_row + .read() + .await + .get_cell(&cloned_primary_field.id) + .and_then(|cell| handler.handle_get_boxed_cell_data(&cell, &cloned_primary_field)) + .and_then(|cell_data| cell_data.unbox_or_none()) + .unwrap_or_else(|| StringCellData("".to_string())); + + RelatedRowDataPB { + row_id, + name: title.0, + } + } + }); + let row_data = join_all(row_data_futures).await; + Ok(row_data) + }, + } } async fn get_auto_updated_fields(&self, view_id: &str) -> Vec { diff --git a/frontend/rust-lib/flowy-database2/src/services/database_view/view_editor.rs b/frontend/rust-lib/flowy-database2/src/services/database_view/view_editor.rs index d907776d40..d2d1970024 100644 --- a/frontend/rust-lib/flowy-database2/src/services/database_view/view_editor.rs +++ b/frontend/rust-lib/flowy-database2/src/services/database_view/view_editor.rs @@ -159,6 +159,7 @@ impl DatabaseViewEditor { params: CreateRowPayloadPB, ) -> FlowyResult { let timestamp = timestamp(); + trace!("[Database]: will create row at: {:?}", params.row_position); let mut result = CreateRowParams { collab_params: collab_database::rows::CreateRowParams { id: gen_row_id(), diff --git a/frontend/rust-lib/flowy-database2/tests/database/database_editor.rs b/frontend/rust-lib/flowy-database2/tests/database/database_editor.rs index 618e1f5fa9..33c8a1e611 100644 --- a/frontend/rust-lib/flowy-database2/tests/database/database_editor.rs +++ b/frontend/rust-lib/flowy-database2/tests/database/database_editor.rs @@ -290,7 +290,7 @@ impl DatabaseEditorTest { self .sdk .database_manager - .get_or_init_database_editor(database_id, None) + .get_or_init_database_editor(database_id) .await .ok() } diff --git a/frontend/rust-lib/flowy-document-pub/src/cloud.rs b/frontend/rust-lib/flowy-document-pub/src/cloud.rs index 18e40691a1..695c16e374 100644 --- a/frontend/rust-lib/flowy-document-pub/src/cloud.rs +++ b/frontend/rust-lib/flowy-document-pub/src/cloud.rs @@ -1,4 +1,5 @@ use anyhow::Error; +use collab::entity::EncodedCollab; pub use collab_document::blocks::DocumentData; use flowy_error::FlowyError; @@ -27,6 +28,13 @@ pub trait DocumentCloudService: Send + Sync + 'static { document_id: &str, workspace_id: &str, ) -> Result, Error>; + + async fn create_document_collab( + &self, + workspace_id: &str, + document_id: &str, + encoded_collab: EncodedCollab, + ) -> Result<(), Error>; } pub struct DocumentSnapshot { diff --git a/frontend/rust-lib/flowy-document/src/manager.rs b/frontend/rust-lib/flowy-document/src/manager.rs index 511d790437..3e42b3af8b 100644 --- a/frontend/rust-lib/flowy-document/src/manager.rs +++ b/frontend/rust-lib/flowy-document/src/manager.rs @@ -2,6 +2,7 @@ use std::sync::Arc; use std::sync::Weak; use collab::core::collab::DataSource; +use collab::core::collab_plugin::CollabPersistence; use collab::core::origin::CollabOrigin; use collab::entity::EncodedCollab; use collab::lock::RwLock; @@ -13,8 +14,7 @@ use collab_document::document_awareness::DocumentAwarenessState; use collab_document::document_awareness::DocumentAwarenessUser; use collab_document::document_data::default_document_data; use collab_entity::CollabType; -use collab_plugins::local_storage::kv::doc::CollabKVAction; -use collab_plugins::local_storage::kv::KVTransactionDB; + use collab_plugins::CollabKVDB; use dashmap::DashMap; use lib_infra::util::timestamp; @@ -25,7 +25,7 @@ use crate::document::{ subscribe_document_changed, subscribe_document_snapshot_state, subscribe_document_sync_state, }; use collab_integrate::collab_builder::{ - AppFlowyCollabBuilder, CollabBuilderConfig, KVDBCollabPersistenceImpl, + AppFlowyCollabBuilder, CollabBuilderConfig, CollabPersistenceImpl, }; use flowy_document_pub::cloud::DocumentCloudService; use flowy_error::{internal_error, ErrorCode, FlowyError, FlowyResult}; @@ -86,7 +86,7 @@ impl DocumentManager { pub fn get_encoded_collab_with_view_id(&self, doc_id: &str) -> FlowyResult { let uid = self.user_service.user_id()?; let doc_state = - KVDBCollabPersistenceImpl::new(self.user_service.collab_db(uid)?, uid).into_data_source(); + CollabPersistenceImpl::new(self.user_service.collab_db(uid)?, uid).into_data_source(); let collab = self.collab_for_document(uid, doc_id, doc_state, false)?; let encoded_collab = collab .try_read() @@ -122,6 +122,12 @@ impl DocumentManager { } } + fn persistence(&self) -> FlowyResult { + let uid = self.user_service.user_id()?; + let db = self.user_service.collab_db(uid)?; + Ok(CollabPersistenceImpl::new(db, uid)) + } + /// Create a new document. /// /// if the document already exists, return the existing document. @@ -129,7 +135,7 @@ impl DocumentManager { #[instrument(level = "info", skip(self, data))] pub async fn create_document( &self, - uid: i64, + _uid: i64, doc_id: &str, data: Option, ) -> FlowyResult { @@ -139,27 +145,22 @@ impl DocumentManager { format!("document {} already exists", doc_id), )) } else { - let db = self - .user_service - .collab_db(uid)? - .upgrade() - .ok_or_else(|| FlowyError::internal().with_context("Failed to get collab db"))?; - let encoded_collab = doc_state_from_document_data( - doc_id, - data.unwrap_or_else(|| default_document_data(doc_id)), - ) - .await?; - - db.with_write_txn(|write_txn| { - write_txn.flush_doc( - uid, - doc_id, - encoded_collab.state_vector.to_vec(), - encoded_collab.doc_state.to_vec(), - )?; - Ok(()) - })?; + let encoded_collab = doc_state_from_document_data(doc_id, data).await?; + self + .persistence()? + .save_collab_to_disk(doc_id, encoded_collab.clone()) + .map_err(internal_error)?; + // Send the collab data to server with a background task. + let cloud_service = self.cloud_service.clone(); + let cloned_encoded_collab = encoded_collab.clone(); + let document_id = doc_id.to_string(); + let workspace_id = self.user_service.workspace_id()?; + tokio::spawn(async move { + let _ = cloud_service + .create_document_collab(&workspace_id, &document_id, cloned_encoded_collab) + .await; + }); Ok(encoded_collab) } } @@ -210,8 +211,7 @@ impl DocumentManager { enable_sync: bool, ) -> FlowyResult>> { let uid = self.user_service.user_id()?; - let mut doc_state = - KVDBCollabPersistenceImpl::new(self.user_service.collab_db(uid)?, uid).into_data_source(); + let mut doc_state = self.persistence()?.into_data_source(); // If the document does not exist in local disk, try get the doc state from the cloud. This happens // When user_device_a create a document and user_device_b open the document. if !self.is_doc_exist(doc_id).await? { @@ -254,9 +254,7 @@ impl DocumentManager { }, Err(err) => { if err.is_invalid_data() { - if let Some(db) = self.user_service.collab_db(uid)?.upgrade() { - db.delete_doc(uid, doc_id).await?; - } + self.delete_document(doc_id).await?; } return Err(err); }, @@ -464,9 +462,10 @@ impl DocumentManager { async fn doc_state_from_document_data( doc_id: &str, - data: DocumentData, + data: Option, ) -> Result { let doc_id = doc_id.to_string(); + let data = data.unwrap_or_else(|| default_document_data(&doc_id)); // spawn_blocking is used to avoid blocking the tokio thread pool if the document is large. let encoded_collab = tokio::task::spawn_blocking(move || { let collab = Collab::new_with_origin(CollabOrigin::Empty, doc_id, vec![], false); diff --git a/frontend/rust-lib/flowy-document/tests/document/util.rs b/frontend/rust-lib/flowy-document/tests/document/util.rs index 2d3fa202a9..64b1ddc8fc 100644 --- a/frontend/rust-lib/flowy-document/tests/document/util.rs +++ b/frontend/rust-lib/flowy-document/tests/document/util.rs @@ -2,6 +2,7 @@ use std::ops::Deref; use std::sync::{Arc, OnceLock}; use anyhow::Error; +use collab::entity::EncodedCollab; use collab::preclude::CollabPlugin; use collab_document::blocks::DocumentData; use collab_document::document::Document; @@ -171,6 +172,15 @@ impl DocumentCloudService for LocalTestDocumentCloudServiceImpl { ) -> Result, Error> { Ok(None) } + + async fn create_document_collab( + &self, + _workspace_id: &str, + _document_id: &str, + _encoded_collab: EncodedCollab, + ) -> Result<(), Error> { + Ok(()) + } } pub struct DocumentTestFileStorageService; diff --git a/frontend/rust-lib/flowy-folder/src/manager.rs b/frontend/rust-lib/flowy-folder/src/manager.rs index ffa203b9c3..c23585b589 100644 --- a/frontend/rust-lib/flowy-folder/src/manager.rs +++ b/frontend/rust-lib/flowy-folder/src/manager.rs @@ -29,7 +29,7 @@ use collab_folder::{ Workspace, }; use collab_integrate::collab_builder::{ - AppFlowyCollabBuilder, CollabBuilderConfig, KVDBCollabPersistenceImpl, + AppFlowyCollabBuilder, CollabBuilderConfig, CollabPersistenceImpl, }; use collab_integrate::CollabKVDB; use flowy_error::{internal_error, ErrorCode, FlowyError, FlowyResult}; @@ -160,7 +160,7 @@ impl FolderManager { let config = CollabBuilderConfig::default().sync_enable(true); let data_source = data_source - .unwrap_or_else(|| KVDBCollabPersistenceImpl::new(collab_db.clone(), uid).into_data_source()); + .unwrap_or_else(|| CollabPersistenceImpl::new(collab_db.clone(), uid).into_data_source()); let object_id = workspace_id; let collab_object = @@ -194,7 +194,7 @@ impl FolderManager { } } - pub(crate) async fn create_empty_collab( + pub(crate) async fn create_folder_with_data( &self, uid: i64, workspace_id: &str, @@ -208,7 +208,7 @@ impl FolderManager { .collab_builder .collab_object(workspace_id, uid, object_id, CollabType::Folder)?; - let doc_state = KVDBCollabPersistenceImpl::new(collab_db.clone(), uid).into_data_source(); + let doc_state = CollabPersistenceImpl::new(collab_db.clone(), uid).into_data_source(); let folder = self.collab_builder.create_folder( collab_object, doc_state, diff --git a/frontend/rust-lib/flowy-folder/src/manager_init.rs b/frontend/rust-lib/flowy-folder/src/manager_init.rs index cec6e56dc7..e333e445b6 100644 --- a/frontend/rust-lib/flowy-folder/src/manager_init.rs +++ b/frontend/rust-lib/flowy-folder/src/manager_init.rs @@ -164,7 +164,7 @@ impl FolderManager { let folder_data = DefaultFolderBuilder::build(uid, workspace_id.to_string(), &self.operation_handlers).await; let folder = self - .create_empty_collab( + .create_folder_with_data( uid, workspace_id, collab_db, diff --git a/frontend/rust-lib/flowy-server/src/af_cloud/impls/database.rs b/frontend/rust-lib/flowy-server/src/af_cloud/impls/database.rs index a7f3e716e9..aa185415fa 100644 --- a/frontend/rust-lib/flowy-server/src/af_cloud/impls/database.rs +++ b/frontend/rust-lib/flowy-server/src/af_cloud/impls/database.rs @@ -3,7 +3,7 @@ use client_api::entity::ai_dto::{ SummarizeRowData, SummarizeRowParams, TranslateRowData, TranslateRowParams, }; use client_api::entity::QueryCollabResult::{Failed, Success}; -use client_api::entity::{QueryCollab, QueryCollabParams}; +use client_api::entity::{CreateCollabParams, QueryCollab, QueryCollabParams}; use client_api::error::ErrorCode::RecordNotFound; use collab::entity::EncodedCollab; use collab_entity::CollabType; @@ -67,6 +67,23 @@ where } } + async fn create_database_encode_collab( + &self, + object_id: &str, + collab_type: CollabType, + workspace_id: &str, + encoded_collab: EncodedCollab, + ) -> Result<(), Error> { + let params = CreateCollabParams { + workspace_id: workspace_id.to_string(), + object_id: object_id.to_string(), + encoded_collab_v1: encoded_collab.encode_to_bytes()?, + collab_type, + }; + self.inner.try_get_client()?.create_collab(params).await?; + Ok(()) + } + #[instrument(level = "debug", skip_all)] async fn batch_get_database_encode_collab( &self, diff --git a/frontend/rust-lib/flowy-server/src/af_cloud/impls/document.rs b/frontend/rust-lib/flowy-server/src/af_cloud/impls/document.rs index 000feac80f..26f282beec 100644 --- a/frontend/rust-lib/flowy-server/src/af_cloud/impls/document.rs +++ b/frontend/rust-lib/flowy-server/src/af_cloud/impls/document.rs @@ -1,7 +1,8 @@ use anyhow::Error; -use client_api::entity::{QueryCollab, QueryCollabParams}; +use client_api::entity::{CreateCollabParams, QueryCollab, QueryCollabParams}; use collab::core::collab::DataSource; use collab::core::origin::CollabOrigin; +use collab::entity::EncodedCollab; use collab::preclude::Collab; use collab_document::document::Document; use collab_entity::CollabType; @@ -32,15 +33,13 @@ where document_id: &str, workspace_id: &str, ) -> Result, FlowyError> { - let workspace_id = workspace_id.to_string(); - let try_get_client = self.inner.try_get_client(); - let document_id = document_id.to_string(); - let cloned_user = self.user.clone(); let params = QueryCollabParams { - workspace_id: workspace_id.clone(), + workspace_id: workspace_id.to_string(), inner: QueryCollab::new(document_id.to_string(), CollabType::Document), }; - let doc_state = try_get_client? + let doc_state = self + .inner + .try_get_client()? .get_collab(params) .await .map_err(FlowyError::from)? @@ -49,8 +48,8 @@ where .to_vec(); check_request_workspace_id_is_match( - &workspace_id, - &cloned_user, + workspace_id, + &self.user, format!("get document doc state:{}", document_id), )?; @@ -72,15 +71,13 @@ where document_id: &str, workspace_id: &str, ) -> Result, Error> { - let try_get_client = self.inner.try_get_client(); - let document_id = document_id.to_string(); - let workspace_id = workspace_id.to_string(); - let cloned_user = self.user.clone(); let params = QueryCollabParams { - workspace_id: workspace_id.clone(), - inner: QueryCollab::new(document_id.clone(), CollabType::Document), + workspace_id: workspace_id.to_string(), + inner: QueryCollab::new(document_id.to_string(), CollabType::Document), }; - let doc_state = try_get_client? + let doc_state = self + .inner + .try_get_client()? .get_collab(params) .await .map_err(FlowyError::from)? @@ -88,13 +85,13 @@ where .doc_state .to_vec(); check_request_workspace_id_is_match( - &workspace_id, - &cloned_user, + workspace_id, + &self.user, format!("Get {} document", document_id), )?; let collab = Collab::new_with_source( CollabOrigin::Empty, - &document_id, + document_id, DataSource::DocStateV1(doc_state), vec![], false, @@ -102,4 +99,20 @@ where let document = Document::open(collab)?; Ok(document.get_document_data().ok()) } + + async fn create_document_collab( + &self, + workspace_id: &str, + document_id: &str, + encoded_collab: EncodedCollab, + ) -> Result<(), Error> { + let params = CreateCollabParams { + workspace_id: workspace_id.to_string(), + object_id: document_id.to_string(), + encoded_collab_v1: encoded_collab.encode_to_bytes()?, + collab_type: CollabType::Document, + }; + self.inner.try_get_client()?.create_collab(params).await?; + Ok(()) + } } diff --git a/frontend/rust-lib/flowy-server/src/local_server/impls/database.rs b/frontend/rust-lib/flowy-server/src/local_server/impls/database.rs index 058b32afa3..3fb2544401 100644 --- a/frontend/rust-lib/flowy-server/src/local_server/impls/database.rs +++ b/frontend/rust-lib/flowy-server/src/local_server/impls/database.rs @@ -34,6 +34,16 @@ impl DatabaseCloudService for LocalServerDatabaseCloudServiceImpl { } } + async fn create_database_encode_collab( + &self, + _object_id: &str, + _collab_type: CollabType, + _workspace_id: &str, + _encoded_collab: EncodedCollab, + ) -> Result<(), Error> { + Ok(()) + } + async fn batch_get_database_encode_collab( &self, _object_ids: Vec, diff --git a/frontend/rust-lib/flowy-server/src/local_server/impls/document.rs b/frontend/rust-lib/flowy-server/src/local_server/impls/document.rs index 2a69a361f8..38e7208bc3 100644 --- a/frontend/rust-lib/flowy-server/src/local_server/impls/document.rs +++ b/frontend/rust-lib/flowy-server/src/local_server/impls/document.rs @@ -1,5 +1,5 @@ use anyhow::Error; - +use collab::entity::EncodedCollab; use flowy_document_pub::cloud::*; use flowy_error::{ErrorCode, FlowyError}; use lib_infra::async_trait::async_trait; @@ -37,4 +37,13 @@ impl DocumentCloudService for LocalServerDocumentCloudServiceImpl { ) -> Result, Error> { Ok(None) } + + async fn create_document_collab( + &self, + _workspace_id: &str, + _document_id: &str, + _encoded_collab: EncodedCollab, + ) -> Result<(), Error> { + Ok(()) + } } diff --git a/frontend/rust-lib/flowy-user/src/user_manager/manager_user_awareness.rs b/frontend/rust-lib/flowy-user/src/user_manager/manager_user_awareness.rs index 0228edae50..d982e4f7b9 100644 --- a/frontend/rust-lib/flowy-user/src/user_manager/manager_user_awareness.rs +++ b/frontend/rust-lib/flowy-user/src/user_manager/manager_user_awareness.rs @@ -6,7 +6,7 @@ use collab::lock::RwLock; use collab_entity::reminder::Reminder; use collab_entity::CollabType; use collab_integrate::collab_builder::{ - AppFlowyCollabBuilder, CollabBuilderConfig, KVDBCollabPersistenceImpl, + AppFlowyCollabBuilder, CollabBuilderConfig, CollabPersistenceImpl, }; use collab_user::core::{UserAwareness, UserAwarenessNotifier}; use dashmap::try_result::TryResult; @@ -157,7 +157,7 @@ impl UserManager { ); let collab_db = self.get_collab_db(session.user_id)?; let doc_state = - KVDBCollabPersistenceImpl::new(collab_db.clone(), session.user_id).into_data_source(); + CollabPersistenceImpl::new(collab_db.clone(), session.user_id).into_data_source(); let awareness = Self::collab_for_user_awareness( &self.collab_builder.clone(), &session.user_workspace.id, @@ -220,7 +220,7 @@ impl UserManager { let create_awareness = if authenticator.is_local() { let doc_state = - KVDBCollabPersistenceImpl::new(collab_db.clone(), session.user_id).into_data_source(); + CollabPersistenceImpl::new(collab_db.clone(), session.user_id).into_data_source(); Self::collab_for_user_awareness( &weak_builder, &session.user_workspace.id, @@ -252,8 +252,8 @@ impl UserManager { Err(err) => { if err.is_record_not_found() { info!("User awareness not found, creating new"); - let doc_state = KVDBCollabPersistenceImpl::new(collab_db.clone(), session.user_id) - .into_data_source(); + let doc_state = + CollabPersistenceImpl::new(collab_db.clone(), session.user_id).into_data_source(); Self::collab_for_user_awareness( &weak_builder, &session.user_workspace.id,