Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
chrislearn committed Jan 17, 2025
1 parent c882033 commit 2da6ca1
Show file tree
Hide file tree
Showing 7 changed files with 202 additions and 40 deletions.
158 changes: 158 additions & 0 deletions template/_base/src/main.rs.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@

use crate::db::init_db_conn;
use tokio::signal;
use tracing::info;
use crate::middleware::{handle_404::handle_404,cors::cors_middleware};
use crate::routers::router;
use salvo::server::ServerHandle;
use salvo::catcher::Catcher;
use salvo::conn::rustls::{Keycert, RustlsConfig};
use salvo::prelude::*;
mod config;
mod db;
mod beams;
mod utils;
{% if db_lib == "diesel" %}
mod schema;
{% endif %}
mod hoops;
mod routers;

use config::ServerConfig;

pub fn config() -> &'static ServerConfig {
&*crate::config::CONFIG
}

#[tokio::main]
async fn main() {
if let Err(e) = dotenv() {
println!("dotenv error: {:?}", e);
}

let raw_config = Figment::new()
.merge(Toml::file(Env::var("APP_CONFIG").as_deref().unwrap_or("config.toml")))
.merge(Env::prefixed("APP_").global());

let config = match raw_config.extract::<ServerConfig>() {
Ok(s) => s,
Err(e) => {
eprintln!("It looks like your config is invalid. The following error occurred: {e}");
std::process::exit(1);
}
};
crate::config::CONFIG.set(config).expect("config should be set");
let config = crate::config();

{% if db_lib == "diesel" %}
let thread_pool = Arc::new(ScheduledThreadPool::new(conf.db.helper_threads));

let db_primary = {
let db_connection_config = ConnectionConfig {
statement_timeout: config.db.statement_timeout,
};

let db_config = r2d2::Pool::builder()
.max_size(conf.db.pool_size)
.min_idle(conf.db.min_idle)
.connection_timeout(Duration::from_millis(config.db.connection_timeout))
.connection_customizer(Box::new(db_connection_config))
.thread_pool(thread_pool.clone());

DieselPool::new(&config.db.url, &config.db, db_config).unwrap()
};
crate::db::DIESEL_POOL
.set(db_primary)
.expect("diesel pool should be set");
{% endif %}

crate::db::migrate();

let _guard = config.log.guard();
tracing::info!("log level: {}", &config.log.filter_level);

let service = Service::new(routers::root()).catcher(Catcher::default().hoop(handle_404)).hoop(cors_hoop()));
println!("🔄 {{listen_on}} {}", &config.listen_addr);
if config.ssl {
println!(
"📖 {{open_api_page}}: https://{}/scalar",
config.listen_addr.replace("0.0.0.0", "127.0.0.1")
);
{% if code_gen == "website" %}
println!("🔑 {{login_page}}: https://{}/login", config.listen_addr.replace("0.0.0.0", "127.0.0.1"));
{% endif %}
let config = RustlsConfig::new(
Keycert::new()
.cert(CERT_KEY.cert.clone())
.key(CERT_KEY.key.clone()),
);
let acceptor = TcpListener::new(&config.server.listen_addr)
.rustls(config)
.bind()
.await;
let server = Server::new(acceptor);
tokio::spawn(shutdown_signal(server.handle()));
server.serve(service).await;
} else {
println!(
"📖 {{open_api_page}}: http://{}/scalar",
config.listen_addr.replace("0.0.0.0", "127.0.0.1")
);
{% if code_gen == "website" %}
println!("🔑 {{login_page}}: http://{}/login", config().server.listen_addr.replace("0.0.0.0", "127.0.0.1"));
{% endif %}
let acceptor = TcpListener::new(&config.listen_addr).bind().await;
let server = Server::new(acceptor);
tokio::spawn(shutdown_signal(server.handle()));
server.serve(service).await;
}
}

async fn shutdown_signal(handle: ServerHandle) {
let ctrl_c = async {
signal::ctrl_c()
.await
.expect("failed to install Ctrl+C handler");
};

#[cfg(unix)]
let terminate = async {
signal::unix::signal(signal::unix::SignalKind::terminate())
.expect("failed to install signal handler")
.recv()
.await;
};

#[cfg(not(unix))]
let terminate = std::future::pending::<()>();

tokio::select! {
_ = ctrl_c => info!("ctrl_c signal received"),
_ = terminate => info!("terminate signal received"),
}
handle.stop_graceful(std::time::Duration::from_secs(60));
}

#[cfg(test)]
mod tests {
use salvo::prelude::*;
use salvo::test::{ResponseExt, TestClient};

use crate::config;

#[tokio::test]
async fn test_hello_world() {
let service = Service::new(super::router());

let content = TestClient::get(format!(
"http://{}",
&config().address.replace("0.0.0.0", "127.0.0.1")
))
.send(&service)
.await
.take_string()
.await
.unwrap();
assert_eq!(content, "Hello World from salvo");
}
}
6 changes: 5 additions & 1 deletion templates/classic/_base/src/main.rs.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,12 @@ mod schema;
mod hoops;
mod routers;

