Use an unbounded channel for peer's outgoing messages
Using a bounded channel may have blocked the collaboration server from making progress handling RPC traffic. There's no need to apply backpressure to calling code within the same process - suspending a task that is attempting to call `send` has an even greater memory cost than just buffering a protobuf message. We do still want a bounded channel for incoming messages, so that we provide backpressure to noisy peers - blocking their writes as opposed to allowing them to buffer arbitrarily many messages in our server. Co-Authored-By: Antonio Scandurra <me@as-cii.com> Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
parent
82afacd33d
commit
d4fe1115e7
7 changed files with 341 additions and 472 deletions
|
@ -460,7 +460,7 @@ impl Project {
|
|||
}
|
||||
})?;
|
||||
|
||||
rpc.send(proto::UnshareProject { project_id }).await?;
|
||||
rpc.send(proto::UnshareProject { project_id })?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.collaborators.clear();
|
||||
this.shared_buffers.clear();
|
||||
|
@ -818,15 +818,13 @@ impl Project {
|
|||
let this = cx.read(|cx| this.upgrade(cx))?;
|
||||
match message {
|
||||
LspEvent::DiagnosticsStart => {
|
||||
let send = this.update(&mut cx, |this, cx| {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.disk_based_diagnostics_started(cx);
|
||||
this.remote_id().map(|project_id| {
|
||||
if let Some(project_id) = this.remote_id() {
|
||||
rpc.send(proto::DiskBasedDiagnosticsUpdating { project_id })
|
||||
})
|
||||
.log_err();
|
||||
}
|
||||
});
|
||||
if let Some(send) = send {
|
||||
send.await.log_err();
|
||||
}
|
||||
}
|
||||
LspEvent::DiagnosticsUpdate(mut params) => {
|
||||
language.process_diagnostics(&mut params);
|
||||
|
@ -836,15 +834,13 @@ impl Project {
|
|||
});
|
||||
}
|
||||
LspEvent::DiagnosticsFinish => {
|
||||
let send = this.update(&mut cx, |this, cx| {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.disk_based_diagnostics_finished(cx);
|
||||
this.remote_id().map(|project_id| {
|
||||
if let Some(project_id) = this.remote_id() {
|
||||
rpc.send(proto::DiskBasedDiagnosticsUpdated { project_id })
|
||||
})
|
||||
.log_err();
|
||||
}
|
||||
});
|
||||
if let Some(send) = send {
|
||||
send.await.log_err();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1311,15 +1307,13 @@ impl Project {
|
|||
};
|
||||
|
||||
if let Some(project_id) = self.remote_id() {
|
||||
let client = self.client.clone();
|
||||
let message = proto::UpdateBufferFile {
|
||||
project_id,
|
||||
buffer_id: *buffer_id as u64,
|
||||
file: Some(new_file.to_proto()),
|
||||
};
|
||||
cx.foreground()
|
||||
.spawn(async move { client.send(message).await })
|
||||
.detach_and_log_err(cx);
|
||||
self.client
|
||||
.send(proto::UpdateBufferFile {
|
||||
project_id,
|
||||
buffer_id: *buffer_id as u64,
|
||||
file: Some(new_file.to_proto()),
|
||||
})
|
||||
.log_err();
|
||||
}
|
||||
buffer.file_updated(Box::new(new_file), cx).detach();
|
||||
}
|
||||
|
@ -1639,8 +1633,7 @@ impl Project {
|
|||
version: (&version).into(),
|
||||
mtime: Some(mtime.into()),
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1669,16 +1662,13 @@ impl Project {
|
|||
// associated with formatting.
|
||||
cx.spawn(|_| async move {
|
||||
match format {
|
||||
Ok(()) => rpc.respond(receipt, proto::Ack {}).await?,
|
||||
Err(error) => {
|
||||
rpc.respond_with_error(
|
||||
receipt,
|
||||
proto::Error {
|
||||
message: error.to_string(),
|
||||
},
|
||||
)
|
||||
.await?
|
||||
}
|
||||
Ok(()) => rpc.respond(receipt, proto::Ack {})?,
|
||||
Err(error) => rpc.respond_with_error(
|
||||
receipt,
|
||||
proto::Error {
|
||||
message: error.to_string(),
|
||||
},
|
||||
)?,
|
||||
}
|
||||
Ok::<_, anyhow::Error>(())
|
||||
})
|
||||
|
@ -1712,27 +1702,21 @@ impl Project {
|
|||
.update(&mut cx, |buffer, cx| buffer.completions(position, cx))
|
||||
.await
|
||||
{
|
||||
Ok(completions) => {
|
||||
rpc.respond(
|
||||
receipt,
|
||||
proto::GetCompletionsResponse {
|
||||
completions: completions
|
||||
.iter()
|
||||
.map(language::proto::serialize_completion)
|
||||
.collect(),
|
||||
},
|
||||
)
|
||||
.await
|
||||
}
|
||||
Err(error) => {
|
||||
rpc.respond_with_error(
|
||||
receipt,
|
||||
proto::Error {
|
||||
message: error.to_string(),
|
||||
},
|
||||
)
|
||||
.await
|
||||
}
|
||||
Ok(completions) => rpc.respond(
|
||||
receipt,
|
||||
proto::GetCompletionsResponse {
|
||||
completions: completions
|
||||
.iter()
|
||||
.map(language::proto::serialize_completion)
|
||||
.collect(),
|
||||
},
|
||||
),
|
||||
Err(error) => rpc.respond_with_error(
|
||||
receipt,
|
||||
proto::Error {
|
||||
message: error.to_string(),
|
||||
},
|
||||
),
|
||||
}
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
|
@ -1767,30 +1751,24 @@ impl Project {
|
|||
})
|
||||
.await
|
||||
{
|
||||
Ok(edit_ids) => {
|
||||
rpc.respond(
|
||||
receipt,
|
||||
proto::ApplyCompletionAdditionalEditsResponse {
|
||||
additional_edits: edit_ids
|
||||
.into_iter()
|
||||
.map(|edit_id| proto::AdditionalEdit {
|
||||
replica_id: edit_id.replica_id as u32,
|
||||
local_timestamp: edit_id.value,
|
||||
})
|
||||
.collect(),
|
||||
},
|
||||
)
|
||||
.await
|
||||
}
|
||||
Err(error) => {
|
||||
rpc.respond_with_error(
|
||||
receipt,
|
||||
proto::Error {
|
||||
message: error.to_string(),
|
||||
},
|
||||
)
|
||||
.await
|
||||
}
|
||||
Ok(edit_ids) => rpc.respond(
|
||||
receipt,
|
||||
proto::ApplyCompletionAdditionalEditsResponse {
|
||||
additional_edits: edit_ids
|
||||
.into_iter()
|
||||
.map(|edit_id| proto::AdditionalEdit {
|
||||
replica_id: edit_id.replica_id as u32,
|
||||
local_timestamp: edit_id.value,
|
||||
})
|
||||
.collect(),
|
||||
},
|
||||
),
|
||||
Err(error) => rpc.respond_with_error(
|
||||
receipt,
|
||||
proto::Error {
|
||||
message: error.to_string(),
|
||||
},
|
||||
),
|
||||
}
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
|
@ -1836,7 +1814,7 @@ impl Project {
|
|||
});
|
||||
}
|
||||
});
|
||||
rpc.respond(receipt, response).await?;
|
||||
rpc.respond(receipt, response)?;
|
||||
Ok::<_, anyhow::Error>(())
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
|
@ -1872,7 +1850,6 @@ impl Project {
|
|||
buffer: Some(buffer),
|
||||
},
|
||||
)
|
||||
.await
|
||||
}
|
||||
.log_err()
|
||||
})
|
||||
|
@ -2106,28 +2083,21 @@ impl<'a> Iterator for CandidateSetIter<'a> {
|
|||
impl Entity for Project {
|
||||
type Event = Event;
|
||||
|
||||
fn release(&mut self, cx: &mut gpui::MutableAppContext) {
|
||||
fn release(&mut self, _: &mut gpui::MutableAppContext) {
|
||||
match &self.client_state {
|
||||
ProjectClientState::Local { remote_id_rx, .. } => {
|
||||
if let Some(project_id) = *remote_id_rx.borrow() {
|
||||
let rpc = self.client.clone();
|
||||
cx.spawn(|_| async move {
|
||||
if let Err(err) = rpc.send(proto::UnregisterProject { project_id }).await {
|
||||
log::error!("error unregistering project: {}", err);
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
self.client
|
||||
.send(proto::UnregisterProject { project_id })
|
||||
.log_err();
|
||||
}
|
||||
}
|
||||
ProjectClientState::Remote { remote_id, .. } => {
|
||||
let rpc = self.client.clone();
|
||||
let project_id = *remote_id;
|
||||
cx.spawn(|_| async move {
|
||||
if let Err(err) = rpc.send(proto::LeaveProject { project_id }).await {
|
||||
log::error!("error leaving project: {}", err);
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
self.client
|
||||
.send(proto::LeaveProject {
|
||||
project_id: *remote_id,
|
||||
})
|
||||
.log_err();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -149,7 +149,7 @@ pub enum Event {
|
|||
impl Entity for Worktree {
|
||||
type Event = Event;
|
||||
|
||||
fn release(&mut self, cx: &mut MutableAppContext) {
|
||||
fn release(&mut self, _: &mut MutableAppContext) {
|
||||
if let Some(worktree) = self.as_local_mut() {
|
||||
if let Registration::Done { project_id } = worktree.registration {
|
||||
let client = worktree.client.clone();
|
||||
|
@ -157,12 +157,7 @@ impl Entity for Worktree {
|
|||
project_id,
|
||||
worktree_id: worktree.id().to_proto(),
|
||||
};
|
||||
cx.foreground()
|
||||
.spawn(async move {
|
||||
client.send(unregister_message).await?;
|
||||
Ok::<_, anyhow::Error>(())
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
client.send(unregister_message).log_err();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -596,7 +591,7 @@ impl LocalWorktree {
|
|||
&mut self,
|
||||
worktree_path: Arc<Path>,
|
||||
diagnostics: Vec<DiagnosticEntry<PointUtf16>>,
|
||||
cx: &mut ModelContext<Worktree>,
|
||||
_: &mut ModelContext<Worktree>,
|
||||
) -> Result<()> {
|
||||
let summary = DiagnosticSummary::new(&diagnostics);
|
||||
self.diagnostic_summaries
|
||||
|
@ -604,30 +599,19 @@ impl LocalWorktree {
|
|||
self.diagnostics.insert(worktree_path.clone(), diagnostics);
|
||||
|
||||
if let Some(share) = self.share.as_ref() {
|
||||
cx.foreground()
|
||||
.spawn({
|
||||
let client = self.client.clone();
|
||||
let project_id = share.project_id;
|
||||
let worktree_id = self.id().to_proto();
|
||||
let path = worktree_path.to_string_lossy().to_string();
|
||||
async move {
|
||||
client
|
||||
.send(proto::UpdateDiagnosticSummary {
|
||||
project_id,
|
||||
worktree_id,
|
||||
summary: Some(proto::DiagnosticSummary {
|
||||
path,
|
||||
error_count: summary.error_count as u32,
|
||||
warning_count: summary.warning_count as u32,
|
||||
info_count: summary.info_count as u32,
|
||||
hint_count: summary.hint_count as u32,
|
||||
}),
|
||||
})
|
||||
.await
|
||||
.log_err()
|
||||
}
|
||||
self.client
|
||||
.send(proto::UpdateDiagnosticSummary {
|
||||
project_id: share.project_id,
|
||||
worktree_id: self.id().to_proto(),
|
||||
summary: Some(proto::DiagnosticSummary {
|
||||
path: worktree_path.to_string_lossy().to_string(),
|
||||
error_count: summary.error_count as u32,
|
||||
warning_count: summary.warning_count as u32,
|
||||
info_count: summary.info_count as u32,
|
||||
hint_count: summary.hint_count as u32,
|
||||
}),
|
||||
})
|
||||
.detach();
|
||||
.log_err();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -787,7 +771,7 @@ impl LocalWorktree {
|
|||
while let Ok(snapshot) = snapshots_to_send_rx.recv().await {
|
||||
let message =
|
||||
snapshot.build_update(&prev_snapshot, project_id, worktree_id, false);
|
||||
match rpc.send(message).await {
|
||||
match rpc.send(message) {
|
||||
Ok(()) => prev_snapshot = snapshot,
|
||||
Err(err) => log::error!("error sending snapshot diff {}", err),
|
||||
}
|
||||
|
@ -1377,8 +1361,7 @@ impl language::File for File {
|
|||
buffer_id,
|
||||
version: (&version).into(),
|
||||
mtime: Some(entry.mtime.into()),
|
||||
})
|
||||
.await?;
|
||||
})?;
|
||||
}
|
||||
Ok((version, entry.mtime))
|
||||
})
|
||||
|
@ -1501,23 +1484,15 @@ impl language::File for File {
|
|||
}
|
||||
|
||||
fn buffer_removed(&self, buffer_id: u64, cx: &mut MutableAppContext) {
|
||||
self.worktree.update(cx, |worktree, cx| {
|
||||
self.worktree.update(cx, |worktree, _| {
|
||||
if let Worktree::Remote(worktree) = worktree {
|
||||
let project_id = worktree.project_id;
|
||||
let rpc = worktree.client.clone();
|
||||
cx.background()
|
||||
.spawn(async move {
|
||||
if let Err(error) = rpc
|
||||
.send(proto::CloseBuffer {
|
||||
project_id,
|
||||
buffer_id,
|
||||
})
|
||||
.await
|
||||
{
|
||||
log::error!("error closing remote buffer: {}", error);
|
||||
}
|
||||
worktree
|
||||
.client
|
||||
.send(proto::CloseBuffer {
|
||||
project_id: worktree.project_id,
|
||||
buffer_id,
|
||||
})
|
||||
.detach();
|
||||
.log_err();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1563,16 +1538,15 @@ impl language::LocalFile for File {
|
|||
) {
|
||||
let worktree = self.worktree.read(cx).as_local().unwrap();
|
||||
if let Some(project_id) = worktree.share.as_ref().map(|share| share.project_id) {
|
||||
let rpc = worktree.client.clone();
|
||||
let message = proto::BufferReloaded {
|
||||
project_id,
|
||||
buffer_id,
|
||||
version: version.into(),
|
||||
mtime: Some(mtime.into()),
|
||||
};
|
||||
cx.background()
|
||||
.spawn(async move { rpc.send(message).await })
|
||||
.detach_and_log_err(cx);
|
||||
worktree
|
||||
.client
|
||||
.send(proto::BufferReloaded {
|
||||
project_id,
|
||||
buffer_id,
|
||||
version: version.into(),
|
||||
mtime: Some(mtime.into()),
|
||||
})
|
||||
.log_err();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue