From 1d10e4528221cffe1cac891b0cf2118c0a70a509 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 28 Jun 2022 15:37:56 -0700 Subject: [PATCH] :art: Tweak some names dealing with user activity * Rename `project_activity_summary` to `top_users_activity_summary` to make clearer the distinction between it and the per-user summary. * Rename `user_activity_summary` to `user_activity_timeline`, since its output is structured a bit differently than the courser-grained "summary" returned by the top-user query. * Rename `ActivityDuration` -> `ActivityPeriod` --- crates/collab/src/api.rs | 12 ++--- crates/collab/src/db.rs | 95 ++++++++++++++++++++++------------------ crates/collab/src/rpc.rs | 2 +- 3 files changed, 60 insertions(+), 49 deletions(-) diff --git a/crates/collab/src/api.rs b/crates/collab/src/api.rs index 0c91a5a079..4fa4781160 100644 --- a/crates/collab/src/api.rs +++ b/crates/collab/src/api.rs @@ -36,8 +36,8 @@ pub fn routes(rpc_server: &Arc, state: Arc) -> Router, +async fn get_top_users_activity_summary( + Query(params): Query, Extension(app): Extension>, ) -> Result { let summary = app .db - .summarize_project_activity(params.start..params.end, 100) + .get_top_users_activity_summary(params.start..params.end, 100) .await?; Ok(ErasedJson::pretty(summary)) } diff --git a/crates/collab/src/db.rs b/crates/collab/src/db.rs index 9429a3ad1d..5268f7f54f 100644 --- a/crates/collab/src/db.rs +++ b/crates/collab/src/db.rs @@ -7,7 +7,7 @@ use axum::http::StatusCode; use collections::HashMap; use futures::StreamExt; use nanoid::nanoid; -use serde::Serialize; +use serde::{Deserialize, Serialize}; pub use sqlx::postgres::PgPoolOptions as DbOptions; use sqlx::{types::Uuid, FromRow, QueryBuilder, Row}; use time::{OffsetDateTime, PrimitiveDateTime}; @@ -63,7 +63,7 @@ pub trait Db: Send + Sync { /// Record which users have been active in which projects during /// a given period of time. - async fn record_project_activity( + async fn record_user_activity( &self, time_period: Range, active_projects: &[(UserId, ProjectId)], @@ -71,18 +71,18 @@ pub trait Db: Send + Sync { /// Get the users that have been most active during the given time period, /// along with the amount of time they have been active in each project. - async fn summarize_project_activity( + async fn get_top_users_activity_summary( &self, time_period: Range, max_user_count: usize, ) -> Result>; /// Get the project activity for the given user and time period. - async fn summarize_user_activity( + async fn get_user_activity_timeline( &self, - user_id: UserId, time_period: Range, - ) -> Result>; + user_id: UserId, + ) -> Result>; async fn get_contacts(&self, id: UserId) -> Result>; async fn has_contact(&self, user_id_a: UserId, user_id_b: UserId) -> Result; @@ -564,7 +564,7 @@ impl Db for PostgresDb { Ok(extension_counts) } - async fn record_project_activity( + async fn record_user_activity( &self, time_period: Range, projects: &[(UserId, ProjectId)], @@ -593,7 +593,7 @@ impl Db for PostgresDb { Ok(()) } - async fn summarize_project_activity( + async fn get_top_users_activity_summary( &self, time_period: Range, max_user_count: usize, @@ -648,11 +648,11 @@ impl Db for PostgresDb { Ok(result) } - async fn summarize_user_activity( + async fn get_user_activity_timeline( &self, - user_id: UserId, time_period: Range, - ) -> Result> { + user_id: UserId, + ) -> Result> { const COALESCE_THRESHOLD: Duration = Duration::from_secs(5); let query = " @@ -689,19 +689,19 @@ impl Db for PostgresDb { .bind(time_period.end) .fetch(&self.pool); - let mut durations: HashMap> = Default::default(); + let mut time_periods: HashMap> = Default::default(); while let Some(row) = rows.next().await { let (ended_at, duration_millis, project_id, extension, extension_count) = row?; let ended_at = ended_at.assume_utc(); let duration = Duration::from_millis(duration_millis as u64); let started_at = ended_at - duration; - let project_durations = durations.entry(project_id).or_default(); + let project_time_periods = time_periods.entry(project_id).or_default(); - if let Some(prev_duration) = project_durations.last_mut() { + if let Some(prev_duration) = project_time_periods.last_mut() { if started_at - prev_duration.end <= COALESCE_THRESHOLD { prev_duration.end = ended_at; } else { - project_durations.push(UserActivityDuration { + project_time_periods.push(UserActivityPeriod { project_id, start: started_at, end: ended_at, @@ -709,7 +709,7 @@ impl Db for PostgresDb { }); } } else { - project_durations.push(UserActivityDuration { + project_time_periods.push(UserActivityPeriod { project_id, start: started_at, end: ended_at, @@ -718,7 +718,7 @@ impl Db for PostgresDb { } if let Some((extension, extension_count)) = extension.zip(extension_count) { - project_durations + project_time_periods .last_mut() .unwrap() .extensions @@ -726,7 +726,7 @@ impl Db for PostgresDb { } } - let mut durations = durations.into_values().flatten().collect::>(); + let mut durations = time_periods.into_values().flatten().collect::>(); durations.sort_unstable_by_key(|duration| duration.start); Ok(durations) } @@ -1206,7 +1206,18 @@ impl Db for PostgresDb { macro_rules! id_type { ($name:ident) => { #[derive( - Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, sqlx::Type, Serialize, + Clone, + Copy, + Debug, + Default, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + sqlx::Type, + Serialize, + Deserialize, )] #[sqlx(transparent)] #[serde(transparent)] @@ -1263,7 +1274,7 @@ pub struct UserActivitySummary { } #[derive(Clone, Debug, PartialEq, Serialize)] -pub struct UserActivityDuration { +pub struct UserActivityPeriod { project_id: ProjectId, start: OffsetDateTime, end: OffsetDateTime, @@ -1549,24 +1560,24 @@ pub mod tests { // User 2 opens a project let t1 = t0 + Duration::from_secs(10); - db.record_project_activity(t0..t1, &[(user_2, project_2)]) + db.record_user_activity(t0..t1, &[(user_2, project_2)]) .await .unwrap(); let t2 = t1 + Duration::from_secs(10); - db.record_project_activity(t1..t2, &[(user_2, project_2)]) + db.record_user_activity(t1..t2, &[(user_2, project_2)]) .await .unwrap(); // User 1 joins the project let t3 = t2 + Duration::from_secs(10); - db.record_project_activity(t2..t3, &[(user_2, project_2), (user_1, project_2)]) + db.record_user_activity(t2..t3, &[(user_2, project_2), (user_1, project_2)]) .await .unwrap(); // User 1 opens another project let t4 = t3 + Duration::from_secs(10); - db.record_project_activity( + db.record_user_activity( t3..t4, &[ (user_2, project_2), @@ -1579,7 +1590,7 @@ pub mod tests { // User 3 joins that project let t5 = t4 + Duration::from_secs(10); - db.record_project_activity( + db.record_user_activity( t4..t5, &[ (user_2, project_2), @@ -1593,18 +1604,18 @@ pub mod tests { // User 2 leaves let t6 = t5 + Duration::from_secs(5); - db.record_project_activity(t5..t6, &[(user_1, project_1), (user_3, project_1)]) + db.record_user_activity(t5..t6, &[(user_1, project_1), (user_3, project_1)]) .await .unwrap(); let t7 = t6 + Duration::from_secs(60); let t8 = t7 + Duration::from_secs(10); - db.record_project_activity(t7..t8, &[(user_1, project_1)]) + db.record_user_activity(t7..t8, &[(user_1, project_1)]) .await .unwrap(); assert_eq!( - db.summarize_project_activity(t0..t6, 10).await.unwrap(), + db.get_top_users_activity_summary(t0..t6, 10).await.unwrap(), &[ UserActivitySummary { id: user_1, @@ -1627,15 +1638,15 @@ pub mod tests { ] ); assert_eq!( - db.summarize_user_activity(user_1, t3..t6).await.unwrap(), + db.get_user_activity_timeline(t3..t6, user_1).await.unwrap(), &[ - UserActivityDuration { + UserActivityPeriod { project_id: project_1, start: t3, end: t6, extensions: HashMap::from_iter([("rs".to_string(), 5), ("md".to_string(), 7)]), }, - UserActivityDuration { + UserActivityPeriod { project_id: project_2, start: t3, end: t5, @@ -1644,21 +1655,21 @@ pub mod tests { ] ); assert_eq!( - db.summarize_user_activity(user_1, t0..t8).await.unwrap(), + db.get_user_activity_timeline(t0..t8, user_1).await.unwrap(), &[ - UserActivityDuration { + UserActivityPeriod { project_id: project_2, start: t2, end: t5, extensions: Default::default(), }, - UserActivityDuration { + UserActivityPeriod { project_id: project_1, start: t3, end: t6, extensions: HashMap::from_iter([("rs".to_string(), 5), ("md".to_string(), 7)]), }, - UserActivityDuration { + UserActivityPeriod { project_id: project_1, start: t7, end: t8, @@ -2450,27 +2461,27 @@ pub mod tests { unimplemented!() } - async fn record_project_activity( + async fn record_user_activity( &self, - _period: Range, + _time_period: Range, _active_projects: &[(UserId, ProjectId)], ) -> Result<()> { unimplemented!() } - async fn summarize_project_activity( + async fn get_top_users_activity_summary( &self, - _period: Range, + _time_period: Range, _limit: usize, ) -> Result> { unimplemented!() } - async fn summarize_user_activity( + async fn get_user_activity_timeline( &self, - _user_id: UserId, _time_period: Range, - ) -> Result> { + _user_id: UserId, + ) -> Result> { unimplemented!() } diff --git a/crates/collab/src/rpc.rs b/crates/collab/src/rpc.rs index 79c1e53a0b..00252f4d6b 100644 --- a/crates/collab/src/rpc.rs +++ b/crates/collab/src/rpc.rs @@ -332,7 +332,7 @@ impl Server { let period_end = OffsetDateTime::now_utc(); this.app_state .db - .record_project_activity(period_start..period_end, &active_projects) + .record_user_activity(period_start..period_end, &active_projects) .await .trace_err(); period_start = period_end;