83 lines
2.3 KiB
Rust
Raw Normal View History

//! 充电柜矩阵系统 — 后端入口
mod config;
mod db;
mod error;
mod middleware;
mod redis;
mod routes;
mod tcp;
use std::net::SocketAddr;
use tracing_subscriber::EnvFilter;
use tcp::commands::AppState;
use tcp::connection::ConnectionPool;
#[tokio::main]
async fn main() {
// 初始化日志
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::try_from_default_env().unwrap_or_else(|_| "info".into()))
.init();
// 加载配置
let cfg = config::Config::from_env();
cfg.validate();
tracing::info!("配置加载完成");
// 初始化 MySQL 连接池
let db_pool = db::init_pool(&cfg.database_url)
.await
.expect("MySQL 连接失败");
tracing::info!("数据库连接成功");
// 执行自动迁移
db::migrate::run(&db_pool)
.await
.expect("数据库迁移失败");
tracing::info!("数据库迁移完成");
// 初始化 Redis 连接ConnectionManager 内部管理重连,可直接 Clone 共享)
let redis_conn = redis::init_connection(&cfg.redis_url)
.await
.expect("Redis 连接失败");
tracing::info!("Redis 连接成功");
// 初始化设备连接池
let device_pool = ConnectionPool::new();
// 构建共享状态
let state = AppState {
device_pool: device_pool.clone(),
redis: redis_conn.clone(),
mysql: db_pool.clone(),
};
// 启动 TCP 设备服务(后台)
let tcp_addr = format!("{}:{}", cfg.host, cfg.tcp_port);
tracing::info!("TCP 设备服务启动于 {}", tcp_addr);
let tcp_pool = device_pool.clone();
let tcp_redis = redis_conn.clone();
let tcp_mysql = db_pool.clone();
tokio::spawn(async move {
tcp::run_tcp_server(tcp_addr, tcp_pool, tcp_redis, tcp_mysql).await;
});
// 构建 HTTP 路由(包含设备指令下发端点和认证中间件)
let app = routes::build(state);
// 启动 HTTP 服务
let addr: SocketAddr = format!("{}:{}", cfg.host, cfg.port)
.parse()
.expect("无效的监听地址");
tracing::info!("HTTP 服务器启动于 http://{}", addr);
let listener = tokio::net::TcpListener::bind(addr)
.await
.expect("端口绑定失败");
axum::serve(listener, app)
.await
.expect("服务器运行失败");
}