Hold client weakly in UserStore

This avoids a reference cycle that is causing some tests
to fail due to leaked handles at the moment. There may be
a better way to fix this though.
This commit is contained in:
Max Brunsfeld 2022-02-28 22:47:50 -08:00
parent 1faaa91e52
commit 02ae2d8a4f

View file

@ -8,7 +8,7 @@ use gpui::{AsyncAppContext, Entity, ImageData, ModelContext, ModelHandle, Task};
use postage::{prelude::Stream, sink::Sink, watch}; use postage::{prelude::Stream, sink::Sink, watch};
use std::{ use std::{
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
sync::Arc, sync::{Arc, Weak},
}; };
use util::TryFutureExt as _; use util::TryFutureExt as _;
@ -38,7 +38,7 @@ pub struct UserStore {
update_contacts_tx: watch::Sender<Option<proto::UpdateContacts>>, update_contacts_tx: watch::Sender<Option<proto::UpdateContacts>>,
current_user: watch::Receiver<Option<Arc<User>>>, current_user: watch::Receiver<Option<Arc<User>>>,
contacts: Arc<[Contact]>, contacts: Arc<[Contact]>,
client: Arc<Client>, client: Weak<Client>,
http: Arc<dyn HttpClient>, http: Arc<dyn HttpClient>,
_maintain_contacts: Task<()>, _maintain_contacts: Task<()>,
_maintain_current_user: Task<()>, _maintain_current_user: Task<()>,
@ -65,7 +65,7 @@ impl UserStore {
users: Default::default(), users: Default::default(),
current_user: current_user_rx, current_user: current_user_rx,
contacts: Arc::from([]), contacts: Arc::from([]),
client: client.clone(), client: Arc::downgrade(&client),
update_contacts_tx, update_contacts_tx,
http, http,
_maintain_contacts: cx.spawn_weak(|this, mut cx| async move { _maintain_contacts: cx.spawn_weak(|this, mut cx| async move {
@ -156,25 +156,26 @@ impl UserStore {
let http = self.http.clone(); let http = self.http.clone();
user_ids.retain(|id| !self.users.contains_key(id)); user_ids.retain(|id| !self.users.contains_key(id));
cx.spawn_weak(|this, mut cx| async move { cx.spawn_weak(|this, mut cx| async move {
if !user_ids.is_empty() { if let Some(rpc) = rpc.upgrade() {
let response = rpc.request(proto::GetUsers { user_ids }).await?; if !user_ids.is_empty() {
let new_users = future::join_all( let response = rpc.request(proto::GetUsers { user_ids }).await?;
response let new_users = future::join_all(
.users response
.into_iter() .users
.map(|user| User::new(user, http.as_ref())), .into_iter()
) .map(|user| User::new(user, http.as_ref())),
.await; )
.await;
if let Some(this) = this.upgrade(&cx) { if let Some(this) = this.upgrade(&cx) {
this.update(&mut cx, |this, _| { this.update(&mut cx, |this, _| {
for user in new_users { for user in new_users {
this.users.insert(user.id, Arc::new(user)); this.users.insert(user.id, Arc::new(user));
} }
}); });
}
} }
} }
Ok(()) Ok(())
}) })
} }