diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 5a08c103..d0408cb0 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -8,4 +8,5 @@ members = [ "cache", "mq", "todos", + "perf-test", ] diff --git a/examples/perf-test/Cargo.toml b/examples/perf-test/Cargo.toml new file mode 100644 index 00000000..51c08070 --- /dev/null +++ b/examples/perf-test/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "tardis-example-perf-test" +version = "0.1.0" +authors = ["gudaoxuri"] +edition = "2021" + +[dependencies] +# Tardis Functions +tardis = { path = "../..", features = ["web-server", "reldb"] } +# Web server dependencies +poem-openapi = { version = "^1.3" } +# Reldb dependencies +sea-orm = { version = "^0.6", features = ["macros"] } diff --git a/examples/perf-test/config/conf-default.toml b/examples/perf-test/config/conf-default.toml new file mode 100644 index 00000000..28c5b41f --- /dev/null +++ b/examples/perf-test/config/conf-default.toml @@ -0,0 +1,15 @@ +[app] +id = "perf-test" +name = "性能测试" +desc = "性能测试" +version = "1.0.0" + +[web_server] +port = 8089 +[[web_server.modules]] +code = "" +title = "性能测试" +doc_urls = [["test env", "http://localhost:8089/"]] + +[db] +url = "mysql://root:123456@localhost:3306/test" diff --git a/examples/perf-test/perf.jmx b/examples/perf-test/perf.jmx new file mode 100644 index 00000000..88b96428 --- /dev/null +++ b/examples/perf-test/perf.jmx @@ -0,0 +1,178 @@ + + + + + + false + true + false + + + + + + + + continue + + false + -1 + + 40 + 1 + false + + + true + + + + + + Content-Type + application/json + + + + + + true + + + + false + { + "description": "AA", + "done": false +} + = + + + + 127.0.0.1 + 8089 + + + todo + POST + true + false + true + false + + + + + + + + + + false + 1 + = + true + page_number + + + false + 10 + = + true + page_size + + + + 127.0.0.1 + 8089 + + + todo + GET + true + false + true + false + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + + diff --git a/examples/perf-test/src/domain/mod.rs b/examples/perf-test/src/domain/mod.rs new file mode 100644 index 00000000..015a6a2b --- /dev/null +++ b/examples/perf-test/src/domain/mod.rs @@ -0,0 +1 @@ +pub mod todos; diff --git a/examples/perf-test/src/domain/todos.rs b/examples/perf-test/src/domain/todos.rs new file mode 100644 index 00000000..dd3c2608 --- /dev/null +++ b/examples/perf-test/src/domain/todos.rs @@ -0,0 +1,15 @@ +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "todos")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + pub description: String, + pub done: bool, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation {} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/examples/perf-test/src/initializer.rs b/examples/perf-test/src/initializer.rs new file mode 100644 index 00000000..b5ba07cf --- /dev/null +++ b/examples/perf-test/src/initializer.rs @@ -0,0 +1,9 @@ +use tardis::basic::result::TardisResult; +use tardis::TardisFuns; + +use crate::domain; + +pub async fn init() -> TardisResult<()> { + TardisFuns::reldb().create_table_from_entity(domain::todos::Entity).await?; + Ok(()) +} diff --git a/examples/perf-test/src/main.rs b/examples/perf-test/src/main.rs new file mode 100644 index 00000000..2d959be4 --- /dev/null +++ b/examples/perf-test/src/main.rs @@ -0,0 +1,25 @@ +use std::env; + +use tardis::basic::config::NoneConfig; +use tardis::basic::result::TardisResult; +use tardis::tokio; +use tardis::TardisFuns; + +use crate::processor::TodoApi; + +mod domain; +mod initializer; +mod processor; + +/// +/// Visit: http://127.0.0.1:8089/ui +/// +#[tokio::main] +async fn main() -> TardisResult<()> { + env::set_var("RUST_LOG", "info"); + // Initial + TardisFuns::init::("config").await?; + initializer::init().await?; + // Register the processor and start the web service + TardisFuns::web_server().add_module("", TodoApi).start().await +} diff --git a/examples/perf-test/src/processor.rs b/examples/perf-test/src/processor.rs new file mode 100644 index 00000000..9d1e1a3c --- /dev/null +++ b/examples/perf-test/src/processor.rs @@ -0,0 +1,107 @@ +use poem_openapi::param::Query; +use poem_openapi::{param::Path, payload::Json, Object, OpenApi}; +use sea_orm::sea_query::Expr; +use sea_orm::ActiveValue::Set; +use sea_orm::*; + +use tardis::db::reldb_client::TardisSeaORMExtend; +use tardis::serde::{self, Deserialize, Serialize}; +use tardis::web::web_resp::{TardisPage, TardisResp}; +use tardis::TardisFuns; + +use crate::domain::todos; + +#[derive(Object, FromQueryResult, Serialize, Deserialize, Debug)] +#[serde(crate = "self::serde")] +struct TodoDetailResp { + id: i32, + description: String, + done: bool, +} + +#[derive(Object, Serialize, Deserialize, Debug)] +#[serde(crate = "self::serde")] +struct TodoAddReq { + #[oai(validator(min_length = "2", max_length = "255"))] + description: String, + done: bool, +} + +#[derive(Object, Serialize, Deserialize, Debug)] +#[serde(crate = "self::serde")] +struct TodoModifyReq { + #[oai(validator(min_length = "2", max_length = "255"))] + description: Option, + done: Option, +} + +pub struct TodoApi; + +#[OpenApi] +impl TodoApi { + #[oai(path = "/todo", method = "post")] + async fn add(&self, todo_add_req: Json) -> TardisResp { + let todo = todos::ActiveModel { + description: Set(todo_add_req.description.to_string()), + done: Set(todo_add_req.done), + ..Default::default() + } + .insert(TardisFuns::reldb().conn()) + .await + .unwrap(); + TardisResp::ok(todo.id) + } + + #[oai(path = "/todo/:id", method = "get")] + async fn get(&self, id: Path) -> TardisResp { + let todo_detail_resp = todos::Entity::find() + .filter(todos::Column::Id.eq(id.0)) + .select_only() + .column(todos::Column::Id) + .column(todos::Column::Description) + .column(todos::Column::Done) + .into_model::() + .one(TardisFuns::reldb().conn()) + .await + .unwrap() + .unwrap(); + TardisResp::ok(todo_detail_resp) + } + + #[oai(path = "/todo", method = "get")] + async fn get_all(&self, page_number: Query, page_size: Query) -> TardisResp> { + let result = todos::Entity::find() + .select_only() + .column(todos::Column::Id) + .column(todos::Column::Description) + .column(todos::Column::Done) + .order_by_desc(todos::Column::Id) + .into_model::() + .paginate(TardisFuns::reldb().conn(), page_size.0); + TardisResp::ok(TardisPage { + page_size: page_size.0, + page_number: result.num_pages().await.unwrap(), + total_size: result.num_items().await.unwrap(), + records: result.fetch_page(page_number.0 - 1).await.unwrap(), + }) + } + + #[oai(path = "/todo/:id", method = "delete")] + async fn delete(&self, id: Path) -> TardisResp { + let delete_num = todos::Entity::find().filter(todos::Column::Id.eq(id.0)).soft_delete(TardisFuns::reldb().conn(), "").await.unwrap(); + TardisResp::ok(delete_num) + } + + #[oai(path = "/todo/:id", method = "put")] + async fn update(&self, id: Path, todo_modify_req: Json) -> TardisResp { + let mut update = todos::Entity::update_many().filter(todos::Column::Id.eq(id.0)); + if let Some(description) = &todo_modify_req.description { + update = update.col_expr(todos::Column::Description, Expr::value(description.clone())); + } + if let Some(done) = todo_modify_req.done { + update = update.col_expr(todos::Column::Done, Expr::value(done)); + } + let update_num = update.exec(TardisFuns::reldb().conn()).await.unwrap().rows_affected; + TardisResp::ok(update_num as usize) + } +}