Browse Source

feat: room(分区)

master
hole-thu 3 years ago
parent
commit
0e1a088575
  1. 3
      migrations/postgres/2022-08-18-234900_add_room_id/down.sql
  2. 3
      migrations/postgres/2022-08-18-234900_add_room_id/up.sql
  3. 2
      src/api/mod.rs
  4. 1
      src/api/operation.rs
  5. 17
      src/api/post.rs
  6. 4
      src/api/search.rs
  7. 15
      src/cache.rs
  8. 4
      src/main.rs
  9. 32
      src/models.rs
  10. 1
      src/schema.rs

3
migrations/postgres/2022-08-18-234900_add_room_id/down.sql

@ -0,0 +1,3 @@
-- This file should undo anything in `up.sql`
ALTER TABLE posts
DROP COLUMN room_id

3
migrations/postgres/2022-08-18-234900_add_room_id/up.sql

@ -0,0 +1,3 @@
-- Your SQL goes here
ALTER TABLE posts
ADD COLUMN room_id INTEGER NOT NULL DEFAULT 0

2
src/api/mod.rs

@ -235,7 +235,7 @@ impl Ugc for Post {
self.is_deleted self.is_deleted
} }
fn extra_delete_condition(&self) -> bool { fn extra_delete_condition(&self) -> bool {
!self.content.starts_with("[系统自动代发]\n") self.room_id != 42
} }
async fn do_set_deleted(&mut self, db: &Db) -> Api<()> { async fn do_set_deleted(&mut self, db: &Db) -> Api<()> {
update!(*self, posts, db, { is_deleted, to true }); update!(*self, posts, db, { is_deleted, to true });

1
src/api/operation.rs

@ -140,6 +140,7 @@ pub async fn report(ri: Form<ReportInput>, user: CurrentUser, db: Db, rconn: Rds
is_tmp: false, is_tmp: false,
n_attentions: 1, n_attentions: 1,
allow_search: true, allow_search: true,
room_id: 42,
}, },
) )
.await?; .await?;

17
src/api/post.rs

