From 8a28b75bedb415ab998146f5fa2ea9520f2f1623 Mon Sep 17 00:00:00 2001 From: Quang Pham Date: Fri, 22 Nov 2024 14:15:23 -0800 Subject: [PATCH 1/7] refactor(model, cache): a full message object for `MessageUpdate` event --- examples/cache-optimization/models/message.rs | 7 -- twilight-cache-inmemory/src/event/message.rs | 41 +++++++++- twilight-cache-inmemory/src/model/message.rs | 43 ----------- twilight-cache-inmemory/src/traits.rs | 5 +- twilight-model/src/gateway/event/mod.rs | 2 +- .../payload/incoming/message_update.rs | 74 ++++--------------- 6 files changed, 56 insertions(+), 116 deletions(-) diff --git a/examples/cache-optimization/models/message.rs b/examples/cache-optimization/models/message.rs index 1e7f07fb627..0e3e4f76036 100644 --- a/examples/cache-optimization/models/message.rs +++ b/examples/cache-optimization/models/message.rs @@ -1,7 +1,6 @@ use twilight_cache_inmemory::CacheableMessage; use twilight_model::{ channel::{message::Reaction, Message}, - gateway::payload::incoming::MessageUpdate, id::{marker::MessageMarker, Id}, }; @@ -50,10 +49,4 @@ impl CacheableMessage for MinimalCachedMessage { fn retain_reactions(&mut self, _f: impl FnMut(&Reaction) -> bool) { // No-op } - - fn update_with_message_update(&mut self, message_update: &MessageUpdate) { - if let Some(content) = &message_update.content { - self.content.clone_from(content); - } - } } diff --git a/twilight-cache-inmemory/src/event/message.rs b/twilight-cache-inmemory/src/event/message.rs index 6a8477b394a..222bf8eb86e 100644 --- a/twilight-cache-inmemory/src/event/message.rs +++ b/twilight-cache-inmemory/src/event/message.rs @@ -1,4 +1,5 @@ -use crate::{config::ResourceType, CacheableMessage, CacheableModels, InMemoryCache, UpdateCache}; +use crate::{config::ResourceType, CacheableModels, InMemoryCache, UpdateCache}; +use dashmap::Entry; use std::borrow::Cow; use twilight_model::gateway::payload::incoming::{ MessageCreate, MessageDelete, MessageDeleteBulk, MessageUpdate, @@ -80,12 +81,46 @@ impl UpdateCache for MessageDeleteBul impl UpdateCache for MessageUpdate { fn update(&self, cache: &InMemoryCache) { + if cache.wants(ResourceType::USER) { + cache.cache_user(Cow::Borrowed(&self.author), self.guild_id); + } + + if let (Some(member), Some(guild_id), true) = ( + &self.member, + self.guild_id, + cache.wants(ResourceType::MEMBER), + ) { + cache.cache_borrowed_partial_member(guild_id, member, self.author.id); + } + if !cache.wants(ResourceType::MESSAGE) { return; } - if let Some(mut message) = cache.messages.get_mut(&self.id) { - message.update_with_message_update(self); + let message = CacheModels::Message::from(self.0.clone()); + + match cache.messages.entry(self.id) { + // If this message exists in message cache, we update it. + Entry::Occupied(mut occupied) => { + occupied.insert(message); + } + // If we miss the MessageCreate event of this message, + // this is the chance for us to cache it. + Entry::Vacant(vacant) => { + let mut channel_messages = + cache.channel_messages.entry(self.0.channel_id).or_default(); + + // If this channel cache is full, we pop an message ID out of + // the channel cache and also remove it from the message cache. + if channel_messages.len() >= cache.config.message_cache_size() { + if let Some(popped_id) = channel_messages.pop_back() { + cache.messages.remove(&popped_id); + } + } + + channel_messages.push_front(self.0.id); + vacant.insert(message); + } } } } diff --git a/twilight-cache-inmemory/src/model/message.rs b/twilight-cache-inmemory/src/model/message.rs index a53ef1ebc02..7f6f8070410 100644 --- a/twilight-cache-inmemory/src/model/message.rs +++ b/twilight-cache-inmemory/src/model/message.rs @@ -11,7 +11,6 @@ use twilight_model::{ }, Attachment, ChannelMention, }, - gateway::payload::incoming::MessageUpdate, guild::PartialMember, id::{ marker::{ @@ -427,48 +426,6 @@ impl PartialEq for CachedMessage { } impl CacheableMessage for CachedMessage { - fn update_with_message_update(&mut self, message_update: &MessageUpdate) { - if let Some(attachments) = &message_update.attachments { - self.attachments.clone_from(attachments); - } - - if let Some(content) = &message_update.content { - self.content.clone_from(content); - } - - if let Some(edited_timestamp) = message_update.edited_timestamp { - self.edited_timestamp.replace(edited_timestamp); - } - - if let Some(embeds) = &message_update.embeds { - self.embeds.clone_from(embeds); - } - - if let Some(mention_everyone) = message_update.mention_everyone { - self.mention_everyone = mention_everyone; - } - - if let Some(mention_roles) = &message_update.mention_roles { - self.mention_roles.clone_from(mention_roles); - } - - if let Some(mentions) = &message_update.mentions { - self.mentions = mentions.iter().map(|x| x.id).collect::>(); - } - - if let Some(pinned) = message_update.pinned { - self.pinned = pinned; - } - - if let Some(timestamp) = message_update.timestamp { - self.timestamp = timestamp; - } - - if let Some(tts) = message_update.tts { - self.tts = tts; - } - } - fn reactions(&self) -> &[Reaction] { &self.reactions } diff --git a/twilight-cache-inmemory/src/traits.rs b/twilight-cache-inmemory/src/traits.rs index 31ac2c0b25c..5a7d9a5c298 100644 --- a/twilight-cache-inmemory/src/traits.rs +++ b/twilight-cache-inmemory/src/traits.rs @@ -31,7 +31,7 @@ use twilight_model::{ Channel, ChannelType, Message, StageInstance, }, gateway::{ - payload::incoming::{GuildUpdate, MemberUpdate, MessageUpdate}, + payload::incoming::{GuildUpdate, MemberUpdate}, presence::Presence, }, guild::{ @@ -235,9 +235,6 @@ pub trait CacheableVoiceState: pub trait CacheableMessage: From + PartialEq + PartialEq + Clone + Debug { - /// Update the cached data with a [`MessageUpdate`] event. - fn update_with_message_update(&mut self, message_update: &MessageUpdate); - /// Reactions added to this message. fn reactions(&self) -> &[Reaction]; diff --git a/twilight-model/src/gateway/event/mod.rs b/twilight-model/src/gateway/event/mod.rs index b57944df45f..0d98a597c76 100644 --- a/twilight-model/src/gateway/event/mod.rs +++ b/twilight-model/src/gateway/event/mod.rs @@ -221,7 +221,7 @@ impl Event { Event::MessageCreate(e) => e.0.guild_id, Event::MessageDelete(e) => e.guild_id, Event::MessageDeleteBulk(e) => e.guild_id, - Event::MessageUpdate(e) => e.guild_id, + Event::MessageUpdate(e) => e.0.guild_id, Event::MessagePollVoteAdd(e) => e.guild_id, Event::MessagePollVoteRemove(e) => e.guild_id, Event::PresenceUpdate(e) => Some(e.0.guild_id), diff --git a/twilight-model/src/gateway/payload/incoming/message_update.rs b/twilight-model/src/gateway/payload/incoming/message_update.rs index d5cf4659068..3cbb4d90c99 100644 --- a/twilight-model/src/gateway/payload/incoming/message_update.rs +++ b/twilight-model/src/gateway/payload/incoming/message_update.rs @@ -1,62 +1,20 @@ -use crate::{ - channel::{ - message::{Embed, Mention, MessageType}, - Attachment, - }, - id::{ - marker::{ChannelMarker, GuildMarker, MessageMarker, RoleMarker}, - Id, - }, - user::User, - util::Timestamp, -}; +use crate::channel::Message; use serde::{Deserialize, Serialize}; +use std::ops::{Deref, DerefMut}; #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] -pub struct MessageUpdate { - /// List of attachments. - /// - /// Refer to the documentation for [`Message::attachments`] for caveats with - /// receiving the attachments of messages. - /// - /// [`Message::attachments`]: crate::channel::Message::attachments - #[serde(skip_serializing_if = "Option::is_none")] - pub attachments: Option>, - #[serde(skip_serializing_if = "Option::is_none")] - pub author: Option, - pub channel_id: Id, - /// Content of the message. - /// - /// Refer to the documentation for [`Message::content`] for caveats with - /// receiving the content of messages. - /// - /// [`Message::content`]: crate::channel::Message::content - pub content: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub edited_timestamp: Option, - /// List of embeds. - /// - /// Refer to the documentation for [`Message::embeds`] for caveats with - /// receiving the embeds of messages. - /// - /// [`Message::embeds`]: crate::channel::Message::embeds - #[serde(skip_serializing_if = "Option::is_none")] - pub embeds: Option>, - #[serde(skip_serializing_if = "Option::is_none")] - pub guild_id: Option>, - pub id: Id, - #[serde(rename = "type", skip_serializing_if = "Option::is_none")] - pub kind: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub mention_everyone: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub mention_roles: Option>>, - #[serde(skip_serializing_if = "Option::is_none")] - pub mentions: Option>, - #[serde(skip_serializing_if = "Option::is_none")] - pub pinned: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub timestamp: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub tts: Option, +pub struct MessageUpdate(pub Message); + +impl Deref for MessageUpdate { + type Target = Message; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for MessageUpdate { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } } From 1abf27dc23f71ae47978c1e51d8f5a2e02ab0e44 Mon Sep 17 00:00:00 2001 From: Quang Pham Date: Sat, 23 Nov 2024 00:29:53 -0800 Subject: [PATCH 2/7] satisfy hack check --- twilight-cache-inmemory/src/event/message.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/twilight-cache-inmemory/src/event/message.rs b/twilight-cache-inmemory/src/event/message.rs index 222bf8eb86e..3aedff10b3b 100644 --- a/twilight-cache-inmemory/src/event/message.rs +++ b/twilight-cache-inmemory/src/event/message.rs @@ -1,5 +1,5 @@ use crate::{config::ResourceType, CacheableModels, InMemoryCache, UpdateCache}; -use dashmap::Entry; +use dashmap::mapref::entry::Entry; use std::borrow::Cow; use twilight_model::gateway::payload::incoming::{ MessageCreate, MessageDelete, MessageDeleteBulk, MessageUpdate, From 5769b919b321d5814f0bc96e8dc12bddd44efe68 Mon Sep 17 00:00:00 2001 From: Quang Pham Date: Sat, 23 Nov 2024 11:44:59 -0800 Subject: [PATCH 3/7] refactor(model, cache): remove the unnecessary condition on updating message cache --- twilight-cache-inmemory/src/event/message.rs | 40 +++++++++----------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/twilight-cache-inmemory/src/event/message.rs b/twilight-cache-inmemory/src/event/message.rs index 3aedff10b3b..7740a8b1109 100644 --- a/twilight-cache-inmemory/src/event/message.rs +++ b/twilight-cache-inmemory/src/event/message.rs @@ -1,5 +1,4 @@ use crate::{config::ResourceType, CacheableModels, InMemoryCache, UpdateCache}; -use dashmap::mapref::entry::Entry; use std::borrow::Cow; use twilight_model::gateway::payload::incoming::{ MessageCreate, MessageDelete, MessageDeleteBulk, MessageUpdate, @@ -97,30 +96,27 @@ impl UpdateCache for MessageUpdate { return; } - let message = CacheModels::Message::from(self.0.clone()); + // In special cases, this message was popped out due to the limitation + // of the message cache capacity, or its Event::MessageCreate was missed. + // If that is the case, we does not only add it to the message cache but + // also add its ID to the channel messages cache. + let exists = cache + .messages + .insert(self.id, CacheModels::Message::from(self.0.clone())) + .is_some(); - match cache.messages.entry(self.id) { - // If this message exists in message cache, we update it. - Entry::Occupied(mut occupied) => { - occupied.insert(message); - } - // If we miss the MessageCreate event of this message, - // this is the chance for us to cache it. - Entry::Vacant(vacant) => { - let mut channel_messages = - cache.channel_messages.entry(self.0.channel_id).or_default(); - - // If this channel cache is full, we pop an message ID out of - // the channel cache and also remove it from the message cache. - if channel_messages.len() >= cache.config.message_cache_size() { - if let Some(popped_id) = channel_messages.pop_back() { - cache.messages.remove(&popped_id); - } - } + if !exists { + let mut channel_messages = cache.channel_messages.entry(self.0.channel_id).or_default(); - channel_messages.push_front(self.0.id); - vacant.insert(message); + // If this channel cache is full, we pop an message ID out of + // the channel cache and also remove it from the message cache. + if channel_messages.len() >= cache.config.message_cache_size() { + if let Some(popped_id) = channel_messages.pop_back() { + cache.messages.remove(&popped_id); + } } + + channel_messages.push_front(self.0.id); } } } From ca301ad39a8f1f88e7cbc2f7baa524c7d2c335b3 Mon Sep 17 00:00:00 2001 From: Quang Pham Date: Sat, 23 Nov 2024 12:35:00 -0800 Subject: [PATCH 4/7] refactor(model, cache): amend the previous commit --- twilight-cache-inmemory/src/event/message.rs | 25 ++++++++++---------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/twilight-cache-inmemory/src/event/message.rs b/twilight-cache-inmemory/src/event/message.rs index 7740a8b1109..a0d62767fee 100644 --- a/twilight-cache-inmemory/src/event/message.rs +++ b/twilight-cache-inmemory/src/event/message.rs @@ -100,24 +100,25 @@ impl UpdateCache for MessageUpdate { // of the message cache capacity, or its Event::MessageCreate was missed. // If that is the case, we does not only add it to the message cache but // also add its ID to the channel messages cache. - let exists = cache + if cache .messages .insert(self.id, CacheModels::Message::from(self.0.clone())) - .is_some(); + .is_some() + { + return; + } - if !exists { - let mut channel_messages = cache.channel_messages.entry(self.0.channel_id).or_default(); + let mut channel_messages = cache.channel_messages.entry(self.0.channel_id).or_default(); - // If this channel cache is full, we pop an message ID out of - // the channel cache and also remove it from the message cache. - if channel_messages.len() >= cache.config.message_cache_size() { - if let Some(popped_id) = channel_messages.pop_back() { - cache.messages.remove(&popped_id); - } + // If this channel cache is full, we pop an message ID out of + // the channel cache and also remove it from the message cache. + if channel_messages.len() >= cache.config.message_cache_size() { + if let Some(popped_id) = channel_messages.pop_back() { + cache.messages.remove(&popped_id); } - - channel_messages.push_front(self.0.id); } + + channel_messages.push_front(self.0.id); } } From 019a5ee22f0354d256b83f8a3d34cd8140a53289 Mon Sep 17 00:00:00 2001 From: Quang Pham <73033278+BooTheDev@users.noreply.github.com> Date: Sun, 24 Nov 2024 15:55:41 -0800 Subject: [PATCH 5/7] Update twilight-model/src/gateway/payload/incoming/message_update.rs Co-authored-by: Erk --- twilight-model/src/gateway/payload/incoming/message_update.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/twilight-model/src/gateway/payload/incoming/message_update.rs b/twilight-model/src/gateway/payload/incoming/message_update.rs index 3cbb4d90c99..e790fcf02d1 100644 --- a/twilight-model/src/gateway/payload/incoming/message_update.rs +++ b/twilight-model/src/gateway/payload/incoming/message_update.rs @@ -3,6 +3,7 @@ use serde::{Deserialize, Serialize}; use std::ops::{Deref, DerefMut}; #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +#[serde(transparent)] pub struct MessageUpdate(pub Message); impl Deref for MessageUpdate { From a5934ae526a9ae3f15b7863bd29bcd3ec3ee2c91 Mon Sep 17 00:00:00 2001 From: Quang Pham Date: Sun, 24 Nov 2024 16:01:21 -0800 Subject: [PATCH 6/7] remove the extra space --- twilight-model/src/gateway/payload/incoming/message_update.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/twilight-model/src/gateway/payload/incoming/message_update.rs b/twilight-model/src/gateway/payload/incoming/message_update.rs index e790fcf02d1..85a9083f794 100644 --- a/twilight-model/src/gateway/payload/incoming/message_update.rs +++ b/twilight-model/src/gateway/payload/incoming/message_update.rs @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize}; use std::ops::{Deref, DerefMut}; #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] -#[serde(transparent)] +#[serde(transparent)] pub struct MessageUpdate(pub Message); impl Deref for MessageUpdate { From 8469984e473f03963f5d2f2efaf108958dc1ee01 Mon Sep 17 00:00:00 2001 From: ITOH Date: Mon, 25 Nov 2024 14:31:55 +0100 Subject: [PATCH 7/7] Update twilight-cache-inmemory/src/event/message.rs --- twilight-cache-inmemory/src/event/message.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/twilight-cache-inmemory/src/event/message.rs b/twilight-cache-inmemory/src/event/message.rs index a0d62767fee..d5ff09c8445 100644 --- a/twilight-cache-inmemory/src/event/message.rs +++ b/twilight-cache-inmemory/src/event/message.rs @@ -98,7 +98,7 @@ impl UpdateCache for MessageUpdate { // In special cases, this message was popped out due to the limitation // of the message cache capacity, or its Event::MessageCreate was missed. - // If that is the case, we does not only add it to the message cache but + // If that is the case, we do not only add it to the message cache but // also add its ID to the channel messages cache. if cache .messages