From b0f8abef33e8558d818edb3b2d84218fd8878eed Mon Sep 17 00:00:00 2001 From: Paul Makles <paulmakles@gmail.com> Date: Mon, 3 Aug 2020 10:51:14 +0200 Subject: [PATCH] Implement basic caching. --- Cargo.lock | 50 +++++++++++++++++++++++ Cargo.toml | 2 + src/database/channel.rs | 89 ++++++++++++++++++++++++++++++++++++----- src/guards/channel.rs | 17 +++++++- src/main.rs | 6 ++- 5 files changed, 150 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d2f4fff..ded248a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,6 +13,14 @@ name = "adler" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ahash" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "const-random 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ahash" version = "0.3.8" @@ -241,6 +249,24 @@ dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "const-random" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "const-random-macro 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "const-random-macro" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cookie" version = "0.11.3" @@ -554,6 +580,15 @@ dependencies = [ "tracing 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hashbrown" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ahash 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "hashbrown" version = "0.7.2" @@ -827,6 +862,14 @@ dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "lru" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "lru-cache" version = "0.1.2" @@ -1512,6 +1555,8 @@ dependencies = [ "chrono 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "dotenv 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lru 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "mongodb 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "num_enum 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "once_cell 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2507,6 +2552,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum addr2line 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072" "checksum adler 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" +"checksum ahash 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6f33b5018f120946c1dcf279194f238a9f146725593ead1c08fa47ff22b0b5d3" "checksum ahash 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217" "checksum aho-corasick 0.7.13 (registry+https://github.com/rust-lang/crates.io-index)" = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86" "checksum async-trait 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "a265e3abeffdce30b2e26b7a11b222fe37c6067404001b434101457d0385eb92" @@ -2537,6 +2583,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum chrono 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "c74d84029116787153e02106bf53e66828452a4b325cc8652b788b5967c0a0b6" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +"checksum const-random 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "2f1af9ac737b2dd2d577701e59fd09ba34822f6f2ebdb30a7647405d9e55e16a" +"checksum const-random-macro 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "25e4c606eb459dd29f7c57b2e0879f2b6f14ee130918c2b78ccb58a9624e6c7a" "checksum cookie 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5795cda0897252e34380a27baf884c53aa7ad9990329cdad96d4c5d027015d44" "checksum core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" "checksum core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" @@ -2575,6 +2623,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum gimli 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724" "checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" "checksum h2 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "993f9e0baeed60001cf565546b0d3dbe6a6ad23f2bd31644a133c641eccf6d53" +"checksum hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8e6073d0ca812575946eb5f35ff68dbe519907b25c42530389ff946dc84c6ead" "checksum hashbrown 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96282e96bfcd3da0d3aa9938bedf1e50df3269b6db08b4876d2da0bb1a0841cf" "checksum hashbrown 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34f595585f103464d8d2f6e9864682d74c1601fed5e07d62b1c9058dba8246fb" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" @@ -2607,6 +2656,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum linked-hash-map 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" +"checksum lru 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "35c456c123957de3a220cd03786e0d86aa542a88b46029973b542f426da6ef34" "checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" "checksum match_cfg 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" diff --git a/Cargo.toml b/Cargo.toml index ca6a8e2..2ccdd24 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,3 +27,5 @@ hashbrown = "0.7.1" serde_json = "1.0.51" rocket_cors = "0.5.2" bitfield = "0.13.2" +lru = "0.5.3" +lazy_static = "1.4.0" diff --git a/src/database/channel.rs b/src/database/channel.rs index d74b477..5da3f91 100644 --- a/src/database/channel.rs +++ b/src/database/channel.rs @@ -1,33 +1,102 @@ +use crate::database::get_collection; + use serde::{Deserialize, Serialize}; +use std::sync::{Arc, Mutex}; +use lru::LruCache; +use bson::{doc, from_bson}; #[derive(Serialize, Deserialize, Debug, Clone)] pub struct LastMessage { + // message id id: String, + // author's id user_id: String, + // truncated content with author's name prepended (for GDM / GUILD) short_content: String, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct Channel { #[serde(rename = "_id")] pub id: String, #[serde(rename = "type")] pub channel_type: u8, - // for Direct Messages + // DM: whether the DM is active pub active: Option<bool>, - - // for DMs / GDMs + // DM + GDM: last message in channel pub last_message: Option<LastMessage>, + // DM + GDM: recipients for channel pub recipients: Option<Vec<String>>, - - // for GDMs + // GDM: owner of group pub owner: Option<String>, - - // for Guilds + // GUILD: channel parent pub guild: Option<String>, - - // for Guilds and Group DMs + // GUILD + GDM: channel name pub name: Option<String>, + // GUILD + GDM: channel description pub description: Option<String>, } + +lazy_static! { + static ref CACHE: Arc<Mutex<LruCache<String, Channel>>> = Arc::new(Mutex::new(LruCache::new(4_000_000))); +} + +/*pub fn test() { + use std::time::Instant; + + let now = Instant::now(); + let mut cache = CACHE.lock().unwrap(); + println!("I'm about to write 4 million entries to cache."); + for i in 0..4_000_000 { + let c = Channel { + id: "potato".to_string(), + channel_type: 0, + + active: None, + last_message: None, + description: None, + guild: None, + name: None, + owner: None, + recipients: None + }; + + cache.put(format!("{}", i), c); + } + + println!("It took {} seconds, roughly {}ms per entry.", now.elapsed().as_secs_f64(), now.elapsed().as_millis() as f64 / 1_000_000.0); + + let now = Instant::now(); + println!("Now I'm going to read every entry and immediately dispose of it."); + for i in 0..4_000_000 { + cache.get(&format!("{}", i)); + } + + println!("It took {} seconds, roughly {}ms per entry.", now.elapsed().as_secs_f64(), now.elapsed().as_millis() as f64 / 1_000_000.0); +}*/ + +pub fn fetch_channel(id: &str) -> Channel { + { + let mut cache = CACHE.lock().unwrap(); + let existing = cache.get(&id.to_string()); + + if let Some(channel) = existing { + return (*channel).clone(); + } + } + + let col = get_collection("channels"); + let result = col.find_one(doc! { "_id": id }, None).unwrap(); + + if let Some(doc) = result { + let channel: Channel = from_bson(bson::Bson::Document(doc)).expect("Failed to unwrap channel."); + + let mut cache = CACHE.lock().unwrap(); + cache.put(id.to_string(), channel.clone()); + + return channel; + } + + panic!("Channel does not exist!"); +} diff --git a/src/guards/channel.rs b/src/guards/channel.rs index ace3096..171136e 100644 --- a/src/guards/channel.rs +++ b/src/guards/channel.rs @@ -27,7 +27,20 @@ pub struct ChannelRef { impl ChannelRef { pub fn from(id: String) -> Option<ChannelRef> { - match database::get_collection("channels").find_one( + let channel = database::channel::fetch_channel(&id); + Some(ChannelRef { + id: channel.id, + channel_type: channel.channel_type, + + name: channel.name, + last_message: channel.last_message, + + recipients: channel.recipients, + guild: channel.guild, + owner: channel.owner + }) + + /*match database::get_collection("channels").find_one( doc! { "_id": id }, FindOneOptions::builder() .projection(doc! { @@ -48,7 +61,7 @@ impl ChannelRef { None => None, }, Err(_) => None, - } + }*/ } pub fn fetch_data(&self, projection: Document) -> Option<Document> { diff --git a/src/main.rs b/src/main.rs index 2b11c3b..2170332 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,12 +6,14 @@ extern crate rocket; extern crate rocket_contrib; #[macro_use] extern crate bitfield; +#[macro_use] +extern crate lazy_static; +pub mod notifications; pub mod database; -pub mod email; pub mod guards; -pub mod notifications; pub mod routes; +pub mod email; pub mod util; use dotenv; -- GitLab