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)
+ }
+}