diff options
| author | zeyla <[email protected]> | 2018-07-05 09:26:46 -0700 |
|---|---|---|
| committer | GitHub <[email protected]> | 2018-07-05 09:26:46 -0700 |
| commit | 9e560628deb1cf66e0c5029f41a79404fadffb40 (patch) | |
| tree | 83b28db08fd1c26fdfd577334252c2b6c618fcf7 /src/cache | |
| parent | Monomorphize all functions (diff) | |
| download | serenity-9e560628deb1cf66e0c5029f41a79404fadffb40.tar.xz serenity-9e560628deb1cf66e0c5029f41a79404fadffb40.zip | |
Make the Cache Update API public (#344)
This commit makes the Cache Update API public, allowing users to manually update
the cache, as well as implementing the caching API on their own types to work
with mutating the cache.
The motivation for this indirectly comes from a message cache: if a user has
multiple processes that can receive cache updates (either splitting a bot's
shards into multiple processes or other processes like web panels or pub/sub
channels), then this will allow them to easily mutate the cache and feed all
types implementing the CacheUpdate trait into `Cache::update`.
Diffstat (limited to 'src/cache')
| -rw-r--r-- | src/cache/cache_update.rs | 100 | ||||
| -rw-r--r-- | src/cache/mod.rs | 22 |
2 files changed, 118 insertions, 4 deletions
diff --git a/src/cache/cache_update.rs b/src/cache/cache_update.rs index a05cc3d..ba79727 100644 --- a/src/cache/cache_update.rs +++ b/src/cache/cache_update.rs @@ -1,7 +1,105 @@ use super::Cache; -pub(crate) trait CacheUpdate { +/// Trait used for updating the cache with a type. +/// +/// This may be implemented on a type and used to update the cache via +/// [`Cache::update`]. +/// +/// # Examples +/// +/// Creating a custom struct implementation to update the cache with: +/// +/// ```rust +/// use serenity::{ +/// cache::{Cache, CacheUpdate}, +/// model::{ +/// id::UserId, +/// user::User, +/// }, +/// prelude::RwLock, +/// }; +/// use std::{ +/// collections::hash_map::Entry, +/// sync::Arc, +/// }; +/// +/// // For example, an update to the user's record in the database was +/// // published to a pubsub channel. +/// struct DatabaseUserUpdate { +/// user_avatar: Option<String>, +/// user_discriminator: u16, +/// user_id: UserId, +/// user_is_bot: bool, +/// user_name: String, +/// } +/// +/// impl CacheUpdate for DatabaseUserUpdate { +/// // A copy of the old user's data, if it existed in the cache. +/// type Output = User; +/// +/// fn update(&mut self, cache: &mut Cache) -> Option<Self::Output> { +/// // If an entry for the user already exists, update its fields. +/// match cache.users.entry(self.user_id) { +/// Entry::Occupied(entry) => { +/// let user = entry.get(); +/// let mut writer = user.write(); +/// let old = writer.clone(); +/// +/// writer.bot = self.user_is_bot; +/// writer.discriminator = self.user_discriminator; +/// writer.id = self.user_id; +/// +/// if writer.avatar != self.user_avatar { +/// writer.avatar = self.user_avatar.clone(); +/// } +/// +/// if writer.name != self.user_name { +/// writer.name = self.user_name.clone(); +/// } +/// +/// // Return the old copy for the user's sake. +/// Some(old) +/// }, +/// Entry::Vacant(entry) => { +/// entry.insert(Arc::new(RwLock::new(User { +/// id: self.user_id, +/// avatar: self.user_avatar.clone(), +/// bot: self.user_is_bot, +/// discriminator: self.user_discriminator, +/// name: self.user_name.clone(), +/// }))); +/// +/// // There was no old copy, so return None. +/// None +/// }, +/// } +/// } +/// } +/// +/// // Create an instance of the cache. +/// let mut cache = Cache::new(); +/// +/// // This is a sample pubsub message that you might receive from your +/// // database. +/// let mut update_message = DatabaseUserUpdate { +/// user_avatar: None, +/// user_discriminator: 6082, +/// user_id: UserId(379740138303127564), +/// user_is_bot: true, +/// user_name: "TofuBot".to_owned(), +/// }; +/// +/// // Update the cache with the message. +/// cache.update(&mut update_message); +/// ``` +/// +/// [`Cache::update`]: struct.Cache.html#method.update +pub trait CacheUpdate { + /// The return type of an update. + /// + /// If there is nothing to return, specify this type as an unit (`()`). type Output; + /// Updates the cache with the implementation. fn update(&mut self, &mut Cache) -> Option<Self::Output>; } diff --git a/src/cache/mod.rs b/src/cache/mod.rs index e0a5ee6..3bf5a5a 100644 --- a/src/cache/mod.rs +++ b/src/cache/mod.rs @@ -56,7 +56,7 @@ use std::{ mod cache_update; -pub(crate) use self::cache_update::*; +pub use self::cache_update::CacheUpdate; /// A cache of all events received over a [`Shard`], where storing at least /// some data from the event is possible. @@ -163,6 +163,12 @@ pub struct Cache { } impl Cache { + /// Creates a new cache. + #[inline] + pub fn new() -> Self { + Self::default() + } + /// Fetches the number of [`Member`]s that have not had data received. /// /// The important detail to note here is that this is the number of @@ -664,8 +670,18 @@ impl Cache { self.categories.get(&channel_id).cloned() } - #[cfg(feature = "client")] - pub(crate) fn update<E: CacheUpdate>(&mut self, e: &mut E) -> Option<E::Output> { + /// Updates the cache with the update implementation for an event or other + /// custom update implementation. + /// + /// Refer to the documentation for [`CacheUpdate`] for more information. + /// + /// # Examples + /// + /// Refer to the [`CacheUpdate` examples]. + /// + /// [`CacheUpdate`]: trait.CacheUpdate.html + /// [`CacheUpdate` examples]: trait.CacheUpdate.html#examples + pub fn update<E: CacheUpdate>(&mut self, e: &mut E) -> Option<E::Output> { e.update(self) } |