@ -26,12 +26,14 @@ pub struct PostInput {
use_title: Option<i8>, use_title: Option<i8>,
#[field(validate = len(0..97))] #[field(validate = len(0..97))]
poll_options: Vec<String>, poll_options: Vec<String>,
room_id: Option<i32>,
} }
#[derive(Serialize)] #[derive(Serialize)]
#[serde(crate = "rocket::serde")] #[serde(crate = "rocket::serde")]
pub struct PostOutput { pub struct PostOutput {
pid: i32, pid: i32,
room_id: i32,
text: String, text: String,
cw: Option<String>, cw: Option<String>,
author_title: Option<String>, author_title: Option<String>,
@ -84,6 +86,7 @@ async fn p2output(p: &Post, user: &CurrentUser, db: &Db, rconn: &RdsConn) -> Api
user.is_admin || (!is_blocked && user.id.is_some() || user.namehash.eq(&p.author_hash)); user.is_admin || (!is_blocked && user.id.is_some() || user.namehash.eq(&p.author_hash));
Ok(PostOutput { Ok(PostOutput {
pid: p.id, pid: p.id,
room_id: p.room_id,
text: can_view.then(|| p.content.clone()).unwrap_or_default(), text: can_view.then(|| p.content.clone()).unwrap_or_default(),
cw: (!p.cw.is_empty()).then(|| p.cw.clone()), cw: (!p.cw.is_empty()).then(|| p.cw.clone()),
n_attentions: p.n_attentions, n_attentions: p.n_attentions,
@ -144,10 +147,11 @@ pub async fn get_one(pid: i32, user: CurrentUser, db: Db, rconn: RdsConn) -> Jso
})) }))
} }
#[get("/getlist?<p>&<order_mode>")] #[get("/getlist?<p>&<order_mode>&<room_id>")]
pub async fn get_list( pub async fn get_list(
p: Option<u32>, p: Option<u32>,
order_mode: u8, order_mode: u8,
room_id: Option<i32>,
user: CurrentUser, user: CurrentUser,
db: Db, db: Db,
rconn: RdsConn, rconn: RdsConn,
@ -156,7 +160,15 @@ pub async fn get_list(
let page = p.unwrap_or(1); let page = p.unwrap_or(1);
let page_size = 25; let page_size = 25;
let start = (page - 1) * page_size; let start = (page - 1) * page_size;
let ps = Post::gets_by_page(&db, &rconn, order_mode, start.into(), page_size.into()).await?; let ps = Post::gets_by_page(
&db,
&rconn,
room_id,
order_mode,
start.into(),
page_size.into(),
)
.await?;
let ps_data = ps2outputs(&ps, &user, &db, &rconn).await?; let ps_data = ps2outputs(&ps, &user, &db, &rconn).await?;
Ok(json!({ Ok(json!({
"data": ps_data, "data": ps_data,
@ -184,6 +196,7 @@ pub async fn publish_post(
is_tmp: user.id.is_none(), is_tmp: user.id.is_none(),
n_attentions: 1, n_attentions: 1,
allow_search: poi.allow_search.is_some(), allow_search: poi.allow_search.is_some(),
room_id: poi.room_id.unwrap_or_default(),
}, },
) )
.await?; .await?;

4
src/api/search.rs

@ -5,8 +5,9 @@ use crate::models::*;
use crate::rds_conn::RdsConn; use crate::rds_conn::RdsConn;
use rocket::serde::json::json; use rocket::serde::json::json;
#[get("/search?<search_mode>&<page>&<keywords>")] #[get("/search?<search_mode>&<page>&<keywords>&<room_id>")]
pub async fn search( pub async fn search(
room_id: Option<i32>,
keywords: String, keywords: String,
search_mode: u8, search_mode: u8,
page: i32, page: i32,
@ -25,6 +26,7 @@ pub async fn search(
Post::search( Post::search(
&db, &db,
&rconn, &rconn,
room_id,
search_mode, search_mode,
keywords.to_string(), keywords.to_string(),
start.into(), start.into(),

15
src/cache.rs

@ -172,17 +172,24 @@ impl PostCommentCache {
} }
} }
pub struct PostListCommentCache { pub struct PostListCache {
key: String, key: String,
mode: u8, mode: u8,
rconn: RdsConn, rconn: RdsConn,
length: isize, length: isize,
} }
impl PostListCommentCache { impl PostListCache {
pub fn init(mode: u8, rconn: &RdsConn) -> Self { pub fn init(room_id: Option<i32>, mode: u8, rconn: &RdsConn) -> Self {
Self { Self {
key: format!("hole_v2:cache:post_list:{}", &mode), key: format!(
"hole_v2:cache:post_list:{}:{}",
match room_id {
Some(i) => i.to_string(),
None => "".to_owned(),
},
&mode
),
mode, mode,
rconn: rconn.clone(), rconn: rconn.clone(),
length: 0, length: 0,

4
src/main.rs

@ -54,7 +54,9 @@ async fn main() -> Result<(), rocket::Error> {
let rconn = RdsConn(rmc.clone()); let rconn = RdsConn(rmc.clone());
tokio::spawn(async move { tokio::spawn(async move {
loop { loop {
cache::PostListCommentCache::init(3, &rconn).clear().await; for room_id in [None, Some(0), Some(1), Some(42)] {
cache::PostListCache::init(room_id, 3, &rconn).clear().await;
}
sleep(Duration::from_secs(5 * 60)).await; sleep(Duration::from_secs(5 * 60)).await;
} }
}); });

32
src/models.rs

@ -119,6 +119,7 @@ pub struct Post {
pub is_reported: bool, pub is_reported: bool,
pub hot_score: i32, pub hot_score: i32,
pub allow_search: bool, pub allow_search: bool,
pub room_id: i32,
} }
#[derive(Queryable, Insertable, Serialize, Deserialize, Debug)] #[derive(Queryable, Insertable, Serialize, Deserialize, Debug)]
@ -140,6 +141,7 @@ pub struct NewPost {
pub is_tmp: bool, pub is_tmp: bool,
pub n_attentions: i32, pub n_attentions: i32,
pub allow_search: bool, pub allow_search: bool,
pub room_id: i32,
} }
impl Post { impl Post {
@ -215,19 +217,21 @@ impl Post {
pub async fn gets_by_page( pub async fn gets_by_page(
db: &Db, db: &Db,
rconn: &RdsConn, rconn: &RdsConn,
room_id: Option<i32>,
order_mode: u8, order_mode: u8,
start: i64, start: i64,
limit: i64, limit: i64,
) -> QueryResult<Vec<Self>> { ) -> QueryResult<Vec<Self>> {
let mut cacher = PostListCommentCache::init(order_mode, &rconn); let mut cacher = PostListCache::init(room_id, order_mode, &rconn);
if cacher.need_fill().await { if cacher.need_fill().await {
let pids = let pids =
Self::_get_ids_by_page(db, order_mode.clone(), 0, cacher.i64_minlen()).await?; Self::_get_ids_by_page(db, room_id, order_mode.clone(), 0, cacher.i64_minlen())
.await?;
let ps = Self::get_multi(db, rconn, &pids).await?; let ps = Self::get_multi(db, rconn, &pids).await?;
cacher.fill(&ps).await; cacher.fill(&ps).await;
} }
let pids = if start + limit > cacher.i64_len() { let pids = if start + limit > cacher.i64_len() {
Self::_get_ids_by_page(db, order_mode, start, limit).await? Self::_get_ids_by_page(db, room_id, order_mode, start, limit).await?
} else { } else {
cacher.get_pids(start, limit).await cacher.get_pids(start, limit).await
}; };
@ -236,6 +240,7 @@ impl Post {
} }
async fn _get_ids_by_page( async fn _get_ids_by_page(
db: &Db, db: &Db,
room_id: Option<i32>,
order_mode: u8, order_mode: u8,
start: i64, start: i64,
limit: i64, limit: i64,
@ -243,7 +248,11 @@ impl Post {
db.run(move |c| { db.run(move |c| {
let mut query = base_query!(posts).select(posts::id); let mut query = base_query!(posts).select(posts::id);
if order_mode > 0 { if order_mode > 0 {
query = query.filter(posts::is_reported.eq(false)) query = query.filter(posts::is_reported.eq(false));
}
if let Some(ri) = room_id {
query = query.filter(posts::room_id.eq(ri));
} }
query = match order_mode { query = match order_mode {
@ -262,6 +271,7 @@ impl Post {
pub async fn search( pub async fn search(
db: &Db, db: &Db,
rconn: &RdsConn, rconn: &RdsConn,
room_id: Option<i32>,
search_mode: u8, search_mode: u8,
search_text: String, search_text: String,
start: i64, start: i64,
@ -276,6 +286,9 @@ impl Post {
.distinct() .distinct()
.left_join(comments::table) .left_join(comments::table)
.filter(posts::is_reported.eq(false)); .filter(posts::is_reported.eq(false));
if let Some(ri) = room_id {
query = query.filter(posts::room_id.eq(ri));
}
// 先用搜索+缓存,性能有问题了再真的做tag表 // 先用搜索+缓存,性能有问题了再真的做tag表
query = match search_mode { query = match search_mode {
0 => { 0 => {
@ -334,9 +347,12 @@ impl Post {
join!( join!(
self.set_instance_cache(rconn), self.set_instance_cache(rconn),
future::join_all((if is_new { 0..4 } else { 1..4 }).map(|mode| async move { future::join_all((if is_new { 0..4 } else { 1..4 }).map(|mode| async move {
PostListCommentCache::init(mode, &rconn.clone()) PostListCache::init(None, mode, &rconn.clone())
.put(self) .put(self)
.await .await;
PostListCache::init(Some(self.room_id), mode, &rconn.clone())
.put(self)
.await;
})), })),
); );
} }
@ -349,7 +365,9 @@ impl Post {
.unwrap(); .unwrap();
PostCache::init(&rconn).clear_all().await; PostCache::init(&rconn).clear_all().await;
PostListCommentCache::init(2, rconn).clear().await for room_id in [None, Some(0), Some(1), Some(42)] {
PostListCache::init(room_id, 2, rconn).clear().await;
}
} }
} }

1
src/schema.rs

@ -28,6 +28,7 @@ table! {
is_reported -> Bool, is_reported -> Bool,
hot_score -> Int4, hot_score -> Int4,
allow_search -> Bool, allow_search -> Bool,
room_id -> Int4,
} }
} }

Loading…
Cancel
Save