Skip to content

Commit

Permalink
fix: import document from database row (AppFlowy-IO#4295)
Browse files Browse the repository at this point in the history
* fix: import document from database row

* chore: update test

* chore: fix test

* chore: fix test

* chore: fix test

* chore: fix local user on appflowy cloud error

* chore: clippy

* chore: bump pubspec version
  • Loading branch information
appflowy authored Jan 4, 2024
1 parent de08c01 commit eac878d
Show file tree
Hide file tree
Showing 19 changed files with 228 additions and 186 deletions.
2 changes: 1 addition & 1 deletion frontend/.vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"program": "./lib/main.dart",
"type": "dart",
"env": {
"RUST_LOG": "debug",
"RUST_LOG": "trace",
"RUST_BACKTRACE": "1"
},
// uncomment the following line to testing performance.
Expand Down
2 changes: 1 addition & 1 deletion frontend/appflowy_flutter/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 0.4.0
version: 0.4.1

environment:
flutter: ">=3.18.0-0.2.pre"
Expand Down
25 changes: 6 additions & 19 deletions frontend/rust-lib/event-integration/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,8 @@ impl EventIntegrationTest {
let path = path_buf.to_str().unwrap().to_string();
let device_id = uuid::Uuid::new_v4().to_string();

let level = "trace";
std::env::set_var("RUST_LOG", level);
let config = AppFlowyCoreConfig::new(path.clone(), path, device_id, name).log_filter(
level,
"trace",
vec![
"flowy_test".to_string(),
"tokio".to_string(),
Expand All @@ -79,27 +77,16 @@ impl EventIntegrationTest {
}
}

pub fn get_appflowy_cloud_server(&self) -> Arc<dyn AppFlowyServer> {
self
.appflowy_core
.server_provider
.get_appflowy_cloud_server()
.unwrap()
pub fn get_server(&self) -> Arc<dyn AppFlowyServer> {
self.appflowy_core.server_provider.get_server().unwrap()
}

pub async fn wait_ws_connected(&self) {
if self
.get_appflowy_cloud_server()
.get_ws_state()
.is_connected()
{
if self.get_server().get_ws_state().is_connected() {
return;
}

let mut ws_state = self
.get_appflowy_cloud_server()
.subscribe_ws_state()
.unwrap();
let mut ws_state = self.get_server().subscribe_ws_state().unwrap();
loop {
select! {
_ = sleep(Duration::from_secs(20)) => {
Expand All @@ -121,7 +108,7 @@ impl EventIntegrationTest {
oid: &str,
collay_type: CollabType,
) -> Result<CollabDocState, FlowyError> {
let server = self.server_provider.get_appflowy_cloud_server().unwrap();
let server = self.server_provider.get_server().unwrap();
let workspace_id = self.get_current_workspace().await.id;
let uid = self.get_user_profile().await?.id;
let doc_state = server
Expand Down
Binary file modified frontend/rust-lib/event-integration/tests/asset/040_local.zip
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::util::unzip_history_user_db;
use assert_json_diff::assert_json_include;
use collab_database::rows::database_row_document_id_from_row_id;
use collab_entity::CollabType;
use event_integration::user_event::user_localhost_af_cloud;
use event_integration::{document_data_from_document_doc_state, EventIntegrationTest};
Expand Down Expand Up @@ -45,6 +46,9 @@ async fn import_appflowy_data_folder_into_new_view_test() {
assert_eq!(views.len(), 2);
assert_eq!(views[1].name, import_container_name);

// the 040_local should be an empty document, so try to get the document data
let _ = test.get_document_data(&views[1].id).await;

let local_child_views = test.get_view(&views[1].id).await.child_views;
assert_eq!(local_child_views.len(), 1);
assert_eq!(local_child_views[0].name, "Document1");
Expand All @@ -61,6 +65,14 @@ async fn import_appflowy_data_folder_into_new_view_test() {
assert_eq!(document2_child_views[0].name, "Grid1");
assert_eq!(document2_child_views[1].name, "Grid2");

let rows = test.get_database(&document2_child_views[1].id).await.rows;
assert_eq!(rows.len(), 3);

// In the 040_local, only the first row has a document with content
let row_document_id = database_row_document_id_from_row_id(&rows[0].id);
let row_document_data = test.get_document_data(&row_document_id).await;
assert_json_include!(actual: json!(row_document_data), expected: expected_row_doc_json());

drop(cleaner);
}

Expand Down Expand Up @@ -370,3 +382,46 @@ fn expected_doc_2_json() -> Value {
"page_id": "ZVogdaK9yO"
})
}

fn expected_row_doc_json() -> Value {
json!( {
"blocks": {
"eSBQHZ28e0": {
"children": "RbLAaE9UDJ",
"data": {},
"external_id": null,
"external_type": null,
"id": "eSBQHZ28e0",
"parent": "",
"ty": "page"
},
"eUIL6qjgj3": {
"children": "fUnGRcvPEA",
"data": {
"delta": [
{
"insert": "document in database row"
}
]
},
"external_id": "-DliEUjHr2",
"external_type": "text",
"id": "eUIL6qjgj3",
"parent": "eSBQHZ28e0",
"ty": "paragraph"
}
},
"meta": {
"children_map": {
"RbLAaE9UDJ": [
"eUIL6qjgj3"
],
"fUnGRcvPEA": []
},
"text_map": {
"-DliEUjHr2": "[{\"insert\":\"document in database row\"}]"
}
},
"page_id": "eSBQHZ28e0"
})
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use event_integration::EventIntegrationTest;
use flowy_core::DEFAULT_NAME;
use flowy_folder::entities::ViewLayoutPB;
use std::time::Duration;

use crate::util::unzip_history_user_db;

Expand Down Expand Up @@ -140,10 +141,7 @@ async fn collab_db_backup_test() {
assert_eq!(backups.len(), 1);
assert_eq!(
backups[0],
format!(
"collab_db_{}",
chrono::Local::now().format("%Y%m%d").to_string()
)
format!("collab_db_{}", chrono::Local::now().format("%Y%m%d"))
);
drop(cleaner);
}
Expand All @@ -157,7 +155,15 @@ async fn delete_outdated_collab_db_backup_test() {
EventIntegrationTest::new_with_user_data_path(user_db_path, DEFAULT_NAME.to_string()).await;

let uid = test.get_user_profile().await.unwrap().id;
// saving the backup is a background task, so we need to wait for it to finish
// 2 seconds should be enough for the background task to finish
tokio::time::sleep(Duration::from_secs(2)).await;
let backups = test.user_manager.get_collab_backup_list(uid);

if backups.len() != 10 {
dbg!("backups: {:?}", backups.clone());
}

assert_eq!(backups.len(), 10);
assert_eq!(backups[0], "collab_db_0.4.0_20231202");
assert_eq!(backups[1], "collab_db_0.4.0_20231203");
Expand All @@ -170,10 +176,7 @@ async fn delete_outdated_collab_db_backup_test() {
assert_eq!(backups[8], "collab_db_0.4.0_20231210");
assert_eq!(
backups[9],
format!(
"collab_db_{}",
chrono::Local::now().format("%Y%m%d").to_string()
)
format!("collab_db_{}", chrono::Local::now().format("%Y%m%d"))
);
drop(cleaner);
}
2 changes: 1 addition & 1 deletion frontend/rust-lib/event-integration/tests/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use flowy_user::entities::{AuthenticatorPB, UpdateUserProfilePayloadPB};
use flowy_user::errors::FlowyError;

use flowy_user::event_map::UserEvent::*;
use flowy_user_deps::cloud::{UserCloudService, UserCloudServiceProvider};
use flowy_user_deps::cloud::UserCloudService;
use flowy_user_deps::entities::Authenticator;

pub fn get_supabase_config() -> Option<SupabaseConfiguration> {
Expand Down
4 changes: 2 additions & 2 deletions frontend/rust-lib/flowy-core/src/integrate/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub(crate) fn create_log_filter(level: String, with_crates: Vec<String>) -> Stri
.map(|crate_name| format!("{}={}", crate_name, level))
.collect::<Vec<String>>();
filters.push(format!("flowy_core={}", level));
filters.push(format!("flowy_folder2={}", level));
filters.push(format!("flowy_folder={}", level));
filters.push(format!("collab_sync={}", level));
filters.push(format!("collab_folder={}", level));
filters.push(format!("collab_persistence={}", level));
Expand All @@ -28,7 +28,7 @@ pub(crate) fn create_log_filter(level: String, with_crates: Vec<String>) -> Stri
filters.push(format!("collab_integrate={}", level));
filters.push(format!("collab={}", level));
filters.push(format!("flowy_user={}", level));
filters.push(format!("flowy_document2={}", level));
filters.push(format!("flowy_document={}", level));
filters.push(format!("flowy_database2={}", level));
filters.push(format!("flowy_server={}", level));
filters.push(format!("flowy_notification={}", "info"));
Expand Down
44 changes: 25 additions & 19 deletions frontend/rust-lib/flowy-core/src/integrate/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ pub enum Server {
Supabase = 2,
}

impl Server {
pub fn is_local(&self) -> bool {
matches!(self, Server::Local)
}
}

impl Display for Server {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Expand All @@ -49,15 +55,14 @@ impl Display for Server {
/// Each server implements the [AppFlowyServer] trait, which provides the [UserCloudService], etc.
pub struct ServerProvider {
config: AppFlowyCoreConfig,
server: RwLock<Server>,
providers: RwLock<HashMap<Server, Arc<dyn AppFlowyServer>>>,
pub(crate) encryption: RwLock<Arc<dyn AppFlowyEncryption>>,
#[allow(dead_code)]
pub(crate) store_preferences: Weak<StorePreferences>,
pub(crate) user_enable_sync: RwLock<bool>,

/// The authenticator type of the user.
pub(crate) user_authenticator: RwLock<Authenticator>,
authenticator: RwLock<Authenticator>,
pub(crate) uid: Arc<RwLock<Option<i64>>>,
}

Expand All @@ -70,41 +75,42 @@ impl ServerProvider {
let encryption = EncryptionImpl::new(None);
Self {
config,
server: RwLock::new(server),
providers: RwLock::new(HashMap::new()),
user_enable_sync: RwLock::new(true),
user_authenticator: RwLock::new(Authenticator::Local),
authenticator: RwLock::new(Authenticator::from(server)),
encryption: RwLock::new(Arc::new(encryption)),
store_preferences,
uid: Default::default(),
}
}

pub fn get_server_type(&self) -> Server {
self.server.read().clone()
match &*self.authenticator.read() {
Authenticator::Local => Server::Local,
Authenticator::AppFlowyCloud => Server::AppFlowyCloud,
Authenticator::Supabase => Server::Supabase,
}
}

pub fn set_server_type(&self, server_type: Server) {
let old_server_type = self.server.read().clone();
if server_type != old_server_type {
pub fn set_authenticator(&self, authenticator: Authenticator) {
let old_server_type = self.get_server_type();
*self.authenticator.write() = authenticator;
let new_server_type = self.get_server_type();

if old_server_type != new_server_type {
self.providers.write().remove(&old_server_type);
}

*self.server.write() = server_type;
}

pub fn get_user_authenticator(&self) -> Authenticator {
self.user_authenticator.read().clone()
}

pub fn get_appflowy_cloud_server(&self) -> FlowyResult<Arc<dyn AppFlowyServer>> {
let server = self.get_server(&Server::AppFlowyCloud)?;
Ok(server)
pub fn get_authenticator(&self) -> Authenticator {
self.authenticator.read().clone()
}

/// Returns a [AppFlowyServer] trait implementation base on the provider_type.
pub fn get_server(&self, server_type: &Server) -> FlowyResult<Arc<dyn AppFlowyServer>> {
if let Some(provider) = self.providers.read().get(server_type) {
pub fn get_server(&self) -> FlowyResult<Arc<dyn AppFlowyServer>> {
let server_type = self.get_server_type();

if let Some(provider) = self.providers.read().get(&server_type) {
return Ok(provider.clone());
}

Expand Down
Loading

0 comments on commit eac878d

Please sign in to comment.