use config::ServerConfig;
mod error;
pub use error::AppError;

pub type AppResult<T> = Result<T, AppError>;

use config::ServerConfig;
pub fn config() -> &'static ServerConfig {
&*crate::config::CONFIG
}
Expand Down
8 changes: 4 additions & 4 deletions templates/classic/diesel/src/db/mod.rs.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
use diesel::prelude::*;
{% if db_type == "sqlite" %}
pub fn establish_connection() -> SqliteConnection {
let conn = SqliteConnection::establish(&CFG.database.database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}", &CFG.database.database_url));
let conn = SqliteConnection::establish(&config().db.database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}", &config().db.database_url));
conn
}
{% endif %}
{% if db_type == "mysql" %}
pub fn establish_connection() -> MysqlConnection {
MysqlConnection::establish(&CFG.database.database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}", &CFG.database.database_url))
MysqlConnection::establish(&config().db.database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}", &config().db.database_url))
}
{% endif %}
{% if db_type == "postgres" %}
Expand Down
18 changes: 9 additions & 9 deletions templates/classic/mongodb/src/db.rs.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@
use diesel::prelude::*;
{% if db_type == "sqlite" %}
pub fn establish_connection() -> SqliteConnection {
let conn = SqliteConnection::establish(&CFG.database.database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}", &CFG.database.database_url));
let conn = SqliteConnection::establish(&config().db.database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}", &config().db.database_url));
conn
}
{% endif %}
{% if db_type == "mysql" %}
pub fn establish_connection() -> MysqlConnection {
MysqlConnection::establish(&CFG.database.database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}", &CFG.database.database_url))
MysqlConnection::establish(&config().db.database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}", &config().db.database_url))
}
{% endif %}
{% if db_type == "postgres" %}
pub fn establish_connection() -> PgConnection {
PgConnection::establish(&CFG.database.database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}", &CFG.database.database_url))
PgConnection::establish(&config().db.database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}", &config().db.database_url))
}
{% endif %}
{% endif %}
Expand All @@ -36,17 +36,17 @@ pub async fn init_db_conn() {
DB.get_or_init(|| async {
{% if db_lib == "sqlx" %}
{% if db_type == "sqlite" %}
SqlitePool::connect(&CFG.database.database_url)
SqlitePool::connect(&config().db.database_url)
.await
.expect("{{database_connection_failed}}")
{% endif %}
{% if db_type == "postgres" %}
PgPool::connect(&CFG.database.database_url)
PgPool::connect(&config().db.database_url)
.await
.expect("{{database_connection_failed}}")
{% endif %}
{% if db_type == "mysql" %}
MySqlPool::connect(&CFG.database.database_url)
MySqlPool::connect(&config().db.database_url)
.await
.expect("{{database_connection_failed}}")
{% endif %}
Expand Down
18 changes: 9 additions & 9 deletions templates/classic/rbatis/src/db.rs.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@
use diesel::prelude::*;
{% if db_type == "sqlite" %}
pub fn establish_connection() -> SqliteConnection {
let conn = SqliteConnection::establish(&CFG.database.database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}", &CFG.database.database_url));
let conn = SqliteConnection::establish(&config().db.database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}", &config().db.database_url));
conn
}
{% endif %}
{% if db_type == "mysql" %}
pub fn establish_connection() -> MysqlConnection {
MysqlConnection::establish(&CFG.database.database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}", &CFG.database.database_url))
MysqlConnection::establish(&config().db.database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}", &config().db.database_url))
}
{% endif %}
{% if db_type == "postgres" %}
pub fn establish_connection() -> PgConnection {
PgConnection::establish(&CFG.database.database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}", &CFG.database.database_url))
PgConnection::establish(&config().db.database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}", &config().db.database_url))
}
{% endif %}
{% endif %}
Expand All @@ -36,17 +36,17 @@ pub async fn init_db_conn() {
DB.get_or_init(|| async {
{% if db_lib == "sqlx" %}
{% if db_type == "sqlite" %}
SqlitePool::connect(&CFG.database.database_url)
SqlitePool::connect(&config().db.database_url)
.await
.expect("{{database_connection_failed}}")
{% endif %}
{% if db_type == "postgres" %}
PgPool::connect(&CFG.database.database_url)
PgPool::connect(&config().db.database_url)
.await
.expect("{{database_connection_failed}}")
{% endif %}
{% if db_type == "mysql" %}
MySqlPool::connect(&CFG.database.database_url)
MySqlPool::connect(&config().db.database_url)
.await
.expect("{{database_connection_failed}}")
{% endif %}
Expand Down
6 changes: 3 additions & 3 deletions templates/classic/seaorm/migration/src/db.rs.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ pub async fn init_db_conn() {
DB.get_or_init(|| async {
{% if db_lib == "sqlx" %}
{% if db_type == "sqlite" %}
SqlitePool::connect(&CFG.database.database_url)
SqlitePool::connect(&config().db.database_url)
.await
.expect("{{database_connection_failed}}")
{% endif %}
{% if db_type == "postgres" %}
PgPool::connect(&CFG.database.database_url)
PgPool::connect(&config().db.database_url)
.await
.expect("{{database_connection_failed}}")
{% endif %}
{% if db_type == "mysql" %}
MySqlPool::connect(&CFG.database.database_url)
MySqlPool::connect(&config().db.database_url)
.await
.expect("{{database_connection_failed}}")
{% endif %}
Expand Down
28 changes: 14 additions & 14 deletions templates/classic/sqlx/src/db.rs.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,21 @@ use tokio::sync::OnceCell;
use diesel::prelude::*;
{% if db_type == "sqlite" %}
pub fn establish_connection() -> SqliteConnection {
let conn = SqliteConnection::establish(&CFG.database.database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}", &CFG.database.database_url));
let conn = SqliteConnection::establish(&config().db.database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}", &config().db.database_url));
conn
}
{% endif %}
{% if db_type == "mysql" %}
pub fn establish_connection() -> MysqlConnection {
MysqlConnection::establish(&CFG.database.database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}", &CFG.database.database_url))
MysqlConnection::establish(&config().db.database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}", &config().db.database_url))
}
{% endif %}
{% if db_type == "postgres" %}
pub fn establish_connection() -> PgConnection {
PgConnection::establish(&CFG.database.database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}", &CFG.database.database_url))
PgConnection::establish(&config().db.database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}", &config().db.database_url))
}
{% endif %}
{% endif %}
Expand All @@ -51,17 +51,17 @@ pub async fn init_db_conn() {
DB.get_or_init(|| async {
{% if db_lib == "sqlx" %}
{% if db_type == "sqlite" %}
SqlitePool::connect(&CFG.database.database_url)
SqlitePool::connect(&config().db.database_url)
.await
.expect("{{database_connection_failed}}")
{% endif %}
{% if db_type == "postgres" %}
PgPool::connect(&CFG.database.database_url)
PgPool::connect(&config().db.database_url)
.await
.expect("{{database_connection_failed}}")
{% endif %}
{% if db_type == "mysql" %}
MySqlPool::connect(&CFG.database.database_url)
MySqlPool::connect(&config().db.database_url)
.await
.expect("{{database_connection_failed}}")
{% endif %}
Expand All @@ -75,7 +75,7 @@ pub static DB: OnceCell<DatabaseConnection> = OnceCell::const_new();

pub async fn init_db_conn() {
DB.get_or_init(|| async {
let mut opt = ConnectOptions::new(CFG.database.database_url.to_owned());
let mut opt = ConnectOptions::new(config().db.database_url.to_owned());
opt.max_connections(1000)
.min_connections(5)
.connect_timeout(Duration::from_secs(8))
Expand All @@ -98,15 +98,15 @@ pub async fn init_db_conn() {

{% if db_type == "postgres" %}
// PostgreSQL
rb.init(rbdc_pg::driver::PgDriver {}, &CFG.database.database_url).unwrap();
rb.init(rbdc_pg::driver::PgDriver {}, &config().db.database_url).unwrap();
{% endif %}
{% if db_type == "mysql" %}
// MySQL
rb.init(rbdc_mysql::driver::MysqlDriver {}, &CFG.database.database_url).unwrap();
rb.init(rbdc_mysql::driver::MysqlDriver {}, &config().db.database_url).unwrap();
{% endif %}
{% if db_type == "sqlite" %}
// SQLite
rb.init(rbdc_sqlite::driver::SqliteDriver {}, &CFG.database.database_url).unwrap();
rb.init(rbdc_sqlite::driver::SqliteDriver {}, &config().db.database_url).unwrap();
{% endif %}

let sql_file = match rb.driver_type().unwrap() {
Expand All @@ -133,7 +133,7 @@ pub const DB_NAME: &str = "myApp";
pub const COLL_NAME: &str = "users";
pub static MONGODB_CLIENT: OnceCell<Client> = OnceCell::new();
pub async fn init_db_conn() {
let mongodb_uri = &CFG.database.database_url;
let mongodb_uri = &config().db.database_url;
let client = Client::with_uri_str(mongodb_uri)
.await
.expect("failed to connect");
Expand Down

0 comments on commit 2da6ca1

Please sign in to comment.