From 789bbf15b7496e39962b750655f0a6b8ee91b1a5 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 4 Jan 2023 12:33:48 -0700 Subject: [PATCH] Update buffer files when synchronizing buffers It's possible that the host was disconnected when attempting to notify guests of a file save, so we need to transmit this in order to correctly update the file's mtime. Next failing seed OPERATIONS=200 SEED=6894 --- crates/collab/src/rpc.rs | 4 +-- .../src/tests/randomized_integration_tests.rs | 28 +++++++++++++------ crates/db/src/db.rs | 2 -- crates/project/src/project.rs | 15 ++++++++-- crates/workspace/src/persistence.rs | 2 +- 5 files changed, 35 insertions(+), 16 deletions(-) diff --git a/crates/collab/src/rpc.rs b/crates/collab/src/rpc.rs index 8e2e5c6041..62db247b9f 100644 --- a/crates/collab/src/rpc.rs +++ b/crates/collab/src/rpc.rs @@ -580,7 +580,7 @@ impl Server { drop(foreground_message_handlers); tracing::info!(%user_id, %login, %connection_id, %address, "signing out"); - if let Err(error) = sign_out(session, teardown, executor).await { + if let Err(error) = connection_lost(session, teardown, executor).await { tracing::error!(%user_id, %login, %connection_id, %address, ?error, "error signing out"); } @@ -781,7 +781,7 @@ pub async fn handle_metrics(Extension(server): Extension>) -> Result } #[instrument(err, skip(executor))] -async fn sign_out( +async fn connection_lost( session: Session, mut teardown: watch::Receiver<()>, executor: Executor, diff --git a/crates/collab/src/tests/randomized_integration_tests.rs b/crates/collab/src/tests/randomized_integration_tests.rs index 1deaafcba2..530ca05af8 100644 --- a/crates/collab/src/tests/randomized_integration_tests.rs +++ b/crates/collab/src/tests/randomized_integration_tests.rs @@ -314,6 +314,7 @@ async fn test_random_collaboration( .read_with(client_cx, |project, _| project.remote_id()) .unwrap() }; + let guest_user_id = client.user_id().unwrap(); let host_project = clients.iter().find_map(|(client, cx)| { let project = client.local_projects.iter().find(|host_project| { @@ -321,14 +322,15 @@ async fn test_random_collaboration( host_project.remote_id() == Some(project_id) }) })?; - Some((project, cx)) + Some((client.user_id().unwrap(), project, cx)) }); - let (host_project, host_cx) = if let Some((host_project, host_cx)) = host_project { - (host_project, host_cx) - } else { - continue; - }; + let (host_user_id, host_project, host_cx) = + if let Some((host_user_id, host_project, host_cx)) = host_project { + (host_user_id, host_project, host_cx) + } else { + continue; + }; for guest_buffer in guest_buffers { let buffer_id = guest_buffer.read_with(client_cx, |buffer, _| buffer.remote_id()); @@ -366,9 +368,17 @@ async fn test_random_collaboration( let guest_file = guest_buffer.read_with(client_cx, |b, _| b.file().cloned()); match (host_file, guest_file) { (Some(host_file), Some(guest_file)) => { - assert_eq!(host_file.mtime(), guest_file.mtime()); - assert_eq!(host_file.path(), guest_file.path()); - assert_eq!(host_file.is_deleted(), guest_file.is_deleted()); + assert_eq!(guest_file.path(), host_file.path()); + assert_eq!(guest_file.is_deleted(), host_file.is_deleted()); + assert_eq!( + guest_file.mtime(), + host_file.mtime(), + "guest {} mtime does not match host {} for path {:?} in project {}", + guest_user_id, + host_user_id, + guest_file.path(), + project_id, + ); } (None, None) => {} (None, _) => panic!("host's file is None, guest's isn't "), diff --git a/crates/db/src/db.rs b/crates/db/src/db.rs index 921b9c8a53..20f2300d89 100644 --- a/crates/db/src/db.rs +++ b/crates/db/src/db.rs @@ -327,8 +327,6 @@ mod tests { .path(); corrupted_backup_dir.push(DB_FILE_NAME); - dbg!(&corrupted_backup_dir); - let backup = Connection::open_file(&corrupted_backup_dir.to_string_lossy()); assert!(backup.select_row::("SELECT * FROM test").unwrap()() .unwrap() diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index be6dc18b35..b1a8c81b9a 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -359,7 +359,7 @@ impl FormatTrigger { impl Project { pub fn init(client: &Arc) { client.add_model_message_handler(Self::handle_add_collaborator); - client.add_model_message_handler(Self::handle_update_collaborator); + client.add_model_message_handler(Self::handle_update_project_collaborator); client.add_model_message_handler(Self::handle_remove_collaborator); client.add_model_message_handler(Self::handle_buffer_reloaded); client.add_model_message_handler(Self::handle_buffer_saved); @@ -4617,7 +4617,7 @@ impl Project { Ok(()) } - async fn handle_update_collaborator( + async fn handle_update_project_collaborator( this: ModelHandle, envelope: TypedEnvelope, _: Arc, @@ -5184,9 +5184,20 @@ impl Project { let operations = buffer.serialize_ops(Some(remote_version), cx); let client = this.client.clone(); + let file = buffer.file().cloned(); cx.background() .spawn( async move { + if let Some(file) = file { + client + .send(proto::UpdateBufferFile { + project_id, + buffer_id: buffer_id as u64, + file: Some(file.to_proto()), + }) + .log_err(); + } + let operations = operations.await; for chunk in split_operations(operations) { client diff --git a/crates/workspace/src/persistence.rs b/crates/workspace/src/persistence.rs index bd4e6653d9..cd425c3a28 100644 --- a/crates/workspace/src/persistence.rs +++ b/crates/workspace/src/persistence.rs @@ -216,7 +216,7 @@ impl WorkspaceDb { let mut result = Vec::new(); let mut delete_tasks = Vec::new(); for (id, location) in self.recent_workspaces()? { - if location.paths().iter().all(|path| dbg!(path).exists()) { + if location.paths().iter().all(|path| path.exists()) { result.push((id, location)); } else { delete_tasks.push(self.delete_stale_workspace(id));