Add Server::{state,state_mut} to catch most deadlocks statically
This commit is contained in:
+71
-79
@@ -112,12 +112,11 @@ impl Server {
|
|||||||
addr: String,
|
addr: String,
|
||||||
user_id: UserId,
|
user_id: UserId,
|
||||||
) -> impl Future<Output = ()> {
|
) -> impl Future<Output = ()> {
|
||||||
let this = self.clone();
|
let mut this = self.clone();
|
||||||
async move {
|
async move {
|
||||||
let (connection_id, handle_io, mut incoming_rx) =
|
let (connection_id, handle_io, mut incoming_rx) =
|
||||||
this.peer.add_connection(connection).await;
|
this.peer.add_connection(connection).await;
|
||||||
this.store
|
this.state_mut()
|
||||||
.write()
|
|
||||||
.await
|
.await
|
||||||
.add_connection(connection_id, user_id);
|
.add_connection(connection_id, user_id);
|
||||||
if let Err(err) = this.update_collaborators_for_users(&[user_id]).await {
|
if let Err(err) = this.update_collaborators_for_users(&[user_id]).await {
|
||||||
@@ -167,9 +166,9 @@ impl Server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn sign_out(self: &Arc<Self>, connection_id: ConnectionId) -> tide::Result<()> {
|
async fn sign_out(self: &mut Arc<Self>, connection_id: ConnectionId) -> tide::Result<()> {
|
||||||
self.peer.disconnect(connection_id).await;
|
self.peer.disconnect(connection_id).await;
|
||||||
let removed_connection = self.store.write().await.remove_connection(connection_id)?;
|
let removed_connection = self.state_mut().await.remove_connection(connection_id)?;
|
||||||
|
|
||||||
for (worktree_id, worktree) in removed_connection.hosted_worktrees {
|
for (worktree_id, worktree) in removed_connection.hosted_worktrees {
|
||||||
if let Some(share) = worktree.share {
|
if let Some(share) = worktree.share {
|
||||||
@@ -210,13 +209,12 @@ impl Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn open_worktree(
|
async fn open_worktree(
|
||||||
self: Arc<Server>,
|
mut self: Arc<Server>,
|
||||||
request: TypedEnvelope<proto::OpenWorktree>,
|
request: TypedEnvelope<proto::OpenWorktree>,
|
||||||
) -> tide::Result<()> {
|
) -> tide::Result<()> {
|
||||||
let receipt = request.receipt();
|
let receipt = request.receipt();
|
||||||
let host_user_id = self
|
let host_user_id = self
|
||||||
.store
|
.state()
|
||||||
.read()
|
|
||||||
.await
|
.await
|
||||||
.user_id_for_connection(request.sender_id)?;
|
.user_id_for_connection(request.sender_id)?;
|
||||||
|
|
||||||
@@ -238,7 +236,7 @@ impl Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let collaborator_user_ids = collaborator_user_ids.into_iter().collect::<Vec<_>>();
|
let collaborator_user_ids = collaborator_user_ids.into_iter().collect::<Vec<_>>();
|
||||||
let worktree_id = self.store.write().await.add_worktree(Worktree {
|
let worktree_id = self.state_mut().await.add_worktree(Worktree {
|
||||||
host_connection_id: request.sender_id,
|
host_connection_id: request.sender_id,
|
||||||
collaborator_user_ids: collaborator_user_ids.clone(),
|
collaborator_user_ids: collaborator_user_ids.clone(),
|
||||||
root_name: request.payload.root_name,
|
root_name: request.payload.root_name,
|
||||||
@@ -255,13 +253,12 @@ impl Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn close_worktree(
|
async fn close_worktree(
|
||||||
self: Arc<Server>,
|
mut self: Arc<Server>,
|
||||||
request: TypedEnvelope<proto::CloseWorktree>,
|
request: TypedEnvelope<proto::CloseWorktree>,
|
||||||
) -> tide::Result<()> {
|
) -> tide::Result<()> {
|
||||||
let worktree_id = request.payload.worktree_id;
|
let worktree_id = request.payload.worktree_id;
|
||||||
let worktree = self
|
let worktree = self
|
||||||
.store
|
.state_mut()
|
||||||
.write()
|
|
||||||
.await
|
.await
|
||||||
.remove_worktree(worktree_id, request.sender_id)?;
|
.remove_worktree(worktree_id, request.sender_id)?;
|
||||||
|
|
||||||
@@ -282,7 +279,7 @@ impl Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn share_worktree(
|
async fn share_worktree(
|
||||||
self: Arc<Server>,
|
mut self: Arc<Server>,
|
||||||
mut request: TypedEnvelope<proto::ShareWorktree>,
|
mut request: TypedEnvelope<proto::ShareWorktree>,
|
||||||
) -> tide::Result<()> {
|
) -> tide::Result<()> {
|
||||||
let worktree = request
|
let worktree = request
|
||||||
@@ -296,8 +293,7 @@ impl Server {
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let collaborator_user_ids =
|
let collaborator_user_ids =
|
||||||
self.store
|
self.state_mut()
|
||||||
.write()
|
|
||||||
.await
|
.await
|
||||||
.share_worktree(worktree.id, request.sender_id, entries);
|
.share_worktree(worktree.id, request.sender_id, entries);
|
||||||
if let Some(collaborator_user_ids) = collaborator_user_ids {
|
if let Some(collaborator_user_ids) = collaborator_user_ids {
|
||||||
@@ -320,13 +316,12 @@ impl Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn unshare_worktree(
|
async fn unshare_worktree(
|
||||||
self: Arc<Server>,
|
mut self: Arc<Server>,
|
||||||
request: TypedEnvelope<proto::UnshareWorktree>,
|
request: TypedEnvelope<proto::UnshareWorktree>,
|
||||||
) -> tide::Result<()> {
|
) -> tide::Result<()> {
|
||||||
let worktree_id = request.payload.worktree_id;
|
let worktree_id = request.payload.worktree_id;
|
||||||
let worktree = self
|
let worktree = self
|
||||||
.store
|
.state_mut()
|
||||||
.write()
|
|
||||||
.await
|
.await
|
||||||
.unshare_worktree(worktree_id, request.sender_id)?;
|
.unshare_worktree(worktree_id, request.sender_id)?;
|
||||||
|
|
||||||
@@ -342,20 +337,16 @@ impl Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn join_worktree(
|
async fn join_worktree(
|
||||||
self: Arc<Server>,
|
mut self: Arc<Server>,
|
||||||
request: TypedEnvelope<proto::JoinWorktree>,
|
request: TypedEnvelope<proto::JoinWorktree>,
|
||||||
) -> tide::Result<()> {
|
) -> tide::Result<()> {
|
||||||
let worktree_id = request.payload.worktree_id;
|
let worktree_id = request.payload.worktree_id;
|
||||||
let user_id = self
|
let user_id = self
|
||||||
.store
|
.state()
|
||||||
.read()
|
|
||||||
.await
|
.await
|
||||||
.user_id_for_connection(request.sender_id)?;
|
.user_id_for_connection(request.sender_id)?;
|
||||||
|
|
||||||
let response;
|
let mut state = self.state_mut().await;
|
||||||
let connection_ids;
|
|
||||||
let collaborator_user_ids;
|
|
||||||
let mut state = self.store.write().await;
|
|
||||||
match state.join_worktree(request.sender_id, user_id, worktree_id) {
|
match state.join_worktree(request.sender_id, user_id, worktree_id) {
|
||||||
Ok(JoinedWorktree {
|
Ok(JoinedWorktree {
|
||||||
replica_id,
|
replica_id,
|
||||||
@@ -376,7 +367,7 @@ impl Server {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
response = proto::JoinWorktreeResponse {
|
let response = proto::JoinWorktreeResponse {
|
||||||
worktree: Some(proto::Worktree {
|
worktree: Some(proto::Worktree {
|
||||||
id: worktree_id,
|
id: worktree_id,
|
||||||
root_name: worktree.root_name.clone(),
|
root_name: worktree.root_name.clone(),
|
||||||
@@ -385,10 +376,29 @@ impl Server {
|
|||||||
replica_id: replica_id as u32,
|
replica_id: replica_id as u32,
|
||||||
peers,
|
peers,
|
||||||
};
|
};
|
||||||
connection_ids = worktree.connection_ids();
|
let connection_ids = worktree.connection_ids();
|
||||||
collaborator_user_ids = worktree.collaborator_user_ids.clone();
|
let collaborator_user_ids = worktree.collaborator_user_ids.clone();
|
||||||
|
drop(state);
|
||||||
|
|
||||||
|
broadcast(request.sender_id, connection_ids, |conn_id| {
|
||||||
|
self.peer.send(
|
||||||
|
conn_id,
|
||||||
|
proto::AddPeer {
|
||||||
|
worktree_id,
|
||||||
|
peer: Some(proto::Peer {
|
||||||
|
peer_id: request.sender_id.0,
|
||||||
|
replica_id: response.replica_id,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
self.peer.respond(request.receipt(), response).await?;
|
||||||
|
self.update_collaborators_for_users(&collaborator_user_ids)
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
|
drop(state);
|
||||||
self.peer
|
self.peer
|
||||||
.respond_with_error(
|
.respond_with_error(
|
||||||
request.receipt(),
|
request.receipt(),
|
||||||
@@ -397,44 +407,23 @@ impl Server {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
return Ok(());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
drop(state);
|
|
||||||
broadcast(request.sender_id, connection_ids, |conn_id| {
|
|
||||||
self.peer.send(
|
|
||||||
conn_id,
|
|
||||||
proto::AddPeer {
|
|
||||||
worktree_id,
|
|
||||||
peer: Some(proto::Peer {
|
|
||||||
peer_id: request.sender_id.0,
|
|
||||||
replica_id: response.replica_id,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
self.peer.respond(request.receipt(), response).await?;
|
|
||||||
self.update_collaborators_for_users(&collaborator_user_ids)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn leave_worktree(
|
async fn leave_worktree(
|
||||||
self: Arc<Server>,
|
mut self: Arc<Server>,
|
||||||
request: TypedEnvelope<proto::LeaveWorktree>,
|
request: TypedEnvelope<proto::LeaveWorktree>,
|
||||||
) -> tide::Result<()> {
|
) -> tide::Result<()> {
|
||||||
let sender_id = request.sender_id;
|
let sender_id = request.sender_id;
|
||||||
let worktree_id = request.payload.worktree_id;
|
let worktree_id = request.payload.worktree_id;
|
||||||
|
let worktree = self
|
||||||
if let Some(worktree) = self
|
.state_mut()
|
||||||
.store
|
|
||||||
.write()
|
|
||||||
.await
|
.await
|
||||||
.leave_worktree(sender_id, worktree_id)
|
.leave_worktree(sender_id, worktree_id);
|
||||||
{
|
if let Some(worktree) = worktree {
|
||||||
broadcast(sender_id, worktree.connection_ids, |conn_id| {
|
broadcast(sender_id, worktree.connection_ids, |conn_id| {
|
||||||
self.peer.send(
|
self.peer.send(
|
||||||
conn_id,
|
conn_id,
|
||||||
@@ -452,10 +441,10 @@ impl Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn update_worktree(
|
async fn update_worktree(
|
||||||
self: Arc<Server>,
|
mut self: Arc<Server>,
|
||||||
request: TypedEnvelope<proto::UpdateWorktree>,
|
request: TypedEnvelope<proto::UpdateWorktree>,
|
||||||
) -> tide::Result<()> {
|
) -> tide::Result<()> {
|
||||||
let connection_ids = self.store.write().await.update_worktree(
|
let connection_ids = self.state_mut().await.update_worktree(
|
||||||
request.sender_id,
|
request.sender_id,
|
||||||
request.payload.worktree_id,
|
request.payload.worktree_id,
|
||||||
&request.payload.removed_entries,
|
&request.payload.removed_entries,
|
||||||
@@ -477,8 +466,7 @@ impl Server {
|
|||||||
) -> tide::Result<()> {
|
) -> tide::Result<()> {
|
||||||
let receipt = request.receipt();
|
let receipt = request.receipt();
|
||||||
let host_connection_id = self
|
let host_connection_id = self
|
||||||
.store
|
.state()
|
||||||
.read()
|
|
||||||
.await
|
.await
|
||||||
.worktree_host_connection_id(request.sender_id, request.payload.worktree_id)?;
|
.worktree_host_connection_id(request.sender_id, request.payload.worktree_id)?;
|
||||||
let response = self
|
let response = self
|
||||||
@@ -494,8 +482,7 @@ impl Server {
|
|||||||
request: TypedEnvelope<proto::CloseBuffer>,
|
request: TypedEnvelope<proto::CloseBuffer>,
|
||||||
) -> tide::Result<()> {
|
) -> tide::Result<()> {
|
||||||
let host_connection_id = self
|
let host_connection_id = self
|
||||||
.store
|
.state()
|
||||||
.read()
|
|
||||||
.await
|
.await
|
||||||
.worktree_host_connection_id(request.sender_id, request.payload.worktree_id)?;
|
.worktree_host_connection_id(request.sender_id, request.payload.worktree_id)?;
|
||||||
self.peer
|
self.peer
|
||||||
@@ -511,7 +498,7 @@ impl Server {
|
|||||||
let host;
|
let host;
|
||||||
let guests;
|
let guests;
|
||||||
{
|
{
|
||||||
let state = self.store.read().await;
|
let state = self.state().await;
|
||||||
host = state
|
host = state
|
||||||
.worktree_host_connection_id(request.sender_id, request.payload.worktree_id)?;
|
.worktree_host_connection_id(request.sender_id, request.payload.worktree_id)?;
|
||||||
guests = state
|
guests = state
|
||||||
@@ -547,8 +534,7 @@ impl Server {
|
|||||||
) -> tide::Result<()> {
|
) -> tide::Result<()> {
|
||||||
broadcast(
|
broadcast(
|
||||||
request.sender_id,
|
request.sender_id,
|
||||||
self.store
|
self.state()
|
||||||
.read()
|
|
||||||
.await
|
.await
|
||||||
.worktree_connection_ids(request.sender_id, request.payload.worktree_id)?,
|
.worktree_connection_ids(request.sender_id, request.payload.worktree_id)?,
|
||||||
|connection_id| {
|
|connection_id| {
|
||||||
@@ -585,8 +571,7 @@ impl Server {
|
|||||||
request: TypedEnvelope<proto::GetChannels>,
|
request: TypedEnvelope<proto::GetChannels>,
|
||||||
) -> tide::Result<()> {
|
) -> tide::Result<()> {
|
||||||
let user_id = self
|
let user_id = self
|
||||||
.store
|
.state()
|
||||||
.read()
|
|
||||||
.await
|
.await
|
||||||
.user_id_for_connection(request.sender_id)?;
|
.user_id_for_connection(request.sender_id)?;
|
||||||
let channels = self.app_state.db.get_accessible_channels(user_id).await?;
|
let channels = self.app_state.db.get_accessible_channels(user_id).await?;
|
||||||
@@ -637,7 +622,7 @@ impl Server {
|
|||||||
) -> tide::Result<()> {
|
) -> tide::Result<()> {
|
||||||
let mut send_futures = Vec::new();
|
let mut send_futures = Vec::new();
|
||||||
|
|
||||||
let state = self.store.read().await;
|
let state = self.state().await;
|
||||||
for user_id in user_ids {
|
for user_id in user_ids {
|
||||||
let collaborators = state.collaborators_for_user(*user_id);
|
let collaborators = state.collaborators_for_user(*user_id);
|
||||||
for connection_id in state.connection_ids_for_user(*user_id) {
|
for connection_id in state.connection_ids_for_user(*user_id) {
|
||||||
@@ -657,12 +642,11 @@ impl Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn join_channel(
|
async fn join_channel(
|
||||||
self: Arc<Self>,
|
mut self: Arc<Self>,
|
||||||
request: TypedEnvelope<proto::JoinChannel>,
|
request: TypedEnvelope<proto::JoinChannel>,
|
||||||
) -> tide::Result<()> {
|
) -> tide::Result<()> {
|
||||||
let user_id = self
|
let user_id = self
|
||||||
.store
|
.state()
|
||||||
.read()
|
|
||||||
.await
|
.await
|
||||||
.user_id_for_connection(request.sender_id)?;
|
.user_id_for_connection(request.sender_id)?;
|
||||||
let channel_id = ChannelId::from_proto(request.payload.channel_id);
|
let channel_id = ChannelId::from_proto(request.payload.channel_id);
|
||||||
@@ -675,8 +659,7 @@ impl Server {
|
|||||||
Err(anyhow!("access denied"))?;
|
Err(anyhow!("access denied"))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.store
|
self.state_mut()
|
||||||
.write()
|
|
||||||
.await
|
.await
|
||||||
.join_channel(request.sender_id, channel_id);
|
.join_channel(request.sender_id, channel_id);
|
||||||
let messages = self
|
let messages = self
|
||||||
@@ -706,12 +689,11 @@ impl Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn leave_channel(
|
async fn leave_channel(
|
||||||
self: Arc<Self>,
|
mut self: Arc<Self>,
|
||||||
request: TypedEnvelope<proto::LeaveChannel>,
|
request: TypedEnvelope<proto::LeaveChannel>,
|
||||||
) -> tide::Result<()> {
|
) -> tide::Result<()> {
|
||||||
let user_id = self
|
let user_id = self
|
||||||
.store
|
.state()
|
||||||
.read()
|
|
||||||
.await
|
.await
|
||||||
.user_id_for_connection(request.sender_id)?;
|
.user_id_for_connection(request.sender_id)?;
|
||||||
let channel_id = ChannelId::from_proto(request.payload.channel_id);
|
let channel_id = ChannelId::from_proto(request.payload.channel_id);
|
||||||
@@ -724,8 +706,7 @@ impl Server {
|
|||||||
Err(anyhow!("access denied"))?;
|
Err(anyhow!("access denied"))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.store
|
self.state_mut()
|
||||||
.write()
|
|
||||||
.await
|
.await
|
||||||
.leave_channel(request.sender_id, channel_id);
|
.leave_channel(request.sender_id, channel_id);
|
||||||
|
|
||||||
@@ -741,7 +722,7 @@ impl Server {
|
|||||||
let user_id;
|
let user_id;
|
||||||
let connection_ids;
|
let connection_ids;
|
||||||
{
|
{
|
||||||
let state = self.store.read().await;
|
let state = self.state().await;
|
||||||
user_id = state.user_id_for_connection(request.sender_id)?;
|
user_id = state.user_id_for_connection(request.sender_id)?;
|
||||||
if let Some(ids) = state.channel_connection_ids(channel_id) {
|
if let Some(ids) = state.channel_connection_ids(channel_id) {
|
||||||
connection_ids = ids;
|
connection_ids = ids;
|
||||||
@@ -829,8 +810,7 @@ impl Server {
|
|||||||
request: TypedEnvelope<proto::GetChannelMessages>,
|
request: TypedEnvelope<proto::GetChannelMessages>,
|
||||||
) -> tide::Result<()> {
|
) -> tide::Result<()> {
|
||||||
let user_id = self
|
let user_id = self
|
||||||
.store
|
.state()
|
||||||
.read()
|
|
||||||
.await
|
.await
|
||||||
.user_id_for_connection(request.sender_id)?;
|
.user_id_for_connection(request.sender_id)?;
|
||||||
let channel_id = ChannelId::from_proto(request.payload.channel_id);
|
let channel_id = ChannelId::from_proto(request.payload.channel_id);
|
||||||
@@ -872,6 +852,18 @@ impl Server {
|
|||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn state<'a>(
|
||||||
|
self: &'a Arc<Self>,
|
||||||
|
) -> impl Future<Output = async_std::sync::RwLockReadGuard<'a, Store>> {
|
||||||
|
self.store.read()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn state_mut<'a>(
|
||||||
|
self: &'a mut Arc<Self>,
|
||||||
|
) -> impl Future<Output = async_std::sync::RwLockWriteGuard<'a, Store>> {
|
||||||
|
self.store.write()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn broadcast<F, T>(
|
pub async fn broadcast<F, T>(
|
||||||
|
|||||||
Reference in New Issue
Block a user