Implement basic caching.

This commit is contained in:
Paul Makles
2020-08-03 10:51:14 +02:00
parent 6f065b7575
commit b0f8abef33
5 changed files with 151 additions and 15 deletions

View File

@@ -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!");
}

View File

@@ -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> {

View File

@@ -6,12 +6,14 @@ extern crate rocket;
extern crate rocket_contrib;
#[macro_use]
extern crate bitfield;
#[macro_use]
extern crate lazy_static;
pub mod database;
pub mod email;
pub mod guards;
pub mod notifications;
pub mod database;
pub mod guards;
pub mod routes;
pub mod email;
pub mod util;
use dotenv;