72 lines
2.3 KiB
Rust
72 lines
2.3 KiB
Rust
use migration::{Migrator, MigratorTrait};
|
||
use sea_orm::{ConnectOptions, Database, DbConn};
|
||
use std::env;
|
||
use std::path::PathBuf;
|
||
use tokio::sync::mpsc;
|
||
use tracing::info;
|
||
|
||
use crate::timer::{NotificationWorker, SharedTimeWheel, WorkerCommand};
|
||
|
||
#[derive(Clone)]
|
||
pub struct AppData {
|
||
pub db: DbConn,
|
||
pub jwt_secret: String,
|
||
pub worker_tx: mpsc::Sender<WorkerCommand>,
|
||
/// 服务器基础 URL,用于生成头像等资源的完整 URL
|
||
/// 本地调试: http://localhost:4000
|
||
/// 生产环境: https://notify.michaelandmeryl.xyz
|
||
pub base_url: String,
|
||
/// 上传文件的存储目录
|
||
pub upload_dir: PathBuf,
|
||
}
|
||
|
||
impl AppData {
|
||
pub async fn new() -> Result<Self, anyhow::Error> {
|
||
let url = env::var("DATABASE_URL")
|
||
.unwrap_or_else(|_| "postgres://postgres:postgres@localhost:5432/notify".to_string());
|
||
let mut opt = ConnectOptions::new(url);
|
||
opt.max_connections(10).sqlx_logging(false);
|
||
let db = Database::connect(opt).await?;
|
||
|
||
// 自动运行数据库迁移
|
||
info!("Running database migrations...");
|
||
Migrator::up(&db, None).await?;
|
||
info!("Database migrations completed.");
|
||
|
||
let jwt_secret = env::var("JWT_SECRET").unwrap_or_else(|_| "dev-secret".to_string());
|
||
|
||
// 从环境变量读取 BASE_URL,默认为本地开发地址
|
||
let base_url = env::var("BASE_URL").unwrap_or_else(|_| "http://localhost:4000".to_string());
|
||
|
||
// 上传目录,默认为当前目录下的 uploads
|
||
let upload_dir = env::var("UPLOAD_DIR")
|
||
.map(PathBuf::from)
|
||
.unwrap_or_else(|_| PathBuf::from("./uploads"));
|
||
|
||
// 确保上传目录存在
|
||
tokio::fs::create_dir_all(&upload_dir).await?;
|
||
tokio::fs::create_dir_all(upload_dir.join("avatars")).await?;
|
||
|
||
// 创建并启动时间轮 Worker
|
||
let time_wheel = SharedTimeWheel::new();
|
||
let worker = NotificationWorker::new(db.clone(), time_wheel);
|
||
let worker_tx = worker.start().await;
|
||
|
||
Ok(Self {
|
||
db,
|
||
jwt_secret,
|
||
worker_tx,
|
||
base_url,
|
||
upload_dir,
|
||
})
|
||
}
|
||
|
||
/// 发送命令给 Worker
|
||
pub async fn send_worker_command(
|
||
&self,
|
||
cmd: WorkerCommand,
|
||
) -> Result<(), mpsc::error::SendError<WorkerCommand>> {
|
||
self.worker_tx.send(cmd).await
|
||
}
|
||
}
|