aboutsummaryrefslogtreecommitdiff
path: root/src/model/user.rs
diff options
context:
space:
mode:
authorZeyla Hellyer <[email protected]>2017-02-09 13:34:08 -0800
committerZeyla Hellyer <[email protected]>2017-02-09 13:34:08 -0800
commit0c9ec377aa7281fb3d4bc390c896b426660a5387 (patch)
treea355bda0c0d02d8b67331e0a99090c7b26206cb1 /src/model/user.rs
parentRelease v0.1.5 (diff)
downloadserenity-0c9ec377aa7281fb3d4bc390c896b426660a5387.tar.xz
serenity-0c9ec377aa7281fb3d4bc390c896b426660a5387.zip
Optimize caching
Improve the cache by keeping track of new maps, making other maps have `Arc<RwLock>` values, optimizing already-existing methods, and take advantage of new, more efficient retrievals (e.g. simply keying a value from a map rather than iterating over vecs or maps and then itering over another vec). Keep track of two new maps in the cache: - **channels**: a map of all guild channels that exist, so that they can be efficiently found, and so a message's guild can be efficiently found - **users**: a map of all users that exist, so that it can be shared across all members and presences Other cache fields now have `Arc<RwLock>` values: - `groups` - `guilds` - `private_channels` `Cache::unavailable_guilds` is now a `HashSet<GuildId>` instead of a `Vec<GuildId>`. This should slightly optimize removals/insertions for large bots. `ext::cache::ChannelRef` has been removed as it became equivilant in functionality to `model::Channel`. Also, `model::Channel` now has all variant data encased in `Arc<RwLock>`s. E.g., `Channel::Group(Group)` is now `Channel::Group(Arc<RwLock<Group>>)`. Some model struct fields are now wrapped in an `Arc<RwLock>`. These are: - `Group::recipients`: `HashMap<UserId, User>` -> `HashMap<UserId, Arc<RwLock<User>>>` - `Guild::channels`: `HashMap<ChannelId, GuildChannel>` -> `HashMap<ChannelId, Arc<RwLock<GuildChannel>>>` - `Member::user`: `User` -> `Arc<RwLock<User>>` - `PrivateChannel::recipient`: `User` -> `Arc<RwLock<User>>` Some (cache-enabled) event handler signatures have changed to use `Arc<RwLock>`s: - `Client::on_call_delete` - `Client::on_call_update` - `Client::on_guild_delete` - `Client::on_guild_update` Many function signatures have changed: - `Cache::get_call` now returns a `Option<Arc<RwLock<Call>>>` instead of a `Option<&Call>` - `Cache::get_channel` now returns a `Option<Channel>` instead of a `Option<ChannelRef>`. This now also retrieves directly from the `Guild::channels` instead of iterating over guilds' for a guild channel - `Cache::get_guild` now returns a `Option<Arc<RwLock<Guild>>>` instead of a `Option<&Guild>` - `Cache::get_guild_channel` now returns a `Option<Arc<RwLock<GuildChannel>>>` instead of a `Option<&GuildChannel>` - `Cache::get_group` now returns a `Option<Arc<RwLock<Group>>>` instead of a `Option<&Group>` - `Cache::get_member` now returns a `Option<Member>` instead of a `Option<&Member>`, due to guilds being behind a lock themselves - `Cache::get_role` now returns a `Option<Role>` instead of a `Option<&Role>` for the above reason - `Cache::get_user` now returns a `Option<Arc<RwLock<User>>>` instead of a `Option<&User>` - `GuildId::find` now returns a `Option<Arc<RwLock<Guild>>>` instead of a `Option<Guild>` - `UserId::find` now returns a `Option<Arc<RwLock<User>>>` instead of a `Option<User>` - `Member::display_name` now returns a `Cow<String>` instead of a `&str` A new cache method has been added, `Cache::get_private_channel`, to retrieve a `PrivateChannel`. The `Display` formatter for `Channel` has been optimized to not clone.
Diffstat (limited to 'src/model/user.rs')
-rw-r--r--src/model/user.rs44
1 files changed, 33 insertions, 11 deletions
diff --git a/src/model/user.rs b/src/model/user.rs
index 8473623..fe2d3bb 100644
--- a/src/model/user.rs
+++ b/src/model/user.rs
@@ -24,6 +24,8 @@ use ::utils::builder::EditProfile;
use ::utils::decode_array;
#[cfg(feature="cache")]
+use std::sync::{Arc, RwLock};
+#[cfg(feature="cache")]
use ::client::CACHE;
impl CurrentUser {
@@ -87,7 +89,6 @@ impl CurrentUser {
}
/// Gets a list of guilds that the current user is in.
- #[inline]
pub fn guilds(&self) -> Result<Vec<GuildInfo>> {
rest::get_guilds(GuildPagination::After(GuildId(1)), 100)
}
@@ -191,15 +192,36 @@ impl User {
///
/// [`PrivateChannel`]: struct.PrivateChannel.html
/// [`User::dm`]: struct.User.html#method.dm
+ // A tale with Clippy:
+ //
+ // A person named Clippy once asked you to unlock a box and take something
+ // from it, but you never re-locked it, so you'll die and the universe will
+ // implode because the box must remain locked unless you're there, and you
+ // can't just borrow that item from it and take it with you forever.
+ //
+ // Instead what you do is unlock the box, take the item out of it, make a
+ // copy of said item, and then re-lock the box, and take your copy of the
+ // item with you.
+ //
+ // The universe is still fine, and nothing implodes.
+ //
+ // (AKA: Clippy is wrong and so we have to mark as allowing this lint.)
+ #[allow(let_and_return)]
pub fn direct_message(&self, content: &str)
-> Result<Message> {
let private_channel_id = feature_cache! {{
- let finding = CACHE.read()
- .unwrap()
- .private_channels
- .values()
- .find(|ch| ch.recipient.id == self.id)
- .map(|ch| ch.id);
+ let finding = {
+ let cache = CACHE.read().unwrap();
+
+ let finding = cache.private_channels
+ .values()
+ .map(|ch| ch.read().unwrap())
+ .find(|ch| ch.recipient.read().unwrap().id == self.id)
+ .map(|ch| ch.id)
+ .clone();
+
+ finding
+ };
if let Some(finding) = finding {
finding
@@ -331,7 +353,7 @@ impl User {
.unwrap()
.guilds
.get(&_guild_id)
- .map(|g| g.roles.contains_key(&role_id))
+ .map(|g| g.read().unwrap().roles.contains_key(&role_id))
.unwrap_or(false)
} else {
true
@@ -393,8 +415,8 @@ impl UserId {
/// Search the cache for the user with the Id.
#[cfg(feature="cache")]
- pub fn find(&self) -> Option<User> {
- CACHE.read().unwrap().get_user(*self).cloned()
+ pub fn find(&self) -> Option<Arc<RwLock<User>>> {
+ CACHE.read().unwrap().get_user(*self)
}
/// Gets a user by its Id over the REST API.
@@ -416,7 +438,7 @@ impl From<CurrentUser> for UserId {
impl From<Member> for UserId {
/// Gets the Id of a `Member`.
fn from(member: Member) -> UserId {
- member.user.id
+ member.user.read().unwrap().id
}
}