From bfe12d3946eda2858e52075f76a44bb4c99df7b7 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Mon, 7 Sep 2020 14:31:45 -0400 Subject: [PATCH] osu: Asyncify oppai cache --- youmubot-osu/src/discord/hook.rs | 44 ++++++++++++------------- youmubot-osu/src/discord/oppai_cache.rs | 41 +++++++++++++---------- 2 files changed, 45 insertions(+), 40 deletions(-) diff --git a/youmubot-osu/src/discord/hook.rs b/youmubot-osu/src/discord/hook.rs index 240a8f1..5efb21b 100644 --- a/youmubot-osu/src/discord/hook.rs +++ b/youmubot-osu/src/discord/hook.rs @@ -128,12 +128,14 @@ fn handle_old_links<'a>( .map(|v| Mods::from_str(v.as_str()).ok()) .flatten() .unwrap_or(Mods::NOMOD); - let info = mode.unwrap_or(b.mode).to_oppai_mode().and_then(|mode| { - cache + let info = match mode.unwrap_or(b.mode).to_oppai_mode() { + Some(mode) => cache .get_beatmap(b.beatmap_id) + .await .and_then(|b| b.get_info_with(Some(mode), mods)) - .ok() - }); + .ok(), + None => None, + }; Some(ToPrint { embed: EmbedType::Beatmap(b, info, mods), link: capture.get(0).unwrap().as_str(), @@ -198,15 +200,14 @@ fn handle_new_links<'a>( .name("mods") .and_then(|v| Mods::from_str(v.as_str()).ok()) .unwrap_or(Mods::NOMOD); - let info = mode - .unwrap_or(beatmap.mode) - .to_oppai_mode() - .and_then(|mode| { - cache - .get_beatmap(beatmap.beatmap_id) - .and_then(|b| b.get_info_with(Some(mode), mods)) - .ok() - }); + let info = match mode.unwrap_or(beatmap.mode).to_oppai_mode() { + Some(mode) => cache + .get_beatmap(beatmap.beatmap_id) + .await + .and_then(|b| b.get_info_with(Some(mode), mods)) + .ok(), + None => None, + }; Some(ToPrint { embed: EmbedType::Beatmap(beatmap, info, mods), link, @@ -265,15 +266,14 @@ fn handle_short_links<'a>( .name("mods") .and_then(|v| Mods::from_str(v.as_str()).ok()) .unwrap_or(Mods::NOMOD); - let info = mode - .unwrap_or(beatmap.mode) - .to_oppai_mode() - .and_then(|mode| { - cache - .get_beatmap(beatmap.beatmap_id) - .and_then(|b| b.get_info_with(Some(mode), mods)) - .ok() - }); + let info = match mode.unwrap_or(beatmap.mode).to_oppai_mode() { + Some(mode) => cache + .get_beatmap(beatmap.beatmap_id) + .await + .and_then(|b| b.get_info_with(Some(mode), mods)) + .ok(), + None => None, + }; let r: Result<_> = Ok(ToPrint { embed: EmbedType::Beatmap(beatmap, info, mods), link: capture.get(0).unwrap().as_str(), diff --git a/youmubot-osu/src/discord/oppai_cache.rs b/youmubot-osu/src/discord/oppai_cache.rs index 60cf6b3..c45ed3a 100644 --- a/youmubot-osu/src/discord/oppai_cache.rs +++ b/youmubot-osu/src/discord/oppai_cache.rs @@ -1,12 +1,12 @@ use serenity::framework::standard::CommandError; -use std::{ffi::CString, sync::Arc}; -use youmubot_prelude::TypeMapKey; +use std::ffi::CString; +use youmubot_prelude::*; /// the information collected from a download/Oppai request. -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct BeatmapContent { id: u64, - content: Arc, + content: CString, } /// the output of "one" oppai run. @@ -56,39 +56,44 @@ impl BeatmapContent { } /// A central cache for the beatmaps. -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct BeatmapCache { - client: reqwest::blocking::Client, - cache: Arc>, + client: reqwest::Client, + cache: dashmap::DashMap, } impl BeatmapCache { /// Create a new cache. - pub fn new(client: reqwest::blocking::Client) -> Self { + pub fn new(client: reqwest::Client) -> Self { BeatmapCache { client, - cache: Arc::new(dashmap::DashMap::new()), + cache: dashmap::DashMap::new(), } } - fn download_beatmap(&self, id: u64) -> Result { + async fn download_beatmap(&self, id: u64) -> Result { let content = self .client .get(&format!("https://osu.ppy.sh/osu/{}", id)) - .send()? - .bytes()?; + .send() + .await? + .bytes() + .await?; Ok(BeatmapContent { id, - content: Arc::new(CString::new(content.into_iter().collect::>())?), + content: CString::new(content.into_iter().collect::>())?, }) } /// Get a beatmap from the cache. - pub fn get_beatmap(&self, id: u64) -> Result { - self.cache - .entry(id) - .or_try_insert_with(|| self.download_beatmap(id)) - .map(|v| v.clone()) + pub async fn get_beatmap<'a>( + &'a self, + id: u64, + ) -> Result + 'a, CommandError> { + if !self.cache.contains_key(&id) { + self.cache.insert(id, self.download_beatmap(id).await?); + } + Ok(self.cache.get(&id).unwrap()) } }