feat: cache for get multi posts
This commit is contained in:
@@ -1,17 +1,19 @@
|
||||
#![allow(clippy::all)]
|
||||
|
||||
use crate::cache::{PostCache, UserCache};
|
||||
use crate::db_conn::Db;
|
||||
use crate::libs::diesel_logger::LoggingConnection;
|
||||
use crate::rds_conn::RdsConn;
|
||||
use crate::cache::{PostCache, UserCache};
|
||||
use crate::schema::*;
|
||||
use chrono::{offset::Utc, DateTime};
|
||||
use diesel::dsl::any;
|
||||
use diesel::{
|
||||
insert_into, BoolExpressionMethods, ExpressionMethods, QueryDsl, QueryResult, RunQueryDsl,
|
||||
TextExpressionMethods,
|
||||
};
|
||||
use diesel::dsl::any;
|
||||
use rocket::serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::convert::identity;
|
||||
|
||||
no_arg_sql_function!(RANDOM, (), "Represents the sql RANDOM() function");
|
||||
|
||||
@@ -28,12 +30,14 @@ macro_rules! get {
|
||||
macro_rules! get_multi {
|
||||
($table:ident) => {
|
||||
pub async fn get_multi(db: &Db, ids: Vec<i32>) -> QueryResult<Vec<Self>> {
|
||||
if ids.is_empty() {
|
||||
return Ok(vec![]);
|
||||
}
|
||||
// eq(any()) is only for postgres
|
||||
db.run(move |c| {
|
||||
$table::table
|
||||
.filter($table::id.eq(any(ids)))
|
||||
.filter($table::is_deleted.eq(false))
|
||||
.order($table::id.desc())
|
||||
.load(with_log!(c))
|
||||
})
|
||||
.await
|
||||
@@ -83,7 +87,7 @@ pub struct Comment {
|
||||
pub post_id: i32,
|
||||
}
|
||||
|
||||
#[derive(Queryable, Insertable, Serialize, Deserialize)]
|
||||
#[derive(Queryable, Insertable, Serialize, Deserialize, Debug)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub struct Post {
|
||||
pub id: i32,
|
||||
@@ -131,15 +135,52 @@ impl Post {
|
||||
|
||||
set_deleted!(posts);
|
||||
|
||||
pub async fn get_with_cache(db: &Db, rconn: &RdsConn, id: i32) -> QueryResult<Self> {
|
||||
let mut cacher = PostCache::init(&id, &rconn);
|
||||
if let Some(p) = cacher.get().await {
|
||||
Ok(p)
|
||||
} else {
|
||||
let p = Self::get(db, id).await?;
|
||||
cacher.set(&p).await;
|
||||
Ok(p)
|
||||
pub async fn get_multi_with_cache(
|
||||
db: &Db,
|
||||
rconn: &RdsConn,
|
||||
ids: &Vec<i32>,
|
||||
) -> QueryResult<Vec<Self>> {
|
||||
let mut cacher = PostCache::init(&rconn);
|
||||
let mut cached_posts = cacher.gets(ids).await;
|
||||
let mut id2po = HashMap::<i32, &mut Option<Post>>::new();
|
||||
|
||||
// dbg!(&cached_posts);
|
||||
|
||||
let missing_ids = ids
|
||||
.iter()
|
||||
.zip(cached_posts.iter_mut())
|
||||
.filter_map(|(pid, p)| match p {
|
||||
None => {
|
||||
id2po.insert(pid.clone(), p);
|
||||
Some(pid)
|
||||
},
|
||||
_ => None,
|
||||
})
|
||||
.copied()
|
||||
.collect();
|
||||
|
||||
dbg!(&missing_ids);
|
||||
let missing_ps = Self::get_multi(db, missing_ids).await?;
|
||||
// dbg!(&missing_ps);
|
||||
|
||||
cacher.sets(&missing_ps.iter().map(identity).collect()).await;
|
||||
|
||||
for p in missing_ps.into_iter() {
|
||||
if let Some(op) = id2po.get_mut(&p.id) {
|
||||
**op = Some(p);
|
||||
}
|
||||
}
|
||||
// dbg!(&cached_posts);
|
||||
Ok(
|
||||
cached_posts.into_iter().filter_map(identity).collect()
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn get_with_cache(db: &Db, rconn: &RdsConn, id: i32) -> QueryResult<Self> {
|
||||
Self::get_multi_with_cache(db, rconn, &vec![id])
|
||||
.await?
|
||||
.pop()
|
||||
.ok_or(diesel::result::Error::NotFound)
|
||||
}
|
||||
|
||||
pub async fn gets_by_page(
|
||||
@@ -177,9 +218,7 @@ impl Post {
|
||||
let search_text2 = search_text.replace("%", "\\%");
|
||||
db.run(move |c| {
|
||||
let pat;
|
||||
let mut query = base_query!(posts)
|
||||
.distinct()
|
||||
.left_join(comments::table);
|
||||
let mut query = base_query!(posts).distinct().left_join(comments::table);
|
||||
// 先用搜索+缓存,性能有问题了再真的做tag表
|
||||
query = match search_mode {
|
||||
0 => {
|
||||
@@ -188,7 +227,11 @@ impl Post {
|
||||
.filter(posts::cw.eq(&search_text))
|
||||
.or_filter(posts::cw.eq(format!("#{}", &search_text)))
|
||||
.or_filter(posts::content.like(&pat))
|
||||
.or_filter(comments::content.like(&pat).and(comments::is_deleted.eq(false)))
|
||||
.or_filter(
|
||||
comments::content
|
||||
.like(&pat)
|
||||
.and(comments::is_deleted.eq(false)),
|
||||
)
|
||||
}
|
||||
1 => {
|
||||
pat = format!("%{}%", search_text2.replace(" ", "%"));
|
||||
@@ -262,7 +305,7 @@ impl Post {
|
||||
}
|
||||
|
||||
pub async fn set_instance_cache(&self, rconn: &RdsConn) {
|
||||
PostCache::init(&self.id, rconn).set(self).await;
|
||||
PostCache::init(rconn).sets(&vec![self]).await;
|
||||
}
|
||||
pub async fn refresh_cache(&self, rconn: &RdsConn, is_new: bool) {
|
||||
self.set_instance_cache(rconn).await;
|
||||
|
||||
Reference in New Issue
Block a user