zero4rs 2.0.0

zero4rs is a powerful, pragmatic, and extremely fast web framework for Rust
Documentation
pub mod application;
pub mod serv;
pub mod startup;

pub use application::*;
pub use serv::*;
pub use startup::*;

use clap::Parser;
use core::fmt::Debug;

use sqlx::MySql;
use sqlx::Pool;

use crate::core::{config, natss};

use crate::core::http_clients::EmailClient;

use crate::core::elasticsearch;
use crate::core::kafka;
use crate::core::mongo;
use crate::core::mysql;
use crate::core::rudis;

use std::sync::{Arc, RwLock};
use tera::Tera;

/// Search for a pattern in a file and display the lines that contain it.
#[derive(Parser, Debug)]
#[clap(
    author = "keesh.zhang",
    version,
    about = "A powerful, pragmatic, and extremely fast web framework for Rust"
)]
pub struct Cli {
    #[clap(flatten)]
    pub environment: Environment,
    #[clap(flatten)]
    pub config: ConfigPath,
}

#[derive(Parser, Debug)]
pub struct Environment {
    /// 环境名
    #[clap(short, long, default_value = "local")]
    pub environment: String,
}

#[derive(Parser, Debug)]
pub struct ConfigPath {
    /// 配置文件
    #[clap(short = 'c', long = "config", default_value = "./configuration")]
    pub path: String,
}

pub struct AppContext {
    pub settings: config::Settings,
    pub tpl: Arc<RwLock<Tera>>,
    pub email_client: crate::core::http_clients::EmailClient,
    pub mongo_client: Option<mongo::MongoClient>,
    pub rudis_client: Option<rudis::RuidsClient>,
    pub nats_client: Option<natss::NatsClient>,
    pub mysql_client: Option<mysql::MysqlClient>,
    pub es_client: Option<crate::core::elasticsearch::EsClient>,
    pub kafka_producer: Option<crate::core::kafka::KafkaClient>,
}

impl AppContext {
    pub async fn build(server_name: &str) -> Self {
        let settings = Self::configuraton(server_name);

        Self {
            tpl: crate::templates::get().templates,
            email_client: EmailClient::new(),
            mongo_client: Self::get_mongo(&settings).await,
            // rudis
            rudis_client: rudis::client(&settings.rudis).await,
            nats_client: natss::client(&settings.nats).await,
            // mysql
            mysql_client: Self::get_mysql(&settings).await,
            // es_client: Some(es_client),
            es_client: None,
            // kafka_producer: Some(kafka_producer),
            kafka_producer: None,
            settings,
        }
    }

    pub fn config(&self) -> config::Settings {
        self.settings.clone()
    }

    fn configuraton(server_name: &str) -> config::Settings {
        let command: Cli = Cli::parse();

        let env_name = &command.environment.environment;
        let config_path = &command.config.path;

        crate::core::buildinfo::cargo_line();
        crate::core::buildinfo::line();
        crate::core::cpu_info::print_line();

        // 设置环境变量
        std::env::set_var("RUST_LOG", "debug");
        std::env::set_var("RUST_MIN_STACK", "1048576");
        std::env::set_var("ENV_NAME", env_name.to_uppercase());
        std::env::set_var("APP_NAME", server_name);

        // 设置 SQLX_LOG 环境变量
        // std::env::set_var("SQLX_LOG", "debug");

        // 加载配置
        let configuration = config::get_configuration(env_name, config_path)
            .expect("Failed to read configuration.");

        // init log4rs
        crate::core::logger::builder(&configuration);

        configuration
    }

    pub fn rudis(&self) -> rudis::RuidsClient {
        self.rudis_client.clone().unwrap()
    }

    pub fn rudis_opt(&self) -> Option<rudis::RuidsClient> {
        self.rudis_client.clone()
    }

    pub fn nats(&self) -> natss::NatsClient {
        self.nats_client.clone().unwrap()
    }

    pub fn nats_opt(&self) -> Option<natss::NatsClient> {
        self.nats_client.clone()
    }

    pub async fn get_mysql(cfg: &config::Settings) -> Option<mysql::MysqlClient> {
        let mysql_settings = mysql::MysqlSettings::get(&cfg.mysql);

        if mysql_settings.enabled() {
            let mysql_client: mysql::MysqlClient = mysql::create_pool(&mysql_settings).unwrap();

            Some(mysql_client)
        } else {
            None
        }
    }

    pub fn mysql(&self) -> &Pool<MySql> {
        &self.mysql_client.as_ref().unwrap().pool
    }

    pub fn mysql_client(&self) -> &mysql::MysqlClient {
        self.mysql_client.as_ref().unwrap()
    }

    pub async fn get_mongo(cfg: &config::Settings) -> Option<mongo::MongoClient> {
        let mongo_settings = mongo::MongoSettings::get(&cfg.mongodb);

        if !mongo_settings.enabled() {
            None
        } else {
            let mongo_client = mongo::MongoClient::build(&mongo_settings).await;

            Some(mongo_client)
        }
    }

    pub fn mongo(&self) -> &mongo::MongoClient {
        self.mongo_client.as_ref().unwrap()
    }

    pub fn mongo_opt(&self) -> Option<&mongo::MongoClient> {
        self.mongo_client.as_ref()
    }

    pub async fn get_es(cfg: &config::Settings) -> elasticsearch::EsClient {
        let es_settings = elasticsearch::ElasticsearchSettings::get(&cfg.elasticsearch);
        elasticsearch::create_single_node(&es_settings)
            .await
            .unwrap()
    }

    pub fn es(&self) -> elasticsearch::EsClient {
        self.es_client.clone().unwrap()
    }

    pub async fn get_kafka(cfg: &config::Settings) -> kafka::KafkaClient {
        let kafka_settings = kafka::KafkaSettings::get(&cfg.kafka);
        kafka::KafkaClient::build(&kafka_settings)
    }

    pub fn kafka(&self) -> kafka::KafkaClient {
        self.kafka_producer.clone().unwrap()
    }
}