add cache
All checks were successful
continuous-integration/drone/push Build is passing

b4tman/qchgk_web#1
using moka
This commit is contained in:
2023-04-02 17:01:51 +03:00
parent d9a060b1b7
commit d1cb2187c1
3 changed files with 410 additions and 11 deletions

View File

@@ -15,11 +15,15 @@ use rocket_contrib::templates::Template;
use rand::distributions::Uniform;
use rand::Rng;
use std::ops::Deref;
use std::sync::Arc;
use chgk_ledb_lib::db;
use chgk_ledb_lib::questions::Question;
use moka::sync::Cache;
use std::time::Duration;
const DB_FILENAME: &str = "db.dat";
trait ErrorEmpty {
@@ -34,9 +38,27 @@ impl<T, E> ErrorEmpty for Result<T, E> {
}
}
#[derive(Clone)]
struct ArcTemplateData {
value: Arc<serde_json::Value>,
}
impl ArcTemplateData {
fn new(value: serde_json::Value) -> ArcTemplateData {
ArcTemplateData {
value: Arc::new(value),
}
}
fn render(&self, name: &'static str) -> Template {
Template::render(name, self.value.deref())
}
}
type TemplateCache = moka::sync::Cache<usize, ArcTemplateData>;
type DataBaseInner = db::Reader<Question>;
type DataBase = Arc<DataBaseInner>;
struct AppState{
struct AppState {
db: DataBase,
database_distribution: Uniform<usize>,
}
@@ -49,7 +71,7 @@ impl From<DataBaseInner> for AppState {
Self {
db,
database_distribution
database_distribution,
}
}
}
@@ -63,7 +85,16 @@ fn get_question(db: &DataBase, id: usize) -> Result<Question, ()> {
db.get(id - 1).err_empty()
}
fn show_question_details(template_name: &'static str, data: &AppState, id: usize) -> Template {
fn show_question_details(
template_name: &'static str,
data: &AppState,
cache: &TemplateCache,
id: usize,
) -> Template {
if let Some(value) = cache.get(&id) {
return value.render(template_name);
}
match get_question(&data.db, id) {
Ok(question) => {
let mut context = serde_json::to_value(question).expect("question serialize");
@@ -71,7 +102,12 @@ fn show_question_details(template_name: &'static str, data: &AppState, id: usize
let next_id = random_question_id(&data.database_distribution);
context["next"] = serde_json::to_value(next_id).expect("question id serialize");
}
Template::render(template_name, &context)
let value = ArcTemplateData::new(context);
let result = value.render(template_name);
cache.insert(id, value);
result
}
Err(_) => {
use std::collections::HashMap;
@@ -82,13 +118,13 @@ fn show_question_details(template_name: &'static str, data: &AppState, id: usize
}
#[get("/q/<id>")]
fn show_question(data: State<AppState>, id: usize) -> Template {
show_question_details("question", data.inner(), id)
fn show_question(data: State<AppState>, cache: State<TemplateCache>, id: usize) -> Template {
show_question_details("question", data.inner(), cache.inner(), id)
}
#[get("/q/<id>/a")]
fn show_answer(data: State<AppState>, id: usize) -> Template {
show_question_details("answer", data.inner(), id)
fn show_answer(data: State<AppState>, cache: State<TemplateCache>, id: usize) -> Template {
show_question_details("answer", data.inner(), cache.inner(), id)
}
#[get("/q/0")]
@@ -116,9 +152,14 @@ fn not_found(_req: &rocket::Request) -> Template {
fn rocket() -> Rocket {
let state: AppState = db::Reader::new(DB_FILENAME, 2048).expect("open db").into();
let cache: TemplateCache = Cache::builder()
.time_to_idle(Duration::from_secs(15 * 60))
.max_capacity(300)
.build();
rocket::ignite()
.manage(state)
.manage(cache)
.register(catchers![not_found])
.mount(
"/",