Make RPC client's current user_id observable

Nathan Sobo and Antonio Scandurra created

Co-Authored-By: Antonio Scandurra <me@as-cii.com>

Change summary

zed/src/channel.rs |  9 +++++++--
zed/src/rpc.rs     | 21 ++++++++++++++++-----
2 files changed, 23 insertions(+), 7 deletions(-)

Detailed changes

zed/src/channel.rs 🔗

@@ -206,7 +206,8 @@ impl Channel {
                     }
                 });
                 Ok(())
-            }.log_err()
+            }
+            .log_err()
         })
         .detach();
         cx.notify();
@@ -222,7 +223,11 @@ impl Channel {
     }
 
     fn current_user_id(&self) -> Result<u64> {
-        self.rpc.user_id().ok_or_else(|| anyhow!("not logged in"))
+        self
+            .rpc
+            .user_id()
+            .borrow()
+            .ok_or_else(|| anyhow!("not logged in"))
     }
 
     fn handle_message_sent(

zed/src/rpc.rs 🔗

@@ -5,6 +5,7 @@ use gpui::{AsyncAppContext, Entity, ModelContext, Task};
 use lazy_static::lazy_static;
 use parking_lot::RwLock;
 use postage::prelude::Stream;
+use postage::watch;
 use std::any::TypeId;
 use std::collections::HashMap;
 use std::sync::Weak;
@@ -28,10 +29,9 @@ pub struct Client {
     state: RwLock<ClientState>,
 }
 
-#[derive(Default)]
 struct ClientState {
     connection_id: Option<ConnectionId>,
-    user_id: Option<u64>,
+    user_id: (watch::Sender<Option<u64>>, watch::Receiver<Option<u64>>),
     entity_id_extractors: HashMap<TypeId, Box<dyn Send + Sync + Fn(&dyn AnyTypedEnvelope) -> u64>>,
     model_handlers: HashMap<
         (TypeId, u64),
@@ -39,6 +39,17 @@ struct ClientState {
     >,
 }
 
+impl Default for ClientState {
+    fn default() -> Self {
+        Self {
+            connection_id: Default::default(),
+            user_id: watch::channel(),
+            entity_id_extractors: Default::default(),
+            model_handlers: Default::default(),
+        }
+    }
+}
+
 pub struct Subscription {
     client: Weak<Client>,
     id: (TypeId, u64),
@@ -67,8 +78,8 @@ impl Client {
         })
     }
 
-    pub fn user_id(&self) -> Option<u64> {
-        self.state.read().user_id
+    pub fn user_id(&self) -> watch::Receiver<Option<u64>> {
+        self.state.read().user_id.1.clone()
     }
 
     pub fn subscribe_from_model<T, M, F>(
@@ -214,7 +225,7 @@ impl Client {
             .detach();
         let mut state = self.state.write();
         state.connection_id = Some(connection_id);
-        state.user_id = Some(user_id);
+        state.user_id = watch::channel_with(Some(user_id));
         Ok(())
     }