fix: write/load database/document collab (#6308)

* chore: post document collab after create

* chore: write database rows

* chore: fix test

* chore: fix test

* chore: bump collab

* chore: fix get related row

* chore: try to fix open database error

* chore: update client api
This commit is contained in:
Nathan.fooo 2024-09-15 00:02:17 +08:00 committed by GitHub
parent aafdb80455
commit 609ea27c42
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 507 additions and 304 deletions

View File

@ -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",

View File

@ -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:

View File

@ -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",

View File

@ -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:

View File

@ -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",

View File

@ -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:

View File

@ -202,10 +202,13 @@ impl AppFlowyCollabBuilder {
) -> Result<Arc<RwLock<Folder>>, 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<T>(
&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<CollabKVDB>,
pub uid: i64,
}
impl KVDBCollabPersistenceImpl {
impl CollabPersistenceImpl {
pub fn new(db: Weak<CollabKVDB>, 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();

View File

@ -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) => {

View File

@ -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<String>,
@ -449,13 +463,10 @@ impl DocumentCloudService for ServerProvider {
document_id: &str,
workspace_id: &str,
) -> Result<Vec<u8>, 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<Vec<DocumentSnapshot>, 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<Option<DocumentData>, 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
}
}

View File

@ -47,6 +47,14 @@ pub trait DatabaseCloudService: Send + Sync {
workspace_id: &str,
) -> Result<Option<EncodedCollab>, 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<String>,

View File

@ -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<DatabaseLayoutMetaPB>,
manager: AFPluginState<Weak<DatabaseManager>>,
@ -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<GetRelatedRowDataPB>,
manager: AFPluginState<Weak<DatabaseManager>>,
@ -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(&params.database_id, None)
.get_or_init_database_editor(&params.database_id)
.await?;
let row_datas = database_editor
.get_related_rows(Some(&params.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<DatabaseIdPB>,
manager: AFPluginState<Weak<DatabaseManager>>,
@ -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 })
}

View File

@ -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<i64, FlowyError>;
@ -145,14 +147,7 @@ impl DatabaseManager {
pub async fn get_database_inline_view_id(&self, database_id: &str) -> FlowyResult<String> {
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<Arc<DatabaseEditor>> {
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<Arc<DatabaseEditor>> {
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<Arc<RwLock<Database>>> {
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<Option<EncodedCollab>, 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<String>,
object_ty: CollabType,
) -> Result<EncodeCollabByOid, DatabaseError> {
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<Weak<CollabKVDB>, DatabaseError> {
@ -758,17 +735,22 @@ impl DatabaseCollabService for WorkspaceDatabaseCollabServiceImpl {
&self,
object_id: &str,
collab_type: CollabType,
encoded_collab: Option<EncodedCollab>,
encoded_collab: Option<(EncodedCollab, bool)>,
) -> Result<Collab, DatabaseError> {
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<String>,
collab_type: CollabType,
) -> Result<EncodeCollabByOid, DatabaseError> {
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<String, EncodedCollab> = 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<Arc<dyn DatabaseCollabPersistenceService>> {
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<EncodedCollab> {
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

View File

@ -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<dyn DatabaseUser>,
collab_builder: Arc<AppFlowyCollabBuilder>,
is_opening: ArcSwap<bool>,
is_loading_rows: ArcSwapOption<broadcast::Sender<()>>,
opening_ret_txs: Arc<RwLock<Vec<OpenDatabaseResult>>>,
database_cancellation: Arc<RwLock<Option<CancellationToken>>>,
un_finalized_rows_cancellation: Arc<ArcSwapOption<CancellationToken>>,
@ -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<Arc<RwLock<DatabaseRow>>> {
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::<Vec<RowMetaPB>>();
@ -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::<Vec<RowMetaPB>>();
.map(|row| (row.id.to_string(), RowMetaPB::from(row.as_ref())))
.collect::<HashMap<String, RowMetaPB>>();
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::<Vec<_>>();
@ -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<String>>,
row_ids: Option<Vec<String>>,
) -> FlowyResult<Vec<RelatedRowDataPB>> {
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<Field> {

View File

@ -159,6 +159,7 @@ impl DatabaseViewEditor {
params: CreateRowPayloadPB,
) -> FlowyResult<CreateRowParams> {
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(),

View File

@ -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()
}

View File

@ -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<Option<DocumentData>, Error>;
async fn create_document_collab(
&self,
workspace_id: &str,
document_id: &str,
encoded_collab: EncodedCollab,
) -> Result<(), Error>;
}
pub struct DocumentSnapshot {

View File

@ -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<EncodedCollab> {
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<CollabPersistenceImpl> {
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<DocumentData>,
) -> FlowyResult<EncodedCollab> {
@ -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<Arc<RwLock<Document>>> {
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<DocumentData>,
) -> Result<EncodedCollab, FlowyError> {
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);

View File

@ -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<Option<DocumentData>, Error> {
Ok(None)
}
async fn create_document_collab(
&self,
_workspace_id: &str,
_document_id: &str,
_encoded_collab: EncodedCollab,
) -> Result<(), Error> {
Ok(())
}
}
pub struct DocumentTestFileStorageService;

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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<Vec<u8>, 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<Option<DocumentData>, 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(())
}
}

View File

@ -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<String>,

View File

@ -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<Option<DocumentData>, Error> {
Ok(None)
}
async fn create_document_collab(
&self,
_workspace_id: &str,
_document_id: &str,
_encoded_collab: EncodedCollab,
) -> Result<(), Error> {
Ok(())
}
}

View File

@ -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,