diff --git a/frameworks/Rust/xitca-web/Cargo.lock b/frameworks/Rust/xitca-web/Cargo.lock index 6a87ff4b1fb..4429973312f 100644 --- a/frameworks/Rust/xitca-web/Cargo.lock +++ b/frameworks/Rust/xitca-web/Cargo.lock @@ -1100,7 +1100,7 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "xitca-http" version = "0.1.0" -source = "git+https://github.com/HFQR/xitca-web.git?rev=23ad63cbb3a853a548bd447cc59625a5d7c5833e#23ad63cbb3a853a548bd447cc59625a5d7c5833e" +source = "git+https://github.com/HFQR/xitca-web.git?rev=263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f#263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f" dependencies = [ "futures-core", "http", @@ -1121,7 +1121,7 @@ dependencies = [ [[package]] name = "xitca-io" version = "0.1.0" -source = "git+https://github.com/HFQR/xitca-web.git?rev=23ad63cbb3a853a548bd447cc59625a5d7c5833e#23ad63cbb3a853a548bd447cc59625a5d7c5833e" +source = "git+https://github.com/HFQR/xitca-web.git?rev=263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f#263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f" dependencies = [ "bytes", "tokio", @@ -1132,7 +1132,7 @@ dependencies = [ [[package]] name = "xitca-postgres" version = "0.1.0" -source = "git+https://github.com/HFQR/xitca-web.git?rev=23ad63cbb3a853a548bd447cc59625a5d7c5833e#23ad63cbb3a853a548bd447cc59625a5d7c5833e" +source = "git+https://github.com/HFQR/xitca-web.git?rev=263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f#263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f" dependencies = [ "fallible-iterator", "percent-encoding", @@ -1148,7 +1148,7 @@ dependencies = [ [[package]] name = "xitca-router" version = "0.1.0" -source = "git+https://github.com/HFQR/xitca-web.git?rev=23ad63cbb3a853a548bd447cc59625a5d7c5833e#23ad63cbb3a853a548bd447cc59625a5d7c5833e" +source = "git+https://github.com/HFQR/xitca-web.git?rev=263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f#263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f" dependencies = [ "xitca-unsafe-collection", ] @@ -1156,7 +1156,7 @@ dependencies = [ [[package]] name = "xitca-server" version = "0.1.0" -source = "git+https://github.com/HFQR/xitca-web.git?rev=23ad63cbb3a853a548bd447cc59625a5d7c5833e#23ad63cbb3a853a548bd447cc59625a5d7c5833e" +source = "git+https://github.com/HFQR/xitca-web.git?rev=263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f#263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f" dependencies = [ "socket2 0.5.5", "tokio", @@ -1170,12 +1170,12 @@ dependencies = [ [[package]] name = "xitca-service" version = "0.1.0" -source = "git+https://github.com/HFQR/xitca-web.git?rev=23ad63cbb3a853a548bd447cc59625a5d7c5833e#23ad63cbb3a853a548bd447cc59625a5d7c5833e" +source = "git+https://github.com/HFQR/xitca-web.git?rev=263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f#263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f" [[package]] name = "xitca-unsafe-collection" version = "0.1.0" -source = "git+https://github.com/HFQR/xitca-web.git?rev=23ad63cbb3a853a548bd447cc59625a5d7c5833e#23ad63cbb3a853a548bd447cc59625a5d7c5833e" +source = "git+https://github.com/HFQR/xitca-web.git?rev=263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f#263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f" dependencies = [ "bytes", ] @@ -1203,13 +1203,13 @@ dependencies = [ "xitca-server", "xitca-service", "xitca-unsafe-collection", - "xitca-web 0.1.0 (git+https://github.com/HFQR/xitca-web.git?rev=23ad63cbb3a853a548bd447cc59625a5d7c5833e)", + "xitca-web 0.1.0 (git+https://github.com/HFQR/xitca-web.git?rev=263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f)", ] [[package]] name = "xitca-web" version = "0.1.0" -source = "git+https://github.com/HFQR/xitca-web.git?rev=23ad63cbb3a853a548bd447cc59625a5d7c5833e#23ad63cbb3a853a548bd447cc59625a5d7c5833e" +source = "git+https://github.com/HFQR/xitca-web.git?rev=263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f#263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f" dependencies = [ "futures-core", "pin-project-lite", diff --git a/frameworks/Rust/xitca-web/Cargo.toml b/frameworks/Rust/xitca-web/Cargo.toml index 10af08ac491..d1367c3fb07 100644 --- a/frameworks/Rust/xitca-web/Cargo.toml +++ b/frameworks/Rust/xitca-web/Cargo.toml @@ -21,13 +21,15 @@ required-features = ["web"] [[bin]] name = "xitca-web-axum" path = "./src/main_axum.rs" -required-features = ["axum", "io-uring"] +required-features = ["axum", "io-uring", "pg-sync", "template"] [features] # pg optional -pg = ["xitca-postgres"] +pg = ["xitca-postgres/single-thread"] +# pg send/sync optional +pg-sync = ["xitca-postgres"] # pg io_uring optional -pg-iou = ["xitca-postgres/io-uring"] +pg-iou = ["pg", "xitca-postgres/io-uring"] # http router optional router = ["xitca-http/router"] # web optional @@ -54,7 +56,7 @@ serde_json = { version = "1" } xitca-web = { version = "0.1", features = ["json"], optional = true } # raw-pg optional -xitca-postgres = { version = "0.1", features = ["single-thread"], optional = true } +xitca-postgres = { version = "0.1", optional = true } # template optional sailfish = { version = "0.8", default-features = false, features = ["derive", "perf-inline"], optional = true } @@ -80,13 +82,13 @@ codegen-units = 1 panic = "abort" [patch.crates-io] -xitca-http = { git = "https://github.com/HFQR/xitca-web.git", rev = "23ad63cbb3a853a548bd447cc59625a5d7c5833e" } -xitca-io = { git = "https://github.com/HFQR/xitca-web.git", rev = "23ad63cbb3a853a548bd447cc59625a5d7c5833e" } -xitca-postgres = { git = "https://github.com/HFQR/xitca-web.git", rev = "23ad63cbb3a853a548bd447cc59625a5d7c5833e" } -xitca-router = { git = "https://github.com/HFQR/xitca-web.git", rev = "23ad63cbb3a853a548bd447cc59625a5d7c5833e" } -xitca-server = { git = "https://github.com/HFQR/xitca-web.git", rev = "23ad63cbb3a853a548bd447cc59625a5d7c5833e" } -xitca-service = { git = "https://github.com/HFQR/xitca-web.git", rev = "23ad63cbb3a853a548bd447cc59625a5d7c5833e" } -xitca-unsafe-collection = { git = "https://github.com/HFQR/xitca-web.git", rev = "23ad63cbb3a853a548bd447cc59625a5d7c5833e" } -xitca-web = { git = "https://github.com/HFQR/xitca-web.git", rev = "23ad63cbb3a853a548bd447cc59625a5d7c5833e" } +xitca-http = { git = "https://github.com/HFQR/xitca-web.git", rev = "263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f" } +xitca-io = { git = "https://github.com/HFQR/xitca-web.git", rev = "263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f" } +xitca-postgres = { git = "https://github.com/HFQR/xitca-web.git", rev = "263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f" } +xitca-router = { git = "https://github.com/HFQR/xitca-web.git", rev = "263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f" } +xitca-server = { git = "https://github.com/HFQR/xitca-web.git", rev = "263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f" } +xitca-service = { git = "https://github.com/HFQR/xitca-web.git", rev = "263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f" } +xitca-unsafe-collection = { git = "https://github.com/HFQR/xitca-web.git", rev = "263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f" } +xitca-web = { git = "https://github.com/HFQR/xitca-web.git", rev = "263ea4e01f8f840dfdb3b82ba804d7b0912d5e7f" } mio = { git = "https://github.com/fakeshadow/mio.git", rev = "52b72d372bfe5807755b7f5e3e1edf282954d6ba" } diff --git a/frameworks/Rust/xitca-web/benchmark_config.json b/frameworks/Rust/xitca-web/benchmark_config.json index 060cb47b354..57c3adddfa8 100755 --- a/frameworks/Rust/xitca-web/benchmark_config.json +++ b/frameworks/Rust/xitca-web/benchmark_config.json @@ -67,10 +67,14 @@ "axum": { "json_url": "/json", "plaintext_url": "/plaintext", + "db_url": "/db", + "fortune_url": "/fortunes", + "query_url": "/queries?q=", + "update_url": "/updates?q=", "port": 8080, - "approach": "Realistic", - "classification": "Micro", - "database": "none", + "approach": "realistic", + "classification": "micro", + "database": "postgres", "framework": "axum [xitca]", "language": "rust", "orm": "raw", diff --git a/frameworks/Rust/xitca-web/src/db.rs b/frameworks/Rust/xitca-web/src/db.rs index 211931c1893..c4614344d0b 100644 --- a/frameworks/Rust/xitca-web/src/db.rs +++ b/frameworks/Rust/xitca-web/src/db.rs @@ -1,4 +1,4 @@ -use std::{cell::RefCell, collections::HashMap, fmt::Write, future::IntoFuture}; +use std::{collections::HashMap, fmt::Write, future::IntoFuture}; use xitca_postgres::{statement::Statement, AsyncIterator, Postgres}; use xitca_unsafe_collection::no_hash::NoHashBuilder; @@ -10,7 +10,10 @@ use super::{ pub struct Client { client: xitca_postgres::Client, - rng: RefCell, + #[cfg(not(feature = "pg-sync"))] + rng: std::cell::RefCell, + #[cfg(feature = "pg-sync")] + rng: std::sync::Mutex, fortune: Statement, world: Statement, updates: HashMap, @@ -29,7 +32,7 @@ impl Drop for Client { pub async fn create(config: &str) -> HandleResult { let (client, driver) = Postgres::new(config.to_string()).connect().await?; - tokio::task::spawn_local(tokio::task::unconstrained(driver.into_future())); + tokio::spawn(tokio::task::unconstrained(driver.into_future())); let fortune = client.prepare("SELECT * FROM fortune", &[]).await?.leak(); @@ -62,7 +65,10 @@ pub async fn create(config: &str) -> HandleResult { Ok(Client { client, - rng: RefCell::new(Rand::default()), + #[cfg(not(feature = "pg-sync"))] + rng: std::cell::RefCell::new(Rand::default()), + #[cfg(feature = "pg-sync")] + rng: std::sync::Mutex::new(Rand::default()), fortune, world, updates, @@ -70,8 +76,18 @@ pub async fn create(config: &str) -> HandleResult { } impl Client { + #[cfg(not(feature = "pg-sync"))] + fn borrow_rng_mut(&self) -> std::cell::RefMut<'_, Rand> { + self.rng.borrow_mut() + } + + #[cfg(feature = "pg-sync")] + fn borrow_rng_mut(&self) -> std::sync::MutexGuard<'_, Rand> { + self.rng.lock().unwrap() + } + pub async fn get_world(&self) -> HandleResult { - let id = self.rng.borrow_mut().gen_id(); + let id = self.borrow_rng_mut().gen_id(); self.client .query_raw(&self.world, [id]) .await? @@ -86,7 +102,7 @@ impl Client { let mut pipe = self.client.pipeline(); { - let mut rng = self.rng.borrow_mut(); + let mut rng = self.borrow_rng_mut(); (0..num).try_for_each(|_| pipe.query_raw(&self.world, [rng.gen_id()]))?; } @@ -112,7 +128,7 @@ impl Client { let mut pipe = self.client.pipeline(); { - let mut rng = self.rng.borrow_mut(); + let mut rng = self.borrow_rng_mut(); (0..num).try_for_each(|_| { let w_id = rng.gen_id(); let r_id = rng.gen_id(); diff --git a/frameworks/Rust/xitca-web/src/main_axum.rs b/frameworks/Rust/xitca-web/src/main_axum.rs index 1345569126d..b0228246346 100644 --- a/frameworks/Rust/xitca-web/src/main_axum.rs +++ b/frameworks/Rust/xitca-web/src/main_axum.rs @@ -3,30 +3,47 @@ #[global_allocator] static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; +mod db; mod ser; mod util; +use std::sync::Arc; + use axum::{ - http::header::{HeaderValue, SERVER}, - response::IntoResponse, + body::Bytes, + extract::{Json, OriginalUri as Uri, State}, + http::{ + header::{HeaderValue, SERVER}, + StatusCode, + }, + response::{Html, IntoResponse, Response}, routing::{get, Router}, - Json, }; use tower_http::set_header::SetResponseHeaderLayer; -use crate::tower_compat::TowerHttp; +use crate::{ + db::Client, + tower_compat::TowerHttp, + util::{QueryParse, DB_URL}, +}; fn main() -> std::io::Result<()> { let service = TowerHttp::service(|| async { - Router::new() + let cli = db::create(DB_URL).await?; + let service = Router::new() .route("/plaintext", get(plain_text)) .route("/json", get(json)) + .route("/db", get(db)) + .route("/fortunes", get(fortunes)) + .route("/queries", get(queries)) + .route("/updates", get(updates)) + .with_state(Arc::new(cli)) .layer(SetResponseHeaderLayer::if_not_present( SERVER, HeaderValue::from_static("A"), - )) + )); + Ok(service) }); - xitca_server::Builder::new() .bind("xitca-axum", "0.0.0.0:8080", service)? .build() @@ -41,10 +58,48 @@ async fn json() -> impl IntoResponse { Json(ser::Message::new()) } +async fn db(State(cli): State>) -> impl IntoResponse { + cli.get_world().await.map(Json).map_err(Error) +} + +async fn fortunes(State(cli): State>) -> impl IntoResponse { + use sailfish::TemplateOnce; + cli.tell_fortune() + .await + .map_err(Error)? + .render_once() + .map(Html) + .map_err(|e| Error(Box::new(e))) +} + +async fn queries(State(cli): State>, Uri(uri): Uri) -> impl IntoResponse { + cli.get_worlds(uri.query().parse_query()) + .await + .map(Json) + .map_err(Error) +} + +async fn updates(State(cli): State>, Uri(uri): Uri) -> impl IntoResponse { + cli.update(uri.query().parse_query()) + .await + .map(Json) + .map_err(Error) +} + +struct Error(util::Error); + +impl IntoResponse for Error { + fn into_response(self) -> Response { + let mut res = Bytes::new().into_response(); + *res.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; + res + } +} + +// compat module between xitca-http and axum. mod tower_compat { use std::{ cell::RefCell, - convert::Infallible, error, fmt, future::Future, io, @@ -78,24 +133,23 @@ mod tower_compat { impl TowerHttp { pub fn service( - service: F, + func: F, ) -> impl Service< Response = impl ReadyService + Service<(TcpStream, SocketAddr)>, Error = impl fmt::Debug, > where F: Fn() -> Fut + Send + Sync + Clone, - Fut: Future, + Fut: Future>, S: tower::Service, Response = Response>, S::Error: fmt::Debug, B: Body + Send + 'static, B::Error: error::Error + Send + Sync, { fn_build(move |_| { - let service = service.clone(); + let func = func.clone(); async move { - let service = service().await; - Ok::<_, Infallible>(TowerHttp { + func().await.map(|service| TowerHttp { service: RefCell::new(service), _p: PhantomData, }) diff --git a/frameworks/Rust/xitca-web/src/main_wasm.rs b/frameworks/Rust/xitca-web/src/main_wasm.rs index f9961afb6ce..5ca2a96adf2 100644 --- a/frameworks/Rust/xitca-web/src/main_wasm.rs +++ b/frameworks/Rust/xitca-web/src/main_wasm.rs @@ -13,8 +13,6 @@ use xitca_web::{ App, }; -use self::util::SERVER_HEADER_VALUE; - fn main() -> io::Result<()> { let fd = env::var("FD_COUNT") .ok() @@ -44,7 +42,7 @@ where S: for<'r> Service, Response = WebResponse, Error = E>, { service.call(ctx).await.map(|mut res| { - res.headers_mut().append(SERVER, SERVER_HEADER_VALUE); + res.headers_mut().append(SERVER, util::SERVER_HEADER_VALUE); res }) } diff --git a/frameworks/Rust/xitca-web/src/util.rs b/frameworks/Rust/xitca-web/src/util.rs index e9bc8695bd0..624b5dcfa95 100755 --- a/frameworks/Rust/xitca-web/src/util.rs +++ b/frameworks/Rust/xitca-web/src/util.rs @@ -30,7 +30,6 @@ pub type Error = Box; pub type HandleResult = Result; #[cfg(not(target_arch = "wasm32"))] -#[cfg(any(feature = "pg", feature = "pg-iou"))] mod non_wasm { use core::{cell::RefCell, future::Future, pin::Pin}; @@ -77,5 +76,4 @@ mod non_wasm { } #[cfg(not(target_arch = "wasm32"))] -#[cfg(any(feature = "pg", feature = "pg-iou"))] pub use non_wasm::*; diff --git a/frameworks/Rust/xitca-web/xitca-web-axum.dockerfile b/frameworks/Rust/xitca-web/xitca-web-axum.dockerfile index 7c45bef27fb..cbfcfcd467f 100644 --- a/frameworks/Rust/xitca-web/xitca-web-axum.dockerfile +++ b/frameworks/Rust/xitca-web/xitca-web-axum.dockerfile @@ -3,7 +3,7 @@ FROM rust:1.74 ADD ./ /xitca-web WORKDIR /xitca-web -RUN cargo build --release --bin xitca-web-axum --features axum,io-uring +RUN cargo build --release --bin xitca-web-axum --features axum,io-uring,pg-sync,template EXPOSE 8080