Skip to content

Commit

Permalink
Cache usage improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
melnary committed Aug 29, 2020
1 parent c9fb233 commit 732d3d3
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 35 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rust-nitro-sniper"
version = "2.6.2"
version = "2.6.3"
authors = ["Mel"]
edition = "2018"

Expand Down
64 changes: 39 additions & 25 deletions src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,38 @@ use serenity::model::id::{ChannelId, GuildId};
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use tokio::sync::Mutex;
use std::sync::Arc;
use std::fmt::Display;
use serde::export::Formatter;
use std::fmt;

#[derive(Clone)]
pub struct Location {
pub guild_name: Option<String>,
pub guild_name: Option<Arc<String>>,
pub channel_name: String,
}

impl Default for Location {
fn default() -> Self {
Location {
guild_name: Some("?".to_string()),
guild_name: None,
channel_name: "?".to_string(),
}
}
}

impl Display for Location {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
if let Some(guild_name) = &self.guild_name {
write!(f, "{} > {}", guild_name, self.channel_name)
} else {
write!(f, "{}", self.channel_name)
}
}
}

impl Location {
pub fn new(guild_name: Option<String>, channel: Channel) -> Self {
pub fn new(guild_name: Option<Arc<String>>, channel: Channel) -> Self {
let channel_name = match channel {
Channel::Guild(guild_channel) => guild_channel.name,
Channel::Private(private_channel) => private_channel.name(),
Expand All @@ -37,50 +51,52 @@ impl Location {
}

pub struct LocationCache {
data: Mutex<HashMap<ChannelId, Location>>,
channel_map: Mutex<HashMap<ChannelId, Location>>,
guild_map: Mutex<HashMap<GuildId, Arc<String>>>
}

impl LocationCache {
pub fn new() -> Self {
LocationCache {
data: Mutex::new(HashMap::new()),
channel_map: Mutex::new(HashMap::new()),
guild_map: Mutex::new(HashMap::new())
}
}

async fn make_request(
async fn make_location_request(
&self,
channel_id: ChannelId,
guild_id: Option<GuildId>,
http: &Http,
) -> Result<Location, ()> {
let guild_result = if let Some(id) = guild_id {
Some(http.get_guild(id.0).await)
Some(self.get_and_cache_guild(id, http).await)
} else {
None
};

let channel_result = http.get_channel(channel_id.0).await;

let location = match (guild_result, channel_result) {
(Some(Ok(guild)), Ok(channel)) => Location::new(Some(guild.name), channel),
(Some(Ok(guild_name)), Ok(channel)) => Location::new(Some(guild_name), channel),
(None, Ok(channel)) => Location::new(None, channel),
_ => return Err(()),
};

Ok(location)
}

pub async fn put(
pub async fn get_and_cache_location(
&self,
channel_id: ChannelId,
guild_id: Option<GuildId>,
http: &Http,
) -> Result<Location, ()> {
let mut channel_map = self.data.lock().await;
let mut channel_map = self.channel_map.lock().await;

match channel_map.entry(channel_id) {
Entry::Vacant(entry) => {
if let Ok(response) = self.make_request(channel_id, guild_id, http).await {
if let Ok(response) = self.make_location_request(channel_id, guild_id, http).await {
Ok(entry.insert(response).clone())
} else {
Err(())
Expand All @@ -90,21 +106,19 @@ impl LocationCache {
}
}

pub async fn get(&self, channel_id: &ChannelId) -> Option<Location> {
let channel_map = self.data.lock().await;
channel_map.get(channel_id).cloned()
}
pub async fn get_and_cache_guild(&self, guild_id: GuildId, http: &Http) -> Result<Arc<String>, ()> {
let mut guild_map = self.guild_map.lock().await;

pub async fn get_or_fetch(
&self,
channel_id: ChannelId,
guild_id: Option<GuildId>,
http: &Http,
) -> Result<Location, ()> {
if let Some(cached) = self.get(&channel_id).await {
Ok(cached)
} else {
self.put(channel_id, guild_id, http).await
match guild_map.entry(guild_id) {
Entry::Vacant(entry) => {

if let Ok(response) = http.get_guild(guild_id.0).await {
Ok(entry.insert(Arc::new(response.name)).clone())
} else {
Err(())
}
}
Entry::Occupied(entry) => Ok(entry.get().clone()),
}
}
}
6 changes: 3 additions & 3 deletions src/discord.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,11 @@ impl Handler {
async fn cache_location(&self, msg: &Message, http: &Http) {
let cache_result = self
.location_cache
.put(msg.channel_id, msg.guild_id, http)
.get_and_cache_location(msg.channel_id, msg.guild_id, http)
.await;

if cache_result.is_err() {
pretty_warn!("(x_x)", "Failed to cache message location.");
pretty_warn!("(x_x)", "Failed to cache message location");
}
}
}
Expand Down Expand Up @@ -185,7 +185,7 @@ impl EventHandler for Handler {

let location = self
.location_cache
.get_or_fetch(msg.channel_id, msg.guild_id, ctx.http())
.get_and_cache_location(msg.channel_id, msg.guild_id, ctx.http())
.await;
log.send(location, user_to_tag(&msg.author));
}
Expand Down
7 changes: 2 additions & 5 deletions src/logging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,10 @@ impl<'a> LogBlock<'a> {
};

println!(
"\n{} › ({}) [{} > {} > {}]",
"\n{} › ({}) [{} > {}]",
chrono::Local::now().format("%H:%M:%S"),
self.profile,
location
.guild_name
.unwrap_or_else(|| "Direct Messages".to_string()),
location.channel_name,
location,
sender
);

Expand Down

0 comments on commit 732d3d3

Please sign in to comment.