perf: 合并 insert_weather_data N+1 查询为单次;添加 Docker 内存限制和磁盘告警
Some checks failed
Deploy Backend / deploy (push) Has been cancelled

This commit is contained in:
2026-07-15 10:52:24 +08:00
parent fff3877f03
commit a47502f07e

View File

@@ -9,15 +9,36 @@ use crate::error::AppError;
// 用于插入weather_data的数据 // 用于插入weather_data的数据
pub async fn insert_weather_data(pool: &PgPool, weather_data: &WeatherData, user_id: i32) -> Result<i32, AppError> { pub async fn insert_weather_data(pool: &PgPool, weather_data: &WeatherData, user_id: i32) -> Result<i32, AppError> {
// 配额检查:非付费用户数据条数限制 // 单次查询获取用户会员状态和数据条数(原 N+1get_user_by_id + count_user_weather_data → 合并为 1 次)
let user = get_user_by_id(pool, user_id).await?; #[derive(FromRow)]
let is_active_member = user.is_member && user.membership_expires_at.is_none_or(|expires| expires > Utc::now()); struct UserQuota {
is_member: bool,
paid_expires_at: Option<chrono::DateTime<Utc>>,
data_count: i64,
}
let quota = sqlx::query_as::<_, UserQuota>(
r#"
SELECT
u.is_member,
u.paid_expires_at,
(SELECT COUNT(*) FROM weather_data w WHERE w.user_id = $1)::BIGINT AS data_count
FROM users u
WHERE u.id = $1
"#,
)
.bind(user_id)
.fetch_optional(pool)
.await
.map_err(|e| AppError::Database(format!("查询用户配额失败: {}", e)))?
.ok_or_else(|| AppError::NotFound("用户不存在".to_string()))?;
let is_active_member = quota.is_member && quota.paid_expires_at.is_none_or(|expires| expires > Utc::now());
// 维护模式:非会员使用更高的临时限额,防止资源滥用 // 维护模式:非会员使用更高的临时限额,防止资源滥用
let is_maintenance = std::env::var("PAYMENT_MAINTENANCE_MODE").ok() == Some("true".to_string()); let is_maintenance = std::env::var("PAYMENT_MAINTENANCE_MODE").ok() == Some("true".to_string());
if !is_active_member { if !is_active_member {
let current_count = count_user_weather_data(pool, user_id).await?;
let limit: i64 = if is_maintenance { let limit: i64 = if is_maintenance {
env::var("MAINTENANCE_MODE_DATA_LIMIT") env::var("MAINTENANCE_MODE_DATA_LIMIT")
.unwrap_or_else(|_| "500".to_string()) .unwrap_or_else(|_| "500".to_string())
@@ -30,7 +51,7 @@ pub async fn insert_weather_data(pool: &PgPool, weather_data: &WeatherData, user
.unwrap_or(20) .unwrap_or(20)
}; };
if current_count >= limit { if quota.data_count >= limit {
return Err(AppError::Forbidden("数据条数已达上限,请升级为付费用户".to_string())); return Err(AppError::Forbidden("数据条数已达上限,请升级为付费用户".to_string()));
} }
} }