Avoid applying outdated UpdateProject messages
Co-authored-by: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
parent
bcf9b2f10d
commit
1ccf174388
3 changed files with 47 additions and 11 deletions
|
@ -10,7 +10,10 @@ use async_tungstenite::tungstenite::{
|
||||||
error::Error as WebsocketError,
|
error::Error as WebsocketError,
|
||||||
http::{Request, StatusCode},
|
http::{Request, StatusCode},
|
||||||
};
|
};
|
||||||
use futures::{future::LocalBoxFuture, AsyncReadExt, FutureExt, SinkExt, StreamExt, TryStreamExt};
|
use futures::{
|
||||||
|
future::LocalBoxFuture, AsyncReadExt, FutureExt, SinkExt, StreamExt, TryFutureExt as _,
|
||||||
|
TryStreamExt,
|
||||||
|
};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions,
|
actions,
|
||||||
serde_json::{self, Value},
|
serde_json::{self, Value},
|
||||||
|
@ -1187,6 +1190,14 @@ impl Client {
|
||||||
&self,
|
&self,
|
||||||
request: T,
|
request: T,
|
||||||
) -> impl Future<Output = Result<T::Response>> {
|
) -> impl Future<Output = Result<T::Response>> {
|
||||||
|
self.request_envelope(request)
|
||||||
|
.map_ok(|envelope| envelope.payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn request_envelope<T: RequestMessage>(
|
||||||
|
&self,
|
||||||
|
request: T,
|
||||||
|
) -> impl Future<Output = Result<TypedEnvelope<T::Response>>> {
|
||||||
let client_id = self.id;
|
let client_id = self.id;
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"rpc request start. client_id:{}. name:{}",
|
"rpc request start. client_id:{}. name:{}",
|
||||||
|
@ -1195,7 +1206,7 @@ impl Client {
|
||||||
);
|
);
|
||||||
let response = self
|
let response = self
|
||||||
.connection_id()
|
.connection_id()
|
||||||
.map(|conn_id| self.peer.request(conn_id, request));
|
.map(|conn_id| self.peer.request_envelope(conn_id, request));
|
||||||
async move {
|
async move {
|
||||||
let response = response?.await;
|
let response = response?.await;
|
||||||
log::debug!(
|
log::debug!(
|
||||||
|
|
|
@ -100,6 +100,7 @@ pub struct Project {
|
||||||
next_language_server_id: usize,
|
next_language_server_id: usize,
|
||||||
client: Arc<client::Client>,
|
client: Arc<client::Client>,
|
||||||
next_entry_id: Arc<AtomicUsize>,
|
next_entry_id: Arc<AtomicUsize>,
|
||||||
|
join_project_response_message_id: u32,
|
||||||
next_diagnostic_group_id: usize,
|
next_diagnostic_group_id: usize,
|
||||||
user_store: ModelHandle<UserStore>,
|
user_store: ModelHandle<UserStore>,
|
||||||
fs: Arc<dyn Fs>,
|
fs: Arc<dyn Fs>,
|
||||||
|
@ -425,6 +426,7 @@ impl Project {
|
||||||
loading_buffers_by_path: Default::default(),
|
loading_buffers_by_path: Default::default(),
|
||||||
loading_local_worktrees: Default::default(),
|
loading_local_worktrees: Default::default(),
|
||||||
buffer_snapshots: Default::default(),
|
buffer_snapshots: Default::default(),
|
||||||
|
join_project_response_message_id: 0,
|
||||||
client_state: None,
|
client_state: None,
|
||||||
opened_buffer: watch::channel(),
|
opened_buffer: watch::channel(),
|
||||||
client_subscriptions: Vec::new(),
|
client_subscriptions: Vec::new(),
|
||||||
|
@ -463,15 +465,15 @@ impl Project {
|
||||||
|
|
||||||
let subscription = client.subscribe_to_entity(remote_id);
|
let subscription = client.subscribe_to_entity(remote_id);
|
||||||
let response = client
|
let response = client
|
||||||
.request(proto::JoinProject {
|
.request_envelope(proto::JoinProject {
|
||||||
project_id: remote_id,
|
project_id: remote_id,
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
let this = cx.add_model(|cx| {
|
let this = cx.add_model(|cx| {
|
||||||
let replica_id = response.replica_id as ReplicaId;
|
let replica_id = response.payload.replica_id as ReplicaId;
|
||||||
|
|
||||||
let mut worktrees = Vec::new();
|
let mut worktrees = Vec::new();
|
||||||
for worktree in response.worktrees {
|
for worktree in response.payload.worktrees {
|
||||||
let worktree = cx.update(|cx| {
|
let worktree = cx.update(|cx| {
|
||||||
Worktree::remote(remote_id, replica_id, worktree, client.clone(), cx)
|
Worktree::remote(remote_id, replica_id, worktree, client.clone(), cx)
|
||||||
});
|
});
|
||||||
|
@ -487,6 +489,7 @@ impl Project {
|
||||||
loading_local_worktrees: Default::default(),
|
loading_local_worktrees: Default::default(),
|
||||||
active_entry: None,
|
active_entry: None,
|
||||||
collaborators: Default::default(),
|
collaborators: Default::default(),
|
||||||
|
join_project_response_message_id: response.message_id,
|
||||||
_maintain_buffer_languages: Self::maintain_buffer_languages(&languages, cx),
|
_maintain_buffer_languages: Self::maintain_buffer_languages(&languages, cx),
|
||||||
_maintain_workspace_config: Self::maintain_workspace_config(languages.clone(), cx),
|
_maintain_workspace_config: Self::maintain_workspace_config(languages.clone(), cx),
|
||||||
languages,
|
languages,
|
||||||
|
@ -505,6 +508,7 @@ impl Project {
|
||||||
language_servers: Default::default(),
|
language_servers: Default::default(),
|
||||||
language_server_ids: Default::default(),
|
language_server_ids: Default::default(),
|
||||||
language_server_statuses: response
|
language_server_statuses: response
|
||||||
|
.payload
|
||||||
.language_servers
|
.language_servers
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|server| {
|
.map(|server| {
|
||||||
|
@ -537,6 +541,7 @@ impl Project {
|
||||||
let subscription = subscription.set_model(&this, &mut cx);
|
let subscription = subscription.set_model(&this, &mut cx);
|
||||||
|
|
||||||
let user_ids = response
|
let user_ids = response
|
||||||
|
.payload
|
||||||
.collaborators
|
.collaborators
|
||||||
.iter()
|
.iter()
|
||||||
.map(|peer| peer.user_id)
|
.map(|peer| peer.user_id)
|
||||||
|
@ -546,7 +551,7 @@ impl Project {
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
this.update(&mut cx, |this, cx| {
|
this.update(&mut cx, |this, cx| {
|
||||||
this.set_collaborators_from_proto(response.collaborators, cx)?;
|
this.set_collaborators_from_proto(response.payload.collaborators, cx)?;
|
||||||
this.client_subscriptions.push(subscription);
|
this.client_subscriptions.push(subscription);
|
||||||
anyhow::Ok(())
|
anyhow::Ok(())
|
||||||
})?;
|
})?;
|
||||||
|
@ -4930,7 +4935,10 @@ impl Project {
|
||||||
mut cx: AsyncAppContext,
|
mut cx: AsyncAppContext,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
this.update(&mut cx, |this, cx| {
|
this.update(&mut cx, |this, cx| {
|
||||||
this.set_worktrees_from_proto(envelope.payload.worktrees, cx)?;
|
// Don't handle messages that were sent before the response to us joining the project
|
||||||
|
if envelope.message_id > this.join_project_response_message_id {
|
||||||
|
this.set_worktrees_from_proto(envelope.payload.worktrees, cx)?;
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use collections::HashMap;
|
||||||
use futures::{
|
use futures::{
|
||||||
channel::{mpsc, oneshot},
|
channel::{mpsc, oneshot},
|
||||||
stream::BoxStream,
|
stream::BoxStream,
|
||||||
FutureExt, SinkExt, StreamExt,
|
FutureExt, SinkExt, StreamExt, TryFutureExt,
|
||||||
};
|
};
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::{Mutex, RwLock};
|
||||||
use serde::{ser::SerializeStruct, Serialize};
|
use serde::{ser::SerializeStruct, Serialize};
|
||||||
|
@ -71,6 +71,7 @@ impl<T> Clone for Receipt<T> {
|
||||||
|
|
||||||
impl<T> Copy for Receipt<T> {}
|
impl<T> Copy for Receipt<T> {}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
pub struct TypedEnvelope<T> {
|
pub struct TypedEnvelope<T> {
|
||||||
pub sender_id: ConnectionId,
|
pub sender_id: ConnectionId,
|
||||||
pub original_sender_id: Option<PeerId>,
|
pub original_sender_id: Option<PeerId>,
|
||||||
|
@ -370,6 +371,15 @@ impl Peer {
|
||||||
receiver_id: ConnectionId,
|
receiver_id: ConnectionId,
|
||||||
request: T,
|
request: T,
|
||||||
) -> impl Future<Output = Result<T::Response>> {
|
) -> impl Future<Output = Result<T::Response>> {
|
||||||
|
self.request_internal(None, receiver_id, request)
|
||||||
|
.map_ok(|envelope| envelope.payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn request_envelope<T: RequestMessage>(
|
||||||
|
&self,
|
||||||
|
receiver_id: ConnectionId,
|
||||||
|
request: T,
|
||||||
|
) -> impl Future<Output = Result<TypedEnvelope<T::Response>>> {
|
||||||
self.request_internal(None, receiver_id, request)
|
self.request_internal(None, receiver_id, request)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,6 +390,7 @@ impl Peer {
|
||||||
request: T,
|
request: T,
|
||||||
) -> impl Future<Output = Result<T::Response>> {
|
) -> impl Future<Output = Result<T::Response>> {
|
||||||
self.request_internal(Some(sender_id), receiver_id, request)
|
self.request_internal(Some(sender_id), receiver_id, request)
|
||||||
|
.map_ok(|envelope| envelope.payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn request_internal<T: RequestMessage>(
|
pub fn request_internal<T: RequestMessage>(
|
||||||
|
@ -387,7 +398,7 @@ impl Peer {
|
||||||
original_sender_id: Option<ConnectionId>,
|
original_sender_id: Option<ConnectionId>,
|
||||||
receiver_id: ConnectionId,
|
receiver_id: ConnectionId,
|
||||||
request: T,
|
request: T,
|
||||||
) -> impl Future<Output = Result<T::Response>> {
|
) -> impl Future<Output = Result<TypedEnvelope<T::Response>>> {
|
||||||
let (tx, rx) = oneshot::channel();
|
let (tx, rx) = oneshot::channel();
|
||||||
let send = self.connection_state(receiver_id).and_then(|connection| {
|
let send = self.connection_state(receiver_id).and_then(|connection| {
|
||||||
let message_id = connection.next_message_id.fetch_add(1, SeqCst);
|
let message_id = connection.next_message_id.fetch_add(1, SeqCst);
|
||||||
|
@ -410,6 +421,7 @@ impl Peer {
|
||||||
async move {
|
async move {
|
||||||
send?;
|
send?;
|
||||||
let (response, _barrier) = rx.await.map_err(|_| anyhow!("connection was closed"))?;
|
let (response, _barrier) = rx.await.map_err(|_| anyhow!("connection was closed"))?;
|
||||||
|
|
||||||
if let Some(proto::envelope::Payload::Error(error)) = &response.payload {
|
if let Some(proto::envelope::Payload::Error(error)) = &response.payload {
|
||||||
Err(anyhow!(
|
Err(anyhow!(
|
||||||
"RPC request {} failed - {}",
|
"RPC request {} failed - {}",
|
||||||
|
@ -417,8 +429,13 @@ impl Peer {
|
||||||
error.message
|
error.message
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
T::Response::from_envelope(response)
|
Ok(TypedEnvelope {
|
||||||
.ok_or_else(|| anyhow!("received response of the wrong type"))
|
message_id: response.id,
|
||||||
|
sender_id: receiver_id,
|
||||||
|
original_sender_id: response.original_sender_id,
|
||||||
|
payload: T::Response::from_envelope(response)
|
||||||
|
.ok_or_else(|| anyhow!("received response of the wrong type"))?,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue