diff --git a/examples/cache-optimization/models/message.rs b/examples/cache-optimization/models/message.rs index 1e7f07fb62..0e3e4f7603 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 6a8477b394..d5ff09c844 100644 --- a/twilight-cache-inmemory/src/event/message.rs +++ b/twilight-cache-inmemory/src/event/message.rs @@ -1,4 +1,4 @@ -use crate::{config::ResourceType, CacheableMessage, CacheableModels, InMemoryCache, UpdateCache}; +use crate::{config::ResourceType, CacheableModels, InMemoryCache, UpdateCache}; use std::borrow::Cow; use twilight_model::gateway::payload::incoming::{ MessageCreate, MessageDelete, MessageDeleteBulk, MessageUpdate, @@ -80,13 +80,45 @@ 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); + // 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 do not only add it to the message cache but + // also add its ID to the channel messages cache. + if cache + .messages + .insert(self.id, CacheModels::Message::from(self.0.clone())) + .is_some() + { + return; + } + + 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); } } diff --git a/twilight-cache-inmemory/src/model/message.rs b/twilight-cache-inmemory/src/model/message.rs index a53ef1ebc0..7f6f807041 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 31ac2c0b25..5a7d9a5c29 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 b57944df45..0d98a597c7 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 d5cf465906..85a9083f79 100644 --- a/twilight-model/src/gateway/payload/incoming/message_update.rs +++ b/twilight-model/src/gateway/payload/incoming/message_update.rs @@ -1,62 +1,21 @@ -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, +#[serde(transparent)] +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 + } }