Skip to content

Commit 45c151d

Browse files
authored
[xitca-web] bug fix and improvements (#9272)
* [xitca-web] bug fix and improvements * comment fix
1 parent 423880c commit 45c151d

13 files changed

+145
-190
lines changed

frameworks/Rust/xitca-web/Cargo.lock

Lines changed: 31 additions & 38 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frameworks/Rust/xitca-web/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ mimalloc = { version = "0.1", default-features = false, optional = true }
8585
# stuff can not be used or not needed in wasi target
8686
[target.'cfg(not(target_family = "wasm"))'.dependencies]
8787
futures-core = { version = "0.3", default-features = false }
88-
nanorand = { version = "0.7", default-features = false, features = ["tls"] }
88+
rand = { version = "0.8", features = ["small_rng"] }
8989
tokio = "1"
9090

9191
[profile.release]
@@ -95,5 +95,5 @@ codegen-units = 1
9595
panic = "abort"
9696

9797
[patch.crates-io]
98-
xitca-postgres = { git = "https://github.com/HFQR/xitca-web.git", rev = "9835c0b" }
98+
xitca-postgres = { git = "https://github.com/HFQR/xitca-web.git", rev = "0cda225" }
9999
mio = { git = "https://github.com/fakeshadow/mio", rev = "9bae6012b7ecfc6083350785f71a5e8265358178" }

frameworks/Rust/xitca-web/src/db.rs

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
use std::fmt::Write;
1+
// clippy is dumb and have no idea what should be lazy or not
2+
#![allow(clippy::unnecessary_lazy_evaluations)]
23

34
use xitca_io::bytes::BytesMut;
4-
use xitca_postgres::{pipeline::Pipeline, AsyncLendingIterator, Pool, Type};
5+
use xitca_postgres::{pipeline::Pipeline, pool::Pool, AsyncLendingIterator, Type};
56

67
use super::{
78
ser::{Fortune, Fortunes, World},
8-
util::{HandleResult, Rand, DB_URL},
9+
util::{bulk_update_gen, HandleResult, Rand, DB_URL},
910
};
1011

1112
pub struct Client {
@@ -28,19 +29,14 @@ const WORLD_SQL: &str = "SELECT * FROM world WHERE id=$1";
2829
const WORLD_SQL_TYPES: &[Type] = &[Type::INT4];
2930

3031
fn update_query(num: usize) -> Box<str> {
31-
const PREFIX: &str = "UPDATE world SET randomNumber = w.r FROM (VALUES ";
32-
const SUFFIX: &str = ") AS w (i,r) WHERE world.id = w.i";
33-
34-
let (_, mut query) = (1..=num).fold((1, String::from(PREFIX)), |(idx, mut query), _| {
35-
write!(query, "(${}::int,${}::int),", idx, idx + 1).unwrap();
36-
(idx + 2, query)
37-
});
38-
39-
query.pop();
40-
41-
query.push_str(SUFFIX);
42-
43-
query.into_boxed_str()
32+
bulk_update_gen(|query| {
33+
use std::fmt::Write;
34+
(1..=num).fold((1, query), |(idx, query), _| {
35+
write!(query, "(${}::int,${}::int),", idx, idx + 1).unwrap();
36+
(idx + 2, query)
37+
});
38+
})
39+
.into_boxed_str()
4440
}
4541

4642
pub async fn create() -> HandleResult<Client> {
@@ -50,14 +46,7 @@ pub async fn create() -> HandleResult<Client> {
5046

5147
let updates = core::iter::once(Box::from(""))
5248
.chain((1..=500).map(update_query))
53-
.collect::<Box<[Box<str>]>>();
54-
55-
{
56-
let mut conn = pool.get().await?;
57-
for update in updates.iter().skip(1) {
58-
conn.prepare(update, &[]).await?;
59-
}
60-
}
49+
.collect();
6150

6251
Ok(Client {
6352
pool,
@@ -120,7 +109,7 @@ impl Client {
120109

121110
let mut conn = self.pool.get().await?;
122111
let world_stmt = conn.prepare(WORLD_SQL, WORLD_SQL_TYPES).await?;
123-
let update_stmt = conn.prepare(&update, &[]).await?;
112+
let update_stmt = conn.prepare(update, &[]).await?;
124113

125114
let mut params = Vec::with_capacity(len);
126115

@@ -169,8 +158,8 @@ impl Client {
169158
}
170159
}
171160

172-
fn sort_update_params(params: &Vec<[i32; 2]>) -> impl ExactSizeIterator<Item = i32> {
173-
let mut params = params.clone();
161+
fn sort_update_params(params: &[[i32; 2]]) -> impl ExactSizeIterator<Item = i32> {
162+
let mut params = params.to_owned();
174163
params.sort_by(|a, b| a[0].cmp(&b[0]));
175164

176165
struct ParamIter<I>(I);

frameworks/Rust/xitca-web/src/db_diesel.rs

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
use std::sync::{Arc, Mutex};
1+
use std::{
2+
io,
3+
sync::{Arc, Mutex},
4+
};
25

36
use diesel::{prelude::*, r2d2};
47

58
use crate::{
69
ser::{Fortune, Fortunes, World},
7-
util::{Error, HandleResult, Rand, DB_URL},
10+
util::{bulk_update_gen, Error, HandleResult, Rand, DB_URL},
811
};
912

1013
pub type Pool = Arc<_Pool>;
@@ -14,15 +17,15 @@ pub struct _Pool {
1417
rng: Mutex<Rand>,
1518
}
1619

17-
pub fn create() -> std::io::Result<Arc<_Pool>> {
20+
pub fn create() -> io::Result<Arc<_Pool>> {
1821
r2d2::Builder::new()
1922
.max_size(100)
2023
.min_idle(Some(100))
2124
.test_on_check_out(false)
2225
.idle_timeout(None)
2326
.max_lifetime(None)
2427
.build(r2d2::ConnectionManager::new(DB_URL))
25-
.map_err(std::io::Error::other)
28+
.map_err(io::Error::other)
2629
.map(|pool| {
2730
Arc::new(_Pool {
2831
pool,
@@ -65,33 +68,32 @@ impl _Pool {
6568
pub fn update(&self, num: u16) -> HandleResult<Vec<World>> {
6669
use crate::schema::world::dsl::*;
6770

71+
let mut rngs = {
72+
let mut rng = self.rng.lock().unwrap();
73+
(0..num).map(|_| (rng.gen_id(), rng.gen_id())).collect::<Vec<_>>()
74+
};
75+
76+
rngs.sort_by(|(a, _), (b, _)| a.cmp(b));
77+
6878
let mut worlds = {
6979
let mut conn = self.pool.get()?;
70-
let worlds = (0..num)
71-
.map(|_| {
72-
let mut rng = self.rng.lock().unwrap();
73-
let w_id = rng.gen_id();
74-
let r_id = rng.gen_id();
75-
drop(rng);
80+
81+
let worlds = rngs
82+
.iter()
83+
.map(|(w_id, num)| {
7684
world
7785
.filter(id.eq(w_id))
7886
.load::<World>(&mut conn)?
7987
.pop()
8088
.map(|mut w| {
81-
w.randomnumber = r_id;
89+
w.randomnumber = *num;
8290
w
8391
})
8492
.ok_or_else(not_found)
8593
})
8694
.collect::<HandleResult<Vec<_>>>()?;
8795

88-
worlds.iter().try_for_each(|w| {
89-
diesel::update(world)
90-
.filter(id.eq(w.id))
91-
.set(randomnumber.eq(w.randomnumber))
92-
.execute(&mut conn)
93-
.map(|_| ())
94-
})?;
96+
diesel::sql_query(update_query(&rngs)).execute(&mut conn)?;
9597

9698
worlds
9799
};
@@ -115,3 +117,14 @@ impl _Pool {
115117
Ok(Fortunes::new(items))
116118
}
117119
}
120+
121+
// diesel does not support high level bulk update api. use raw sql to bypass the limitation.
122+
// relate discussion: https://github.com/diesel-rs/diesel/discussions/2879
123+
fn update_query(ids: &[(i32, i32)]) -> String {
124+
bulk_update_gen(|query| {
125+
use std::fmt::Write;
126+
ids.iter().for_each(|(w_id, num)| {
127+
write!(query, "({}::int,{}::int),", w_id, num).unwrap();
128+
});
129+
})
130+
}

0 commit comments

Comments
 (0)