From 3ef549537e6c11a7f5f84ed79256f8363b8747b1 Mon Sep 17 00:00:00 2001 From: Paul Makles Date: Sun, 21 May 2023 16:22:42 +0100 Subject: [PATCH] feat: de-duplicate user update events sent to clients --- crates/quark/src/events/client.rs | 1 + crates/quark/src/events/impl.rs | 13 +++++++++++++ crates/quark/src/events/state.rs | 21 ++++++++++++++++++++- crates/quark/src/impl/generic/users/user.rs | 1 + 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/crates/quark/src/events/client.rs b/crates/quark/src/events/client.rs index d6c6b018..1de1b764 100644 --- a/crates/quark/src/events/client.rs +++ b/crates/quark/src/events/client.rs @@ -183,6 +183,7 @@ pub enum EventV1 { id: String, data: PartialUser, clear: Vec, + event_id: Option, }, /// Relationship with another user changed diff --git a/crates/quark/src/events/impl.rs b/crates/quark/src/events/impl.rs index 0ea6e05b..1c7e3e4a 100644 --- a/crates/quark/src/events/impl.rs +++ b/crates/quark/src/events/impl.rs @@ -302,6 +302,7 @@ impl State { ..Default::default() }, clear: vec![], + event_id: Some(ulid::Ulid::new().to_string()), }; for server in self.cache.servers.keys() { @@ -499,6 +500,17 @@ impl State { } } + EventV1::UserUpdate { event_id, .. } => { + if let Some(id) = event_id { + if self.cache.seen_events.contains(id) { + return false; + } + + self.cache.seen_events.put(id.to_string(), ()); + } + + *event_id = None; + } EventV1::UserRelationship { id, user, .. } => { self.cache.users.insert(id.clone(), user.clone()); @@ -508,6 +520,7 @@ impl State { self.remove_subscription(id); } } + _ => {} } diff --git a/crates/quark/src/events/state.rs b/crates/quark/src/events/state.rs index 8b502d22..278a18ac 100644 --- a/crates/quark/src/events/state.rs +++ b/crates/quark/src/events/state.rs @@ -1,5 +1,7 @@ use std::collections::{HashMap, HashSet}; +use lru::LruCache; + use crate::models::{Channel, Member, Server, User}; /// Enumeration representing some change in subscriptions @@ -26,7 +28,7 @@ pub enum SubscriptionStateChange { /// ------------------------------------------------ /// We can strip these objects to core information!! /// ------------------------------------------------ -#[derive(Debug, Default)] +#[derive(Debug)] pub struct Cache { pub user_id: String, @@ -34,6 +36,23 @@ pub struct Cache { pub channels: HashMap, pub members: HashMap, pub servers: HashMap, + + pub seen_events: LruCache, +} + +impl Default for Cache { + fn default() -> Self { + Cache { + user_id: Default::default(), + + users: Default::default(), + channels: Default::default(), + members: Default::default(), + servers: Default::default(), + + seen_events: LruCache::new(20), + } + } } /// Client state diff --git a/crates/quark/src/impl/generic/users/user.rs b/crates/quark/src/impl/generic/users/user.rs index 2707723b..3355a5c7 100644 --- a/crates/quark/src/impl/generic/users/user.rs +++ b/crates/quark/src/impl/generic/users/user.rs @@ -33,6 +33,7 @@ impl User { id: self.id.clone(), data: partial, clear: remove, + event_id: Some(ulid::Ulid::new().to_string()), } .p_user(self.id.clone(), db) .await;