Merge branch 'gpui2' into marshall/gpui2-playground

Marshall Bowers created

Change summary

Cargo.lock                                  |  2 
crates/client/src/telemetry.rs              | 45 ++++++++-------
crates/collab/Cargo.toml                    |  2 
crates/collab/src/db/queries/messages.rs    |  3 
crates/collab/src/db/tests/message_tests.rs | 67 ++++++++++++++++++++++
crates/zed/src/main.rs                      | 11 ++-
6 files changed, 101 insertions(+), 29 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -1497,7 +1497,7 @@ dependencies = [
 
 [[package]]
 name = "collab"
-version = "0.23.2"
+version = "0.23.3"
 dependencies = [
  "anyhow",
  "async-trait",

crates/client/src/telemetry.rs 🔗

@@ -8,7 +8,6 @@ use sysinfo::{Pid, PidExt, ProcessExt, System, SystemExt};
 use tempfile::NamedTempFile;
 use util::http::HttpClient;
 use util::{channel::ReleaseChannel, TryFutureExt};
-use uuid::Uuid;
 
 pub struct Telemetry {
     http_client: Arc<dyn HttpClient>,
@@ -20,7 +19,7 @@ pub struct Telemetry {
 struct TelemetryState {
     metrics_id: Option<Arc<str>>,      // Per logged-in user
     installation_id: Option<Arc<str>>, // Per app installation (different for dev, preview, and stable)
-    session_id: String,                // Per app launch
+    session_id: Option<Arc<str>>,      // Per app launch
     app_version: Option<Arc<str>>,
     release_channel: Option<&'static str>,
     os_name: &'static str,
@@ -43,7 +42,7 @@ lazy_static! {
 struct ClickhouseEventRequestBody {
     token: &'static str,
     installation_id: Option<Arc<str>>,
-    session_id: String,
+    session_id: Option<Arc<str>>,
     is_staff: Option<bool>,
     app_version: Option<Arc<str>>,
     os_name: &'static str,
@@ -134,7 +133,7 @@ impl Telemetry {
                 release_channel,
                 installation_id: None,
                 metrics_id: None,
-                session_id: Uuid::new_v4().to_string(),
+                session_id: None,
                 clickhouse_events_queue: Default::default(),
                 flush_clickhouse_events_task: Default::default(),
                 log_file: None,
@@ -149,9 +148,15 @@ impl Telemetry {
         Some(self.state.lock().log_file.as_ref()?.path().to_path_buf())
     }
 
-    pub fn start(self: &Arc<Self>, installation_id: Option<String>, cx: &mut AppContext) {
+    pub fn start(
+        self: &Arc<Self>,
+        installation_id: Option<String>,
+        session_id: String,
+        cx: &mut AppContext,
+    ) {
         let mut state = self.state.lock();
         state.installation_id = installation_id.map(|id| id.into());
+        state.session_id = Some(session_id.into());
         let has_clickhouse_events = !state.clickhouse_events_queue.is_empty();
         drop(state);
 
@@ -283,23 +288,21 @@ impl Telemetry {
 
                     {
                         let state = this.state.lock();
+                        let request_body = ClickhouseEventRequestBody {
+                            token: ZED_SECRET_CLIENT_TOKEN,
+                            installation_id: state.installation_id.clone(),
+                            session_id: state.session_id.clone(),
+                            is_staff: state.is_staff.clone(),
+                            app_version: state.app_version.clone(),
+                            os_name: state.os_name,
+                            os_version: state.os_version.clone(),
+                            architecture: state.architecture,
+
+                            release_channel: state.release_channel,
+                            events,
+                        };
                         json_bytes.clear();
-                        serde_json::to_writer(
-                            &mut json_bytes,
-                            &ClickhouseEventRequestBody {
-                                token: ZED_SECRET_CLIENT_TOKEN,
-                                installation_id: state.installation_id.clone(),
-                                session_id: state.session_id.clone(),
-                                is_staff: state.is_staff.clone(),
-                                app_version: state.app_version.clone(),
-                                os_name: state.os_name,
-                                os_version: state.os_version.clone(),
-                                architecture: state.architecture,
-
-                                release_channel: state.release_channel,
-                                events,
-                            },
-                        )?;
+                        serde_json::to_writer(&mut json_bytes, &request_body)?;
                     }
 
                     this.http_client

crates/collab/Cargo.toml 🔗

@@ -3,7 +3,7 @@ authors = ["Nathan Sobo <nathan@zed.dev>"]
 default-run = "collab"
 edition = "2021"
 name = "collab"
-version = "0.23.2"
+version = "0.23.3"
 publish = false
 
 [[bin]]

crates/collab/src/db/queries/messages.rs 🔗

@@ -89,7 +89,7 @@ impl Database {
 
             let mut rows = channel_message::Entity::find()
                 .filter(condition)
-                .order_by_asc(channel_message::Column::Id)
+                .order_by_desc(channel_message::Column::Id)
                 .limit(count as u64)
                 .stream(&*tx)
                 .await?;
@@ -110,6 +110,7 @@ impl Database {
                 });
             }
             drop(rows);
+            messages.reverse();
             Ok(messages)
         })
         .await

crates/collab/src/db/tests/message_tests.rs 🔗

@@ -1,10 +1,75 @@
 use crate::{
-    db::{Database, NewUserParams},
+    db::{Database, MessageId, NewUserParams},
     test_both_dbs,
 };
 use std::sync::Arc;
 use time::OffsetDateTime;
 
+test_both_dbs!(
+    test_channel_message_retrieval,
+    test_channel_message_retrieval_postgres,
+    test_channel_message_retrieval_sqlite
+);
+
+async fn test_channel_message_retrieval(db: &Arc<Database>) {
+    let user = db
+        .create_user(
+            "user@example.com",
+            false,
+            NewUserParams {
+                github_login: "user".into(),
+                github_user_id: 1,
+                invite_count: 0,
+            },
+        )
+        .await
+        .unwrap()
+        .user_id;
+    let channel = db
+        .create_channel("channel", None, "room", user)
+        .await
+        .unwrap();
+
+    let owner_id = db.create_server("test").await.unwrap().0 as u32;
+    db.join_channel_chat(channel, rpc::ConnectionId { owner_id, id: 0 }, user)
+        .await
+        .unwrap();
+
+    let mut all_messages = Vec::new();
+    for i in 0..10 {
+        all_messages.push(
+            db.create_channel_message(channel, user, &i.to_string(), OffsetDateTime::now_utc(), i)
+                .await
+                .unwrap()
+                .0
+                .to_proto(),
+        );
+    }
+
+    let messages = db
+        .get_channel_messages(channel, user, 3, None)
+        .await
+        .unwrap()
+        .into_iter()
+        .map(|message| message.id)
+        .collect::<Vec<_>>();
+    assert_eq!(messages, &all_messages[7..10]);
+
+    let messages = db
+        .get_channel_messages(
+            channel,
+            user,
+            4,
+            Some(MessageId::from_proto(all_messages[6])),
+        )
+        .await
+        .unwrap()
+        .into_iter()
+        .map(|message| message.id)
+        .collect::<Vec<_>>();
+    assert_eq!(messages, &all_messages[2..6]);
+}
+
 test_both_dbs!(
     test_channel_message_nonces,
     test_channel_message_nonces_postgres,

crates/zed/src/main.rs 🔗

@@ -74,7 +74,8 @@ fn main() {
     let mut app = gpui::App::new(Assets).unwrap();
 
     let installation_id = app.background().block(installation_id()).ok();
-    init_panic_hook(&app, installation_id.clone());
+    let session_id = Uuid::new_v4().to_string();
+    init_panic_hook(&app, installation_id.clone(), session_id.clone());
 
     load_embedded_fonts(&app);
 
@@ -177,7 +178,7 @@ fn main() {
         })
         .detach();
 
-        client.telemetry().start(installation_id, cx);
+        client.telemetry().start(installation_id, session_id, cx);
 
         let app_state = Arc::new(AppState {
             languages,
@@ -402,6 +403,7 @@ struct Panic {
     panicked_on: u128,
     #[serde(skip_serializing_if = "Option::is_none")]
     installation_id: Option<String>,
+    session_id: String,
 }
 
 #[derive(Serialize)]
@@ -412,7 +414,7 @@ struct PanicRequest {
 
 static PANIC_COUNT: AtomicU32 = AtomicU32::new(0);
 
-fn init_panic_hook(app: &App, installation_id: Option<String>) {
+fn init_panic_hook(app: &App, installation_id: Option<String>, session_id: String) {
     let is_pty = stdout_is_a_pty();
     let platform = app.platform();
 
@@ -477,7 +479,7 @@ fn init_panic_hook(app: &App, installation_id: Option<String>) {
                 line: location.line(),
             }),
             app_version: app_version.clone(),
-            release_channel: RELEASE_CHANNEL.dev_name().into(),
+            release_channel: RELEASE_CHANNEL.display_name().into(),
             os_name: platform.os_name().into(),
             os_version: platform
                 .os_version()
@@ -490,6 +492,7 @@ fn init_panic_hook(app: &App, installation_id: Option<String>) {
                 .as_millis(),
             backtrace,
             installation_id: installation_id.clone(),
+            session_id: session_id.clone(),
         };
 
         if is_pty {